Last active
August 13, 2020 14:16
-
-
Save izelnakri/b2913b0422cc5868b23a9e82b7257701 to your computer and use it in GitHub Desktop.
node.js microservice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import axios from "axios"; | |
| import express from "express"; | |
| import bodyParser from "body-parser"; | |
| import Workflow from "./models/workflow.js"; | |
| const { ARGO_SERVER_URL, ARGO_SERVER_TOKEN, GITEA_SERVER_URL, GITEA_SERVER_TOKEN } = process.env; | |
| const TARGET_PORT = process.env.PORT || 1234; | |
| const CI_RUNNING_IMAGE = | |
| process.env.TESTS_RUNNING_IMAGE || "https://media.giphy.com/media/8WeatsYCC54TC/giphy.gif"; | |
| const CI_SUCCEED_IMAGE = | |
| process.env.TESTS_SUCCEED_IMAGE || "https://media.giphy.com/media/11sBLVxNs7v6WA/giphy.gif"; | |
| const CI_FAILED_IMAGE = | |
| process.env.TESTS_FAILED_IMAGE || "https://media.giphy.com/media/N35rW3vRNeaDC/giphy.gif"; | |
| const app = express(); | |
| app.use(bodyParser.json()); | |
| app.post("/submit-workflow", (req, res) => { | |
| const { repository, ref, commits } = req.body; | |
| const project = repository.full_name; | |
| const workflowTemplate = req.body.secret || "default"; | |
| if ("commits" in req.body) { | |
| const branch = ref.replace("refs/heads/", ""); | |
| const targetCommit = commits[commits.length - 1]; | |
| if (targetCommit) { | |
| console.log(`Git push to existing repo ${project}/${branch}:`); | |
| return sendWorkflowToArgo(res, { | |
| workflowTemplate, | |
| sender: targetCommit.committer.username, | |
| project, | |
| branch, | |
| commitHash: targetCommit.id, | |
| event: "git-push", | |
| }); | |
| } else if (isNewBranch(req.body)) { | |
| console.log(`New branch on ${project}/${branch}:`); | |
| return sendWorkflowToArgo(res, { | |
| workflowTemplate, | |
| sender: req.body.username, | |
| project, | |
| branch, | |
| commitHash: req.body.after, | |
| event: "new-branch", | |
| }); | |
| } | |
| } else if (isNewPullRequest(req.body)) { | |
| const branch = req.body.pull_request.head.ref; | |
| console.log( | |
| `New pull request on ${project}/${branch} -> ${project}/${req.body.pull_request.base.ref}` | |
| ); | |
| return sendWorkflowToArgo(res, { | |
| workflowTemplate, | |
| sender: req.body.username, | |
| project, | |
| branch, | |
| commitHash: req.body.pull_request.head.sha, | |
| event: "new-pull-request", | |
| pullRequestNumber: req.body.pull_request.number, | |
| }); | |
| } | |
| res.end(); | |
| }); | |
| app.post("/submit-workflow-result", (req, res) => { | |
| const workflow = Workflow.findBy({ | |
| workflowName: req.body.workflowName, | |
| }); | |
| if (workflow && workflow.pullRequestNumber) { | |
| return postCIResultsToPR(res, workflow, req.body); | |
| } | |
| return res.status(201).end(); | |
| }); | |
| app.listen(TARGET_PORT, () => console.log(`server listening on ${TARGET_PORT}`)); | |
| function sendWorkflowToArgo(res, workflowDetails) { | |
| const { | |
| workflowTemplate, | |
| sender, | |
| project, | |
| branch, | |
| commitHash, | |
| event, | |
| pullRequestNumber, | |
| } = workflowDetails; | |
| const projectLabel = project.replace("/", "."); | |
| // IN FUTURE: ownerReference to k8s ServiceAccount | |
| return axios | |
| .post( | |
| `${ARGO_SERVER_URL}/api/v1/workflows/argo/submit`, | |
| { | |
| resourceKind: "WorkflowTemplate", | |
| resourceName: workflowTemplate, | |
| submitOptions: { | |
| labels: | |
| `workflows.argoproj.io/workflow-template=${workflowTemplate},workflows.argoproj.io/creator=${sender}` + | |
| `,workflows.argoproj.io/project=${projectLabel},workflows.argoproj.io/branch=${branch}` + | |
| `,workflows.argoproj.io/commit-hash=${commitHash},workflows.argoproj.io/event=${event}`, | |
| parameters: [ | |
| `branch=${branch}`, | |
| `sender=${sender}`, | |
| `project=${project}`, | |
| `commitHash=${commitHash}`, | |
| `event=${event}`, | |
| ], | |
| }, | |
| }, | |
| { | |
| headers: { | |
| Authorization: `Bearer ${ARGO_SERVER_TOKEN}`, | |
| }, | |
| } | |
| ) | |
| .then(async (argoResult) => { | |
| const metadata = argoResult.data.metadata; | |
| const workflow = Workflow.insert({ | |
| branch, | |
| project, | |
| workflowName: metadata.name, | |
| status: "Running", | |
| pullRequestNumber: | |
| event === "new-pull-request" | |
| ? pullRequestNumber | |
| : await getPullRequestNumber(project, branch), | |
| startAt: metadata.creationTimestamp, | |
| }); | |
| console.log(`Job #${metadata.name} submitted`); | |
| res.status(201).end(); | |
| return postCIRunningToPR(workflow, argoResult); | |
| }) | |
| .catch((error) => { | |
| console.log(error); | |
| console.error(`Error occured during job submission, HTTP ${error.response.status}:`); | |
| console.error(error.response.data); | |
| return res.status(error.response.status).end(); | |
| }); | |
| } | |
| function isNewBranch(requestBody) { | |
| return requestBody.before === "0000000000000000000000000000000000000000"; | |
| } | |
| function isNewPullRequest(requestBody) { | |
| return requestBody.action === "opened" && requestBody.pull_request; | |
| } | |
| function postCIRunningToPR(workflow, argoResult) { | |
| const { project, branch, pullRequestNumber, workflowName } = workflow; | |
| const message = | |
| `Tests running on ${ARGO_SERVER_URL}/workflows/argo/${workflowName} \n\n` + | |
| `;`; | |
| return axios | |
| .post( | |
| `${GITEA_SERVER_URL}/api/v1/repos/${project}/issues/${pullRequestNumber}/comments`, | |
| { | |
| body: message, | |
| }, | |
| { | |
| headers: { | |
| Authorization: `token ${GITEA_SERVER_TOKEN}`, | |
| }, | |
| } | |
| ) | |
| .then((result) => { | |
| console.log(`CI Running comment posted on ${project}/${branch} PR#${pullRequestNumber}`); | |
| }) | |
| .catch((error) => { | |
| console.error( | |
| `Error occured during posting CI running comment to PR#${pullRequestNumber}, HTTP ${error.response.status}` | |
| ); | |
| console.error(error.response.data); | |
| }); | |
| } | |
| function postCIResultsToPR(res, workflow, requestBody) { | |
| return axios | |
| .post( | |
| `${GITEA_SERVER_URL}/api/v1/repos/${workflow.project}/issues/${workflow.pullRequestNumber}/comments`, | |
| { | |
| body: | |
| requestBody.workflowStatus === "Succeeded" | |
| ? `Tests succeeded on ${ARGO_SERVER_URL}/workflows/argo/${requestBody.workflowName} \n\n` + | |
| `;` | |
| : `Tests failed on ${ARGO_SERVER_URL}/workflows/argo/${requestBody.workflowName} \n\n` + | |
| `;`, | |
| }, | |
| { | |
| headers: { | |
| Authorization: `token ${GITEA_SERVER_TOKEN}`, | |
| }, | |
| } | |
| ) | |
| .then((result) => { | |
| console.log( | |
| `CI Result comment posted on ${workflow.project}/${workflow.branch} PR#${workflow.pullRequestNumber}` | |
| ); | |
| return res.status(201).end(); | |
| }) | |
| .catch((error) => { | |
| console.error( | |
| `Error occured during posting CI result comment to PR#${workflow.pullRequestNumber}, HTTP ${error.response.status}` | |
| ); | |
| console.error(error.response.data); | |
| return res.status(error.response.status).end(); | |
| }); | |
| } | |
| async function getPullRequestNumber(project, branch) { | |
| const { status, data } = await axios.get( | |
| `${GITEA_SERVER_URL}/api/v1/repos/${project}/pulls?state=open`, | |
| { | |
| headers: { | |
| Authorization: `token ${GITEA_SERVER_TOKEN}`, | |
| }, | |
| } | |
| ); | |
| if (status === 200) { | |
| const targetPullRequest = data.find((pullRequest) => pullRequest.head.ref === branch); | |
| return targetPullRequest && targetPullRequest.number; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment