Skip to content

ci: pin action SHAs to latest and fix devportal docs publishing#71

Merged
mrcointreau merged 1 commit into
mainfrom
ci/harden-workflows
May 28, 2026
Merged

ci: pin action SHAs to latest and fix devportal docs publishing#71
mrcointreau merged 1 commit into
mainfrom
ci/harden-workflows

Conversation

@mrcointreau
Copy link
Copy Markdown
Contributor

@mrcointreau mrcointreau commented May 25, 2026

Summary

This PR makes a few related CI/CD changes:

  1. Hardens the CI workflows by pinning all third-party GitHub Actions to immutable commit SHAs, bumping them to their latest versions, and tightening workflow permissions to least privilege.
  2. Fixes versioned DevPortal docs publishing so a devportal-docs.tar.gz asset is attached to each vX.Y.Z release, not only to the rolling docs-latest pre-release. This required switching the release pipeline to a GitHub App token and removing a [skip ci] directive.
  3. Keeps the DevPortal docs current by refreshing the rolling docs-latest build on every push to main.

Changes

CI security hardening

  • Pin all third-party actions to full commit SHAs (with # vX comments) instead of mutable tags, in cd.yaml, ci.yaml, gh-pages.yaml, publish-devportal-docs.yml, and the local composite action .github/actions/build-documentation/action.yml. First-party refs stay as-is per policy: the DevPortal action remains on @release/ak-v4, and the local ./.github/actions/build-documentation reference is unchanged (its internal actions are pinned).
  • Version bumps (each pinned to the corresponding SHA): actions/checkout v4 to v6, actions/setup-python v5 to v6, actions/setup-node v4 to v6, pnpm/action-setup v4 to v6, actions/upload-artifact v4 to v7, actions/upload-pages-artifact v3 to v5, and actions/deploy-pages v4 to v5.
  • Move actions off rolling branch refs to fixed, pinned releases: python-semantic-release from @master to v10.5.3, and pypa/gh-action-pypi-publish from @release/v1 to v1.14.0. Updates now come via manual bumps, or via Dependabot if the github-actions ecosystem is added to .github/dependabot.yml.
  • actions/create-github-app-token is added (see DevPortal section) and pinned at v3.
  • Tighten workflow permissions to least privilege:
    • cd.yaml: top-level reduced from contents: write + packages: read to contents: read. The release job keeps its own block (id-token: write, contents: write, packages: read), which is what it needs.
    • ci.yaml: add a top-level permissions: contents: read (it previously had none).
    • gh-pages.yaml: add a top-level permissions: contents: read. The publish job keeps contents: read + pages: write + id-token: write (job-level permissions replace the default, so the contents: read there is required, not redundant).
    • publish-devportal-docs.yml: top-level contents: write kept (single job that creates GitHub Releases).

DevPortal docs publishing

  • cd.yaml: switch the release pipeline from secrets.GITHUB_TOKEN to a GitHub App token (actions/create-github-app-token with BOT_ID / BOT_SK) for both the checkout and the python-semantic-release step. Tags pushed with GITHUB_TOKEN do not trigger downstream on: push: tags workflows, so the versioned devportal-docs.tar.gz was never built. App-token pushes do trigger them.
  • pyproject.toml: change the python-semantic-release commit_message from [skip ci] to skip-checks: true. [skip ci] on the release bump commit was suppressing the tag-push run of publish-devportal-docs.yml (the tag points to that commit), so no vX.Y.Z release ever had the tarball. skip-checks: true is not honored by GitHub Actions as a skip, so the tag push now fires the workflow and attaches the asset.
  • publish-devportal-docs.yml: replace the trigger (previously tags: ['v*'] only, with the publish action pointed at the now-deleted ci/update-publish-devportal-docs-workflow branch) with push: branches: [main] plus tags: ['v*'], and point the action at release/ak-v4. Also align Node to 24.x and normalize indentation. This refreshes the rolling docs-latest pre-release on every merge to main, while tag pushes attach devportal-docs.tar.gz to the corresponding version release.

Why

  • Pinning actions to SHAs protects the supply chain against tag-retargeting attacks, and bumping to latest keeps runtimes (Node 24) and features current. Each bump was checked against this repo's usage; none change how the actions are used here. All workflows run on GitHub-hosted ubuntu-latest, so the higher minimum runner versions that the Node 24 bumps require are satisfied automatically.
  • The DevPortal importer pulls each library's "Latest" docs from the docs-latest release, which is only refreshed by non-tag runs. The workflow previously triggered on a temporary feature branch and only on tags, so docs-latest was never refreshed from main. Triggering on main keeps it current.
  • A [skip ci] directive suppresses every workflow for that push, including the tag push, because the tag points to the bump commit. Combined with releasing via GITHUB_TOKEN (which never triggers downstream workflows), that is why no vX.Y.Z release had a devportal-docs.tar.gz. The App token and skip-checks: true together fix both halves.

Notes

  • The App-token steps assume the organisation's GitHub App (the BOT_ID / BOT_SK secrets, installed with contents: write) is available on this repository. If it is not, the app-token step will fail.
  • Producing the tarball is necessary but not sufficient for the docs to appear on the portal: this repository is not yet registered in the DevPortal import config, so a corresponding entry must be added there before the portal imports these docs.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the repository’s CI/CD workflows to improve supply-chain security and to correct/refresh DevPortal docs publishing behavior (both for rolling docs-latest and for versioned vX.Y.Z releases).

Changes:

  • Pin third-party GitHub Actions to immutable commit SHAs across workflows and the local composite action, and tighten default workflow permissions.
  • Adjust the release pipeline to use a GitHub App token (instead of GITHUB_TOKEN) so tag pushes can trigger downstream workflows, and update the semantic-release bump commit message to avoid [skip ci].
  • Update the DevPortal docs workflow triggers to run on main pushes (refresh docs-latest) and on v* tags (attach devportal-docs.tar.gz to versioned releases), and bump Node to 24.x in that workflow.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pyproject.toml Updates semantic-release bump commit message to avoid suppressing GitHub Actions runs.
.github/workflows/publish-devportal-docs.yml Runs docs publish on main and v* tags; pins actions; bumps Node to 24.x; targets stable DevPortal action ref.
.github/workflows/gh-pages.yaml Adds least-privilege default permissions and pins actions to SHAs.
.github/workflows/ci.yaml Adds least-privilege default permissions and pins actions to SHAs.
.github/workflows/cd.yaml Switches release automation to a GitHub App token; pins actions; tightens top-level permissions; pins publishing actions.
.github/actions/build-documentation/action.yml Pins internal composite action dependencies (setup-python/node/pnpm, upload-pages-artifact) to SHAs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mrcointreau mrcointreau merged commit a8f1703 into main May 28, 2026
4 checks passed
@mrcointreau mrcointreau deleted the ci/harden-workflows branch May 28, 2026 15:15
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.

3 participants