ci(actions): update workflows for Node 24 - #39
Conversation
📝 WalkthroughWalkthroughPinned and upgraded core GitHub Actions across CI, release, and docs workflows; bumped Node.js from 20→24 for web/build/docs jobs; replaced GitHub App token actions with inline JWT/token-exchange scripts for dispatch/homebrew flows; replaced PR-title action with inline validator; updated CHANGELOG and tests. ChangesGitHub Actions and CI Infrastructure Updates
Sequence Diagram (high-level token exchange flow): sequenceDiagram
participant Workflow
participant JWT as JWT Generator (bash)
participant GitHubAPI
participant Repo as Target Repo
Workflow->>JWT: read APP_ID & PRIVATE_KEY, build JWT
JWT->>GitHubAPI: POST /app/installations (auth: JWT) -> get installation id
JWT->>GitHubAPI: POST /app/installations/{id}/access_tokens -> get installation token
GitHubAPI->>Workflow: return installation token (masked / set in GITHUB_OUTPUT)
Workflow->>Repo: POST /repos/${DISPATCH_OWNER}/${DISPATCH_REPO}/dispatches (Authorization: token)
🎯 4 (Complex) | ⏱️ ~45 minutes Possibly Related PRs
🚥 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: 17
🤖 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/ci-pythinker-cli.yml:
- Line 34: Pin every third-party GitHub Action referenced in the workflow to its
immutable 40-character commit SHA instead of mutable tags/branches: locate each
uses: entry such as actions/checkout@v6, actions/setup-node@...,
actions/cache@..., docker/login-action@..., docker/build-push-action@...,
Determinatesystems/nix-installer-action@main, actions/upload-artifact@...,
actions/setup-python@..., etc., and replace the tag/branch with the
corresponding full commit SHA from the action’s repository; commit the updated
workflow and verify the workflow runs using those SHAs.
In @.github/workflows/ci-pythinker-core.yml:
- Line 31: The workflow uses tag-based actions (e.g. the `uses` entries
`actions/checkout@v6`, `actions/setup-python@v6`, `astral-sh/setup-uv@v8.1.0`,
and `actions/upload-artifact@v7`) which are mutable; replace each tag with the
corresponding immutable full commit SHA for that action (update the `uses:`
values to the action@<full-commit-sha> form) so CI references immutable versions
and avoids future surprises.
In @.github/workflows/ci-pythinker-host.yml:
- Line 54: Replace mutable action tags with immutable commit SHAs: update the
three uses entries currently specified as actions/checkout@v6,
actions/setup-python@v6, and astral-sh/setup-uv@v8.1.0 to point at the
corresponding full commit SHA for each action; locate those uses lines in the CI
workflow and substitute the tag with the exact commit SHA for the release you
want to pin (ensuring you copy the SHA from the official action repo/tags page)
so the workflow references a fixed commit rather than a movable tag.
In @.github/workflows/ci-pythinker-sdk.yml:
- Line 31: The workflow uses mutable tag refs (e.g., actions/checkout@v6,
actions/setup-python@v6, astral-sh/setup-uv@v8.1.0, actions/upload-artifact@v7)
which must be pinned to immutable full commit SHAs; for each occurrence replace
the tag ref with the corresponding commit SHA for that action (obtain via the
action's GitHub repo — e.g., git ls-remote or the release commit on
github.com/actions/checkout — and substitute actions/checkout@<full-sha> etc.),
update all refs listed in the review (lines referencing actions/checkout,
actions/setup-python, astral-sh/setup-uv, actions/upload-artifact) so the
workflow uses the exact commit SHAs.
In @.github/workflows/homebrew-tap.yml:
- Line 28: Replace the mutable action tags used in the workflow—specifically the
uses entries "actions/checkout@v6" and "actions/setup-python@v6"—with their
corresponding immutable full commit SHAs; locate the canonical commit SHAs on
the actions' GitHub repositories (or the marketplace), update the two uses lines
to the form "actions/checkout@<commit-sha>" and
"actions/setup-python@<commit-sha>", and keep the rest of the step configuration
unchanged so the workflow behavior remains identical while ensuring
immutability.
In @.github/workflows/linux-installer.yml:
- Line 36: The workflow uses floating tags for third-party actions
(actions/checkout@v6, docker/setup-qemu-action@v4, actions/setup-python@v6,
actions/upload-artifact@v7, softprops/action-gh-release@v3); replace each
`uses:` occurrence with the corresponding action pinned to its full commit SHA
(e.g., `actions/checkout@<full-commit-sha>`) so the workflow is immutable and
reproducible, updating the five referenced actions and verifying the SHAs are
correct and current in the same YAML where those `uses:` lines appear.
In @.github/workflows/pr-title-checker.yml:
- Around line 7-11: Add inline explanatory comments to the permissions block
explaining why each permission is needed: annotate the "contents: read" entry to
state it's used for reading repo metadata and workflow files, annotate "issues:
write" to state it's required for creating/updating issue comments or labels
during CI, and annotate "pull-requests: read" to state it's used for reading PR
metadata (title/body) for the title-checker job; keep comments short, one-line,
and adjacent to each permission key so future maintainers understand the intent.
- Around line 7-11: The workflow-level permission "issues: write" is overly
broad; remove "issues: write" from the top-level permissions block and instead
add it only to the check job's permissions (the job named "check") by creating
or updating jobs.check.permissions to include "issues: write" while keeping
other top-level permissions (contents: read, pull-requests: read) intact.
- Around line 17-18: The Checkout repository step using "uses:
actions/checkout@v6" is missing persist-credentials: false; update that step to
include persist-credentials: false (as a key under the same step) so the
GITHUB_TOKEN is not written into .git/config and cannot be leaked to later
steps.
- Around line 25-40: Add explicit checks and error handling around reading and
parsing .github/pr-title-checker-config.json before using variables regexp,
label, color, and failure: verify the file exists (exit with a clear error if
missing), run jq commands with status checks and capture their output or errors
(fail with a descriptive message if jq returns non-zero or yields "null"/empty),
and only proceed to use regexp/label/color/failure after confirming they are
non-empty; update the run block so failures print a clear error (using echo
"::error::…") and exit non-zero instead of allowing opaque failures from jq or
missing file.
- Line 18: Replace the floating action reference in the checkout step by pinning
actions/checkout to the given full commit SHA: change the uses entry from
"actions/checkout@v6" to
"actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" in the workflow, and
optionally add "persist-credentials: false" to that checkout step if the job
does not require authenticated git operations to further harden the step.
In @.github/workflows/release-pythinker-cli.yml:
- Line 134: The workflow uses mutable action tags that should be pinned to
immutable commit SHAs; replace every occurrence of astral-sh/setup-uv@v8.1.0
(all instances) and softprops/action-gh-release@v3 with the corresponding full
commit SHA refs (e.g., astral-sh/setup-uv@<full-commit-sha> and
softprops/action-gh-release@<full-commit-sha>), ensuring you update all
occurrences consistently and verify the SHAs come from the official action
repos' commit history before committing.
In @.github/workflows/release-pythinker-core.yml:
- Line 55: Replace all mutable third-party action refs in the workflow with
immutable commit SHAs: find the uses entries astral-sh/setup-uv@v8.1.0,
actions/checkout@v6, actions/setup-python@v6, and
pypa/gh-action-pypi-publish@release/v1 and change each to the corresponding full
commit SHA (e.g., astral-sh/setup-uv@<full-sha>, actions/checkout@<full-sha>,
actions/setup-python@<full-sha>, pypa/gh-action-pypi-publish@<full-sha>); verify
each SHA points to the intended release tag in the upstream repo, update any
workflow references (both occurrences of actions/checkout and
actions/setup-python) consistently, and commit the updated workflow file.
In @.github/workflows/release-pythinker-host.yml:
- Line 55: The workflow uses a mutable tag for the GitHub Action
"astral-sh/setup-uv@v8.1.0"; replace that tag with the action's full commit SHA
(e.g., "astral-sh/setup-uv@<FULL_COMMIT_SHA>") so the run is pinned to an
immutable revision — update the `uses: astral-sh/setup-uv@v8.1.0` entry in the
workflow to `uses: astral-sh/setup-uv@<commit SHA>` (obtain the full SHA from
the action's repository commits) and commit the change.
In @.github/workflows/release-pythinker-sdk.yml:
- Line 55: Replace the mutable tag for the GitHub Action referenced by the line
"uses: astral-sh/setup-uv@v8.1.0" with a full immutable commit SHA (e.g., "uses:
astral-sh/setup-uv@<full-commit-sha>") so the workflow is pinned; locate the
"uses: astral-sh/setup-uv@v8.1.0" entry in the release workflow and update it to
reference the repository's exact commit SHA from the action's upstream repo.
In @.github/workflows/typos.yml:
- Line 13: Replace the mutable action tags with immutable commit SHAs: locate
the workflow entries that use the actions via the "uses: actions/checkout@v6"
and "uses: crate-ci/typos@v1.38.1" lines and update each to their corresponding
full commit SHA (e.g., "uses: actions/checkout@<full-commit-sha>" and "uses:
crate-ci/typos@<full-commit-sha>"); fetch the correct commit SHAs from the
respective GitHub action repositories' releases/tags pages or via git ls-remote,
then commit the updated workflow so the actions are pinned to those SHAs.
In @.github/workflows/windows-installer.yml:
- Line 92: Replace the mutable GitHub Action tag usages of
softprops/action-gh-release (the lines containing "uses:
softprops/action-gh-release@v3") with an immutable commit SHA: find each
occurrence (in the workflow steps that reference softprops/action-gh-release)
and change the reference from `@v3` to the specific full commit hash for the
desired release (e.g., @<commit-sha>), then update all three files
(.github/workflows/windows-installer.yml, linux-installer.yml,
release-pythinker-cli.yml) to use that same pinned SHA so the workflows are
stable.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 634f431e-fe5e-4287-8ec0-ee8fc41aa8db
📒 Files selected for processing (17)
.github/workflows/changelog-entry-required.yml.github/workflows/ci-docs.yml.github/workflows/ci-pythinker-cli.yml.github/workflows/ci-pythinker-core.yml.github/workflows/ci-pythinker-host.yml.github/workflows/ci-pythinker-sdk.yml.github/workflows/dispatch-pythinker-home-sync.yml.github/workflows/docs-pages.yml.github/workflows/homebrew-tap.yml.github/workflows/linux-installer.yml.github/workflows/pr-title-checker.yml.github/workflows/release-pythinker-cli.yml.github/workflows/release-pythinker-core.yml.github/workflows/release-pythinker-host.yml.github/workflows/release-pythinker-sdk.yml.github/workflows/typos.yml.github/workflows/windows-installer.yml
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 `@tests/test_release_update_pipeline.py`:
- Line 76: The test currently asserts a whitespace- and formatting-sensitive
string ('permissions:{contents:"write"}') in the workflow; change it to assert
the semantic intent instead by parsing the workflow YAML/JSON into a data
structure (e.g., using yaml.safe_load or json.loads) and then assert that the
permissions entry for the relevant job contains contents: "write" (or that
"write" appears in the permissions contents list/dict). Update the assertion in
tests/test_release_update_pipeline.py to inspect the parsed object (variable
name workflow) and check permissions include contents:"write" rather than
matching the exact minified string.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 8ffae882-5e2b-44d1-9656-23daf33bfe1d
📒 Files selected for processing (21)
.github/workflows/changelog-entry-required.yml.github/workflows/ci-docs.yml.github/workflows/ci-pythinker-cli.yml.github/workflows/ci-pythinker-core.yml.github/workflows/ci-pythinker-host.yml.github/workflows/ci-pythinker-sdk.yml.github/workflows/dispatch-pythinker-home-sync.yml.github/workflows/docs-pages.yml.github/workflows/homebrew-tap.yml.github/workflows/linux-installer.yml.github/workflows/pr-title-checker.yml.github/workflows/promote-release.yml.github/workflows/release-pythinker-cli.yml.github/workflows/release-pythinker-core.yml.github/workflows/release-pythinker-host.yml.github/workflows/release-pythinker-sdk.yml.github/workflows/translator.yml.github/workflows/typos.yml.github/workflows/windows-installer.ymlCHANGELOG.mdtests/test_release_update_pipeline.py
There was a problem hiding this comment.
♻️ Duplicate comments (1)
tests/test_release_update_pipeline.py (1)
76-76:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winMake the permissions assertion style-agnostic.
This regex still couples to inline-map YAML (
{...}) and quoted"write", so it can fail on valid block-style formatting.Suggested minimal hardening
- assert re.search(r"permissions\s*:\s*\{[^}]*contents\s*:\s*\"write\"", workflow) + assert re.search( + r"permissions\s*:\s*(?:\{[^}]*\bcontents\s*:\s*\"?write\"?[^}]*\}|\n(?:[ \t]+[^\n]+\n)*[ \t]+contents\s*:\s*\"?write\"?)", + workflow, + )As per coding guidelines, “When reviewing code, treat low-delta maintainability as a primary quality signal.”
🤖 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 `@tests/test_release_update_pipeline.py` at line 76, The permissions assertion in tests/test_release_update_pipeline.py tightly couples to inline-map YAML and quoted values; update the assert that checks the variable workflow so the regex matches both inline ({...}) and block-style YAML and accepts write with or without quotes. Locate the failing assertion (the assert referencing workflow) and replace its pattern with a more permissive one that (1) finds the permissions: key, (2) then searches for a nested contents: key under that section regardless of inline or block formatting, and (3) allows the value write to be quoted or unquoted.
🤖 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.
Duplicate comments:
In `@tests/test_release_update_pipeline.py`:
- Line 76: The permissions assertion in tests/test_release_update_pipeline.py
tightly couples to inline-map YAML and quoted values; update the assert that
checks the variable workflow so the regex matches both inline ({...}) and
block-style YAML and accepts write with or without quotes. Locate the failing
assertion (the assert referencing workflow) and replace its pattern with a more
permissive one that (1) finds the permissions: key, (2) then searches for a
nested contents: key under that section regardless of inline or block
formatting, and (3) allows the value write to be quoted or unquoted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: e88be165-595f-4064-bef6-aa659a8c2b28
📒 Files selected for processing (1)
tests/test_release_update_pipeline.py
Summary
Validation
actions/checkout@v6,actions/setup-node@v6, andactions/setup-python@v6action.ymlruntimeuv run pythonYAML parse for.github/workflows/*.ymluses:reference is a full 40-character SHAmake check-pythinker-codemake test-pythinker-codeuv run python -m pytest tests/test_release_update_pipeline.py -qCI failure fixed
Dispatch pythinker-home sync:[@octokit/auth-app] appId option is required. The workflow now mints the app installation token directly fromPYTHINKER_RELEASE_BOT_APP_ID/private key and fails with a clear configuration error if credentials are missing.Summary by CodeRabbit