Skip to content

Commit 4390858

Browse files
jeffhandleyCopilot
andcommitted
Add Copilot PAT pool support for agentic workflows
- Add select-copilot-pat composite action with README - Update agentic-workflows agent with mandatory PAT pool instructions - Add PAT pool frontmatter blocks to conformance-tier-audit workflow - Use fork detection instead of repo name check in workflow condition - Change schedule to fuzzy 'weekly on thursday around 9am utc-7' - Move release.md out of .github/workflows/ to avoid treatment as agentic workflow - Recompile conformance-tier-audit lock file Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 97934ab commit 4390858

8 files changed

Lines changed: 648 additions & 57 deletions

File tree

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# Select Copilot PAT
2+
3+
Selects a random Copilot PAT from a numbered pool of secrets. This addresses limitations that arise from having a single PAT shared across all agentic workflows, such as rate-limiting.
4+
5+
**This is a stop-gap workaround.** As soon as organization/enterprise billing is offered for agentic workflows, this approach will be removed from our workflows.
6+
7+
## Repository Onboarding
8+
9+
To use this action in a repository:
10+
11+
1. Copy this `select-copilot-pat` folder into the repository under `.github/actions/select-copilot-pat`, including both the `README.md` and `action.yml`.
12+
2. Merge those additions into the repository and then follow the instructions for PAT Creation and Usage below.
13+
14+
## PAT Management
15+
16+
Team members provide PATs into the pools for the repository by adding them as repository secrets with secret names matching the pattern of `<pool_name>_<0-9>`, such as `COPILOT_PAT_0`.
17+
18+
[Use this link to prefill the PAT creation form with the required settings][create-pat]:
19+
20+
1. **Resource owner** is your **user account**, not an organization.
21+
2. **Copilot Requests (Read)** must be the only permission granted.
22+
3. **8-day expiration** must be used, which enforces a weekly renewal.
23+
4. **Repository access** set to **Public repositories** only.
24+
25+
The **Token Name** _does not_ need to match the secret name and is only visible to the owner of the PAT. It's recommended to use a token name indicating the PAT is used for modelcontextprotocol org agentic workflows. The **Description** is also only used for your own reference.
26+
27+
Team members providing PATs for workflows should set weekly recurring reminders to regenerate and update their PATs in the repository secrets. With an 8-day expiration, renewal can be done on the same day each week.
28+
29+
PATs are added to repositories through the **Settings > Secrets and variables > Actions** UI, saved as **Repository secrets** and matching the `<pool_name>_<0-9>` naming convention. This can also be done using the GitHub CLI.
30+
31+
```sh
32+
gh aw secrets set "<pool_name>_<0-9>" --value "<your-github-pat>" --repo modelcontextprotocol/<repo>
33+
```
34+
35+
## Workflow Output Attribution
36+
37+
Team members' PATs are _only_ used for the Copilot requests from within the agentic portion of the workflow. All outputs from the workflow use the `github-actions[bot]` account token. Issues, PRs, comments, and all other content generated by the workflow will be attributed to `github-actions[bot]`--not the team member's account or token.
38+
39+
## Usage
40+
41+
Add the following frontmatter at the top-level of an agentic workflow. These elements are not supported through [imports][imports], so they must be copied into all workflows.
42+
43+
Up to 10 `SECRET_#` environment variables can be passed to the action, numbered 0-9. Different workflows can use different pools of PATs if desired. Change the `secrets.COPILOT_PAT_0` through `secrets.COPILOT_PAT_9` secret names in both the `select-copilot-pat` step `env` values and in the `case` expression under the `engine: env` configuration.
44+
45+
```yml
46+
on:
47+
# Add the pre-activation step of selecting a random PAT from the supplied secrets
48+
steps:
49+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
50+
name: Checkout the select-copilot-pat action folder
51+
with:
52+
persist-credentials: false
53+
sparse-checkout: .github/actions/select-copilot-pat
54+
sparse-checkout-cone-mode: true
55+
fetch-depth: 1
56+
57+
- id: select-copilot-pat
58+
name: Select Copilot token from pool
59+
uses: ./.github/actions/select-copilot-pat
60+
env:
61+
# If the secret names are changed here, they must also be changed
62+
# in the `engine: env` case expression
63+
SECRET_0: ${{ secrets.COPILOT_PAT_0 }}
64+
SECRET_1: ${{ secrets.COPILOT_PAT_1 }}
65+
SECRET_2: ${{ secrets.COPILOT_PAT_2 }}
66+
SECRET_3: ${{ secrets.COPILOT_PAT_3 }}
67+
SECRET_4: ${{ secrets.COPILOT_PAT_4 }}
68+
SECRET_5: ${{ secrets.COPILOT_PAT_5 }}
69+
SECRET_6: ${{ secrets.COPILOT_PAT_6 }}
70+
SECRET_7: ${{ secrets.COPILOT_PAT_7 }}
71+
SECRET_8: ${{ secrets.COPILOT_PAT_8 }}
72+
SECRET_9: ${{ secrets.COPILOT_PAT_9 }}
73+
74+
# Add the pre-activation output of the randomly selected PAT
75+
jobs:
76+
pre-activation:
77+
outputs:
78+
copilot_pat_number: ${{ steps.select-copilot-pat.outputs.copilot_pat_number }}
79+
80+
# Override the COPILOT_GITHUB_TOKEN expression used in the activation job
81+
# Consume the PAT number from the pre-activation step and select the corresponding secret
82+
engine:
83+
id: copilot
84+
env:
85+
# We cannot use line breaks in this expression as it leads to a syntax error in the compiled workflow
86+
# If none of the `COPILOT_PAT_#` secrets were selected, then the default COPILOT_GITHUB_TOKEN is used
87+
COPILOT_GITHUB_TOKEN: ${{ case(needs.pre_activation.outputs.copilot_pat_number == '0', secrets.COPILOT_PAT_0, needs.pre_activation.outputs.copilot_pat_number == '1', secrets.COPILOT_PAT_1, needs.pre_activation.outputs.copilot_pat_number == '2', secrets.COPILOT_PAT_2, needs.pre_activation.outputs.copilot_pat_number == '3', secrets.COPILOT_PAT_3, needs.pre_activation.outputs.copilot_pat_number == '4', secrets.COPILOT_PAT_4, needs.pre_activation.outputs.copilot_pat_number == '5', secrets.COPILOT_PAT_5, needs.pre_activation.outputs.copilot_pat_number == '6', secrets.COPILOT_PAT_6, needs.pre_activation.outputs.copilot_pat_number == '7', secrets.COPILOT_PAT_7, needs.pre_activation.outputs.copilot_pat_number == '8', secrets.COPILOT_PAT_8, needs.pre_activation.outputs.copilot_pat_number == '9', secrets.COPILOT_PAT_9, secrets.COPILOT_GITHUB_TOKEN) }}
88+
```
89+
90+
## References
91+
92+
- [Agentic Workflows CLI Extension][cli-setup]
93+
- [Agentic Authoring][configure-repo]
94+
- [Authentication][authentication]
95+
- [Agentic Workflow Imports][imports]
96+
- [Custom Steps][steps]
97+
- [Custom Jobs][jobs]
98+
- [Job Outputs][job-outputs]
99+
- [Engine Configuration][engine]
100+
- [Engine Environment Variables][engine-vars]
101+
- [Case Function in Workflow Expressions][case-expression]
102+
- [Update agentic engine token handling to use user-provided secrets (github/gh-aw#18017)][secret-override]
103+
104+
[cli-setup]: https://github.github.com/gh-aw/setup/cli/
105+
[configure-repo]: https://github.github.com/gh-aw/guides/agentic-authoring/#configuring-your-repository
106+
[authentication]: https://github.github.com/gh-aw/reference/auth/
107+
[create-pat]: https://github.com/settings/personal-access-tokens/new?name=modelcontextprotocol%20org%20agentic%20workflows&description=GitHub+Agentic+Workflows+-+Copilot+engine+authentication.++Used+for+modelcontextprotocol+org+workflows.+MUST+be+configured+with+only+Copilot+Requests+permissions+and+user+account+as+resource+owner.+Weekly+expiration+and+required+renewal.&user_copilot_requests=read&expires_in=8
108+
[imports]: https://github.github.com/gh-aw/reference/imports/
109+
[steps]: https://github.github.com/gh-aw/reference/frontmatter/#custom-steps-steps
110+
[jobs]: https://github.github.com/gh-aw/reference/frontmatter/#custom-jobs-jobs
111+
[job-outputs]: https://github.github.com/gh-aw/reference/frontmatter/#job-outputs
112+
[engine]: https://github.github.com/gh-aw/reference/frontmatter/#ai-engine-engine
113+
[engine-vars]: https://github.github.com/gh-aw/reference/engines/#engine-environment-variables
114+
[case-expression]: https://docs.github.com/en/actions/reference/workflows-and-actions/expressions#case
115+
[secret-override]: https://github.com/github/gh-aw/pull/18017
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
name: 'Select Copilot PAT from Pool'
2+
description: >
3+
Selects a random Copilot PAT from a numbered pool of secrets. Secrets
4+
are passed as environment variables SECRET_0 through SECRET_9
5+
by the calling workflow step.
6+
7+
inputs:
8+
random-seed:
9+
description: 'A seed number to use for the random PAT selection, for deterministic selection if needed.'
10+
required: false
11+
default: ''
12+
13+
outputs:
14+
copilot_pat_number:
15+
description: 'The 0-9 secret number selected from the pool of specified secrets'
16+
value: ${{ steps.select-pat-number.outputs.copilot_pat_number }}
17+
18+
runs:
19+
using: composite
20+
steps:
21+
- id: select-pat-number
22+
shell: bash
23+
env:
24+
RANDOM_SEED: ${{ inputs.random-seed }}
25+
run: |
26+
# Collect all secret numbers with non-empty values from SECRET_0..SECRET_9
27+
PAT_NUMBERS=()
28+
for i in $(seq 0 9); do
29+
var="SECRET_${i}"
30+
val="${!var}"
31+
if [ -n "$val" ]; then
32+
PAT_NUMBERS+=(${i})
33+
fi
34+
done
35+
36+
# If none of the secrets in the pool have values, then emit a warning and do not
37+
# set an output value. The consumer can then fall back to using COPILOT_GITHUB_TOKEN.
38+
if [ ${#PAT_NUMBERS[@]} -eq 0 ]; then
39+
echo "::warning::None of the specified secrets had values (checked SECRET_0 through SECRET_9)"
40+
exit 0
41+
fi
42+
43+
# Select a random index using the seed if specified
44+
if [ -n "$RANDOM_SEED" ]; then
45+
RANDOM=$RANDOM_SEED
46+
fi
47+
48+
PAT_INDEX=$(( RANDOM % ${#PAT_NUMBERS[@]} ))
49+
PAT_NUMBER="${PAT_NUMBERS[$PAT_INDEX]}"
50+
echo "Selected token ${PAT_NUMBER} (index: ${PAT_INDEX}; pool size: ${#PAT_NUMBERS[@]})"
51+
52+
# Set the PAT number as the output
53+
echo "copilot_pat_number=${PAT_NUMBER}" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)