ci: align release-plz with the standard fg-labs publish workflow#35
ci: align release-plz with the standard fg-labs publish workflow#35nh13 wants to merge 1 commit into
Conversation
|
@coderabbitai review |
📝 WalkthroughWalkthroughReplaces ChangesRelease Automation Overhaul
Sequence Diagram(s)sequenceDiagram
participant Event as main push event
participant ReleasePR as release-pr job
participant Publish as publish job
participant ReleaseAction as release-plz/action
participant CargoMeta as cargo metadata
participant CratesIO as crates.io API
participant CargoPublish as cargo publish
participant GitOps as git & gh release
Event->>ReleasePR: trigger on main push
ReleasePR->>ReleaseAction: GitHub App token + release-pr command
ReleaseAction-->>Event: PR with version/changelog
Event->>Publish: trigger on main push
Publish->>CargoMeta: extract local version
CargoMeta-->>Publish: local version
Publish->>CratesIO: fetch current max version
CratesIO-->>Publish: published version
Publish->>CargoPublish: publish if versions differ
CargoPublish-->>Publish: published flag
Publish->>GitOps: create tag and GitHub Release
GitOps-->>Event: idempotent tag/release
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
🧹 Nitpick comments (4)
.github/workflows/publish.yml (4)
92-93: 💤 Low valueGate release creation on
published == 'true'instead ofversion != ''.The current condition runs the release-creation step on every push, even when no publish occurred. While the idempotent checks skip duplicate work, conditioning on
published == 'true'makes the intent clearer and avoids unnecessary API calls.Suggested change
- name: Create GitHub release - if: steps.publish.outputs.version != '' + if: steps.publish.outputs.published == 'true' env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}🤖 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/publish.yml around lines 92 - 93, The "Create GitHub release" step currently gates its execution on steps.publish.outputs.version not being empty, which causes the step to run even when no actual publish occurred. Replace the if condition from steps.publish.outputs.version != '' to steps.publish.outputs.published == 'true' to make the intent explicit and prevent unnecessary API calls when no publish has taken place.
96-99: 💤 Low valueUse environment variable indirection for
versionto avoid template expansion in shell.While Cargo enforces semver format (limiting injection risk), passing workflow outputs through
env:rather than direct template expansion in the script is cleaner and follows defense-in-depth.Suggested change
- name: Create GitHub release if: steps.publish.outputs.version != '' env: GITHUB_TOKEN: ${{ steps.app-token.outputs.token }} + VERSION: ${{ steps.publish.outputs.version }} run: | set -euo pipefail - VERSION="${{ steps.publish.outputs.version }}" TAG="v${VERSION}"🤖 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/publish.yml around lines 96 - 99, Move the VERSION variable assignment from the inline shell script to the workflow's env section to avoid direct template expansion in the shell. Define VERSION as an environment variable in the `env:` section using the workflow output from steps.publish.outputs.version, then reference it directly as an environment variable in the shell script instead of using template expansion syntax. This provides better separation of concerns and follows defense-in-depth practices.Source: Linters/SAST tools
3-5: ⚡ Quick winMove permissions to job level for least-privilege.
Workflow-level
pull-requests: writeandcontents: writegrant these permissions to all jobs. Since thepublishjob already declares its own permissions block (lines 44-46), consider movingpull-requests: writedown to therelease-prjob only. This limits each job's token to only the scopes it actually needs.Suggested change
name: Manage Release PRs and Publish Crates -permissions: - pull-requests: write - contents: write - on: push: branches: @@ -17,6 +14,9 @@ concurrency: jobs: release-pr: runs-on: ubuntu-latest + permissions: + pull-requests: write + contents: read if: ${{ github.repository_owner == 'fg-labs' }}🤖 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/publish.yml around lines 3 - 5, The workflow-level permissions at the top of the file grant pull-requests and contents write access to all jobs, violating the principle of least privilege. Since the publish job already declares its own permissions block at lines 44-46, move the pull-requests write permission from the workflow-level permissions block (lines 3-5) down to the release-pr job level only. Ensure each job declares exactly the permissions it needs by reviewing what tokens each job actually uses and adjusting the permission blocks accordingly.Source: Linters/SAST tools
27-31: ⚡ Quick winAdd
persist-credentials: falseto checkout steps.When passing a custom token to checkout, the credential is stored in git config and remains available to later steps or artifact uploads. Setting
persist-credentials: falseremoves the credential after checkout, limiting exposure.Suggested change
- name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 token: ${{ steps.app-token.outputs.token }} + persist-credentials: falseApply the same change to the checkout step in the
publishjob (lines 54-58).🤖 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/publish.yml around lines 27 - 31, The checkout step in the workflow uses a custom token from the app-token output but does not set persist-credentials to false, which leaves the credential stored in git config and available to later steps. Add persist-credentials: false to the with section of the checkout step (which uses actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd) to ensure the credential is removed after checkout, limiting exposure to subsequent steps or artifact uploads.Source: Linters/SAST tools
🤖 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.
Nitpick comments:
In @.github/workflows/publish.yml:
- Around line 92-93: The "Create GitHub release" step currently gates its
execution on steps.publish.outputs.version not being empty, which causes the
step to run even when no actual publish occurred. Replace the if condition from
steps.publish.outputs.version != '' to steps.publish.outputs.published == 'true'
to make the intent explicit and prevent unnecessary API calls when no publish
has taken place.
- Around line 96-99: Move the VERSION variable assignment from the inline shell
script to the workflow's env section to avoid direct template expansion in the
shell. Define VERSION as an environment variable in the `env:` section using the
workflow output from steps.publish.outputs.version, then reference it directly
as an environment variable in the shell script instead of using template
expansion syntax. This provides better separation of concerns and follows
defense-in-depth practices.
- Around line 3-5: The workflow-level permissions at the top of the file grant
pull-requests and contents write access to all jobs, violating the principle of
least privilege. Since the publish job already declares its own permissions
block at lines 44-46, move the pull-requests write permission from the
workflow-level permissions block (lines 3-5) down to the release-pr job level
only. Ensure each job declares exactly the permissions it needs by reviewing
what tokens each job actually uses and adjusting the permission blocks
accordingly.
- Around line 27-31: The checkout step in the workflow uses a custom token from
the app-token output but does not set persist-credentials to false, which leaves
the credential stored in git config and available to later steps. Add
persist-credentials: false to the with section of the checkout step (which uses
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd) to ensure the
credential is removed after checkout, limiting exposure to subsequent steps or
artifact uploads.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c1f4b9b1-5104-4a1d-821b-43d400f4eed7
📒 Files selected for processing (4)
.github/workflows/publish.yml.github/workflows/release-plz.ymlREADME.mdrelease-plz.toml
💤 Files with no reviewable changes (1)
- .github/workflows/release-plz.yml
Replace the upstream-style `release-plz.yml` (which ran release-plz's `release` command with the default `GITHUB_TOKEN`) with the canonical `publish.yml` used across the other fg-labs/fulcrumgenomics Rust crates. The new workflow splits work into two jobs: - `release-pr`: release-plz opens/updates the version-bump + changelog PR. - `publish`: on merge, publishes to crates.io via Trusted Publishing (OIDC) and tags + creates the GitHub release idempotently. Both jobs authenticate with the `FG_LABS_BOT` GitHub App token instead of the default `GITHUB_TOKEN`, so the release PR and tags can trigger other workflows. `release-plz.toml` now delegates publishing, tagging, and GitHub releases to the `publish` job (`publish`/`git_tag_enable`/`git_release_enable` are disabled), enables `cargo update` and a `release` PR label, and keeps `semver_check` on (redskull is already past v0.1.0). The existing "Keep a Changelog" format is retained.
d27dbaf to
622abcb
Compare
|
Addressed the CodeRabbit nitpicks on
Two suggestions intentionally not applied:
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
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/publish.yml:
- Around line 23-28: The GitHub App token generation steps using
`actions/create-github-app-token` are not constraining token scopes with
`permission-*` inputs, causing tokens to inherit the full app installation's
repo permission set. This creates unnecessary security risk. Add appropriate
`permission-*` input parameters to both token generation steps (at lines 23-28
and lines 53-58) to scope each token to only the minimum permissions required
for its respective job's downstream steps, reducing the blast radius if a step
is compromised.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9675ee2a-8872-4348-a453-3f577b162ce6
📒 Files selected for processing (4)
.github/workflows/publish.yml.github/workflows/release-plz.ymlREADME.mdrelease-plz.toml
💤 Files with no reviewable changes (1)
- .github/workflows/release-plz.yml
✅ Files skipped from review due to trivial changes (1)
- release-plz.toml
| - name: Generate app token | ||
| id: app-token | ||
| uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1 | ||
| with: | ||
| app-id: ${{ secrets.FG_LABS_BOT_APP_ID }} | ||
| private-key: ${{ secrets.FG_LABS_BOT_PRIVATE_KEY }} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Check if the workflow file exists and examine the token generation steps
cd /root/repo && cat -n .github/workflows/publish.ymlRepository: fg-labs/redskull
Length of output: 121
🌐 Web query:
actions/create-github-app-token v3.1.1 input parameters permission-contents permission-pull-requests
💡 Result:
In version 3.1.1 of the actions/create-github-app-token action, permissions are managed via optional input parameters prefixed with permission- [1][2]. These inputs allow you to explicitly define the scopes granted to the generated token, which is a recommended practice to follow the principle of least privilege [1][2]. Regarding your specific inquiries: - permission-contents: This input allows you to specify the 'contents' permission scope [3][4]. It accepts 'read' or 'write' as values [5][6]. When provided, it controls the token's ability to access repository contents, commits, and branches [6]. - permission-pull-requests: This input allows you to specify the 'pull-requests' permission scope [3][4]. It accepts 'read' or 'write' as values [5][6]. When provided, it controls the token's ability to interact with pull requests, reviews, and merges [6]. Key points regarding these permissions: - Default Behavior: If no permission-* inputs are specified, the generated token defaults to inheriting all permissions granted to the GitHub App's installation [1][2][6]. - Validation: You must ensure that any permission requested via these inputs has already been granted to the GitHub App installation [2]. Requesting a permission that the app does not possess will result in an error [5][2]. - Normalization: The action internally maps these input keys (e.g., permission-pull-requests) to the corresponding GitHub API permission format (e.g., pull_requests) [6].
Citations:
- 1: https://github.com/actions/create-github-app-token?tab=readme-ov-file
- 2: https://github.com/actions/create-github-app-token
- 3: https://github.com/actions/create-github-app-token/blob/93c1f04d6f14ea5b416e7a8dfd80446101c6adef/action.yml
- 4: https://github.com/actions/create-github-app-token/blob/df432cee/action.yml
- 5: https://deepwiki.com/actions/create-github-app-token/4.1-action-inputs
- 6: https://deepwiki.com/actions/create-github-app-token/4.2-permission-system
🏁 Script executed:
# Find the repository root and examine the workflow file
find / -name "publish.yml" -path "*/.github/workflows/*" 2>/dev/null | head -5Repository: fg-labs/redskull
Length of output: 109
🏁 Script executed:
# Try listing git repositories to locate the correct path
git ls-files .github/workflows/publish.yml 2>/dev/null || find . -name "publish.yml" 2>/dev/null | grep -E "\.github/workflows"Repository: fg-labs/redskull
Length of output: 90
🏁 Script executed:
cat -n .github/workflows/publish.ymlRepository: fg-labs/redskull
Length of output: 5483
Scope GitHub App tokens to least privilege per job.
Both token-generation steps mint installation tokens without explicit permission narrowing, so each token inherits the app installation's full repo permission set. Constrain token scopes with permission-* inputs (and optionally explicit repo scoping) to reduce blast radius if a downstream step is compromised.
Suggested hardening diff
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.FG_LABS_BOT_APP_ID }}
private-key: ${{ secrets.FG_LABS_BOT_PRIVATE_KEY }}
+ owner: fg-labs
+ repositories: redskull
+ permission-contents: write
+ permission-pull-requests: write
@@
- name: Generate app token
id: app-token
uses: actions/create-github-app-token@1b10c78c7865c340bc4f6099eb2f838309f1e8c3 # v3.1.1
with:
app-id: ${{ secrets.FG_LABS_BOT_APP_ID }}
private-key: ${{ secrets.FG_LABS_BOT_PRIVATE_KEY }}
+ owner: fg-labs
+ repositories: redskull
+ permission-contents: writeAlso applies to: 53-58
🧰 Tools
🪛 zizmor (1.25.2)
[error] 25-25: dangerous use of GitHub App tokens (github-app): app token inherits blanket installation permissions
(github-app)
🤖 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/publish.yml around lines 23 - 28, The GitHub App token
generation steps using `actions/create-github-app-token` are not constraining
token scopes with `permission-*` inputs, causing tokens to inherit the full app
installation's repo permission set. This creates unnecessary security risk. Add
appropriate `permission-*` input parameters to both token generation steps (at
lines 23-28 and lines 53-58) to scope each token to only the minimum permissions
required for its respective job's downstream steps, reducing the blast radius if
a step is compromised.
Source: Linters/SAST tools
|
Closing: redskull already has a fully working release-plz setup ( |
Summary
Brings redskull's release automation in line with the canonical setup used across the other fg-labs / fulcrumgenomics Rust crates (tricord, mako, primer3-rs, refget-rs, bwa-mem3-rs, fg-sra, …).
Previously redskull used the upstream-style
release-plz.yml, which ran release-plz'sreleasecommand directly with the defaultGITHUB_TOKEN. This PR replaces it with the standardpublish.ymlworkflow and a matchingrelease-plz.toml.What changed
.github/workflows/release-plz.yml→.github/workflows/publish.yml("Manage Release PRs and Publish Crates"), split into two jobs:release-pr— release-plz opens/updates the version-bump + changelog PR.publish— on merge (whenCargo.toml's version no longer matches crates.io), publishes via crates.io Trusted Publishing (OIDC) and idempotently tags + creates the GitHub release.FG_LABS_BOTGitHub App token instead of the defaultGITHUB_TOKEN, so the release PR and tags it creates can trigger other workflows.release-plz.toml— delegates publishing/tagging/GitHub releases to thepublishjob (publish,git_tag_enable,git_release_enableall disabled), enablesdependencies_update(cargo update) and thereleasePR label, and keepssemver_check = true(redskull is already past v0.1.0).README.md— "Releasing a New Version" section updated to describe the two-jobpublish.yml, the app-token auth, and the new Trusted Publishing workflow filename.Notes
cliff.toml: the existingCHANGELOG.mdis in release-plz's default "Keep a Changelog" format (with PR links + compare URLs), which is richer than thecliff.tomloutput other repos use, so keeping the default avoids a mid-file format break.fg-labs, reporedskull, workflowpublish.yml(the README documents this), and the repo needs theFG_LABS_BOT_APP_ID/FG_LABS_BOT_PRIVATE_KEYsecrets.Summary by CodeRabbit
main, with concurrency controls and idempotent tagging/release creation.publish.yml-based process and Trusted Publishing details.