Skip to content

Fix release publish recovery path#110

Open
Fieldnote-Echo wants to merge 1 commit into
mainfrom
codex/release-crate-attested-tempdir
Open

Fix release publish recovery path#110
Fieldnote-Echo wants to merge 1 commit into
mainfrom
codex/release-crate-attested-tempdir

Conversation

@Fieldnote-Echo
Copy link
Copy Markdown
Owner

Summary

  • keep the attested .crate download outside the checkout so the crates.io publish job can re-run cargo package --locked on a clean worktree
  • make PyPI publishing idempotent with skip-existing: true while retaining the post-publish hash verification against PyPI-served files
  • extend release publish invariants to pin both recovery properties

Validation

  • bash tests/release_publish_invariants.sh
  • bash tests/release_signed_release_invariants.sh
  • python3 -m py_compile tests/release_publish_invariants.py
  • git diff --check

Signed-off-by: Nelson Spence <nelson@projectnavi.ai>
@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Improve release publish recovery with attested crate temp directory

✨ Enhancement 🧪 Tests

Grey Divider

Walkthroughs

Description
• Keep attested .crate download outside checkout for clean cargo package re-run
• Add skip-existing flag to PyPI publish for idempotent recovery reruns
• Extend release publish invariants to validate crate recovery properties
• Add new check_publish_crate validation function for crate job requirements
Diagram
flowchart LR
  A["Attested .crate artifact"] -->|"Download to runner.temp"| B["Clean checkout for cargo package"]
  B -->|"Re-package with --locked"| C["Byte-identity verification"]
  C -->|"Pre-publish check"| D["Publish to crates.io"]
  D -->|"Post-publish verification"| E["Download from crates.io"]
  E -->|"Hash comparison"| F["Verify match"]
  G["PyPI publish"] -->|"skip-existing: true"| H["Idempotent recovery reruns"]
  I["Invariants validation"] -->|"check_publish_crate"| J["Validate crate job structure"]
  I -->|"check_publish_pypi"| K["Validate PyPI job structure"]

Loading

Grey Divider

File Changes

1. tests/release_publish_invariants.py 🧪 Tests +59/-1

Add crate recovery validation and PyPI idempotency checks

• Updated module docstring to reflect validation for all registry upload jobs
• Added validation for PyPI publish step to require skip-existing: true flag
• Implemented new check_publish_crate() function to validate crate job structure
• Added checks for dist-crate artifact download path using ${{ runner.temp }}/attested
• Added verification of both pre-publish and post-publish byte-identity verification steps
• Integrated check_publish_crate() call in main() before PyPI validation

tests/release_publish_invariants.py


2. .github/workflows/release.yml ✨ Enhancement +9/-3

Move crate artifact to temp directory and add PyPI idempotency

• Changed attested .crate download path from attested to ${{ runner.temp }}/attested
• Updated all references to attested .crate path to use ${RUNNER_TEMP}/attested environment
 variable
• Added comment explaining why artifact is kept outside checkout for clean cargo package execution
• Added skip-existing: true flag to PyPI publish step with explanatory comment
• Added comment documenting idempotent recovery behavior for PyPI publishing

.github/workflows/release.yml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented May 30, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Qodo Logo

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request updates tests/release_publish_invariants.py to enforce invariants for publishing crates and PyPI packages, including ensuring PyPI uploads set skip-existing: true and introducing a new check_publish_crate function to validate the publish-crate job. Feedback was provided to improve the verification step check in check_publish_crate by tracking unique step names to prevent false positives from duplicate steps.

Comment on lines +203 to +209
verify_steps: list[dict[str, Any]] = []
for index, raw_step in enumerate(steps):
step = mapping(raw_step, f"{path}: jobs.publish-crate.steps[{index}]")
if step.get("name") in verify_step_names:
verify_steps.append(step)
if len(verify_steps) != 2:
fail(f"{path}: publish-crate must have both attested .crate verification steps")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The current check only verifies that the total number of matched steps is 2. If one of the steps is duplicated and the other is missing, the check will still pass. To ensure both unique verification steps are present, we should track the unique names found and verify that both expected names are matched.

Suggested change
verify_steps: list[dict[str, Any]] = []
for index, raw_step in enumerate(steps):
step = mapping(raw_step, f"{path}: jobs.publish-crate.steps[{index}]")
if step.get("name") in verify_step_names:
verify_steps.append(step)
if len(verify_steps) != 2:
fail(f"{path}: publish-crate must have both attested .crate verification steps")
verify_steps: list[dict[str, Any]] = []
found_names: set[str] = set()
for index, raw_step in enumerate(steps):
step = mapping(raw_step, f"{path}: jobs.publish-crate.steps[{index}]")
name = step.get("name")
if name in verify_step_names:
verify_steps.append(step)
found_names.add(name)
if len(found_names) != 2:
fail(f"{path}: publish-crate must have both attested .crate verification steps")

@codecov
Copy link
Copy Markdown

codecov Bot commented May 30, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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