saleor-dashboard/.github/workflows/approveAndMergeReleasePR.js

120 lines
3.3 KiB
JavaScript

const { Octokit } = require("@octokit/core");
const { Command } = require("commander");
const { GraphQLClient } = require("graphql-request");
const program = new Command();
const repo = "saleor-cloud-deployments";
const owner = "saleor";
program
.name("Approve PR")
.description("Approve and merge PR if patch release")
.option("--version <version>", "version of a project")
.option("--pull_request_number <pull_request_number>", "Pull Request number")
.option("--auto_release <auto_release>", "is auto release")
.option("--dashboard_url <dashboard_url>", "Cypress dashboard url")
.action(async options => {
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
});
const pullNumber = options.pull_request_number;
const pullRequest = await octokit.request(
"GET /repos/{owner}/{repo}/pulls/{pull_number}",
{
owner,
repo,
pull_number: pullNumber,
},
);
const commitId = pullRequest.data.merge_commit_sha;
const testsStatus = await getTestsStatus(options.dashboard_url);
const requestBody =
testsStatus === "PASSED"
? `Cypress tests passed. See results at ${options.dashboard_url}`
: `Some tests failed, need manual approve. See results at ${options.dashboard_url}`;
const event = "COMMENT";
await octokit.request(
"POST /repos/{owner}/{repo}/pulls/{pull_number}/reviews",
{
owner,
repo,
pull_number: pullNumber,
commit_id: commitId,
body: requestBody,
event,
comments: [],
},
);
if (
options.auto_release &&
isPatchRelease(options.version) &&
testsStatus === "PASSED"
) {
await octokit.request(
"PUT /repos/{owner}/{repo}/pulls/{pull_number}/merge",
{
owner,
repo,
pull_number: pullNumber,
},
);
}
})
.parse();
function isPatchRelease(version) {
const regex = /\d+\.\d+\.[1-9]/;
return version.match(regex) ? true : false;
}
async function getTestsStatus(dashboardUrl) {
const getProjectRegex = /\/projects\/([^\/]*)/;
const getRunRegex = /\/runs\/([^\/]*)/;
const requestVariables = {
projectId: dashboardUrl.match(getProjectRegex)[1],
buildNumber: dashboardUrl.match(getRunRegex)[1],
};
const client = new GraphQLClient("https://dashboard.cypress.io/graphql");
const throwErrorAfterTimeout = setTimeout(function() {
throw new Error("Run have still running status, after all tests executed");
}, 1200000);
const status = await waitForTestsToFinish(client, requestVariables);
clearTimeout(throwErrorAfterTimeout);
return status;
}
async function waitForTestsToFinish(client, requestVariables) {
return new Promise((resolve, reject) => {
client
.request(
`query ($projectId: String!, $buildNumber: ID!) {
runByBuildNumber(buildNumber: $buildNumber, projectId: $projectId) {
status
}
}`,
requestVariables,
)
.then(response => {
if (response.runByBuildNumber.status === "RUNNING") {
setTimeout(async function() {
resolve(await waitForTestsToFinish(client, requestVariables));
}, 10000);
} else {
resolve(response.runByBuildNumber.status);
}
});
});
}