Skip to content

feat(release): move release to own workflow, triggered manually - #620

Merged
twitchyliquid64 merged 1 commit into
mainfrom
tom/release
Jul 2, 2026
Merged

feat(release): move release to own workflow, triggered manually#620
twitchyliquid64 merged 1 commit into
mainfrom
tom/release

Conversation

@twitchyliquid64

@twitchyliquid64 twitchyliquid64 commented Jul 2, 2026

Copy link
Copy Markdown
Member
  • Moves the core test logic to a composite action, so we can share it across workflows
  • Splits release jobs out of CI.yml into their own release.yml
  • Make the release run manually rather than on every commit to main

Summary by CodeRabbit

  • New Features

    • Added a more structured release pipeline that builds and publishes downloadable artifacts for multiple platforms.
    • Release builds now include shell completion files alongside binaries.
  • Bug Fixes

    • Improved CI coverage with clearer separation between core tests and additional feature-based test suites.
    • Added a dependency/licensing check to catch issues earlier in the workflow.
  • Chores

    • Streamlined test execution to make routine CI runs faster and more focused.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a reusable "Core Tests" composite GitHub Action, refactors the CI workflow to use it alongside a new cargo-deny job and reduced permissions, and introduces a new Release workflow that runs tests, builds platform-specific binaries (Linux amd64/arm64, macOS arm64), and publishes artifacts to GCS and GitHub Releases.

Changes

CI and Release Pipeline Changes

Layer / File(s) Summary
Core tests composite action
.github/actions/core-tests/action.yml
New composite action installs protobuf-compiler, caches Rust, installs nextest, validates Cargo.lock, and runs workspace tests plus doctests.
CI workflow refactor
.github/workflows/ci.yml
Changes permissions.contents to read, replaces prior test setup with the new core-tests action plus explicit minimald feature-gated tests, and adds a cargo-deny job.
Release workflow trigger and test job
.github/workflows/release.yml
New manual-dispatch release workflow with concurrency serialization, read permissions, and a test job reusing core-tests plus feature-gated tests.
Platform-specific release build jobs
.github/workflows/release.yml
Adds Linux amd64 (musl static binaries + native minvmd via libkrun), Linux arm64 (cross-built musl binaries), and macOS arm64 (native minvmd/minimal) build jobs, each uploading renamed artifacts.
Release packaging and publishing
.github/workflows/release.yml
Merges artifacts, generates shell completions, authenticates to Google Cloud, uploads a compressed archive to GCS, and creates a GitHub Release.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • gominimal/minimal#353: Both PRs refactor the CI workflow's test execution to use cargo nextest plus cargo test --doc.
  • gominimal/minimal#614: Related release build flow changes for minvmd, including libkrun materialization and platform-specific artifacts.
  • gominimal/minimal#615: Both PRs update release CI logic ensuring minimal macOS arm64 binary is built and uploaded alongside minvmd.

Suggested labels: github_actions

Suggested reviewers: norrietaylor

Poem

A rabbit hops through YAML fields so wide,
Core tests bundled up, with nextest at its side.
New release rigs rise, amd64 and arm anew,
macOS joins the burrow, artifacts breaking through.
🐇📦✨ Ship it, ship it, off we go!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: release logic moved to a separate workflow and now runs manually.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (5)
.github/actions/core-tests/action.yml (1)

1-6: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Document the runner requirement here
This composite action assumes an Ubuntu/Debian runner (apt-get and endersonmenezes/free-disk-space), so add a short note that it’s intended for ubuntu-latest jobs to avoid reuse from macOS/Windows workflows later.

🤖 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/actions/core-tests/action.yml around lines 1 - 6, The composite
action description in Core Tests should explicitly note that it is intended for
ubuntu-latest jobs. Update the action metadata in action.yml to mention the
Ubuntu/Debian runner requirement because the setup relies on apt-get and
endersonmenezes/free-disk-space, so callers don’t reuse it from macOS or Windows
workflows.
.github/workflows/release.yml (4)

93-133: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Uploads silently succeed even if a binary is missing.

None of the upload-artifact steps set if-no-files-found, which defaults to warn. If a build/rename step silently produces no file (e.g. a bug in an earlier step), the job won't fail — it'll just warn, and the release job will proceed with a missing binary until gh release create or a user notices at runtime.

🛡️ Proposed fix (apply to all upload-artifact steps)
             - name: Upload binary (mip)
               uses: actions/upload-artifact@v7
               with:
                   name: mip-linux-amd64
                   path: target/x86_64-unknown-linux-musl/release/mip-linux-amd64
                   retention-days: 7
+                  if-no-files-found: error

Also applies to: 163-194, 234-245

🤖 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/release.yml around lines 93 - 133, The upload steps in
release.yml currently use actions/upload-artifact@v7 with the default
if-no-files-found behavior, so missing binaries only trigger warnings. Update
each upload-artifact block (for mip, minimal, minimald, and minvmd) to fail the
job when the expected artifact path is absent by setting if-no-files-found to
error, keeping the existing artifact names and paths intact.

154-188: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Combine the three cross build invocations into one.

The amd64 job builds all three packages (mip, minimal, minimald) in a single cargo build invocation with multiple --package flags. This arm64 job instead runs three separate cross build invocations (each spins up its own container), which is slower and inconsistent with the amd64 approach.

♻️ Proposed consolidation
-            - name: Build static minimal binary
-              # Rename with a platform suffix so download-artifact's merge-multiple
-              # flatten does not collide with the amd64 build's basename.
-              run: |
-                  cross build --release \
-                     --package minimal \
-                     --target aarch64-unknown-linux-musl
-                  mv target/aarch64-unknown-linux-musl/release/minimal \
-                     target/aarch64-unknown-linux-musl/release/minimal-linux-arm64
-            - name: Upload binary (minimal)
-              uses: actions/upload-artifact@v7
-              with:
-                  name: minimal-linux-arm64
-                  path: target/aarch64-unknown-linux-musl/release/minimal-linux-arm64
-                  retention-days: 7
-            - name: Build static mip binary
-              run: |
-                  cross build --release \
-                     --package mip \
-                     --target aarch64-unknown-linux-musl
-                  mv target/aarch64-unknown-linux-musl/release/mip \
-                     target/aarch64-unknown-linux-musl/release/mip-linux-arm64
-            - name: Upload binary (mip)
-              uses: actions/upload-artifact@v7
-              with:
-                  name: mip-linux-arm64
-                  path: target/aarch64-unknown-linux-musl/release/mip-linux-arm64
-                  retention-days: 7
-            - name: Build static minimald binary
-              run: |
-                  cross build --release \
-                     --package minimald \
-                     --target aarch64-unknown-linux-musl
-                  mv target/aarch64-unknown-linux-musl/release/minimald \
-                     target/aarch64-unknown-linux-musl/release/minimald-linux-arm64
-            - name: Upload binary (minimald)
-              uses: actions/upload-artifact@v7
-              with:
-                  name: minimald-linux-arm64
-                  path: target/aarch64-unknown-linux-musl/release/minimald-linux-arm64
-                  retention-days: 7
+            - name: Build static release binaries
+              run: |
+                  cross build --release --target aarch64-unknown-linux-musl \
+                     --package mip \
+                     --package minimal \
+                     --package minimald
+            - name: Rename binaries with platform suffix
+              run: |
+                  cd target/aarch64-unknown-linux-musl/release
+                  mv mip mip-linux-arm64
+                  mv minimal minimal-linux-arm64
+                  mv minimald minimald-linux-arm64
+            - name: Upload binary (mip)
+              uses: actions/upload-artifact@v7
+              with:
+                  name: mip-linux-arm64
+                  path: target/aarch64-unknown-linux-musl/release/mip-linux-arm64
+                  retention-days: 7
+            - name: Upload binary (minimal)
+              uses: actions/upload-artifact@v7
+              with:
+                  name: minimal-linux-arm64
+                  path: target/aarch64-unknown-linux-musl/release/minimal-linux-arm64
+                  retention-days: 7
+            - name: Upload binary (minimald)
+              uses: actions/upload-artifact@v7
+              with:
+                  name: minimald-linux-arm64
+                  path: target/aarch64-unknown-linux-musl/release/minimald-linux-arm64
+                  retention-days: 7
🤖 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/release.yml around lines 154 - 188, The arm64 job
currently runs three separate cross build steps for minimal, mip, and minimald,
which is slower and inconsistent with the amd64 workflow. Update the release
workflow build section to consolidate these into a single cross build invocation
in the same style used by the amd64 job, while keeping the existing mv renames
and the Upload binary steps for each artifact. Use the Build static minimal
binary, Build static mip binary, and Build static minimald binary entries to
locate the affected block.

262-268: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant recomputation of the short SHA.

steps.release_info.outputs.short_sha is already computed and available; re-running git rev-parse --short=8 HEAD here is duplicate logic that could theoretically drift if HEAD ever changed within the job.

♻️ Reuse the existing output
             - name: Package and upload archive to GCS
               run: |
-                  SHA=$(git rev-parse --short=8 HEAD)
+                  SHA="${{ steps.release_info.outputs.short_sha }}"
                   tar --zstd -cf "minimalone-${SHA}.tar.zst" -C artifacts .

Also applies to: 294-297

🤖 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/release.yml around lines 262 - 268, The release info step
is recomputing the short SHA instead of reusing the existing output from
release_info. Update the later workflow step(s) that build the release tag/name
to reference steps.release_info.outputs.short_sha directly, and remove the
duplicate git rev-parse logic so the values all come from the same computed
source.

302-311: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

Static analysis flags template-expansion into run: blocks.

zizmor flags ${{ steps.release_info.outputs.tag }} / .name being expanded directly inside the shell script as a template-injection risk. In this case both values are derived from git rev-parse --short=8 HEAD on a workflow_dispatch-only trigger, so real exploitability is low, but passing them via env: and referencing $TAG/$NAME avoids the pattern entirely as defense-in-depth.

🛡️ Optional hardening
             - name: Create Release
               env:
                   GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+                  RELEASE_TAG: ${{ steps.release_info.outputs.tag }}
+                  RELEASE_NAME: ${{ steps.release_info.outputs.name }}
               run: |
                   tar -C artifacts/completions -czf artifacts/completions.tar.gz .
                   cd artifacts/
-                  gh release create "${{ steps.release_info.outputs.tag }}" \
+                  gh release create "$RELEASE_TAG" \
                     $(find . -maxdepth 1 -type f) \
                     --repo="${GITHUB_REPOSITORY}" \
-                    --title="${{ steps.release_info.outputs.name }}"
+                    --title="$RELEASE_NAME"
🤖 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/release.yml around lines 302 - 311, The Create Release
step is expanding release metadata directly inside the shell script, which
triggers template-injection warnings. Move the release tag and title values from
steps.release_info.outputs into env variables for the Create Release step, then
reference those variables inside the run block instead of using direct template
expressions. Keep the rest of the gh release create flow unchanged and use the
existing Create Release / release_info symbols to locate the update.

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/actions/core-tests/action.yml:
- Around line 1-6: The composite action description in Core Tests should
explicitly note that it is intended for ubuntu-latest jobs. Update the action
metadata in action.yml to mention the Ubuntu/Debian runner requirement because
the setup relies on apt-get and endersonmenezes/free-disk-space, so callers
don’t reuse it from macOS or Windows workflows.

In @.github/workflows/release.yml:
- Around line 93-133: The upload steps in release.yml currently use
actions/upload-artifact@v7 with the default if-no-files-found behavior, so
missing binaries only trigger warnings. Update each upload-artifact block (for
mip, minimal, minimald, and minvmd) to fail the job when the expected artifact
path is absent by setting if-no-files-found to error, keeping the existing
artifact names and paths intact.
- Around line 154-188: The arm64 job currently runs three separate cross build
steps for minimal, mip, and minimald, which is slower and inconsistent with the
amd64 workflow. Update the release workflow build section to consolidate these
into a single cross build invocation in the same style used by the amd64 job,
while keeping the existing mv renames and the Upload binary steps for each
artifact. Use the Build static minimal binary, Build static mip binary, and
Build static minimald binary entries to locate the affected block.
- Around line 262-268: The release info step is recomputing the short SHA
instead of reusing the existing output from release_info. Update the later
workflow step(s) that build the release tag/name to reference
steps.release_info.outputs.short_sha directly, and remove the duplicate git
rev-parse logic so the values all come from the same computed source.
- Around line 302-311: The Create Release step is expanding release metadata
directly inside the shell script, which triggers template-injection warnings.
Move the release tag and title values from steps.release_info.outputs into env
variables for the Create Release step, then reference those variables inside the
run block instead of using direct template expressions. Keep the rest of the gh
release create flow unchanged and use the existing Create Release / release_info
symbols to locate the update.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: eabd496a-f3f0-4708-a8f9-d14336abd018

📥 Commits

Reviewing files that changed from the base of the PR and between fb618f9 and 73a320b.

📒 Files selected for processing (3)
  • .github/actions/core-tests/action.yml
  • .github/workflows/ci.yml
  • .github/workflows/release.yml

@twitchyliquid64
twitchyliquid64 enabled auto-merge (squash) July 2, 2026 18:40
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.

2 participants