Blame Raw
Cohee · b06a6295 · · 327 lines (12.9 KB)
1 contributor
1name: 🔀 Pull Request Manager
2
3on:
4 workflow_dispatch: # Allow to manually call this workflow
5 pull_request_target:
6 types: [opened, synchronize, reopened, edited, labeled, unlabeled, closed]
7 pull_request_review_comment:
8 types: [created]
9
10permissions:
11 contents: read
12 pull-requests: write
13
14jobs:
15 label-by-size:
16 name: 🏷️ Label PR by Size
17 # This job should run after all others, to prevent possible concurrency issues
18 needs: [label-by-branches, label-by-files, label-copilot-prs, remove-stale-label, check-merge-blocking-labels, write-auto-comments]
19 runs-on: ubuntu-latest
20 # Only needs to run when code is changed
21 if: always() && (github.event.action == 'opened' || github.event.action == 'synchronize')
22
23 # Override permissions, the labeler needs issues write access
24 permissions:
25 contents: read
26 issues: write
27 pull-requests: write
28
29 steps:
30 - name: Mint App Token
31 id: app
32 # Create a GitHub App token
33 # https://github.com/marketplace/actions/create-github-app-token
34 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
35 with:
36 app-id: ${{ vars.ST_BOT_APP_ID }}
37 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
38 owner: ${{ github.repository_owner }}
39
40 - name: Label PR Size
41 # Pull Request Size Labeler
42 # https://github.com/marketplace/actions/pull-request-size-labeler
43 uses: codelytv/pr-size-labeler@4ec67706cd878fbc1c8db0a5dcd28b6bb412e85a # v1.10.3
44 with:
45 GITHUB_TOKEN: ${{ steps.app.outputs.token }}
46 xs_label: '🟩 ⬤○○○○'
47 xs_max_size: '20'
48 s_label: '🟩 ⬤⬤○○○'
49 s_max_size: '100'
50 m_label: '🟨 ⬤⬤⬤○○'
51 m_max_size: '500'
52 l_label: '🟧 ⬤⬤⬤⬤○'
53 l_max_size: '1000'
54 xl_label: '🟥 ⬤⬤⬤⬤⬤'
55 fail_if_xl: 'false'
56 files_to_ignore: |
57 "package-lock.json"
58 "public/lib/*"
59
60 label-by-branches:
61 name: 🏷️ Label PR by Branches
62 runs-on: ubuntu-latest
63 # Only label once when PR is created or when base branch is changed, to allow manual label removal
64 if: always() && (github.event.action == 'opened' || (github.event.action == 'synchronize' && github.event.changes.base))
65
66 steps:
67 - name: Mint App Token
68 id: app
69 # Create a GitHub App token
70 # https://github.com/marketplace/actions/create-github-app-token
71 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
72 with:
73 app-id: ${{ vars.ST_BOT_APP_ID }}
74 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
75 owner: ${{ github.repository_owner }}
76
77 - name: Checkout Repository
78 # Checkout
79 # https://github.com/marketplace/actions/checkout
80 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
81
82 - name: Apply Labels Based on Branch Name and Target Branch
83 # Pull Request Labeler
84 # https://github.com/marketplace/actions/labeler
85 uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
86 with:
87 configuration-path: .github/pr-auto-labels-by-branch.yml
88 repo-token: ${{ steps.app.outputs.token }}
89
90 label-by-files:
91 name: 🏷️ Label PR by Files
92 needs: [label-by-branches]
93 runs-on: ubuntu-latest
94 # Only needs to run when code is changed
95 if: always() && (github.event.action == 'opened' || github.event.action == 'synchronize')
96
97 steps:
98 - name: Mint App Token
99 id: app
100 # Create a GitHub App token
101 # https://github.com/marketplace/actions/create-github-app-token
102 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
103 with:
104 app-id: ${{ vars.ST_BOT_APP_ID }}
105 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
106 owner: ${{ github.repository_owner }}
107
108 - name: Checkout Repository
109 # Checkout
110 # https://github.com/marketplace/actions/checkout
111 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
112
113 - name: Apply Labels Based on Changed Files
114 # Pull Request Labeler
115 # https://github.com/marketplace/actions/labeler
116 uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
117 env:
118 GITHUB_TOKEN: ${{ steps.app.outputs.token }} # labeler action needs some handholding
119 with:
120 configuration-path: .github/pr-auto-labels-by-files.yml
121 repo-token: ${{ steps.app.outputs.token }}
122
123 label-copilot-prs:
124 name: 🏷️ Label Copilot PRs as Vibe Coded
125 runs-on: ubuntu-latest
126 # Only label once when PR is created by Copilot
127 if: >
128 github.event.action == 'opened' &&
129 github.event.pull_request.user.login == 'Copilot'
130
131 steps:
132 - name: Mint App Token
133 id: app
134 # Create a GitHub App token
135 # https://github.com/marketplace/actions/create-github-app-token
136 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
137 with:
138 app-id: ${{ vars.ST_BOT_APP_ID }}
139 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
140 owner: ${{ github.repository_owner }}
141
142 - name: Add Vibe Coded Label
143 # 🤖 Issues Helper
144 # https://github.com/marketplace/actions/issues-helper
145 uses: actions-cool/issues-helper@a610082f8ac0cf03e357eb8dd0d5e2ba075e017e # v3.6.0
146 with:
147 actions: 'add-labels'
148 token: ${{ steps.app.outputs.token }}
149 issue-number: ${{ github.event.pull_request.number }}
150 labels: '✨ Vibe Coded'
151
152 remove-stale-label:
153 name: 🗑️ Remove Stale Label on Comment
154 needs: [label-by-branches, label-by-files, label-copilot-prs]
155 runs-on: ubuntu-latest
156 # Only runs on comments not done by the github actions bot
157 if: always() && (github.event_name == 'pull_request_review_comment' && github.event.sender.type != 'Bot')
158
159 # Override permissions, issue labeler needs issues write access
160 permissions:
161 contents: read
162 issues: write
163 pull-requests: write
164
165 steps:
166 - name: Mint App Token
167 if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
168 id: app
169 # Only run if the PR is from the same repository
170 # This action runs on comments, which will not receive the env vars for this
171 # Create a GitHub App token
172 # https://github.com/marketplace/actions/create-github-app-token
173 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
174 with:
175 app-id: ${{ vars.ST_BOT_APP_ID }}
176 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
177 owner: ${{ github.repository_owner }}
178
179 - name: Remove Stale Label
180 if: always()
181 # 🤖 Issues Helper
182 # https://github.com/marketplace/actions/issues-helper
183 uses: actions-cool/issues-helper@a610082f8ac0cf03e357eb8dd0d5e2ba075e017e # v3.6.0
184 with:
185 actions: 'remove-labels'
186 token: ${{ steps.app.outputs.token || github.token }} # Use fallback to GITHUB_TOKEN if app token is not available
187 issue-number: ${{ github.event.pull_request.number }}
188 labels: '⚰️ Stale'
189
190 check-merge-blocking-labels:
191 name: 🚫 Check Merge Blocking Labels
192 needs: [label-by-branches, label-by-files, label-copilot-prs, remove-stale-label]
193 runs-on: ubuntu-latest
194 # Run, even if the previous jobs were skipped/failed
195 if: always()
196
197 # Override permissions, as this needs to write a check
198 permissions:
199 checks: write
200 contents: read
201 pull-requests: read
202
203 steps:
204 - name: Check Merge Blocking
205 # GitHub Script
206 # https://github.com/marketplace/actions/github-script
207 id: label-check
208 uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
209 with:
210 script: |
211 const prLabels = context.payload.pull_request.labels.map(label => label.name);
212 const blockingLabels = [
213 "⛔ Don't Merge",
214 "🔨 Needs Work",
215 "🔬 Needs Testing",
216 "⛔ Waiting For External/Upstream",
217 "❗ Against Release Branch",
218 "💥💣 Breaking Changes"
219 ];
220 const hasBlockingLabel = prLabels.some(label => blockingLabels.includes(label));
221
222 if (hasBlockingLabel) {
223 console.log("Blocking label detected. Setting warning status.");
224 await github.rest.checks.create({
225 owner: context.repo.owner,
226 repo: context.repo.repo,
227 name: "PR Label Warning",
228 head_sha: context.payload.pull_request.head.sha,
229 status: "completed",
230 conclusion: "neutral",
231 output: {
232 title: "Potential Merge Issue",
233 summary: "This PR has a merge-blocking label. Proceed with caution."
234 }
235 });
236 } else {
237 console.log("No merge-blocking labels found.");
238 }
239
240 write-auto-comments:
241 name: 💬 Post PR Comments Based on Labels
242 needs: [label-by-branches, label-by-files, label-copilot-prs, remove-stale-label, check-merge-blocking-labels]
243 runs-on: ubuntu-latest
244 # Run, even if the previous jobs were skipped/failed
245 if: always() && (github.event_name == 'pull_request_target')
246
247 steps:
248 - name: Mint App Token
249 id: app
250 # Create a GitHub App token
251 # https://github.com/marketplace/actions/create-github-app-token
252 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
253 with:
254 app-id: ${{ vars.ST_BOT_APP_ID }}
255 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
256 owner: ${{ github.repository_owner }}
257
258 - name: Checkout Repository
259 # Checkout
260 # https://github.com/marketplace/actions/checkout
261 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
262
263 - name: Post PR Comments Based on Labels
264 # Label Commenter for PRs
265 # https://github.com/marketplace/actions/label-commenter
266 uses: peaceiris/actions-label-commenter@f0dbbef043eb1b150b566db36b0bdc8b7f505579 # v1.10.0
267 with:
268 config_file: .github/pr-auto-comments.yml
269 github_token: ${{ steps.app.outputs.token }}
270
271 # This runs on merged PRs to staging, reading the PR body and directly linked issues. Check `issues-updates-on-merge.yml`:`update-linked-issues` for commit-based updates.
272 update-linked-issues:
273 name: 🔗 Mark Linked Issues Done on Staging Merge
274 runs-on: ubuntu-latest
275 if: >
276 always() &&
277 github.event_name == 'pull_request_target' &&
278 github.event.pull_request.merged == true &&
279 github.event.pull_request.base.ref == 'staging'
280
281 # Override permissions, We need to be able to write to issues
282 permissions:
283 contents: read
284 issues: write
285 pull-requests: write
286
287 steps:
288 - name: Mint App Token
289 id: app
290 # Create a GitHub App token
291 # https://github.com/marketplace/actions/create-github-app-token
292 uses: actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349 # v2
293 with:
294 app-id: ${{ vars.ST_BOT_APP_ID }}
295 private-key: ${{ secrets.ST_BOT_PRIVATE_KEY }}
296 owner: ${{ github.repository_owner }}
297
298 - name: Extract Linked Issues From PR Description
299 id: extract_issues
300 run: |
301 ISSUES=$(jq -r '.pull_request.body' "$GITHUB_EVENT_PATH" | grep -oiE '(close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved) #([0-9]+)' | awk '{print $2}' | tr -d '#' | jq -R -s -c 'split("\n")[:-1]')
302 echo "issues=$ISSUES" >> $GITHUB_ENV
303
304 - name: Fetch Directly Linked Issues
305 id: fetch_linked_issues
306 run: |
307 PR_NUMBER=${{ github.event.pull_request.number }}
308 REPO=${{ github.repository }}
309 API_URL="https://api.github.com/repos/$REPO/pulls/$PR_NUMBER/issues"
310 ISSUES=$(curl -s -H "Authorization: token ${{ steps.app.outputs.token }}" "$API_URL" | jq -r '.[].number' | jq -R -s -c 'split("\n")[:-1]')
311 echo "linked_issues=$ISSUES" >> $GITHUB_ENV
312
313 - name: Merge Issue Lists
314 id: merge_issues
315 run: |
316 ISSUES=$(jq -c -n --argjson a "$issues" --argjson b "$linked_issues" '$a + $b | unique')
317 echo "final_issues=$ISSUES" >> $GITHUB_ENV
318
319 - name: Label Linked Issues
320 id: label_linked_issues
321 env:
322 GH_TOKEN: ${{ steps.app.outputs.token }}
323 run: |
324 for ISSUE in $(echo $final_issues | jq -r '.[]'); do
325 gh issue edit $ISSUE -R ${{ github.repository }} --add-label "✅ Done (staging)" --remove-label "🧑‍💻 In Progress"
326 echo "Added label '✅ Done (staging)' (and removed '🧑‍💻 In Progress' if present) in issue #$ISSUE"
327 done