11# Organization-funded Copilot reviews
22
33The ` Organization-funded Copilot reviews ` workflow requests Copilot code review
4- (CCR) using the repository's ` GITHUB_TOKEN ` , not a contributor's personal token.
4+ (CCR) using an installation token for ` aspire-repo-bot ` , not the workflow's
5+ ` GITHUB_TOKEN ` or a contributor's personal token. Organization funding is the
6+ goal, not a verified billing guarantee.
57It covers open PRs (including drafts) targeting ` main ` or ` release/** ` , including forks
68and bot-authored PRs. There is no author permission or license filter.
79
8- ** The default is dry-run. Merging this workflow does not enable billable review
9- requests or change any GitHub rulesets.**
10+ ** The default is dry-run only when the mode variable is unset. If it is already
11+ ` enabled ` , merging this change switches subsequent runs to the App immediately.
12+ Set dry-run and a pilot PR before merging to stage the rollout.** No GitHub
13+ rulesets are changed by the workflow.
14+
15+ ## App prerequisites
16+
17+ The Aspire App must be installed on ` microsoft/aspire ` with Pull requests: write.
18+ The workflow uses the existing ` ASPIRE_BOT_APP_ID ` and ` ASPIRE_BOT_PRIVATE_KEY `
19+ Actions secrets. The token action accepts the existing identifier via its
20+ ` client-id ` input, matching other repository workflows.
21+
22+ Each run mints an installation token scoped explicitly to the ` microsoft `
23+ installation and the ` aspire ` repository. Only Pull requests access is requested:
24+ write when the mode is exactly ` enabled ` , otherwise read. Token creation or
25+ permission failures stop the job; there is no fallback to ` GITHUB_TOKEN ` .
1026
1127## Controls
1228
@@ -16,7 +32,7 @@ Variables**. No follow-up PR is needed to change modes.
1632| Variable | Value | Effect |
1733| --- | --- | --- |
1834| ` COPILOT_REVIEW_MODE ` | Unset or ` dry-run ` | Read metadata and report decisions; never request reviews. |
19- | ` COPILOT_REVIEW_MODE ` | ` enabled ` | Request reviews using the Actions bot . |
35+ | ` COPILOT_REVIEW_MODE ` | ` enabled ` | Request reviews using the Aspire App . |
2036| ` COPILOT_REVIEW_MODE ` | ` disabled ` | Skip the job (kill switch). |
2137| ` COPILOT_REVIEW_PR_NUMBER ` | Unset | Consider all eligible PRs, including PRs opened before rollout. |
2238| ` COPILOT_REVIEW_PR_NUMBER ` | A positive PR number | Restrict both event-driven and scheduled processing to that PR for a pilot. |
@@ -33,6 +49,15 @@ including for draft PRs. Reopening a PR or marking a draft ready does not trigge
3349an additional run. Manual dispatch on ` main ` and a scheduled
3450scan every 15 minutes reconcile open PRs. GitHub can delay scheduled runs.
3551
52+ ` pull_request_target ` runs initiated by ` dependabot[bot] ` skip the entire job,
53+ before App token creation, because [ Dependabot PR events can lack Actions
54+ secrets] ( https://docs.github.com/en/code-security/reference/supply-chain-security/dependabot-on-actions#restrictions-when-dependabot-triggers-events ) .
55+ Dependabot-authored PRs remain eligible for scheduled scans and maintainer
56+ manual dispatches, which use their own execution context and credentials.
57+ Their reviews therefore normally wait for the next scan rather than running
58+ immediately on creation or push. Do not copy the App private key into Dependabot
59+ secrets; it is not needed for this recovery path.
60+
3661Scheduled scans skip PRs with no activity in the last 14 days, using GitHub's
3762` updated_at ` timestamp (not the PR creation date or latest commit date). The
3863cutoff is inclusive: an update exactly 14 days before the run is stale. The
@@ -76,11 +101,17 @@ removes someone else's review request to force a retry.
76101
77102- The privileged workflow does not check out source, execute PR code, load local
78103 actions, install packages, or consume artifacts or caches.
79- - The only action is a full-SHA-pinned ` actions/github-script ` . All logic is
80- inline so even loading policy code does not require checkout.
81- - The only token permission is ` pull-requests: write ` . The job uses an ephemeral
82- GitHub-hosted runner with a ten-minute timeout. No App private key or PAT is
83- used.
104+ - Both actions (` actions/create-github-app-token ` and ` actions/github-script ` )
105+ are full-SHA-pinned. All policy logic is inline, requiring no checkout.
106+ - The workflow's ` GITHUB_TOKEN ` has no granted permissions. The App installation
107+ token is restricted to this repository and Pull requests read/write as
108+ described above, plus GitHub's mandatory metadata read access. The token action
109+ revokes it during job cleanup; installation tokens also expire after one hour.
110+ - The App private key is passed only to the token action, not to the inline
111+ reconciliation script. Unlike the narrowed token, the private key can mint
112+ tokens with the App's broader installed permissions: protecting the secret
113+ and trusted workflow/runtime remains essential. No PAT is used. The job uses
114+ an ephemeral GitHub-hosted runner with a ten-minute timeout.
84115- Repository and reviewer identities are fixed. PR-controlled values are API
85116 data, never interpolated into scripts or used as API URLs. Logs and summaries
86117 include only validated PR numbers, SHAs, and fixed decision messages.
@@ -91,45 +122,56 @@ removes someone else's review request to force a retry.
91122 suggestions. CCR's own runner/setup and secret configuration is a separate
92123 security boundary that must be assessed before the pilot.
93124
94- Dry-run uses the same token permissions but never calls the write endpoint.
125+ Dry-run uses a read-only App token and never calls the write endpoint. It still
126+ requires the App secrets for token creation; disabled mode skips the entire job.
95127The single-PR scope and kill switch are rollout controls, not a hard spending
96- limit. Once enabled for everyone, contributors can generate organization-paid
97- reviews by pushing changes. Configure organization budgets/alerts and monitor
128+ limit. Once enabled for everyone, contributors can generate potentially billable
129+ reviews by pushing changes. Configure appropriate budgets/alerts and monitor
98130usage; reconsider cadence if this becomes expensive or is abused.
99131
100132## Billing and rollout
101133
102134[ GitHub's CCR documentation] ( https://docs.github.com/en/copilot/concepts/agents/code-review#code-review-usage )
103135attributes built-in automatic reviews to the author and explicitly states that
104136bot-requested reviews are billed directly to the organization.
105- [ ` GITHUB_TOKEN ` ] ( https://docs.github.com/en/actions/concepts/security/github_token )
106- is an installation token, not the identity of the contributor triggering the
107- workflow. GitHub documents
137+ However, the previous ` GITHUB_TOKEN ` implementation showed an Actions-bot review
138+ request followed by CCR starting on behalf of the contributor on PR #18530 ,
139+ and a quota-limit rejection on PR #17949 . Neither is a billing receipt, but
140+ they undermine the assumption that a bot requester alone proves organization
141+ funding. ` GITHUB_TOKEN ` is itself an installation token; using a separate App
142+ changes the requesting identity, not a documented billing-account selector.
143+
144+ GitHub documents
108145[ requesting the Copilot reviewer through REST] ( https://docs.github.com/en/copilot/how-tos/use-copilot-agents/request-a-code-review/use-code-review ) .
109- These rules support this design, but actual execution and billing under
110- Microsoft's policies must be confirmed before broad rollout.
146+ Actual execution, quota enforcement, and billing under Microsoft's policies must
147+ be confirmed separately before broad rollout.
111148
112- 1 . Merge in dry-run mode and inspect workflow decisions. No production billing
113- settings or automatic review rules are changed by this PR.
149+ 1 . Before merging, set ` COPILOT_REVIEW_MODE=dry-run ` and
150+ ` COPILOT_REVIEW_PR_NUMBER ` to an agreed team-owned pilot PR. Cancel existing
151+ enabled workflow runs if needed; changing variables does not stop them.
152+ After merging, inspect workflow decisions and successful App token creation.
1141532 . Identify applicable repository and organization automatic CCR rules,
115154 including "Review new pushes." Disable those paths before enabling writes,
116155 or they can still create author-attributed or duplicate reviews.
117- 3 . Set ` COPILOT_REVIEW_PR_NUMBER ` to an agreed pilot PR. Assess CCR's downstream
118- runner permissions and confirm organization funding/budget policies.
119- 4 . Set ` COPILOT_REVIEW_MODE=enabled ` . Confirm that the Actions bot starts a
156+ 3 . Assess CCR's downstream runner permissions and confirm organization
157+ funding/budget policies. Obtain the pilot participant's consent for possible
158+ personal allowance consumption; do not experiment on unsuspecting customers.
159+ 4 . Set ` COPILOT_REVIEW_MODE=enabled ` . Confirm that ` aspire-repo-bot[bot] ` requests a
120160 review, then push another commit and confirm a re-review, including a push
121- during an active review. Include an external contributor in the pilot.
161+ during an active review. Record PR/head, timestamps, requesting actor,
162+ execution attribution, and any quota errors for billing correlation.
1221635 . Have a billing administrator confirm organization attribution and no
123164 contributor allowance consumption for these bot-requested reviews. An API
124165 success or a posted review alone is not proof of billing attribution.
1251666 . Clear the pilot variable to cover all eligible open PRs. Keep human approval
126167 requirements unchanged and monitor spend and failed workflow runs.
127168
128- If ` GITHUB_TOKEN ` cannot initiate CCR under organization policy, leave writes
129- disabled until that failure is understood. An Aspire bot App installation token
130- is a possible follow-up, scoped to this repository with Pull requests: write.
131- Do not substitute a personal token, silently escalate permissions, or claim
132- organization billing based only on the human who triggered a workflow run.
169+ If the App cannot initiate CCR or attribution remains unclear, leave writes
170+ disabled and escalate the pilot evidence to GitHub support. Ask which principal
171+ is checked for quota and which account is billed, and whether Actions and
172+ independent App installation tokens are handled differently. Do not substitute
173+ a personal token, silently escalate permissions, or infer billing solely from
174+ the requesting bot or the displayed "on behalf of" identity.
133175
134176Personal automatic-review settings and manual requests are outside this
135177workflow's control and retain their own billing attribution. Actions usage for
0 commit comments