-
Notifications
You must be signed in to change notification settings - Fork 507
325 lines (295 loc) · 11.8 KB
/
Copy pathtrigger-pr-sync.yaml
File metadata and controls
325 lines (295 loc) · 11.8 KB
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
name: Trigger PR Sync
on:
push:
branches:
- main
workflow_dispatch:
inputs:
pr_number:
description: "PR Number"
required: true
type: number
permissions: {}
jobs:
pr-sync:
name: Trigger PR Sync
environment: pr-sync
runs-on:
# Ubuntu 24.04 generic (6.11.0-29) [x86_64]
- graas_ami-03dbff05cae3a30d0_${{ github.event.number || 0 }}${{ github.run_attempt }}-${{ github.run_id }}
- EXECUTION_TYPE=SHORT
- INSTANCE_TYPE=MICRO
permissions:
contents: read # sparse checkout for ci-helpers.sh
issues: write # gh label create
pull-requests: write # gh pr list, comment, edit labels
container:
image: alpine:3.23.3@sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659
steps:
- name: Install tools
run: apk add --no-cache github-cli
shell: sh
- name: Determine PR Number
id: pr-number
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
INPUT_PR_NUMBER: ${{ github.event.inputs.pr_number }}
COMMIT_SHA: ${{ github.sha }}
GH_REPO: ${{ github.repository }}
shell: sh
run: |
set -eu
if [ "${EVENT_NAME}" = "workflow_dispatch" ]; then
num="${INPUT_PR_NUMBER}"
else
max_attempts=5
sleep_time=3
attempts=0
echo "Searching for merged PR for commit: ${COMMIT_SHA}"
while [ "${attempts}" -lt "${max_attempts}" ]; do
num=$(
gh pr list \
--repo "${GH_REPO}" \
--state merged \
--search "${COMMIT_SHA}" \
--json number \
--jq 'first(.[] | .number) // empty'
) || true
if [ -n "${num}" ] && [ "${num}" != "null" ]; then
break
fi
attempts=$((attempts + 1))
if [ "${attempts}" -lt "${max_attempts}" ]; then
sleep "${sleep_time}"
echo "Attempt ${attempts} failed, retrying..."
fi
done
if [ -z "${num}" ]; then
echo "ERROR: No merged PR found after ${max_attempts} attempts." >&2
exit 1
fi
fi
echo "Found PR number: ${num}"
echo "pr_number=${num}" >> "${GITHUB_OUTPUT}"
- name: Check if PR already synced
id: check-synced
if: steps.pr-number.outcome == 'success'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
shell: sh
run: |
set -eu
readonly LABEL_SYNCED="pr-synced"
already_synced=$(
gh pr view "${PR_NUMBER}" \
--repo "${GH_REPO}" \
--json labels \
--jq "any(.labels[]; .name == \"${LABEL_SYNCED}\")"
)
case "${already_synced}" in
true)
echo "PR #${PR_NUMBER} already has label ${LABEL_SYNCED}; skipping sync."
echo "already_synced=true" >> "${GITHUB_OUTPUT}"
;;
*)
echo "already_synced=false" >> "${GITHUB_OUTPUT}"
;;
esac
- name: Validate pr-sync configuration
if: >-
steps.pr-number.outcome == 'success' &&
steps.check-synced.outputs.already_synced != 'true'
env:
TRACEE_PRIVATE_REPO_OWNER: ${{ secrets.TRACEE_PRIVATE_REPO_OWNER }}
TRACEE_PRIVATE_REPO: ${{ secrets.TRACEE_PRIVATE_REPO }}
TRACEE_PRIVATE_SYNC_WORKFLOW: ${{ secrets.TRACEE_PRIVATE_SYNC_WORKFLOW }}
GH_APP_CLIENT_ID: ${{ secrets.ACTIONS_TRACEE_WRITE_GH_APP_CLIENT_ID }}
GH_APP_PRIVATE_KEY: ${{ secrets.ACTIONS_TRACEE_WRITE_GH_APP_PRIVATE_KEY }}
shell: sh
run: |
set -eu
for v in "${TRACEE_PRIVATE_REPO_OWNER}" \
"${TRACEE_PRIVATE_REPO}" \
"${TRACEE_PRIVATE_SYNC_WORKFLOW}" \
"${GH_APP_CLIENT_ID}" \
"${GH_APP_PRIVATE_KEY}"; do
if [ -z "${v}" ]; then
echo "ERROR: One or more required pr-sync secrets are not configured." >&2
echo "Set them under Environments -> pr-sync -> Environment secrets." >&2
exit 1
fi
done
case "${TRACEE_PRIVATE_REPO}" in
*/*)
echo "ERROR: TRACEE_PRIVATE_REPO must be the repository name only (no owner/ prefix)." >&2
exit 1
;;
esac
- name: Create GitHub App token
id: app-token
if: >-
steps.pr-number.outcome == 'success' &&
steps.check-synced.outputs.already_synced != 'true'
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
client-id: ${{ secrets.ACTIONS_TRACEE_WRITE_GH_APP_CLIENT_ID }}
private-key: ${{ secrets.ACTIONS_TRACEE_WRITE_GH_APP_PRIVATE_KEY }}
owner: ${{ secrets.TRACEE_PRIVATE_REPO_OWNER }}
repositories: ${{ secrets.TRACEE_PRIVATE_REPO }}
permission-actions: write
- name: Trigger pr sync workflow
id: sync
if: >-
steps.pr-number.outcome == 'success' &&
steps.check-synced.outputs.already_synced != 'true'
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
TRACEE_PRIVATE_REPO_OWNER: ${{ secrets.TRACEE_PRIVATE_REPO_OWNER }}
TRACEE_PRIVATE_REPO: ${{ secrets.TRACEE_PRIVATE_REPO }}
TRACEE_PRIVATE_SYNC_WORKFLOW: ${{ secrets.TRACEE_PRIVATE_SYNC_WORKFLOW }}
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
shell: sh
run: |
set -eu
gh_repo="${TRACEE_PRIVATE_REPO_OWNER}/${TRACEE_PRIVATE_REPO}"
gh_err_file=$(mktemp)
trap 'rm -f "${gh_err_file}"' EXIT
max_attempts=5
attempts=0
succeeded=false
while [ "${attempts}" -lt "${max_attempts}" ]; do
attempts=$((attempts + 1))
: > "${gh_err_file}"
if gh workflow run "${TRACEE_PRIVATE_SYNC_WORKFLOW}" \
--repo "${gh_repo}" \
--ref main \
-f "oss_pr_number=${PR_NUMBER}" \
2> "${gh_err_file}"; then
succeeded=true
break
fi
echo "Attempt ${attempts}/${max_attempts} failed to dispatch pr sync workflow." >&2
if [ -s "${gh_err_file}" ]; then
echo "gh error output:" >&2
cat "${gh_err_file}" >&2
fi
if [ "${attempts}" -lt "${max_attempts}" ]; then
sleep 1
fi
done
if [ "${succeeded}" != true ]; then
echo "ERROR: Failed to dispatch pr sync workflow after ${max_attempts} attempts." >&2
{
echo ""
echo "### Workflow dispatch failure"
echo ""
echo "Could not trigger the pr sync workflow for OSS PR #${PR_NUMBER}."
if [ -s "${gh_err_file}" ]; then
echo ""
echo "<details><summary>Last gh error output</summary>"
echo ""
echo '```'
cat "${gh_err_file}"
echo '```'
echo ""
echo "</details>"
fi
} >> "${GITHUB_STEP_SUMMARY}"
exit 1
fi
- name: Checkout helpers
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: |
.github/scripts
sparse-checkout-cone-mode: false
- name: Update PR sync labels
if: >-
always() &&
steps.pr-number.outcome == 'success' &&
steps.check-synced.outputs.already_synced != 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
SYNC_RESULT: ${{ steps.sync.outcome }}
shell: sh
run: |
set -eu
. .github/scripts/ci-helpers.sh
readonly LABEL_SYNCED="pr-synced"
readonly LABEL_NOT_SYNCED="pr-non-synced"
ensure_label "${LABEL_SYNCED}" "1d76db" \
"PR sync dispatch succeeded"
ensure_label "${LABEL_NOT_SYNCED}" "d73a4a" \
"PR sync dispatch failed"
case "${SYNC_RESULT}" in
success)
add_label "${PR_NUMBER}" "${LABEL_SYNCED}"
remove_label "${PR_NUMBER}" "${LABEL_NOT_SYNCED}"
;;
*)
add_label "${PR_NUMBER}" "${LABEL_NOT_SYNCED}"
remove_label "${PR_NUMBER}" "${LABEL_SYNCED}"
;;
esac
- name: Comment on original PR
if: always() && steps.pr-number.outcome == 'success'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_REPO: ${{ github.repository }}
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
ALREADY_SYNCED: ${{ steps.check-synced.outputs.already_synced }}
SYNC_RESULT: ${{ steps.sync.outcome }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
shell: sh
run: |
set -eu
if [ "${ALREADY_SYNCED}" = "true" ]; then
body="PR sync was already completed for this PR (label \`pr-synced\`). Skipping sync dispatch."
else
case "${SYNC_RESULT}" in
success)
body="PR sync was triggered successfully."
;;
failure)
body="PR sync could not be triggered. See [workflow run](${RUN_URL}) for details."
;;
skipped|cancelled)
body="PR sync was not run (an earlier step failed or was skipped). See [workflow run](${RUN_URL})."
;;
*)
body="PR sync status is unknown. See [workflow run](${RUN_URL})."
;;
esac
fi
gh pr comment "${PR_NUMBER}" \
--repo "${GH_REPO}" \
--body "${body}"
- name: Summary
if: always()
env:
PR_NUMBER: ${{ steps.pr-number.outputs.pr_number }}
PR_NUMBER_OUTCOME: ${{ steps.pr-number.outcome }}
ALREADY_SYNCED: ${{ steps.check-synced.outputs.already_synced }}
SYNC_RESULT: ${{ steps.sync.outcome }}
shell: sh
run: |
{
echo "## PR Sync"
echo ""
if [ "${PR_NUMBER_OUTCOME}" != "success" ]; then
echo "Did not run: merged PR number could not be determined."
elif [ "${ALREADY_SYNCED}" = "true" ]; then
echo "Skipped: OSS PR **#${PR_NUMBER}** already has the \`pr-synced\` label."
elif [ "${SYNC_RESULT}" = "success" ]; then
echo "Triggered the pr sync workflow for OSS PR **#${PR_NUMBER}**."
elif [ "${SYNC_RESULT}" = "skipped" ]; then
echo "Did not run: a step before sync failed or was skipped."
else
echo "Failed to trigger the pr sync workflow for OSS PR **#${PR_NUMBER}**."
fi
} >> "${GITHUB_STEP_SUMMARY}"