1
+ name : Automerge Renovate PRs
2
+
3
+ on :
4
+ schedule :
5
+ # Runs at 12:00 PM Pacific Time on Wednesdays.
6
+ - cron : ' 0 19 * * 3'
7
+ workflow_dispatch : # Allows manual triggering
8
+
9
+ permissions :
10
+ contents : read
11
+ pull-requests : write
12
+
13
+ jobs :
14
+ automerge :
15
+ runs-on : ubuntu-latest
16
+ steps :
17
+ - name : Checkout repository
18
+ uses : actions/checkout@v4
19
+
20
+ - name : Automerge PRs
21
+ uses : actions/github-script@v7
22
+ with :
23
+ github-token : ${{ secrets.GITHUB_TOKEN }}
24
+ script : |
25
+ const owner = context.repo.owner;
26
+ const repo = context.repo.repo;
27
+ const now = new Date();
28
+
29
+ async function processPRs(label, daysToWait, mergeMethod = 'squash') {
30
+ console.log(`\n--- Processing PRs with label: ${label}, waiting ${daysToWait} days ---`);
31
+ const { data: prs } = await github.rest.pulls.list({
32
+ owner,
33
+ repo,
34
+ state: 'open',
35
+ per_page: 10,
36
+ });
37
+
38
+ let foundPrsWithLabel = 0;
39
+
40
+ for (const pr of prs) {
41
+ if (!pr.labels.find(l => l.name === label)) {
42
+ continue;
43
+ }
44
+ foundPrsWithLabel++;
45
+ console.log(`\nProcessing PR #${pr.number} ('${pr.title}')`);
46
+
47
+ const createdAt = new Date(pr.created_at);
48
+ const ageInMilliseconds = now - createdAt;
49
+ const requiredAgeInMilliseconds = daysToWait * 24 * 60 * 60 * 1000;
50
+
51
+ if (ageInMilliseconds < requiredAgeInMilliseconds) {
52
+ const ageHours = Math.floor(ageInMilliseconds / (1000 * 60 * 60));
53
+ const requiredHours = daysToWait * 24;
54
+ console.log(` PR #${pr.number} is too new. Age: ${ageHours} hours. Required: ${requiredHours} hours (${daysToWait} days).`);
55
+ continue;
56
+ }
57
+ console.log(` PR #${pr.number} is old enough.`);
58
+
59
+ // Check CI status using combined status for the PR's head commit
60
+ const { data: status } = await github.rest.repos.getCombinedStatusForRef({
61
+ owner,
62
+ repo,
63
+ ref: pr.head.sha,
64
+ });
65
+
66
+ if (status.state !== 'success') {
67
+ console.log(` PR #${pr.number} CI status is '${status.state}' (not 'success'). Skipping merge.`);
68
+ continue;
69
+ }
70
+ console.log(` PR #${pr.number} CI status is 'success'.`);
71
+
72
+ // Attempt to merge
73
+ try {
74
+ console.log(` Attempting to merge PR #${pr.number} with method '${mergeMethod}'...`);
75
+ await github.rest.pulls.merge({
76
+ owner,
77
+ repo,
78
+ pull_number: pr.number,
79
+ merge_method: mergeMethod,
80
+ });
81
+ console.log(` Successfully merged PR #${pr.number}.`);
82
+ } catch (error) {
83
+ console.error(` Failed to merge PR #${pr.number}: ${error.message}`);
84
+ if (error.response && error.response.data) {
85
+ console.error(` Error details: ${JSON.stringify(error.response.data, null, 2)}`);
86
+ }
87
+ }
88
+ }
89
+ if (foundPrsWithLabel === 0) {
90
+ console.log(`No open PRs found with label '${label}'.`);
91
+ }
92
+ }
93
+
94
+ console.log("Starting automerge workflow...");
95
+ await processPRs("automerge-patch-candidate", 3, 'squash'); // Patches wait 3 days
96
+ await processPRs("automerge-minor-candidate", 10, 'squash'); // Minors wait 10 days
97
+ console.log("Automerge workflow finished.");
0 commit comments