CI: Protect manual package publishing workflows - #34733
Conversation
There was a problem hiding this comment.
Pull request overview
This PR tightens protections around manual publishing/deployment workflows by introducing explicit GitHub Actions permissions and adding environment-gated approval steps for sensitive operations (package publishing, storybook cleanup, demos deployment).
Changes:
- Added explicit
permissionsblocks to reduce default token scope and introduced environment protections for deploy/publish jobs. - Added manual-approval “gate” jobs (via protected environments) for storybook cleanup and package publishing/scheduler manual runs.
- Refactored the packages publishing scheduler to call the publishing workflow via
workflow_calland added abranchinput to publish from specific branches.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/publish-demos.yml | Restricts default token permissions; adds environment + job-level permissions for gh-pages deployment. |
| .github/workflows/pr-storybook-deploy.yml | Associates cleanup/removal job with the Storybook environment + deployment URL. |
| .github/workflows/pr-storybook-cleanup.yml | Adds an environment-gated approval job for manual cleanup runs and wires it into the cleanup job. |
| .github/workflows/packages_publishing.yml | Adds workflow_call support + branch selection and introduces an environment-gated approval job before publishing. |
| .github/workflows/packages_publishing_scheduler.yml | Adds an environment-gated approval job for manual dispatch and switches to calling the reusable publishing workflow. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (2)
.github/workflows/packages_publishing.yml:179
- If workflow-level permissions are reduced (recommended), the
publishjob should explicitly requestpackages: write(and keepcontents: readfor checkout) since it performspnpm publishto GitHub Packages.
publish:
name: Publish package
runs-on: ubuntu-slim
needs: [build, approve-package-publishing]
if: ${{ always() && !cancelled() && needs.build.result == 'success' && (needs.approve-package-publishing.result == 'success' || needs.approve-package-publishing.result == 'skipped') }}
.github/workflows/packages_publishing.yml:35
- Workflow-level
packages: writegrants write access to GitHub Packages for all jobs (including build/notify), which increases blast radius if any step or action is compromised. Consider defaulting topackages: readand grantingpackages: writeonly on thepublishjob that actually pushes packages.
This issue also appears on line 175 of the same file.
permissions:
contents: read
packages: write
…b for package publishing
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
.github/workflows/packages_publishing.yml:47
- The approval gate condition uses
contains(github.workflow_ref, '/.github/workflows/packages_publishing_scheduler.yml@'), butgithub.workflow_refpoints to the workflow being executed (this file), not the caller workflow. That substring will never match, so the extra clause is ineffective and makes the protection logic harder to reason about.
Consider basing the condition purely on how the workflow was invoked (dispatch vs reusable call) and the requested tag.
approve-package-publishing:
name: Approve package publishing
if: ${{ inputs.tag == 'stable' || (github.event_name == 'workflow_dispatch' && !contains(github.workflow_ref, '/.github/workflows/packages_publishing_scheduler.yml@')) }}
runs-on: ubuntu-latest
a2685f8
| steps: | ||
| - name: Get sources | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| ref: ${{ inputs.branch || github.ref }} |
There was a problem hiding this comment.
Tested manually: skipped job will not re-run.
No description provided.