-
Notifications
You must be signed in to change notification settings - Fork 2
165 lines (153 loc) · 6.76 KB
/
Copy pathcursor-review-auto-label.yml
File metadata and controls
165 lines (153 loc) · 6.76 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
name: Cursor Review Auto-Label (reusable)
# Reusable companion to cursor-review.yml. Translates the moment an opted-in
# person becomes responsible for a PR into the review label that
# cursor-review.yml triggers on — keeping the "fire on label" contract intact
# while letting people opt in without UI clicks.
#
# Which moments fire is decided by the CALLER's `on:` triggers; this workflow
# just reacts to whatever pull_request event was passed through:
# - assigned -> the newly-assigned reviewer
# - opened -> the PR author (skipped while the PR is a draft)
# - ready_for_review -> the PR author
# A caller that lists only `[assigned]` keeps the original assignment-only
# behavior; add `opened` / `ready_for_review` to also label on PR creation.
#
# The opt-in roster is NOT baked into this file. It lives in the CALLER repo's
# `vars.CURSOR_REVIEW_OPTED_IN_LOGINS` (whitespace-separated GitHub logins). The
# `vars` context in a reusable workflow resolves to the caller's repository/org
# variables, so each consumer manages its own roster by editing the variable,
# not this workflow.
#
# IMPORTANT: the label MUST be applied with a GitHub App token, not the default
# GITHUB_TOKEN. Label events triggered by GITHUB_TOKEN do not create new
# workflow runs, so a GITHUB_TOKEN-applied label would silently fail to fire the
# review. The caller therefore sets `vars.APP_ID` (the CLOUD_CODE_BOT app id) and
# passes `secrets.CLOUD_CODE_BOT_PRIVATE_KEY`.
#
# Example caller (consumer repo):
#
# name: CI - Cursor Review Auto-Label
# on:
# pull_request:
# types: [assigned, opened, ready_for_review] # or just [assigned]
# jobs:
# auto-label:
# permissions:
# contents: read
# uses: Comfy-Org/github-workflows/.github/workflows/cursor-review-auto-label.yml@<sha>
# secrets:
# CLOUD_CODE_BOT_PRIVATE_KEY: ${{ secrets.CLOUD_CODE_BOT_PRIVATE_KEY }}
on:
workflow_call:
inputs:
review_label:
description: >-
Label to apply. MUST match the label cursor-review.yml triggers on
(its `review_label` input, default `cursor-review`).
type: string
required: false
default: cursor-review
skip_label:
description: >-
If this label is already present on the PR, auto-labeling is
suppressed — don't fight an explicit opt-out.
type: string
required: false
default: skip-cursor-review
runs_on:
description: >-
JSON-encoded runs-on value for this workflow's single job. Default
'"ubuntu-latest"' (a JSON string) preserves existing GitHub-hosted
behavior for all callers. Override with a JSON array to target a
self-hosted runner, e.g. '["self-hosted", "macOS"]' — useful for
repos that would otherwise burn GitHub-hosted minutes (private repos
over quota). Parsed with fromJSON, so the value MUST be valid JSON.
Matches the same input on cursor-review.yml so a caller can pin both
workflows to one runner.
type: string
required: false
default: '"ubuntu-latest"'
secrets:
CLOUD_CODE_BOT_PRIVATE_KEY:
description: >-
Private key for the CLOUD_CODE_BOT GitHub App (app id = vars.APP_ID).
Required: the label must be applied by a GitHub App so it triggers the
downstream review run (GITHUB_TOKEN-applied labels do not).
required: true
permissions:
contents: read
jobs:
auto-label:
name: Auto-apply review label
runs-on: ${{ fromJSON(inputs.runs_on) }}
permissions:
contents: read
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
with:
app-id: ${{ vars.APP_ID }}
private-key: ${{ secrets.CLOUD_CODE_BOT_PRIVATE_KEY }}
- name: Apply label when an opted-in person opens / readies / is assigned
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
ACTION: ${{ github.event.action }}
ASSIGNEE: ${{ github.event.assignee.login }}
AUTHOR: ${{ github.event.pull_request.user.login }}
IS_DRAFT: ${{ github.event.pull_request.draft }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
PR_LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }}
# Whitespace-separated GitHub logins, from the caller repo's variable.
OPTED_IN_LOGINS: ${{ vars.CURSOR_REVIEW_OPTED_IN_LOGINS }}
REVIEW_LABEL: ${{ inputs.review_label }}
SKIP_LABEL: ${{ inputs.skip_label }}
run: |
# Empty/unset roster -> nothing is opted in. Don't fail the run;
# consumers that haven't set the variable just get a no-op.
if [ -z "$(echo "$OPTED_IN_LOGINS" | tr -d '[:space:]')" ]; then
echo "vars.CURSOR_REVIEW_OPTED_IN_LOGINS is empty/unset — no-op."
exit 0
fi
# Pick the login this event is "about":
# assigned -> the newly-assigned reviewer
# opened / ready_for_review -> the PR author
case "$ACTION" in
assigned)
candidate="$ASSIGNEE" ;;
opened|ready_for_review)
candidate="$AUTHOR" ;;
*)
echo "Unhandled action '$ACTION' — no-op."
exit 0 ;;
esac
# Don't fire on a PR opened as a draft — the ready_for_review event
# re-triggers this workflow once it's marked ready.
if [ "$ACTION" = "opened" ] && [ "$IS_DRAFT" = "true" ]; then
echo "PR opened as a draft — deferring until marked ready for review."
exit 0
fi
matched=false
for login in $OPTED_IN_LOGINS; do
if [ "$candidate" = "$login" ]; then
matched=true
break
fi
done
if [ "$matched" = "false" ]; then
echo "$candidate is not opted in (action=$ACTION) — no-op."
exit 0
fi
# Already labeled — don't re-add (would just no-op anyway).
if echo "$PR_LABELS" | jq -e --arg l "$REVIEW_LABEL" 'index($l)' > /dev/null; then
echo "$REVIEW_LABEL already present — no-op."
exit 0
fi
# An explicit skip label wins — don't silently fight the user's intent.
if echo "$PR_LABELS" | jq -e --arg l "$SKIP_LABEL" 'index($l)' > /dev/null; then
echo "$SKIP_LABEL present — not auto-applying."
exit 0
fi
echo "Applying $REVIEW_LABEL label for $candidate (action=$ACTION)."
gh pr edit "$PR_NUMBER" --repo "$REPO" --add-label "$REVIEW_LABEL"