-
Notifications
You must be signed in to change notification settings - Fork 180
147 lines (129 loc) · 6.36 KB
/
rerun-ci.yml
File metadata and controls
147 lines (129 loc) · 6.36 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
# Copyright (c) 2025, Zededa, Inc.
# SPDX-License-Identifier: Apache-2.0
---
name: Rerun CI
on: # yamllint disable-line rule:truthy
issue_comment:
types: [created]
jobs:
rerun-workflows:
if: |
github.event.issue.pull_request && startsWith(github.event.comment.body, '/rerun')
runs-on: ubuntu-latest
permissions:
actions: write
issues: read
pull-requests: read
contents: read
steps:
- name: Checkout code
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
- name: Parse CODEOWNERS to get allowed users
run: |
CODEOWNERS=".github/CODEOWNERS"
awk '{for(i=1;i<=NF;i++) if($i ~ /^@/) print substr($i,2)}' "$CODEOWNERS" | sort -u > allowed_users.txt
- name: Check if comment author is allowed
run: |
COMMENT_USER="${{ github.event.comment.user.login }}"
echo "User: $COMMENT_USER"
if ! grep -Fxq "$COMMENT_USER" allowed_users.txt; then
echo "User $COMMENT_USER is not allowed to rerun CI." >&2
exit 1
fi
- name: Set run mode (red or yellow)
id: mode
run: |
BODY="${{ github.event.comment.body }}"
if [[ "$BODY" =~ ^/rerun[[:space:]]+yellow ]]; then
echo "mode=yellow" >> $GITHUB_OUTPUT
elif [[ "$BODY" =~ ^/rerun[[:space:]]+red ]]; then
echo "mode=red" >> $GITHUB_OUTPUT
else
echo "Unknown rerun mode" >&2
exit 1
fi
- name: Gather PR branch and SHA
id: prinfo
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
PR_NUMBER="${{ github.event.issue.number }}"
REPO="${{ github.repository }}"
BRANCH=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json headRefName -q .headRefName)
SHA=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json headRefOid -q .headRefOid)
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
echo "sha=$SHA" >> $GITHUB_OUTPUT
- name: Find and act on workflow runs for this PR's latest commit
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: ${{ steps.prinfo.outputs.branch }}
SHA: ${{ steps.prinfo.outputs.sha }}
REPO: ${{ github.repository }}
MODE: ${{ steps.mode.outputs.mode }}
run: |
# Get all runs for the branch (could be for old commits, so we'll filter below)
RUNS=$(gh run list --repo "$REPO" --branch "$BRANCH" --json databaseId,status,conclusion,headSha,workflowName,displayTitle,event)
# Find Eden Runner run ID for this commit. We assume the PR already has an Eden Runner run as a status check (added by Eden Trusted WF)
EDEN_RUNNER_RUN=$(gh api "repos/$REPO/commits/$SHA/statuses" | jq -r \
'.[] | select(.context | contains("Eden Runner")) | .target_url' | \
grep -oE '/runs/[0-9]+' | awk -F'/' '{print $3}' | head -n 1 )
# Getting the status of the Eden Runner run if it exists
EDEN_RUNNER_STATUS=$(gh run view "$EDEN_RUNNER_RUN" --repo "$REPO" --json status -q .status 2>/dev/null || echo "not_found")
# Cancel all in-progress runs for this commit if requested
if [[ "$MODE" == "yellow" ]]; then
echo "Cancelling all in-progress or queued runs for commit $SHA on branch $BRANCH..."
echo "$RUNS" | jq -r \
'.[] | select(.headSha == env.SHA and .status != "completed") | .databaseId' | while read -r run_id; do
[ -z "$run_id" ] && continue
echo "Canceling run $run_id"
gh run cancel "$run_id" --repo "$REPO"
done
# Poll (with short backoff) until all in-progress/queued runs for this commit are done
# Max 15 iterations, summing to 120 seconds
for i in {1..15}; do
sleep $((i))
RUNS_LEFT=$(gh run list --repo "$REPO" --branch "$BRANCH" --json databaseId,status,headSha | jq \
'[.[] | select(.headSha == env.SHA and .status != "completed")] | length')
echo "Still running: $RUNS_LEFT"
[ "$RUNS_LEFT" -eq 0 ] && break
done
# Cancel the Eden Runner run if it exists and is in-progress
if [ -n "$EDEN_RUNNER_RUN" ] && [ "$EDEN_RUNNER_STATUS" != "completed" ]; then
echo "Eden Runner run $EDEN_RUNNER_RUN is in-progress, cancelling it..."
gh run cancel "$EDEN_RUNNER_RUN" --repo "$REPO"
else
echo "Eden Runner run $EDEN_RUNNER_RUN is not in-progress or does not exist."
fi
# Wait for the Eden Runner run to be fully cancelled
for i in {1..15}; do
sleep $((i))
# Check if the Eden Runner run is still in-progress
EDEN_RUNNER_STATUS=$(gh run view "$EDEN_RUNNER_RUN" --repo "$REPO" --json status -q .status 2>/dev/null || echo "not_found")
if [ "$EDEN_RUNNER_STATUS" == "completed" ]; then
echo "Eden Runner run $EDEN_RUNNER_RUN is now completed."
break
elif [ "$EDEN_RUNNER_STATUS" == "not_found" ]; then
echo "Eden Runner run $EDEN_RUNNER_RUN not found, assuming it was cancelled."
break
else
echo "Waiting for Eden Runner run $EDEN_RUNNER_RUN to complete..."
fi
done
# Refresh RUNS after cancellation!
RUNS=$(gh run list --repo "$REPO" --branch "$BRANCH" --json databaseId,status,conclusion,headSha,workflowName,displayTitle,event)
fi
# Now rerun all runs for this commit that are completed and not successful
echo "$RUNS" | jq -r \
'.[] | select(.headSha == env.SHA and .status == "completed" and (.conclusion != "success" and .conclusion != "skipped")) | .databaseId' \
| while read -r run_id; do
[ -z "$run_id" ] && continue
echo "Re-running failed/canceled run $run_id"
gh run rerun "$run_id" --repo "$REPO"
done
# Rerun the Eden Runner run if it exists
if [ -n "$EDEN_RUNNER_RUN" ]; then
echo "Re-running Eden Runner run $EDEN_RUNNER_RUN"
gh run rerun "$EDEN_RUNNER_RUN" --repo "$REPO"
else
echo "No Eden Runner run found for commit $SHA"
fi