Skip to content

Commit 2296264

Browse files
lpcoxCopilot
andcommitted
refactor(ci-gate): use comment prompt + ready-for-aw label
GITHUB_TOKEN-added labels don't trigger other workflows (GitHub's anti-cascade protection). Instead of auto-labeling, ci-gate now posts a comment instructing the PR owner to manually add the 'ready-for-aw' label to trigger agentic CI smoke tests. Changes: - Rename label from 'ready-for-ci' to 'ready-for-aw' across all workflows - ci-gate posts/updates a comment instead of calling issues.addLabels - Add 'opened' to pull_request trigger types - Add copilot-pull-request-reviewer[bot] to reviewer Set - Rename test file to match new label name Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent b0e3c61 commit 2296264

32 files changed

Lines changed: 169 additions & 160 deletions

.github/workflows/build-test.lock.yml

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/build-test.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
roles: all
55
workflow_dispatch:
66
label_command:
7-
name: ready-for-ci
7+
name: ready-for-aw
88
events: [pull_request]
99
remove_label: false
1010
permissions:

.github/workflows/ci-gate.yml

Lines changed: 59 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
name: CI Gate
2-
# Automatically adds the "ready-for-ci" label to PRs when:
3-
# 1. Copilot review completes with no actionable feedback, OR
4-
# 2. A push is made after Copilot review (indicating feedback was addressed)
2+
# Posts a comment instructing the PR owner to add the "ready-for-aw" label
3+
# when Copilot review passes. This gates expensive agentic CI (smoke tests,
4+
# contribution check, etc.) to avoid wasting tokens on code that will change
5+
# after review.
56
#
6-
# This gates expensive agentic CI (smoke tests, contribution check, etc.)
7-
# to avoid wasting tokens on code that will change after review.
7+
# Note: We cannot auto-add the label because GITHUB_TOKEN-added labels don't
8+
# trigger other workflows (GitHub's anti-cascade protection). The label must
9+
# be added manually by a human or a GitHub App.
810

911
on:
1012
pull_request_review:
1113
types: [submitted]
1214
pull_request:
13-
types: [synchronize] # push to PR branch
15+
types: [opened, synchronize]
1416

1517
permissions:
1618
issues: write
@@ -21,16 +23,20 @@ jobs:
2123
gate:
2224
runs-on: ubuntu-latest
2325
steps:
24-
- name: Check if ready for CI
26+
- name: Check if ready for agentic CI
2527
uses: actions/github-script@v7
2628
with:
2729
script: |
28-
const copilotReviewers = new Set(['copilot', 'copilot[bot]', 'Copilot', 'copilot-pull-request-reviewer']);
30+
const LABEL = 'ready-for-aw';
31+
const COMMENT_MARKER = '<!-- ci-gate-bot -->';
32+
const copilotReviewers = new Set(['copilot', 'copilot[bot]', 'Copilot', 'copilot-pull-request-reviewer', 'copilot-pull-request-reviewer[bot]']);
2933
const isCopilotReviewer = login => copilotReviewers.has(login ?? '');
3034
const { owner, repo } = context.repo;
3135
const pr_number = context.payload.pull_request?.number
3236
|| context.payload.review?.pull_request?.number;
3337
38+
core.info(`Event: ${context.eventName}, PR: ${pr_number || 'none'}`);
39+
3440
if (!pr_number) {
3541
core.info('No PR number found, skipping');
3642
return;
@@ -40,61 +46,74 @@ jobs:
4046
const { data: labels } = await github.rest.issues.listLabelsOnIssue({
4147
owner, repo, issue_number: pr_number
4248
});
43-
if (labels.some(l => l.name === 'ready-for-ci')) {
49+
if (labels.some(l => l.name === LABEL)) {
4450
core.info('Label already present, skipping');
4551
return;
4652
}
4753
48-
// For synchronize events (push after review), add label if review exists
54+
// Helper: post or update the gate comment
55+
async function postGateComment(message) {
56+
const { data: comments } = await github.rest.issues.listComments({
57+
owner, repo, issue_number: pr_number
58+
});
59+
const existing = comments.find(c => c.body?.includes(COMMENT_MARKER));
60+
const body = `${COMMENT_MARKER}\n${message}`;
61+
if (existing) {
62+
await github.rest.issues.updateComment({ owner, repo, comment_id: existing.id, body });
63+
} else {
64+
await github.rest.issues.createComment({ owner, repo, issue_number: pr_number, body });
65+
}
66+
}
67+
68+
// Determine if Copilot has reviewed
69+
let copilotReviewed = false;
70+
let hasInlineComments = false;
71+
4972
if (context.eventName === 'pull_request') {
5073
const { data: reviews } = await github.rest.pulls.listReviews({
5174
owner, repo, pull_number: pr_number
5275
});
53-
const hasCopilotReview = reviews.some(r => isCopilotReviewer(r.user?.login));
54-
if (hasCopilotReview) {
55-
core.info('Post-review push detected, adding ready-for-ci label');
56-
await github.rest.issues.addLabels({
57-
owner, repo, issue_number: pr_number,
58-
labels: ['ready-for-ci']
59-
});
60-
}
61-
return;
76+
const reviewLogins = reviews.map(r => r.user?.login);
77+
core.info(`Found ${reviews.length} review(s): ${reviewLogins.join(', ')}`);
78+
copilotReviewed = reviews.some(r => isCopilotReviewer(r.user?.login));
6279
}
6380
64-
// For review events, check if review has actionable comments
6581
if (context.eventName === 'pull_request_review') {
6682
const reviewer = context.payload.review?.user?.login;
83+
core.info(`Review event from: ${reviewer}`);
6784
if (!isCopilotReviewer(reviewer)) {
6885
core.info(`Review from ${reviewer}, not Copilot — skipping`);
6986
return;
7087
}
88+
copilotReviewed = true;
7189
72-
// Check for unresolved review comments on this PR
90+
// Check for inline comments
7391
const { data: comments } = await github.rest.pulls.listReviewComments({
7492
owner, repo, pull_number: pr_number
7593
});
7694
const copilotComments = comments.filter(c =>
77-
isCopilotReviewer(c.user?.login)
78-
&& !c.in_reply_to_id
95+
isCopilotReviewer(c.user?.login) && !c.in_reply_to_id
7996
);
80-
81-
if (copilotComments.length === 0) {
82-
core.info('Copilot review with no inline comments, adding ready-for-ci label');
83-
await github.rest.issues.addLabels({
84-
owner, repo, issue_number: pr_number,
85-
labels: ['ready-for-ci']
86-
});
87-
} else {
97+
hasInlineComments = copilotComments.length > 0;
98+
if (hasInlineComments) {
8899
core.info(`Copilot left ${copilotComments.length} inline comment(s), waiting for fixes`);
89100
}
90101
}
91102
92-
- name: Remove label on new push (reset gate)
93-
if: github.event_name == 'pull_request' && github.event.action == 'synchronize'
94-
uses: actions/github-script@v7
95-
with:
96-
script: |
97-
// This step intentionally does NOT remove the label on push.
98-
// The label persists so that re-triggered agentic workflows can run.
99-
// The label is only meaningful as a "review addressed" signal.
100-
core.info('Label preserved across pushes to allow agentic CI to re-run');
103+
if (!copilotReviewed) {
104+
core.info('No Copilot review found yet, waiting');
105+
return;
106+
}
107+
108+
if (hasInlineComments) {
109+
await postGateComment(
110+
'⏳ Copilot review has inline comments. Address the feedback, then add the `ready-for-aw` label to trigger agentic CI.'
111+
);
112+
return;
113+
}
114+
115+
// Copilot reviewed with no inline comments — prompt to add label
116+
await postGateComment(
117+
'✅ Copilot review passed. Add the `ready-for-aw` label to trigger agentic CI smoke tests.'
118+
);
119+
core.info('Posted comment instructing PR owner to add ready-for-aw label');

.github/workflows/contribution-check.lock.yml

Lines changed: 3 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/contribution-check.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
roles: all
55
workflow_dispatch:
66
label_command:
7-
name: ready-for-ci
7+
name: ready-for-aw
88
events: [pull_request]
99
remove_label: false
1010
permissions:

.github/workflows/security-guard.lock.yml

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/security-guard.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on:
44
roles: all
55
workflow_dispatch:
66
label_command:
7-
name: ready-for-ci
7+
name: ready-for-aw
88
events: [pull_request]
99
remove_label: false
1010
permissions:

0 commit comments

Comments
 (0)