fix(ci): restore changesets version PR flow#462
Conversation
|
Wondering what really moved? Review this PR in Change Stack to inspect semantic changes, definitions, and references. 📝 WalkthroughWalkthroughThe PR refactors release automation: workflow concurrency/permissions and checkout behavior are updated; changeset-based versioning/publishing replaces custom prepare/detect/commit scripts; a new Node script builds and publishes annotated GitHub releases with generated changelogs. ChangesRelease Automation Refactor
Sequence DiagramsequenceDiagram
participant GitHubActions
participant ChangesetsAction
participant ReleaseScript
participant GH_CLI
GitHubActions->>ChangesetsAction: run pnpm changeset:version & publish (with npm tag)
ChangesetsAction->>GitHubActions: outputs published, dist-tag info
GitHubActions->>ReleaseScript: invoke scripts/create-github-release.mjs (prerelease/latest flags)
ReleaseScript->>GH_CLI: gh release create --notes-file --prerelease/--latest
ReleaseScript->>GitHubActions: push annotated tag (if created)
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 22-31: The checkout step currently sets persist-credentials: true
while the job has contents/id-token/pull-requests write permissions, so change
the actions/checkout@... step to set persist-credentials: false to avoid
exposing write-capable creds to intermediate steps, and then remove global
exposure by explicitly injecting the GITHUB_TOKEN env only into the
changesets/action step (i.e., add env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
to the specific changesets/action step) so write credentials are scoped to that
release step; reference the actions/checkout use block and the changesets/action
step when making these changes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4afe44a2-e4b7-4ff4-850d-a8c4b2cf85c7
📒 Files selected for processing (4)
.github/workflows/release.ymlpackage.jsonscripts/release-commit-and-push.mjsscripts/release-detect-changes.mjs
💤 Files with no reviewable changes (3)
- scripts/release-detect-changes.mjs
- package.json
- scripts/release-commit-and-push.mjs
| permissions: | ||
| contents: write | ||
| id-token: write | ||
| pull-requests: read | ||
| statuses: read | ||
| pull-requests: write | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | ||
| with: | ||
| fetch-depth: 0 | ||
| persist-credentials: false | ||
| persist-credentials: true # changesets/action pushes version PR commits |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Does actions/checkout with persist-credentials: true store the workflow token in local git config for later steps, and what do the changesets/action docs recommend when only the final push step needs git authentication?
💡 Result:
The actions/checkout action, with persist-credentials set to true (the default), provides the workflow token (or a specified PAT/SSH key) to git so that later steps in the same job can perform authenticated git operations [1][2]. Regarding how this is implemented: - In older versions (v5 and earlier), the authentication token was directly stored in the local.git/config file [3][4]. - In v6 and later, the action was improved to store credentials in a separate, more secure file under $RUNNER_TEMP rather than directly in.git/config [5]. Git is configured to point to this secure file, maintaining compatibility with git commands like push and fetch without requiring changes to your workflow scripts [5]. Recommendation for workflows where only a final step needs git authentication: If you are concerned about security or want to follow the principle of least privilege, you can set persist-credentials: false to opt-out of this behavior [1][6]. If you do this, the git configuration will not be automatically populated with the workflow token. When you reach the step that requires authentication (e.g., a git push), you will need to manually authenticate the git client using the token or secret, typically by providing the credentials in the environment or using a command like git config to inject them only at the necessary time [1][2]. Many users prefer this approach to avoid having active credentials available throughout the entire job's duration [3][7].
Citations:
- 1: https://github.com/actions/checkout
- 2: https://github.com/actions/checkout/blob/72f2cec99f417b1a1c5e2e88945068983b7965f9/action.yml
- 3: Remove
persist-credentialsor change the default tofalseactions/checkout#485 - 4: Persist credentials shouldn't persist
GITHUB_TOKENwhen usingssh-keyactions/checkout#704 - 5: https://github.com/actions/checkout/tree/v6.0.2?tab=readme-ov-file
- 6: https://github.com/actions/checkout/?tab=readme-ov-file
- 7: [security] Escalate concerning default
persist-credentials=trueplease actions/checkout#2312
🏁 Script executed:
cat -n .github/workflows/release.yml | head -60Repository: TanStack/cli
Length of output: 2111
🌐 Web query:
changesets/action github authentication requirements persist-credentials false
💡 Result:
When using persist-credentials: false with the actions/checkout step in a workflow that includes changesets/action, you must manually provide the necessary GitHub authentication token to the changesets/action step [1][2][3]. By default, actions/checkout automatically persists a GitHub token in the local git configuration to allow authenticated git operations [4]. Setting persist-credentials: false disables this behavior, which is often done for security reasons or to use a specific Personal Access Token (PAT) that has elevated permissions (e.g., to trigger further workflow actions that the default GITHUB_TOKEN would ignore) [5][1][2]. If you disable credential persistence, changesets/action will fail to push changes or create release pull requests unless it has access to a valid authentication token [1][2][6]. You must explicitly provide this token by configuring the GITHUB_TOKEN environment variable within the changesets/action step, typically using a secret [1][2][3]. Example configuration: - name: Checkout Repo uses: actions/checkout@v4 with: persist-credentials: false - name: Run Changesets uses: changesets/action@v1 env: GITHUB_TOKEN: ${{ secrets.YOUR_PAT_SECRET }} Recent updates to changesets/action have introduced an explicit github-token input (defaulting to the GitHub-provided token), but if you have explicitly disabled persistence in your checkout step, ensuring that an appropriate token (like a PAT) is passed via the environment variable or input remains a critical requirement for successful git operations [7]. Additionally, ensure your workflow job has the necessary permissions (such as contents: write) to perform git pushes [1][8].
Citations:
- 1: Pushing to repo fails... possibly related to publishing to GPR? changesets/action#106
- 2: updating Version Packages PR uses GITHUB_TOKEN instead of PAT changesets/action#70
- 3: https://github.com/hyperlane-xyz/hyperlane-monorepo/blob/main/.github/workflows/release.yml
- 4: https://github.com/actions/checkout
- 5: Setting GitHub credentials unnecessary? changesets/action#22
- 6: claude-code-action fails when actions/checkout uses persist-credentials: false anthropics/claude-code-action#1236
- 7: changesets/action@935fe87
- 8: https://github.com/changesets/changesets/blob/main/.github/workflows/ci.yml
Scope the write-capable git credentials to the release step.
Line 31 persists the job token before setup, build, and test commands run. Combined with the write permissions on lines 23–25, any compromised install or test script gains repo-write access throughout the entire job. Although actions/checkout v6.0.2 stores credentials in a secure file rather than .git/config, the token remains available to all intermediate steps; set persist-credentials: false and explicitly provide the token only to the changesets/action step via the GITHUB_TOKEN environment variable.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/release.yml around lines 22 - 31, The checkout step
currently sets persist-credentials: true while the job has
contents/id-token/pull-requests write permissions, so change the
actions/checkout@... step to set persist-credentials: false to avoid exposing
write-capable creds to intermediate steps, and then remove global exposure by
explicitly injecting the GITHUB_TOKEN env only into the changesets/action step
(i.e., add env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} to the specific
changesets/action step) so write credentials are scoped to that release step;
reference the actions/checkout use block and the changesets/action step when
making these changes.
b574b4c to
e49fe35
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/create-github-release.mjs`:
- Around line 17-19: The fetch call building the GitHub search URL uses the raw
email variable and can produce invalid/unescaped query strings; update the URL
construction in the fetch that assigns to res so the email is URL-encoded (e.g.,
use encodeURIComponent on the email variable before inserting into `q=`) to
ensure reserved characters are escaped and the search works reliably, keeping
the existing headers/ghToken logic unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2e0b3395-afb3-42e4-84e7-87f0eee71ce0
📒 Files selected for processing (6)
.github/workflows/release.ymlpackage.jsonscripts/create-github-release.mjsscripts/prepare-release.mjsscripts/release-commit-and-push.mjsscripts/release-detect-changes.mjs
💤 Files with no reviewable changes (4)
- scripts/release-detect-changes.mjs
- scripts/prepare-release.mjs
- scripts/release-commit-and-push.mjs
- package.json
| const res = await fetch(`https://api.github.com/search/users?q=${email}`, { | ||
| headers: { Authorization: `token ${ghToken}` }, | ||
| }) |
There was a problem hiding this comment.
URL-encode the email search query.
This request builds q=... from the raw email string. Reserved URI characters are not escaped in that form, and MDN explicitly recommends encoding dynamic URL components with encodeURIComponent() instead of inserting them directly. That can make fallback attribution miss valid authors. (developer.mozilla.org)
💡 Proposed fix
- const res = await fetch(`https://api.github.com/search/users?q=${email}`, {
+ const q = new URLSearchParams({ q: email })
+ const res = await fetch(`https://api.github.com/search/users?${q}`, {
headers: { Authorization: `token ${ghToken}` },
})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const res = await fetch(`https://api.github.com/search/users?q=${email}`, { | |
| headers: { Authorization: `token ${ghToken}` }, | |
| }) | |
| const q = new URLSearchParams({ q: email }) | |
| const res = await fetch(`https://api.github.com/search/users?${q}`, { | |
| headers: { Authorization: `token ${ghToken}` }, | |
| }) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@scripts/create-github-release.mjs` around lines 17 - 19, The fetch call
building the GitHub search URL uses the raw email variable and can produce
invalid/unescaped query strings; update the URL construction in the fetch that
assigns to res so the email is URL-encoded (e.g., use encodeURIComponent on the
email variable before inserting into `q=`) to ensure reserved characters are
escaped and the search works reliably, keeping the existing headers/ghToken
logic unchanged.
Switches the release workflow back to changesets/action so pushes with pending changesets create or update a version PR, and merging that PR publishes packages. Removes the direct git push helper path that failed because checkout credentials were disabled.
Also brings the release pipeline closer to Router/Query parity:
Validation:
Summary by CodeRabbit
Chores
New Features