Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ Re-running replaces the draft for that version rather than adding a second,
so a failed or wrong attempt costs nothing.

If the notes open with an HTML comment instead of a paragraph, the summary
model was unavailable — `COPILOT_PAT` missing or expired, or the service
down. The draft is still good: write the paragraph by hand at review, or
delete the draft and re-run later.
model was unavailable — the account's Copilot entitlement, or the service
itself, down. The draft is still good: write the paragraph by hand at
review, or delete the draft and re-run later.

## Review

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/draft-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
permissions:
contents: write # Needed to create the release
actions: read # Needed to read artifacts from the CI run
copilot-requests: write # Needed for the release-notes summary

steps:
- name: Checkout repo
Expand All @@ -43,4 +44,3 @@ jobs:
uses: TaffarelJr/.actions/draft-release@v1
with:
version: ${{ inputs.version }}
copilot-pat: ${{ secrets.COPILOT_PAT }}
31 changes: 14 additions & 17 deletions docs/ReleaseProcess.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ how binaries are built, and how a release is cut and published.
- [3. Publish](#3-publish)
- [Release Notes vs. Changelog](#release-notes-vs-changelog)
- [Writing the Summary](#writing-the-summary)
- [Getting the token](#getting-the-token)
- [Authentication](#authentication)
- [What Each Layer Owns](#what-each-layer-owns)

## Principles
Expand Down Expand Up @@ -266,9 +266,10 @@ which changes the history it is trying to describe.
### Writing the Summary

The workflow always asks a model to draft the opening paragraph
from the generated changelog, using the `COPILOT_PAT` secret.
from the generated changelog, using the workflow's own `copilot-requests: write`
permission — no token to create or store.

It is never required. A missing or expired token, a service outage,
It is never required. A missing permission, a service outage,
a network error — all land in the same place:
the summary stays a placeholder and the release is still drafted.
A missing paragraph is not worth failing a release over.
Expand All @@ -278,23 +279,20 @@ simply has no opening paragraph, rather than a visible `TODO`.
Replace the whole comment with a paragraph or two to fill it in,
or delete the draft and re-run once the service is back.

#### Getting the token
#### Authentication

The summary runs through the [`actions/ai-inference`][aiAction] action,
which drives the Copilot CLI.
That authenticates an *account* holding a Copilot entitlement,
so it needs a personal access token — the built-in `GITHUB_TOKEN` will not do.
As of the built-in `GITHUB_TOKEN` support GitHub added for Actions,
that needs nothing beyond the `copilot-requests: write` permission
already declared on `draft-release.yml` — there is no secret to create,
store, or rotate.

1. `Settings` → `Developer settings` → `Personal access tokens`
2. Generate a **fine-grained** token with no repository access,
because it authenticates the account rather than a repo
3. [Add it as the `COPILOT_PAT` secret][actionsSecrets]

A personal account cannot share an Actions secret across repos —
that is an organization feature — so the secret is per-repo.
`New-Repo.ps1` sets it when creating a repo,
reading the value from the `COPILOT_PAT` environment variable
so there is nothing to paste in.
This still depends on the repo's owner having an active Copilot
entitlement. On an organization-owned repo, that also needs the
"Allow use of Copilot CLI billed to the organization" policy enabled;
the equivalent for a personal-account repo has not been exercised here
yet, so treat that combination as unverified until a real run confirms it.

## What Each Layer Owns

Expand Down Expand Up @@ -331,7 +329,6 @@ Everything else works without modification.
<!-- GitHub URIs (alphabetical) -->

[actionsRepo]: https://github.com/TaffarelJr/.actions
[actionsSecrets]: https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions
[aiAction]: https://github.com/actions/ai-inference

<!-- Public URIs (alphabetical) -->
Expand Down
22 changes: 4 additions & 18 deletions scripts/New-Repo.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@

Every value is prompted for - there are no command-line parameters to
supply instead, so a template layer can always add its own prompt but can
never add a parameter to this inherited script. The three secret tokens
never add a parameter to this inherited script. The two secret tokens
are the one exception: each is read from its environment variable first
(CODECOV_TOKEN, COPILOT_PAT, TEMPLATE_SYNC_PAT), so setting one up is a
one-time task rather than something typed in on every run.
(CODECOV_TOKEN, TEMPLATE_SYNC_PAT), so setting one up is a one-time task
rather than something typed in on every run.

Idempotent & resumable: re-running verifies what's already done
and only fills gaps. It never overwrites post-scaffold changes.

.EXAMPLE
./scripts/New-Repo.ps1
Prompts for everything - Kind, Name, Visibility, Description, Homepage,
Topics, and the three tokens (skipped for any already set as an
Topics, and the two tokens (skipped for any already set as an
environment variable).
#>

Expand Down Expand Up @@ -155,13 +155,6 @@ try {
-Hint "Codecov token at https://app.codecov.io/account/gh/$owner/org-upload-token" `
-Secret

$CopilotToken = Resolve-Input -Name CopilotToken `
-Prompt 'COPILOT_PAT value (blank to skip)' `
-EnvVar 'COPILOT_PAT' `
-Hint 'Copilot PAT at https://github.com/settings/personal-access-tokens', `
'Drafts the release-notes summary; without it the notes get a placeholder' `
-Secret

$TemplateSyncToken = Resolve-Input -Name TemplateSyncToken `
-Prompt 'TEMPLATE_SYNC_PAT value (blank to skip)' `
-EnvVar 'TEMPLATE_SYNC_PAT' `
Expand Down Expand Up @@ -204,13 +197,6 @@ try {
Set-RepoVariable -OwnerRepo $ownerRepo -Name TEMPLATE_SYNC_STRATEGY `
-Value $(if ($Kind -eq 'Code') { 'merge' } else { 'rebase' })

if ($CopilotToken) {
Set-RepoSecret -OwnerRepo $ownerRepo -Name COPILOT_PAT -Token $CopilotToken
}
else {
Write-Skip 'COPILOT_PAT not provided - release summaries stay manual'
}

# Sync still runs without this, but a PR opened with the default token cannot
# trigger CI, so a required status check would never report and the PR would
# never become mergeable.
Expand Down
4 changes: 2 additions & 2 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ with a default where one makes sense (press ENTER to take it),
and a confirmation before anything is created.
A bad answer is explained and asked again.

The one exception is the three secret tokens.
The one exception is the two secret tokens.
Each is read from the **environment variable of the same name** first —
`CODECOV_TOKEN`, `COPILOT_PAT`, `TEMPLATE_SYNC_PAT` —
`CODECOV_TOKEN`, `TEMPLATE_SYNC_PAT` —
and only prompted for when that is unset.
Set them once as user environment variables and they are never asked for again.
Leave one blank to skip it; the run says what that costs.
Expand Down