Skip to content

ci(actions): update workflows for Node 24 - #39

Merged
elkaix merged 4 commits into
mainfrom
ci/update-node24-actions
Jun 1, 2026
Merged

ci(actions): update workflows for Node 24#39
elkaix merged 4 commits into
mainfrom
ci/update-node24-actions

Conversation

@elkaix

@elkaix elkaix commented May 31, 2026

Copy link
Copy Markdown
Member

Summary

  • update GitHub Actions workflows to Node 24-backed action releases and pin all workflow actions to immutable 40-character SHAs
  • switch workflow Node setup from 20 to 24
  • replace Node-based token minting for cross-repo dispatches with explicit GitHub App JWT/token minting via GitHub REST API
  • harden PR title validation with least-privilege permissions, pinned checkout, config validation, and no persisted checkout credentials

Validation

  • Context7 docs: verified latest/current Node 24 action lines for actions/checkout@v6, actions/setup-node@v6, and actions/setup-python@v6
  • Firecrawl: fetched GitHub Node 20 deprecation guidance confirming workflows should update to action versions that declare Node 24 instead of only forcing runtime
  • Repository metadata: verified pinned action SHAs map to the intended release tags and inspected each action.yml runtime
  • uv run python YAML parse for .github/workflows/*.yml
  • pinned-action check: every non-local workflow uses: reference is a full 40-character SHA
  • make check-pythinker-code
  • make test-pythinker-code
  • uv run python -m pytest tests/test_release_update_pipeline.py -q

CI failure fixed

  • Latest main failure was Dispatch pythinker-home sync: [@octokit/auth-app] appId option is required. The workflow now mints the app installation token directly from PYTHINKER_RELEASE_BOT_APP_ID/private key and fails with a clear configuration error if credentials are missing.

Summary by CodeRabbit

  • Chores
    • Updated CI/CD workflows to pin GitHub Action revisions, upgrade tooling, and run docs/builds on Node.js 24.
    • Replaced several GitHub App token steps with inline minting scripts and improved credential error messages and token handling.
  • Tests
    • Adjusted tests to reflect new dispatch token strategy and scoped permission checks.
  • Documentation
    • Enforced presence of a CHANGELOG entry for shipped-code PRs and updated the Unreleased notes.

@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Pinned 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.

Changes

GitHub Actions and CI Infrastructure Updates

Layer / File(s) Summary
Core action pinning and CI job upgrades
.github/workflows/changelog-entry-required.yml, .github/workflows/ci-docs.yml, .github/workflows/ci-pythinker-*.yml, .github/workflows/release-pythinker-*.yml, .github/workflows/typos.yml, .github/workflows/windows-installer.yml, .github/workflows/linux-installer.yml
Pinned/upgraded core actions (actions/checkout → v6 commit, actions/setup-python → v6 commit, astral-sh/setup-uv → v8.1.0 commit) across validation, test, build, and publish jobs.
Node.js runtime, cache, and artifact handling
.github/workflows/ci-docs.yml, .github/workflows/ci-pythinker-cli.yml, .github/workflows/ci-pythinker-core.yml, .github/workflows/ci-pythinker-sdk.yml, .github/workflows/docs-pages.yml, .github/workflows/release-pythinker-*.yml, .github/workflows/linux-installer.yml, .github/workflows/windows-installer.yml
Node.js updated from 20→24 in web/build/docs jobs; actions/cache, Pages upload/deploy, and artifact upload/download/release publisher actions upgraded to pinned revisions.
GitHub App token minting rewritten (inline)
.github/workflows/dispatch-pythinker-home-sync.yml, .github/workflows/promote-release.yml, .github/workflows/homebrew-tap.yml
Replaces actions/create-github-app-token with inline JWT construction and installation access token exchange, validates required App secrets, masks/outputs token, and errors loudly when token/secrets are missing or empty.
PR title validation replaced with inline script
.github/workflows/pr-title-checker.yml
Removes third-party action in favor of an inline Bash validator that reads regex/label config with jq, tests PR title, and manages label state via gh.
Changelog and tests
CHANGELOG.md, tests/test_release_update_pipeline.py
Add Unreleased entry describing these CI/release tooling changes; update tests to assert absence of actions/create-github-app-token, presence of scoped permissions:{contents:"write"}, required App ID/private key variables, and loud failure text for missing secrets.

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)
Loading

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly Related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows conventional commits format with 'ci' type and 'actions' scope, clearly describing the main change: updating workflows for Node 24.
Description check ✅ Passed The description includes a comprehensive summary, validation details, and CI fix explanation, but lacks the template sections (Related Issue link and Checklist). The core content is substantial and specific.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/update-node24-actions

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between f0c080b and 175581b.

📒 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

Comment thread .github/workflows/ci-pythinker-cli.yml Outdated
Comment thread .github/workflows/ci-pythinker-core.yml Outdated
Comment thread .github/workflows/ci-pythinker-host.yml Outdated
Comment thread .github/workflows/ci-pythinker-sdk.yml Outdated
Comment thread .github/workflows/homebrew-tap.yml Outdated
Comment thread .github/workflows/release-pythinker-core.yml Outdated
Comment thread .github/workflows/release-pythinker-host.yml Outdated
Comment thread .github/workflows/release-pythinker-sdk.yml Outdated
Comment thread .github/workflows/typos.yml Outdated
Comment thread .github/workflows/windows-installer.yml Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 175581b and 503c080.

📒 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.yml
  • CHANGELOG.md
  • tests/test_release_update_pipeline.py

Comment thread tests/test_release_update_pipeline.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
tests/test_release_update_pipeline.py (1)

76-76: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Make 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

📥 Commits

Reviewing files that changed from the base of the PR and between 503c080 and 755e806.

📒 Files selected for processing (1)
  • tests/test_release_update_pipeline.py

@elkaix
elkaix merged commit fb7fdbf into main Jun 1, 2026
45 checks passed
@elkaix
elkaix deleted the ci/update-node24-actions branch July 17, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant