Skip to content

Commit f52e2f1

Browse files
committed
fix: prevent trigger when there is an open and mergeable PR
1 parent 79c47e7 commit f52e2f1

File tree

2 files changed

+103
-61
lines changed

2 files changed

+103
-61
lines changed

.github/workflows/trigger.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,5 @@ jobs:
5252
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5353
with:
5454
script: |
55-
const {trigger} = await import('${{ github.workspace }}/renovate-config/trigger.ts')
56-
console.log(await trigger({github, context, exec}))
55+
const {trigger} = await import('${{ github.workspace }}/renovate-config/trigger.ts');
56+
console.log(await trigger({github, context, core, exec}));

trigger.ts

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,79 +11,104 @@ import path from "node:path";
1111
* If another checkbox is checked in the issue, nothing will be triggered.
1212
* The function executed the `gh` CLI to talk to the GitHub API.
1313
*/
14-
export const trigger = async ({ exec }: AsyncFunctionArguments) => {
14+
export const trigger = async ({
15+
context,
16+
core,
17+
exec,
18+
}: AsyncFunctionArguments) => {
1519
const { gh, ghJson } = ghExec(exec);
1620
await gh("auth", "status");
21+
const log = (message: string) => {
22+
console.log(message);
23+
core.summary.addRaw(message, true);
24+
return message;
25+
};
26+
try {
27+
// parse input
28+
const OWNER_REPO = process.env.OWNER_REPO ?? "bettermarks/renovate-config";
29+
const repoArgs = ["--repo", OWNER_REPO] as const;
30+
const DASHBOARD_ISSUE = parseInt(process.env.DASHBOARD_ISSUE || "0");
31+
console.log("Inputs:", { OWNER_REPO, DASHBOARD_ISSUE });
1732

18-
// parse input
19-
const OWNER_REPO = process.env.OWNER_REPO ?? "bettermarks/renovate-config";
20-
const DASHBOARD_ISSUE = parseInt(process.env.DASHBOARD_ISSUE || "0");
21-
console.log("Inputs:", { OWNER_REPO, DASHBOARD_ISSUE });
33+
let dashboardIssue: GithubIssue | undefined;
34+
if (DASHBOARD_ISSUE) {
35+
dashboardIssue = await ghJson<GithubIssue>(
36+
"issue",
37+
"view",
38+
DASHBOARD_ISSUE,
39+
...repoArgs,
40+
...jsonIssue,
41+
);
42+
} else {
43+
const parsed = await ghJson<ReadonlyArray<GithubIssue> | unknown>(
44+
"issue",
45+
"list",
46+
...authorRenovate,
47+
...repoArgs,
48+
...jsonIssue,
49+
);
50+
if (!Array.isArray(parsed))
51+
throw "JSON.parse should have returned an Array!";
52+
dashboardIssue = parsed.find(
53+
(it): it is GithubIssue =>
54+
it.title === defaultJson.dependencyDashboardTitle,
55+
);
56+
}
57+
if (!dashboardIssue)
58+
throw `Not able to get dashboard issue for ${OWNER_REPO}`;
2259

23-
let dashboardIssue: GithubIssue | undefined;
24-
if (DASHBOARD_ISSUE) {
25-
dashboardIssue = await ghJson<GithubIssue>(
26-
"issue",
27-
"view",
28-
`${DASHBOARD_ISSUE}`,
29-
"--repo",
30-
OWNER_REPO,
31-
"--json",
32-
"url,number,body,title",
60+
log(
61+
`Picked issue ${dashboardIssue.url} with title "${dashboardIssue.title}".`,
3362
);
34-
} else {
35-
const parsed = await ghJson<ReadonlyArray<GithubIssue> | unknown>(
36-
"issue",
63+
if (!dashboardIssue.body.includes(manualTrigger)) {
64+
throw "Issue does not contain manual trigger checkbox, exiting.";
65+
}
66+
if (dashboardIssue.body.includes(checkedCheckbox)) {
67+
return log(
68+
"Dashboard already contains checked checkbox. No action triggered.",
69+
);
70+
}
71+
const openRenovatePRs = await ghJson<ReadonlyArray<GithubPr>>(
72+
"pr",
3773
"list",
38-
"--repo",
39-
OWNER_REPO,
40-
"--author",
41-
"renovate[bot]",
42-
"--state",
43-
"open",
44-
"--json",
45-
"url,number,body,title",
74+
...repoArgs,
75+
...authorRenovate,
76+
...jsonPr,
4677
);
47-
if (!Array.isArray(parsed))
48-
throw "JSON.parse should have returned an Array!";
49-
dashboardIssue = parsed.find(
50-
(it): it is GithubIssue =>
51-
it.title === defaultJson.dependencyDashboardTitle,
78+
if (openRenovatePRs.filter((pr) => pr.mergeable).length) {
79+
openRenovatePRs.forEach((pr) =>
80+
log(
81+
`- #${pr.number} is open and ${pr.mergeable ? "mergeable" : "not mergeable"} (${pr.commits.length} commits)`,
82+
),
83+
);
84+
return log("There are open and mergeable renovate PRs. No action taken.");
85+
}
86+
console.log(
87+
`Triggering renovate via ${OWNER_REPO}#${dashboardIssue.number}...`,
5288
);
89+
const bodyFile = path.join(import.meta.dirname, ".dashboard-body.md");
90+
writeFileSync(
91+
bodyFile,
92+
dashboardIssue.body.replace(manualTrigger, manuallyTriggered),
93+
);
94+
await gh(
95+
"issue",
96+
"edit",
97+
dashboardIssue.number,
98+
"--body-file",
99+
bodyFile,
100+
...repoArgs,
101+
);
102+
return "Done.";
103+
} finally {
104+
await core.summary.write();
53105
}
54-
if (!dashboardIssue)
55-
throw `Not able to get dashboard issue for ${OWNER_REPO}`;
56-
57-
console.log("Picked issue", dashboardIssue.url, "\n", dashboardIssue.title);
58-
if (!dashboardIssue.body.includes(manualTrigger)) {
59-
throw "Dashboard does not contain manual trigger checkbox, exiting.";
60-
}
61-
if (dashboardIssue.body.includes(checkedCheckbox)) {
62-
return "Dashboard already contains checked checkbox, not triggering manual update.";
63-
}
64-
console.log(
65-
`Triggering renovate via ${OWNER_REPO}#${dashboardIssue.number}...`,
66-
);
67-
const bodyFile = path.join(import.meta.dirname, ".dashboard-body.md");
68-
writeFileSync(
69-
bodyFile,
70-
dashboardIssue.body.replace(manualTrigger, manuallyTriggered),
71-
);
72-
await gh(
73-
"issue",
74-
"edit",
75-
dashboardIssue.number,
76-
"--repo",
77-
OWNER_REPO,
78-
"--body-file",
79-
bodyFile,
80-
);
81-
return "Done.";
82106
};
83107

84108
const checkedCheckbox = "- [x]";
85109
const manualTrigger = "- [ ] <!-- manual job -->";
86110
const manuallyTriggered = "- [x] <!-- manual job -->";
111+
const authorRenovate = ["--author", "renovate[bot]"] as const;
87112

88113
const ghExec = ({
89114
getExecOutput,
@@ -100,9 +125,26 @@ const ghExec = ({
100125

101126
return { gh, ghJson };
102127
};
128+
129+
const jsonIssue = ["--json", "url,number,body,title"];
103130
type GithubIssue = Readonly<{
104131
body: string;
105132
number: number;
106133
title: string;
107134
url: string;
108135
}>;
136+
const jsonPr = [
137+
"--json",
138+
"autoMergeRequest,commits,mergeable,number,reviewDecision,statusCheckRollup,title,updatedAt,url",
139+
];
140+
type GithubPr = Readonly<{
141+
autoMergeRequest: unknown;
142+
commits: readonly unknown[];
143+
mergeable: unknown;
144+
number: number;
145+
reviewDecision: string;
146+
statusCheckRollup: unknown;
147+
title: string;
148+
updatedAt: string;
149+
url: string;
150+
}>;

0 commit comments

Comments
 (0)