ci: add crates.io publish job to release workflow#29
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Greptile SummaryThis PR adds a Key changes:
Issue found:
Confidence Score: 3/5
|
| Filename | Overview |
|---|---|
| .github/workflows/release.yml | Adds a publish-crate job that runs after release; the job's dry-run and actual-publish steps both use --allow-dirty, and the publish step also adds --no-verify, meaning neither step performs a complete independent integrity check on the packaged crate. |
Sequence Diagram
sequenceDiagram
participant GH as GitHub (tag push)
participant build as build jobs
participant sign as sign job
participant release as release job
participant publish as publish-crate job
participant cio as crates.io
GH->>build: trigger on v* tag
build->>sign: artifacts uploaded
sign->>release: signed artifacts
release->>GH: GitHub Release created
release->>publish: needs: release
publish->>publish: cargo publish --dry-run --allow-dirty
publish->>cio: cargo publish --no-verify --allow-dirty\n(CARGO_REGISTRY_TOKEN)
cio-->>publish: published ✓
Prompt To Fix All With AI
This is a comment left during a code review.
Path: .github/workflows/release.yml
Line: 396-399
Comment:
**Dry-run + publish bypass each other's safety checks**
The two steps together end up verifying very little. The dry-run step uses `--allow-dirty`, which tells cargo to ignore any untracked or modified files in the working tree — so it isn't checking the exact committed snapshot. The actual publish step then uses `--no-verify`, which skips cargo's own packaging verification entirely.
The intended safety net is: "dry-run catches problems, so actual publish can skip re-checking." But because the dry-run already skips the dirty-state guard (`--allow-dirty`), the chain of trust is weakened. If anything modifies the working tree between checkout and publication (e.g., the `rust-cache` action writing files, or a future workflow change), neither step will flag the discrepancy.
In a clean `actions/checkout@v4` environment, `--allow-dirty` is not needed. Removing it from the dry-run step restores the guarantee that you are verifying exactly what was committed:
```suggestion
- name: Verify crate
run: cargo publish --dry-run
- name: Publish to crates.io
run: cargo publish --allow-dirty
```
(The `--allow-dirty` can stay on the publish step alone to handle the edge case where `cargo publish --dry-run` updates `Cargo.lock` and leaves the tree slightly dirty, but the verification itself should run against the clean tree.)
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "ci: add crates.io pu..."
| run: cargo publish --dry-run --allow-dirty | ||
|
|
||
| - name: Publish to crates.io | ||
| run: cargo publish --no-verify --allow-dirty |
There was a problem hiding this comment.
Dry-run + publish bypass each other's safety checks
The two steps together end up verifying very little. The dry-run step uses --allow-dirty, which tells cargo to ignore any untracked or modified files in the working tree — so it isn't checking the exact committed snapshot. The actual publish step then uses --no-verify, which skips cargo's own packaging verification entirely.
The intended safety net is: "dry-run catches problems, so actual publish can skip re-checking." But because the dry-run already skips the dirty-state guard (--allow-dirty), the chain of trust is weakened. If anything modifies the working tree between checkout and publication (e.g., the rust-cache action writing files, or a future workflow change), neither step will flag the discrepancy.
In a clean actions/checkout@v4 environment, --allow-dirty is not needed. Removing it from the dry-run step restores the guarantee that you are verifying exactly what was committed:
| run: cargo publish --dry-run --allow-dirty | |
| - name: Publish to crates.io | |
| run: cargo publish --no-verify --allow-dirty | |
| - name: Verify crate | |
| run: cargo publish --dry-run | |
| - name: Publish to crates.io | |
| run: cargo publish --allow-dirty |
(The --allow-dirty can stay on the publish step alone to handle the edge case where cargo publish --dry-run updates Cargo.lock and leaves the tree slightly dirty, but the verification itself should run against the clean tree.)
Prompt To Fix With AI
This is a comment left during a code review.
Path: .github/workflows/release.yml
Line: 396-399
Comment:
**Dry-run + publish bypass each other's safety checks**
The two steps together end up verifying very little. The dry-run step uses `--allow-dirty`, which tells cargo to ignore any untracked or modified files in the working tree — so it isn't checking the exact committed snapshot. The actual publish step then uses `--no-verify`, which skips cargo's own packaging verification entirely.
The intended safety net is: "dry-run catches problems, so actual publish can skip re-checking." But because the dry-run already skips the dirty-state guard (`--allow-dirty`), the chain of trust is weakened. If anything modifies the working tree between checkout and publication (e.g., the `rust-cache` action writing files, or a future workflow change), neither step will flag the discrepancy.
In a clean `actions/checkout@v4` environment, `--allow-dirty` is not needed. Removing it from the dry-run step restores the guarantee that you are verifying exactly what was committed:
```suggestion
- name: Verify crate
run: cargo publish --dry-run
- name: Publish to crates.io
run: cargo publish --allow-dirty
```
(The `--allow-dirty` can stay on the publish step alone to handle the edge case where `cargo publish --dry-run` updates `Cargo.lock` and leaves the tree slightly dirty, but the verification itself should run against the clean tree.)
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
Adds crates.io publishing to the existing tag-based release pipeline so that a Rust crate is published after the GitHub Release is created.
Changes:
- Introduces a new
publish-cratejob that runs after thereleasejob. - Runs
cargo publish --dry-runbefore attempting an actualcargo publish. - Uses the repository secret
CRATES_IO_TOKENviaCARGO_REGISTRY_TOKEN.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| run: cargo publish --dry-run --allow-dirty | ||
|
|
||
| - name: Publish to crates.io | ||
| run: cargo publish --no-verify --allow-dirty |
| run: cargo publish --dry-run --allow-dirty | ||
|
|
||
| - name: Publish to crates.io | ||
| run: cargo publish --no-verify --allow-dirty |
| uses: dtolnay/rust-toolchain@stable | ||
|
|
||
| - uses: Swatinem/rust-cache@v2 | ||
|
|
| publish-crate: | ||
| name: Publish to crates.io | ||
| needs: release | ||
| runs-on: ubuntu-22.04 |
Aligns with saorsa-core's release workflow pattern: - validate job checks version format and Cargo.toml match - test job runs fmt, clippy, and tests before building - security-audit job runs cargo audit - publish-crate runs parallel to build pipeline after gates pass - workflow_dispatch support with dry_run option - all version references use validate job outputs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the remaining untested scenarios from REPLICATION_DESIGN.md Section 18, bringing coverage from 47/56 to 56/56: - #20: paid-list local hit bypasses presence quorum (quorum.rs) - #22: paid-list rejection below threshold (quorum.rs) - #29: audit start gate during bootstrap (audit.rs) - #30: audit peer selection from sampled keys (audit.rs) - #31: audit periodic cadence with jitter bounds (config.rs) - #32: dynamic challenge size equals PeerKeySet (audit.rs) - #47: bootstrap claim grace period in audit path (audit.rs) - #48: bootstrap claim abuse after grace period (paid_list.rs) - #53: audit partial per-key failure with mixed responsibility (audit.rs) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements the remaining untested scenarios from REPLICATION_DESIGN.md Section 18, bringing coverage from 47/56 to 56/56: - #20: paid-list local hit bypasses presence quorum (quorum.rs) - #22: paid-list rejection below threshold (quorum.rs) - #29: audit start gate during bootstrap (audit.rs) - #30: audit peer selection from sampled keys (audit.rs) - #31: audit periodic cadence with jitter bounds (config.rs) - #32: dynamic challenge size equals PeerKeySet (audit.rs) - #47: bootstrap claim grace period in audit path (audit.rs) - #48: bootstrap claim abuse after grace period (paid_list.rs) - #53: audit partial per-key failure with mixed responsibility (audit.rs) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
publish-cratejob to the release workflow that publishes to crates.io after the GitHub release is createdCRATES_IO_TOKENsecret (matching saorsa-core's convention)Before merging
CRATES_IO_TOKENsecret is configured in repo settingsAfter merging
Re-tag v0.4.0 to trigger the release with crates.io publish:
🤖 Generated with Claude Code