Skip to content

Conversation

@spoorcc
Copy link
Contributor

@spoorcc spoorcc commented Jan 2, 2026

Summary by CodeRabbit

  • New Features

    • Automated release orchestration: draft release pages are created with generated release notes, installers for all major platforms, SBOMs, and uploaded wheel distributions.
  • Documentation

    • Contributing guide updated to reflect the new CI-driven release workflow.
  • Chores

    • Build tooling dependency pinned for more reproducible builds.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Centralizes CI and release orchestration via a new ci.yml workflow calling reusable release, build, and run workflows; adds scripted release-notes, SBOM and platform-aware packaging, pins setuptools-scm, and updates workflows to produce/upload wheels, installers, and draft GitHub releases.

Changes

Cohort / File(s) Summary
CI Orchestrator & coordination
.github/workflows/ci.yml
New orchestrator that calls release, build, and run reusable workflows; routes release_id from prep-release to build and manages triggers for main, tags, PRs, and manual dispatch.
Release workflow
.github/workflows/release.yml
New workflow_call workflow that determines tag/release_id, generates release_notes.txt, optionally deletes existing release, and creates a draft GitHub release (attaches LICENSE).
Build workflow
.github/workflows/build.yml
Converted to workflow_call with release_id input; permission changes, added Windows Zig install, expanded step Create sbom, binary & package, uploads installers to release when release_id provided, and adds a wheel build job/artifact path.
Run / Test / docs / publish
.github/workflows/run.yml, .github/workflows/docs.yml, .github/workflows/python-publish.yml
run.yml: converted to workflow_call, broadened matrix, interleaves Windows Zig install, and renames/adjusts test job. docs.yml: Python pinned to 3.13. python-publish.yml: trigger changed to published, removed workflow_dispatch.
Packaging & SBOM scripts
script/package.py, script/create_sbom.py
script/package.py: dynamic versioning via setuptools_scm, adds PLATFORM_NAME, includes platform in installer filenames and MSI/WiX outputs. script/create_sbom.py: defers OUTPUT_FILE creation, obtains version dynamically, and names SBOM including version/platform.
Release notes script
script/create_release_notes.py
New CLI script that extracts the latest release section from CHANGELOG.rst and writes release_notes.txt; includes error handling and entrypoint.
Project metadata & docs
pyproject.toml, .gitignore, CHANGELOG.rst, README.md, doc/contributing.rst
pyproject.toml: pins setuptools-scm==9.2.2. .gitignore: adds release_notes.txt. CHANGELOG.rst: adds unreleased note. README.md and doc/contributing.rst: updated to reflect CI-driven release flow.

Sequence Diagram

sequenceDiagram
    autonumber
    actor Developer
    participant CI as CI Orchestrator (ci.yml)
    participant Prep as Release Workflow (release.yml)
    participant Build as Build Workflow (build.yml)
    participant Run as Test Workflow (run.yml)
    participant GH as GitHub Releases

    Developer->>CI: push / tag / manual dispatch
    CI->>Prep: workflow_call (prep-release)
    Prep->>GH: create/update draft release (generate notes, attach LICENSE)
    Prep-->>CI: outputs.release_id

    par Build and Test
        CI->>Build: workflow_call (with release_id)
        CI->>Run: workflow_call (with/without release_id as configured)
        Build->>Build: build wheel, SBOM, binaries, installers
        Build->>GH: upload installers & wheel to draft release (if release_id present)
        Run->>Run: execute test matrix
    end

    GH-->>Developer: draft release populated with artifacts
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 I hopped through workflows, neat and spry,
Draft notes penned beneath the sky.
Wheels and SBOMs in tidy rows,
Installers bound for highs and lows.
A happy rabbit stamps goodbye.

Pre-merge checks

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the changeset, which implements automated release and artifact uploading through GitHub Actions workflows.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 39d87a1 and d7655f7.

📒 Files selected for processing (1)
  • .github/workflows/run.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/run.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: Publish Python distribution 📦 to TestPyPI
  • GitHub Check: build / build (macos-latest)
  • GitHub Check: build / build (ubuntu-latest)
  • GitHub Check: build / build (windows-latest)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: run / run (ubuntu-latest, 3.12)
  • GitHub Check: run / run (windows-latest, 3.11)
  • GitHub Check: run / run (windows-latest, 3.10)
  • GitHub Check: run / run (windows-latest, 3.13)
  • GitHub Check: run / run (windows-latest, 3.9)
  • GitHub Check: run / run (windows-latest, 3.14)
  • GitHub Check: run / run (macos-latest, 3.9)
  • GitHub Check: run / run (windows-latest, 3.12)
  • GitHub Check: run / test-cygwin
  • GitHub Check: test
  • GitHub Check: DevContainer Build & Test

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@spoorcc spoorcc force-pushed the automate-release branch 3 times, most recently from 956203e to 49ceb37 Compare January 2, 2026 13:11
@spoorcc spoorcc force-pushed the automate-release branch 2 times, most recently from 1f44736 to 332afaf Compare January 2, 2026 13:29
@spoorcc spoorcc changed the title Automate-release Automate release & uploading artifacts Jan 2, 2026
@spoorcc spoorcc marked this pull request as ready for review January 2, 2026 21:55
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (6)
.github/workflows/landing-page.yml (1)

16-22: Consider retaining step names for workflow log clarity.

Removing the step names for "Harden the runner" and "Setup Python" reduces readability in GitHub Actions logs, making it harder to quickly identify steps during debugging. While functionally equivalent, explicit names improve maintainability.

.github/workflows/docs.yml (1)

12-16: Consider retaining step names for workflow log clarity.

Removing explicit step names reduces readability in GitHub Actions logs, making troubleshooting less efficient. While functionally identical, named steps improve maintainability.

.github/workflows/test.yml (1)

17-21: Consider retaining step names for workflow log clarity.

Removing step names ("Harden the runner", "Setup Python") makes GitHub Actions logs less descriptive. Named steps help identify failures quickly during CI runs and improve overall workflow maintainability.

.github/workflows/ci.yml (1)

7-8: Refine tag pattern to match semantic versions only.

The current pattern '*.*.*' will match any three dot-separated segments, including non-version tags like 'test.1.2' or 'fix.bug.now'. Consider using a more specific pattern that enforces numeric semantic versioning.

🔎 Suggested improvement
     tags:
-      - '*.*.*'
+      - '[0-9]+.[0-9]+.[0-9]+'
script/create_release_notes.py (1)

31-37: Consider clarifying the end_idx=None behavior.

When only one release section exists, end_idx remains None, and the slice lines[start_idx:None] correctly captures all remaining lines. While this works correctly in Python, the implicit behavior could be made more explicit for maintainability.

🔎 Optional clarification
     for idx in range(start_idx + 1, len(lines)):
         if version_header_pattern.match(lines[idx].strip()):
             end_idx = idx
             break

+    # If end_idx is None, capture all lines to the end (single release section)
     section_lines = lines[start_idx:end_idx]
     return "\n".join(section_lines).strip()
.github/workflows/build.yml (1)

40-42: Consider version pinning for Zig installation.

Similar to the installation in run.yml, the Zig version is not pinned, which could lead to build inconsistencies over time as new versions are released.

🔎 Suggested improvement
       - name: Install Zig (Windows)
         if: runner.os == 'Windows'
-        run: choco install zig -y
+        run: choco install zig --version=0.13.0 -y
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c677cb and 45696fe.

📒 Files selected for processing (15)
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/docs.yml
  • .github/workflows/landing-page.yml
  • .github/workflows/python-publish.yml
  • .github/workflows/release.yml
  • .github/workflows/run.yml
  • .github/workflows/test.yml
  • .gitignore
  • CHANGELOG.rst
  • README.md
  • pyproject.toml
  • script/create_release_notes.py
  • script/create_sbom.py
  • script/package.py
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-12-25T23:53:05.742Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:53:05.742Z
Learning: When building macOS PKG installers with fpm in CI, account for the known issue (fpm #1996) where --prefix can be duplicated (e.g., /opt/dfetch becomes /opt/dfetch/opt/dfetch). In the workflow at .github/workflows/build.yml, verify install paths and PATH entries do not assume a single-prefix layout. Adjust packaging scripts or fpm arguments to normalize the final install location and update PATH references accordingly. Add a test step to validate the expected runtime paths after installation.

Applied to files:

  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • .github/workflows/test.yml
  • .github/workflows/landing-page.yml
  • .github/workflows/run.yml
  • .github/workflows/docs.yml
  • .github/workflows/python-publish.yml
📚 Learning: 2025-12-25T22:46:27.554Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: dfetch/resources/__init__.py:12-17
Timestamp: 2025-12-25T22:46:27.554Z
Learning: In dfetch, when building standalone binaries with Nuitka, resources are packaged at the top level as "resources" (not "dfetch.resources") to avoid name clashes with the binary executable named "dfetch". The code in dfetch/resources/__init__.py uses `"resources"` string when `__compiled__` is detected, which correctly references the top-level resources folder in the standalone build.

Applied to files:

  • script/create_sbom.py
📚 Learning: 2025-12-25T23:53:09.596Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:53:09.596Z
Learning: When using fpm to create macOS PKG installers, there is a known issue (fpm #1996) where the --prefix value is duplicated during installation. For example, with --prefix=/opt/dfetch, files are installed to /opt/dfetch/opt/dfetch instead of /opt/dfetch. This means PATH entries and references should account for this duplication.

Applied to files:

  • script/package.py
📚 Learning: 2025-12-25T23:52:41.740Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:52:41.740Z
Learning: In macOS PKG installers created with fpm for the dfetch project, the installation path `/opt/dfetch/opt/dfetch` is correct and intentional due to fpm's osxpkg prefix behavior (related to fpm issue #1996). This apparent path duplication should not be flagged as an error.

Applied to files:

  • script/package.py
📚 Learning: 2025-12-15T20:30:35.254Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 865
File: .readthedocs.yml:19-19
Timestamp: 2025-12-15T20:30:35.254Z
Learning: Read the Docs supports Python 3.13 and 3.14 (and newer versions). The build.tools.python configuration in .readthedocs.yml accepts version strings like "3.13", "3.14", or "latest" to use the newest available Python version.

Applied to files:

  • CHANGELOG.rst
🪛 actionlint (1.7.9)
.github/workflows/release.yml

52-52: if: condition "${{ steps.release_info.outputs.tag }} == 'latest'" is always evaluated to true because extra characters are around ${{ }}

(if-cond)

.github/workflows/python-publish.yml

98-98: property "release_id" is not defined in object type {}

(expression)


112-112: property "release_id" is not defined in object type {}

(expression)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: build / build (windows-latest)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (12)
.gitignore (1)

16-16: LGTM!

Ignoring the generated release notes file is appropriate and consistent with other build artifacts already in the ignore list.

.github/workflows/docs.yml (1)

18-18: Python version pinned from '3.x' to '3.13'.

This changes behavior from using the latest Python 3.x to specifically 3.13. While this improves consistency across workflows (matching other files in this PR), ensure documentation builds are compatible with 3.13 and consider whether automatic adoption of future 3.x versions was intentional.

.github/workflows/python-publish.yml (1)

8-8: LGTM! Appropriate trigger for production releases.

Changing from created to published ensures the workflow only runs when releases are actually published, not when they're created as drafts.

script/create_sbom.py (2)

19-24: LGTM! Consistent platform naming.

The platform naming convention (nix/osx/win) is consistent with script/package.py and provides clear identification for cross-platform artifacts.


46-58: Dynamic version retrieval is correctly implemented.

This approach properly retrieves the version after dfetch is installed in the temporary venv. Using importlib.metadata.version is the standard method for getting an installed package's version, which will reflect the setuptools-scm computed version.

script/package.py (1)

48-53: LGTM! Consistent platform naming.

The PLATFORM_NAME logic matches script/create_sbom.py, ensuring consistent artifact naming across the build process.

README.md (1)

57-57: Documentation updated to reflect new release workflow.

The change accurately reflects that installers are now available on the releases page, aligning with the automated release workflow introduced in this PR.

CHANGELOG.rst (1)

4-6: LGTM! Clear indication of unreleased status.

The note clearly communicates that this is the latest unreleased version, which is helpful for users and aligns with the automated release process.

.github/workflows/ci.yml (1)

25-41: LGTM: Efficient parallel execution design.

The build and run jobs correctly depend only on prep-release and execute in parallel, which is appropriate since the run job performs testing that doesn't require build artifacts. This design optimizes CI execution time.

.github/workflows/build.yml (2)

30-33: LGTM: Good security and versioning practices.

The addition of fetch-depth: 0 is essential for setuptools-scm dynamic versioning (as configured in pyproject.toml), and persist-credentials: false follows security best practices by not persisting GitHub tokens in git config.


173-222: LGTM: Well-structured wheel build and release jobs.

The build-whl and release jobs follow good practices:

  • Proper dependency chain (release depends on build-whl)
  • Appropriate security hardening and credential handling
  • Clean artifact passing via upload/download-artifact actions
  • Consistent versioning support with fetch-depth: 0
.github/workflows/run.yml (1)

38-39: Remove unnecessary Zig installation from Windows jobs.

Zig is installed in the workflow but never used in any subsequent test steps. The dfetch project is a Python-based dependency manager with no dependency on Zig. After the installation, only dfetch commands are executed, which do not require Zig. This appears to be a debugging artifact or copy-paste error and should be removed to reduce build time and complexity.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (3)
.github/workflows/release.yml (2)

78-88: Draft release blocks automatic PyPI publishing.

The workflow creates a draft release but never publishes it. Since python-publish.yml triggers only on release.types: [published], the PyPI package won't be published automatically. This appears intentional for manual review before publishing, but should be documented.

Is the draft-then-manual-publish workflow intentional? If so, consider adding a comment explaining this design choice.


41-42: Remove hardcoded PR branch before merging.

The special case for branch "automate-release" appears to be for testing this PR. This should be removed before merging to avoid treating future pushes to this branch as release candidates.

🔎 Suggested cleanup
-              if [[ "$BRANCH" == "main" || "$BRANCH" == "automate-release" ]]; then
+              if [[ "$BRANCH" == "main" ]]; then
                 TAG="latest"
script/package.py (1)

10-18: Importing dfetch.__version__ may fail when dfetch is not installed.

Line 12 imports __version__ from the dfetch package, which requires dfetch to be installed and importable. This script runs after building standalone binaries with Nuitka, where dfetch may not be installed as a Python package.

Consider using setuptools_scm consistently for both version strings, as suggested in the previous review.

🧹 Nitpick comments (1)
script/create_release_notes.py (1)

57-59: Uncaught ValueError from extract_latest_section will crash with a traceback.

If no release section is found in the changelog (line 30 raises ValueError), the exception propagates uncaught, producing a stack trace instead of a clean error message. While this does fail the script (non-zero exit), consider catching it for cleaner CI output.

🔎 Optional improvement
+    try:
+        notes = extract_latest_section(changelog_path)
+    except ValueError as e:
+        print(f"Error: {e}")
+        sys.exit(1)
+
     Path("release_notes.txt").write_text(
-        extract_latest_section(changelog_path), encoding="UTF-8"
+        notes, encoding="UTF-8"
     )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45696fe and 13f10e3.

📒 Files selected for processing (10)
  • .github/workflows/build.yml
  • .github/workflows/ci.yml
  • .github/workflows/docs.yml
  • .github/workflows/python-publish.yml
  • .github/workflows/release.yml
  • .github/workflows/run.yml
  • doc/contributing.rst
  • pyproject.toml
  • script/create_release_notes.py
  • script/package.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • .github/workflows/docs.yml
  • .github/workflows/python-publish.yml
  • pyproject.toml
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-12-25T23:53:05.742Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:53:05.742Z
Learning: When building macOS PKG installers with fpm in CI, account for the known issue (fpm #1996) where --prefix can be duplicated (e.g., /opt/dfetch becomes /opt/dfetch/opt/dfetch). In the workflow at .github/workflows/build.yml, verify install paths and PATH entries do not assume a single-prefix layout. Adjust packaging scripts or fpm arguments to normalize the final install location and update PATH references accordingly. Add a test step to validate the expected runtime paths after installation.

Applied to files:

  • .github/workflows/run.yml
  • .github/workflows/release.yml
  • .github/workflows/ci.yml
  • .github/workflows/build.yml
📚 Learning: 2026-01-01T11:05:39.533Z
Learnt from: ben-edna
Repo: dfetch-org/dfetch PR: 898
File: script/package.py:201-205
Timestamp: 2026-01-01T11:05:39.533Z
Learning: In the dfetch project's script/package.py, prefer explicit failures ("crash and burn") over silently handling missing configuration values, ensuring that builds fail if required metadata (e.g., URLs in pyproject.toml) is not properly configured.

Applied to files:

  • script/package.py
📚 Learning: 2025-12-25T23:52:41.740Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:52:41.740Z
Learning: In macOS PKG installers created with fpm for the dfetch project, the installation path `/opt/dfetch/opt/dfetch` is correct and intentional due to fpm's osxpkg prefix behavior (related to fpm issue #1996). This apparent path duplication should not be flagged as an error.

Applied to files:

  • script/package.py
📚 Learning: 2025-12-25T22:46:27.554Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: dfetch/resources/__init__.py:12-17
Timestamp: 2025-12-25T22:46:27.554Z
Learning: In dfetch, when building standalone binaries with Nuitka, resources are packaged at the top level as "resources" (not "dfetch.resources") to avoid name clashes with the binary executable named "dfetch". The code in dfetch/resources/__init__.py uses `"resources"` string when `__compiled__` is detected, which correctly references the top-level resources folder in the standalone build.

Applied to files:

  • script/package.py
📚 Learning: 2025-12-25T23:53:09.596Z
Learnt from: spoorcc
Repo: dfetch-org/dfetch PR: 861
File: .github/workflows/build.yml:120-125
Timestamp: 2025-12-25T23:53:09.596Z
Learning: When using fpm to create macOS PKG installers, there is a known issue (fpm #1996) where the --prefix value is duplicated during installation. For example, with --prefix=/opt/dfetch, files are installed to /opt/dfetch/opt/dfetch instead of /opt/dfetch. This means PATH entries and references should account for this duplication.

Applied to files:

  • script/package.py
🧬 Code graph analysis (1)
script/package.py (1)
dfetch/manifest/version.py (1)
  • Version (6-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: run / run (macos-latest, 3.12)
  • GitHub Check: run / run (windows-latest, 3.12)
  • GitHub Check: run / run (windows-latest, 3.13)
  • GitHub Check: run / run (windows-latest, 3.11)
  • GitHub Check: run / run (macos-latest, 3.10)
  • GitHub Check: run / run (windows-latest, 3.9)
  • GitHub Check: run / run (windows-latest, 3.10)
  • GitHub Check: run / run (macos-latest, 3.9)
  • GitHub Check: run / run (windows-latest, 3.14)
  • GitHub Check: build / build (windows-latest)
  • GitHub Check: build / build (ubuntu-latest)
  • GitHub Check: build / build (macos-latest)
  • GitHub Check: run / test-cygwin
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test
  • GitHub Check: DevContainer Build & Test
🔇 Additional comments (15)
doc/contributing.rst (1)

111-112: LGTM!

Documentation accurately reflects the new automated release workflow where ci.yml creates a draft release and publishing triggers PyPI deployment.

script/package.py (2)

49-56: LGTM!

The PLATFORM_NAME constant provides clear platform identification for installer naming. The logic correctly handles Linux (default "nix"), macOS ("osx"), and Windows ("win").


72-82: Version usage pattern is appropriate.

Using __version__ (with dev suffix) for installer filenames and __digit_only_version__ for package metadata (fpm's -v flag) correctly separates human-readable artifact naming from strict semver requirements of package managers.

.github/workflows/ci.yml (1)

1-17: Well-structured CI orchestration workflow.

The centralized orchestration pattern with explicit permissions and trigger conditions is clean. The tag pattern '[0-9]+.[0-9]+.[0-9]+' correctly matches semantic version tags.

.github/workflows/run.yml (3)

3-4: Trigger change aligns with centralized orchestration.

Changing from push/pull_request to workflow_call correctly integrates this workflow into the CI orchestration defined in ci.yml.


60-64: No action needed. Python 3.14 is a stable release (3.14.0 shipped October 7, 2025, with bugfix versions in December 2025), not an alpha/beta version. Including it in the CI matrix is appropriate.

Likely an incorrect or invalid review comment.


34-36: Remove unnecessary Zig installation on Windows.

Zig is not a dependency of dfetch and is not referenced anywhere in the codebase, configuration files, or git history. The dfetch commands that follow (environment, validate, check, update, report -t sbom) do not require Zig. This installation step should be removed from both the test-cygwin job (lines 34-36) and the run job (lines 104-106).

Likely an incorrect or invalid review comment.

.github/workflows/release.yml (2)

51-58: If-condition syntax is now correct.

The condition has been fixed to properly evaluate within the expression: ${{ steps.release_info.outputs.tag == 'latest' }}.


66-76: Release deletion now properly scoped to 'latest' tag only.

The deletion step is now gated by if: ${{ steps.release_info.outputs.tag == 'latest' }}, which limits the aggressive deletion behavior to only the rolling "latest" release. This is a reasonable approach for a continuously-updated pre-release tag.

script/create_release_notes.py (1)

52-59: Error handling for missing file is now correct.

The script now properly exits with code 1 when the changelog file is missing, which will fail the CI workflow appropriately.

.github/workflows/build.yml (5)

4-8: Workflow now accepts release_id input for release coordination.

The change from push/pull_request triggers to workflow_call with a required release_id input properly integrates this workflow into the centralized CI orchestration.


31-33: Checkout configuration enables version detection.

fetch-depth: 0 fetches all history and tags, which is required for setuptools_scm to determine the version from git tags. persist-credentials: false is a security best practice.


105-119: Race condition mitigated with preserve_order: true.

Adding preserve_order: true forces sequential asset uploads, which helps avoid race conditions when multiple matrix instances upload to the same release. This addresses the concern from the previous review.


174-200: Clean wheel build job.

The build-whl job correctly builds and stores Python wheel distributions. Using python -m build is the modern, recommended approach for building Python packages.


202-224: Wheel upload job follows best practices.

The release job properly:

  • Gates on inputs.release_id
  • Depends on build-whl to ensure artifacts exist
  • Uses preserve_order: true for sequential uploads
  • Has appropriate permissions

Note: The build job and release job may still run concurrently (both upload to the same release). Consider whether this could cause issues or if GitHub's release API handles concurrent uploads gracefully.

@spoorcc spoorcc requested a review from ben-edna January 2, 2026 22:59
@spoorcc spoorcc merged commit 415105d into main Jan 2, 2026
39 checks passed
@spoorcc spoorcc deleted the automate-release branch January 2, 2026 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

development Tools for development github_actions Pull requests that update GitHub Actions code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Binary Artifacts not part of release Create & release standalone binaries

3 participants