-
Notifications
You must be signed in to change notification settings - Fork 0
159 lines (140 loc) · 6.42 KB
/
push_via_PR_example.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
name: Push via PR example
# WARN : need write main protection rule
## REQUIREMENTS
# repository settings requirement : Allow GitHub Actions to create and approve pull requests
permissions:
contents: write
pull-requests: write
## Actions > Secrets
# BYPASS_USER_PAT - fine-grained PAT with content+pullrequest write from user that can review
# this workflow is triggered from UI
on:
workflow_dispatch:
jobs:
handle-dispatch:
runs-on: ubuntu-latest
strategy:
matrix:
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
node-version: [ 20.x ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Run create some diff
run: |
date > my_new_date.txt
echo "BRANCH_NAME=update-version-${{ github.sha }}" >> $GITHUB_ENV
echo "VERSION=0.0.1-fake" >> $GITHUB_ENV
- name: Create a pull request
id: cpr
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.BYPASS_USER_PAT }}
# base: main
branch: ${{ env.BRANCH_NAME}}
commit-message: Add version ${{ env.VERSION }}
title: Automated version update to ${{ env.VERSION }}
body: This PR updates the version file automatically. Generated from `push_via_PR_example.yml`.
author: ChickArmy[bot] <github-actions[bot][email protected]>
- name: Create Pull request outputs
if: ${{ steps.cpr.outputs.pull-request-number }}
run: |
echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
# WARN this step expects at least 1 check in success to pass ! (0 check results in timeout error)
- name: Wait for PR related Checks to Pass
if: ${{ steps.cpr.outputs.pull-request-number }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.BYPASS_USER_PAT }}
script: |
const prNumber = ${{ steps.cpr.outputs.pull-request-number }};
let allChecksCompleted = false;
const checkInterval = 30 * 1000; // 30 seconds
const maxAttempts = 20; // Total wait time = maxAttempts * checkInterval
let attempt = 0;
let checks = [];
while (attempt < maxAttempts) {
console.log(`Checking status of CI/CD checks (Attempt ${attempt + 1}/${maxAttempts})...`);
try {
// Get PR details to retrieve PR SHA
const { data: { head: { sha } } } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber,
});
console.log(`ℹ️ PR #${prNumber} ref is ${sha}`);
// Get PR checks
const { data } = await github.rest.checks.listForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: sha,
});
checks = data.check_runs;
if (checks.length < 1) {
console.log('⌛ Await until CI/CD at least one check_run appears.');
} else {
console.log("checks :\n" + JSON.stringify(checks, null, 2));
allChecksCompleted = checks.every(check => check.status === 'completed');
if (allChecksCompleted) {
console.log(`ℹ️ ${checks.length} CI/CD checks have completed.`);
break;
} else {
console.log(`⌛ Not all ${checks.length} checks are complete yet. Waiting...`);
}
}
} catch (error) {
if (error.status === 404) {
console.log('⌛ Pull request not yet available, waiting...');
} else {
throw error; // Rethrow if it's a different error
}
}
await new Promise(resolve => setTimeout(resolve, checkInterval));
attempt++;
}
if (!allChecksCompleted) {
throw new Error(`🔴 Some of ${checks.length} CI/CD checks did not complete within the expected timeframe.`);
}
// Check if all completed checks passed
const failedChecks = [];
allChecksPassed = checks.every(check => {
const passed = check.conclusion === 'success';
if (!passed) {
// Gather details for failed checks
failedChecks.push({
name: check.name,
conclusion: check.conclusion,
completed_at: check.completed_at,
html_url: check.html_url
});
}
return passed;
});
if (!allChecksPassed) {
console.log('Some checks failed:');
failedChecks.forEach(check => {
console.log(`- Name: ${check.name}`);
console.log(` Conclusion: ${check.conclusion}`);
console.log(` Completed at: ${check.completed_at}`);
console.log(` Details: ${check.html_url}`);
});
throw new Error('🔴 Some CI/CD checks did not pass successfully.');
} else {
console.log(`✅ ${checks.length} CI/CD checks in SUCCESS 🥇`);
}
- name: Merge Pull Request using authorized user to bypass rule
if: ${{ steps.cpr.outputs.pull-request-number }}
uses: actions/github-script@v7
with:
github-token: ${{ secrets.BYPASS_USER_PAT }}
script: |
const pull_number = ${{ steps.cpr.outputs.pull-request-number }};
console.log(`Merging pull request: #${pull_number}`);
await github.rest.pulls.merge({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number,
merge_method: 'rebase'
});
console.log(`✅ Pull request #${pull_number} merged successfully. 🥳`);