From 3b846cadacf0ed146e0d3f4ba38feb865befe4a5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 17 Jul 2020 13:41:20 -0400 Subject: [PATCH 1/6] - adds output to the action so people can use it in condition for subquent steps --- action.yml | 3 +++ sources/main.ts | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index e840357..b6e0c89 100644 --- a/action.yml +++ b/action.yml @@ -14,6 +14,9 @@ inputs: description: "Number of seconds after which the action runs again if the mergable state is unknown." retryMax: description: "Number of times the action retries calculating the mergable state" +ouputs: + isPrDirty: + description: "(boolean) Whether the PR is dirty or not" runs: using: "node12" main: "dist/index.js" diff --git a/sources/main.ts b/sources/main.ts index 274c9c2..be43211 100644 --- a/sources/main.ts +++ b/sources/main.ts @@ -2,6 +2,7 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; type GitHub = ReturnType; +const isPrDirtyOutputKey = `isPrDirty`; async function main() { const repoToken = core.getInput("repoToken", { required: true }); @@ -14,7 +15,7 @@ async function main() { const client = github.getOctokit(repoToken); - return await checkDirty({ + await checkDirty({ client, dirtyLabel, removeOnDirtyLabel, @@ -111,6 +112,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { addLabelIfNotExists(dirtyLabel, pullRequest, { client }), removeLabelIfExists(removeOnDirtyLabel, pullRequest, { client }), ]); + core.setOutput(isPrDirtyOutputKey, true); break; case "MERGEABLE": info(`remove "${dirtyLabel}"`); @@ -119,10 +121,12 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { // we don't add it again because we assume that the removeOnDirtyLabel // is used to mark a PR as "merge!". // So we basically require a manual review pass after rebase. + core.setOutput(isPrDirtyOutputKey, false); break; case "UNKNOWN": info(`Retrying after ${retryAfter}s.`); - return new Promise((resolve) => { + core.setOutput(isPrDirtyOutputKey, false); + await new Promise((resolve) => { setTimeout(async () => { core.info(`retrying with ${retryMax} retries remaining.`); resolve(await checkDirty({ ...context, retryMax: retryMax - 1 })); @@ -137,7 +141,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { } if (pageInfo.hasNextPage) { - return checkDirty({ + await checkDirty({ ...context, after: pageInfo.endCursor, }); From f39981f0b5f2902400f0414a1d68fded13b2c788 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Jul 2020 08:49:00 -0400 Subject: [PATCH 2/6] - switches output to array to support multiple PRs --- action.yml | 4 ++-- sources/main.ts | 24 ++++++++++++++---------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/action.yml b/action.yml index b6e0c89..45c6424 100644 --- a/action.yml +++ b/action.yml @@ -15,8 +15,8 @@ inputs: retryMax: description: "Number of times the action retries calculating the mergable state" ouputs: - isPrDirty: - description: "(boolean) Whether the PR is dirty or not" + prDirtyStatuses: + description: "Array of booleans which indicate whether a PR is dirty or not and where the index is the PR ID." runs: using: "node12" main: "dist/index.js" diff --git a/sources/main.ts b/sources/main.ts index be43211..d7e030b 100644 --- a/sources/main.ts +++ b/sources/main.ts @@ -2,7 +2,7 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; type GitHub = ReturnType; -const isPrDirtyOutputKey = `isPrDirty`; +const prDirtyStatusesOutputKey = `prDirtyStatuses`; async function main() { const repoToken = core.getInput("repoToken", { required: true }); @@ -38,7 +38,7 @@ interface CheckDirtyContext { // number of allowed retries retryMax: number; } -async function checkDirty(context: CheckDirtyContext): Promise { +async function checkDirty(context: CheckDirtyContext): Promise { const { after, client, @@ -97,7 +97,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { if (pullRequests.length === 0) { return; } - + let dirtyStatuses: any = {}; for (const pullRequest of pullRequests) { core.debug(JSON.stringify(pullRequest, null, 2)); @@ -112,7 +112,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { addLabelIfNotExists(dirtyLabel, pullRequest, { client }), removeLabelIfExists(removeOnDirtyLabel, pullRequest, { client }), ]); - core.setOutput(isPrDirtyOutputKey, true); + dirtyStatuses[pullRequest.number] = true; break; case "MERGEABLE": info(`remove "${dirtyLabel}"`); @@ -121,15 +121,16 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { // we don't add it again because we assume that the removeOnDirtyLabel // is used to mark a PR as "merge!". // So we basically require a manual review pass after rebase. - core.setOutput(isPrDirtyOutputKey, false); + dirtyStatuses[pullRequest.number] = false; break; case "UNKNOWN": info(`Retrying after ${retryAfter}s.`); - core.setOutput(isPrDirtyOutputKey, false); await new Promise((resolve) => { - setTimeout(async () => { + setTimeout(() => { core.info(`retrying with ${retryMax} retries remaining.`); - resolve(await checkDirty({ ...context, retryMax: retryMax - 1 })); + resolve(async () => { + dirtyStatuses = {...dirtyStatuses, ...(await checkDirty({ ...context, retryMax: retryMax - 1 }))}; + }); }, retryAfter * 1000); }); break; @@ -141,11 +142,14 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { } if (pageInfo.hasNextPage) { - await checkDirty({ + dirtyStatuses = {...dirtyStatuses, ...(await checkDirty({ ...context, after: pageInfo.endCursor, - }); + }))}; + } else { + core.setOutput(prDirtyStatusesOutputKey, dirtyStatuses); } + return dirtyStatuses; } /** From 55bdde8665738e5354a537a442517557621b6cd3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Jul 2020 09:11:12 -0400 Subject: [PATCH 3/6] Apply suggestions from code review Co-authored-by: Sebastian Silbermann --- action.yml | 2 +- sources/main.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 45c6424..cec4b48 100644 --- a/action.yml +++ b/action.yml @@ -16,7 +16,7 @@ inputs: description: "Number of times the action retries calculating the mergable state" ouputs: prDirtyStatuses: - description: "Array of booleans which indicate whether a PR is dirty or not and where the index is the PR ID." + description: "Object-map. The keys are pull request numbers and their values whether a PR is dirty or not." runs: using: "node12" main: "dist/index.js" diff --git a/sources/main.ts b/sources/main.ts index d7e030b..9a5ebdf 100644 --- a/sources/main.ts +++ b/sources/main.ts @@ -38,7 +38,7 @@ interface CheckDirtyContext { // number of allowed retries retryMax: number; } -async function checkDirty(context: CheckDirtyContext): Promise { +async function checkDirty(context: CheckDirtyContext): Promise> { const { after, client, @@ -97,7 +97,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { if (pullRequests.length === 0) { return; } - let dirtyStatuses: any = {}; + let dirtyStatuses: Record = {}; for (const pullRequest of pullRequests) { core.debug(JSON.stringify(pullRequest, null, 2)); From da460048dafb641b1d173a628a7d4e5169369d23 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Jul 2020 09:13:48 -0400 Subject: [PATCH 4/6] - fixes empty returns on defensive programming --- sources/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sources/main.ts b/sources/main.ts index 9a5ebdf..6c092b2 100644 --- a/sources/main.ts +++ b/sources/main.ts @@ -50,7 +50,7 @@ async function checkDirty(context: CheckDirtyContext): Promise = {}; for (const pullRequest of pullRequests) { From 3f800591c90ee154845d0cd2d1e38a52ef970ae2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Jul 2020 09:30:48 -0400 Subject: [PATCH 5/6] - formatting --- sources/main.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/sources/main.ts b/sources/main.ts index 6c092b2..8114630 100644 --- a/sources/main.ts +++ b/sources/main.ts @@ -38,7 +38,9 @@ interface CheckDirtyContext { // number of allowed retries retryMax: number; } -async function checkDirty(context: CheckDirtyContext): Promise> { +async function checkDirty( + context: CheckDirtyContext +): Promise> { const { after, client, @@ -129,7 +131,10 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { setTimeout(() => { core.info(`retrying with ${retryMax} retries remaining.`); resolve(async () => { - dirtyStatuses = {...dirtyStatuses, ...(await checkDirty({ ...context, retryMax: retryMax - 1 }))}; + dirtyStatuses = { + ...dirtyStatuses, + ...(await checkDirty({ ...context, retryMax: retryMax - 1 })), + }; }); }, retryAfter * 1000); }); @@ -142,10 +147,13 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { } if (pageInfo.hasNextPage) { - dirtyStatuses = {...dirtyStatuses, ...(await checkDirty({ - ...context, - after: pageInfo.endCursor, - }))}; + dirtyStatuses = { + ...dirtyStatuses, + ...(await checkDirty({ + ...context, + after: pageInfo.endCursor, + })), + }; } else { core.setOutput(prDirtyStatusesOutputKey, dirtyStatuses); } From 7d5299dc79901835dd0cde52c6f58b0e6420393c Mon Sep 17 00:00:00 2001 From: Sebastian Silbermann Date: Mon, 20 Jul 2020 15:43:59 +0200 Subject: [PATCH 6/6] Check-in build --- dist/index.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/dist/index.js b/dist/index.js index 5296290..917d285 100644 --- a/dist/index.js +++ b/dist/index.js @@ -7586,6 +7586,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(__webpack_require__(470)); const github = __importStar(__webpack_require__(469)); +const prDirtyStatusesOutputKey = `prDirtyStatuses`; function main() { return __awaiter(this, void 0, void 0, function* () { const repoToken = core.getInput("repoToken", { required: true }); @@ -7596,7 +7597,7 @@ function main() { const retryAfter = parseInt(core.getInput("retryAfter") || "120", 10); const retryMax = parseInt(core.getInput("retryMax") || "5", 10); const client = github.getOctokit(repoToken); - return yield checkDirty({ + yield checkDirty({ client, dirtyLabel, removeOnDirtyLabel, @@ -7611,7 +7612,7 @@ function checkDirty(context) { const { after, client, dirtyLabel, removeOnDirtyLabel, retryAfter, retryMax, } = context; if (retryMax <= 0) { core.warning("reached maximum allowed retries"); - return; + return {}; } const query = ` query openPullRequests($owner: String!, $repo: String!, $after: String) { @@ -7646,8 +7647,9 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { const { repository: { pullRequests: { nodes: pullRequests, pageInfo }, }, } = pullsResponse; core.debug(JSON.stringify(pullsResponse, null, 2)); if (pullRequests.length === 0) { - return; + return {}; } + let dirtyStatuses = {}; for (const pullRequest of pullRequests) { core.debug(JSON.stringify(pullRequest, null, 2)); const info = (message) => core.info(`for PR "${pullRequest.title}": ${message}`); @@ -7659,6 +7661,7 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { addLabelIfNotExists(dirtyLabel, pullRequest, { client }), removeLabelIfExists(removeOnDirtyLabel, pullRequest, { client }), ]); + dirtyStatuses[pullRequest.number] = true; break; case "MERGEABLE": info(`remove "${dirtyLabel}"`); @@ -7667,14 +7670,17 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { // we don't add it again because we assume that the removeOnDirtyLabel // is used to mark a PR as "merge!". // So we basically require a manual review pass after rebase. + dirtyStatuses[pullRequest.number] = false; break; case "UNKNOWN": info(`Retrying after ${retryAfter}s.`); - return new Promise((resolve) => { - setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield new Promise((resolve) => { + setTimeout(() => { core.info(`retrying with ${retryMax} retries remaining.`); - resolve(yield checkDirty(Object.assign(Object.assign({}, context), { retryMax: retryMax - 1 }))); - }), retryAfter * 1000); + resolve(() => __awaiter(this, void 0, void 0, function* () { + dirtyStatuses = Object.assign(Object.assign({}, dirtyStatuses), (yield checkDirty(Object.assign(Object.assign({}, context), { retryMax: retryMax - 1 })))); + })); + }, retryAfter * 1000); }); break; default: @@ -7682,8 +7688,12 @@ query openPullRequests($owner: String!, $repo: String!, $after: String) { } } if (pageInfo.hasNextPage) { - return checkDirty(Object.assign(Object.assign({}, context), { after: pageInfo.endCursor })); + dirtyStatuses = Object.assign(Object.assign({}, dirtyStatuses), (yield checkDirty(Object.assign(Object.assign({}, context), { after: pageInfo.endCursor })))); + } + else { + core.setOutput(prDirtyStatusesOutputKey, dirtyStatuses); } + return dirtyStatuses; }); } /**