Skip to content

feat(gha): use released mip to fetch pkgs artifacts for CI - #692

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

feat(gha): use released mip to fetch pkgs artifacts for CI#692
twitchyliquid64 merged 1 commit into
mainfrom
tom/release

Conversation

@twitchyliquid64

@twitchyliquid64 twitchyliquid64 commented Jul 9, 2026

Copy link
Copy Markdown
Member

Hopefully this will shave 20 mins off our CI.

Summary by CodeRabbit

  • New Features

    • Added a reusable action for materializing prebuilt guest artifacts.
    • Workflows now use this action to fetch kernel and root filesystem images for Linux, macOS, and release jobs.
  • Bug Fixes

    • Added checks for supported runner OS and architecture to prevent unsupported runs.
    • Improved handling of environments that require relaxed user-namespace settings before materialization.

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

A new reusable GitHub composite action resolves a channel-specific mip binary and materializes repository outputs. Linux KVM, macOS, and release workflows now use it for guest kernels and rootfs images across supported architectures.

Changes

Guest artifact materialization

Layer / File(s) Summary
Reusable materialize action
.github/actions/materialize/action.yml
Defines inputs and version output, validates Linux and architecture requirements, resolves the selected mip version, downloads the binary, and materializes the requested output.
CI workflow integration
.github/workflows/ci-linux-kvm.yml, .github/workflows/ci-macos.yml
Replaces artifact fetch-script calls with action steps for kernel and rootfs outputs in temporary destinations.
Release workflow integration
.github/workflows/release.yml
Replaces release artifact dependency setup, caching, and fetch-script calls with architecture-specific materialization steps.

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

Sequence Diagram(s)

sequenceDiagram
  participant Workflow as GitHub workflow
  participant Action as materialize action
  participant Storage as storage.googleapis.com/minimal-one
  participant Mip as mip materialize
  Workflow->>Action: provide artifact output and target architecture
  Action->>Storage: fetch channel pointer and mip binary
  Action->>Mip: materialize output into destination
  Mip-->>Workflow: produce kernel or rootfs artifact
Loading

Possibly related PRs

Suggested labels: github_actions

Suggested reviewers: norrietaylor, jtnkminimal

Poem

I’m a rabbit with artifacts bright,
Materializing kernels tonight.
Rootfs hops from channel to place,
mip runs swiftly in the race.
CI and releases now align—
Four little paws, one cleaner line.

🚥 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 clearly matches the main change: CI now uses the released mip-based materialization flow to fetch artifacts.
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/workflows/ci-macos.yml (1)

46-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stale comment: job no longer builds the minimal CLI to materialize artifacts.

With this change, materializing the kernel/rootfs (Lines 79-92) is now done by fetching a prebuilt mip via the composite action, not by building minimal from source. The remaining toolchain/cargo-cache steps are for cross-compiling minimald into the initramfs (Line 97), not for the materialize step. Worth updating the comment so it doesn't mislead future readers about what's actually happening here.

🤖 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/ci-macos.yml around lines 46 - 54, Update the stale
explanatory comment in the CI macOS workflow so it matches the current flow: the
kernel/rootfs materialization is no longer done by building the `minimal` CLI
from this repo, but by fetching a prebuilt `mip` through the composite action.
Keep the comment focused on the actual steps around the materialize job and the
later `minimald` cross-compilation/initramfs cache steps, and remove references
to building `minimal` or repo-source artifact generation.
.github/actions/materialize/action.yml (4)

71-73: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

fetch() has no request timeout.

--retry 3 only retries failed connections; it doesn't bound a stalled/slow transfer. A hung download would block the step until the job-level timeout-minutes kills it.

⏱️ Suggested fix
 fetch() {
-  curl --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 -fsSL "$1" -o "$2"
+  curl --proto '=https' --proto-redir '=https' --tlsv1.2 --retry 3 \
+       --connect-timeout 10 --max-time 120 -fsSL "$1" -o "$2"
 }
🤖 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/materialize/action.yml around lines 71 - 73, The fetch()
helper currently relies on curl retries but has no request timeout, so a stalled
download can hang the action step. Update fetch() in the materialize action to
add an explicit curl timeout option (for both connect and overall transfer)
while keeping the existing HTTPS-only and retry behavior, so the download fails
fast instead of waiting for the job timeout.

83-88: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value

INPUT_CHANNEL isn't restricted to an allowlist before being interpolated into the fetch URL.

arch is validated with a case statement (Lines 49-52), but channel flows straight into "$BASE/$INPUT_CHANNEL" unchecked. All current callers pass hardcoded literals (stable/unstable), so this isn't exploitable today, but as a reusable action it's worth constraining for defense-in-depth.

🤖 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/materialize/action.yml around lines 83 - 88, Validate
INPUT_CHANNEL in the action before it is used in fetch and only allow the
expected literals (for example, stable and unstable), similar to the existing
arch case check. Update the version-resolution block in materialize/action.yml
so the "$BASE/$INPUT_CHANNEL" URL is only constructed after the allowlist check,
and fail early with a clear error if the channel is anything else.

90-98: 🔒 Security & Privacy | 🔵 Trivial | 🏗️ Heavy lift

No integrity verification of the downloaded mip binary before execution.

The script fetches mip over TLS and immediately chmod +x + executes it (Line 98) with no checksum/signature check against the resolved version. TLS protects transport, but not against a compromised/tampered object in the bucket. Other fetch scripts in this repo are described elsewhere as "pin-verified" (e.g. gvproxy fetch) — this new path departs from that pattern for a binary that gets executed directly.

🔒 Suggested approach

Publish a checksum (e.g. sha256) alongside each mip-linux-$runner_arch build and verify it after fetch:

         bin="$RUNNER_TEMP/mip"
         fetch "$BASE/versions/$version/mip-linux-$runner_arch" "$bin"
+        fetch "$BASE/versions/$version/mip-linux-$runner_arch.sha256" "$bin.sha256"
+        (cd "$RUNNER_TEMP" && sha256sum -c <(awk '{print $1, "mip"}' mip.sha256))
         chmod +x "$bin"
🤖 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/materialize/action.yml around lines 90 - 98, The `mip`
download-and-execute path in the action script is missing integrity verification
before running the binary. Update the fetch flow around the `fetch`, `chmod +x`,
and `materialize` steps to verify the downloaded `mip-linux-$runner_arch`
artifact against a checksum or signature tied to the resolved `version` before
execution. Use the existing `version`/`runner_arch` resolution in this action to
locate the right verification data, and only proceed to `"$bin" materialize`
after the verification succeeds.

83-93: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Every materialize call re-resolves the channel and re-downloads mip, even within the same job.

release.yml's fetch-release-guest-artifacts job invokes this action 4 times back-to-back; ci-macos.yml/ci-linux-kvm.yml invoke it twice each. Each call re-fetches the channel pointer and the mip binary from scratch, since nothing persists resolution across steps in the same job ($RUNNER_TEMP is per-job, but the script never checks for an existing/matching binary before fetching again).

♻️ Suggested optimization
+        if [[ -x "$bin" ]] && [[ "$(cat "$RUNNER_TEMP/.mip-version" 2>/dev/null)" == "$version" ]]; then
+          echo "Reusing already-fetched mip $version"
+        else
+          fetch "$BASE/versions/$version/mip-linux-$runner_arch" "$bin"
+          chmod +x "$bin"
+          echo "$version" > "$RUNNER_TEMP/.mip-version"
+        fi
🤖 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/materialize/action.yml around lines 83 - 93, The materialize
action always re-resolves the channel and re-downloads mip on every invocation,
even when the same job has already resolved the same channel/version. Update the
action logic around the channel-pointer resolution and mip download to first
check for an existing cached/matching binary in the job temp area before calling
fetch again, and only re-fetch when the channel or version has changed. Keep the
behavior localized to the existing resolve-and-download flow using the
channel-pointer, version, and bin steps.
🤖 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/materialize/action.yml:
- Around line 71-73: The fetch() helper currently relies on curl retries but has
no request timeout, so a stalled download can hang the action step. Update
fetch() in the materialize action to add an explicit curl timeout option (for
both connect and overall transfer) while keeping the existing HTTPS-only and
retry behavior, so the download fails fast instead of waiting for the job
timeout.
- Around line 83-88: Validate INPUT_CHANNEL in the action before it is used in
fetch and only allow the expected literals (for example, stable and unstable),
similar to the existing arch case check. Update the version-resolution block in
materialize/action.yml so the "$BASE/$INPUT_CHANNEL" URL is only constructed
after the allowlist check, and fail early with a clear error if the channel is
anything else.
- Around line 90-98: The `mip` download-and-execute path in the action script is
missing integrity verification before running the binary. Update the fetch flow
around the `fetch`, `chmod +x`, and `materialize` steps to verify the downloaded
`mip-linux-$runner_arch` artifact against a checksum or signature tied to the
resolved `version` before execution. Use the existing `version`/`runner_arch`
resolution in this action to locate the right verification data, and only
proceed to `"$bin" materialize` after the verification succeeds.
- Around line 83-93: The materialize action always re-resolves the channel and
re-downloads mip on every invocation, even when the same job has already
resolved the same channel/version. Update the action logic around the
channel-pointer resolution and mip download to first check for an existing
cached/matching binary in the job temp area before calling fetch again, and only
re-fetch when the channel or version has changed. Keep the behavior localized to
the existing resolve-and-download flow using the channel-pointer, version, and
bin steps.

In @.github/workflows/ci-macos.yml:
- Around line 46-54: Update the stale explanatory comment in the CI macOS
workflow so it matches the current flow: the kernel/rootfs materialization is no
longer done by building the `minimal` CLI from this repo, but by fetching a
prebuilt `mip` through the composite action. Keep the comment focused on the
actual steps around the materialize job and the later `minimald`
cross-compilation/initramfs cache steps, and remove references to building
`minimal` or repo-source artifact generation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 411f96dd-dc7f-4f83-8d0f-47333ca05a9c

📥 Commits

Reviewing files that changed from the base of the PR and between 71b364b and 0a6fe80.

📒 Files selected for processing (4)
  • .github/actions/materialize/action.yml
  • .github/workflows/ci-linux-kvm.yml
  • .github/workflows/ci-macos.yml
  • .github/workflows/release.yml

@twitchyliquid64
twitchyliquid64 merged commit 3c9ea9b into main Jul 9, 2026
13 checks passed
@twitchyliquid64
twitchyliquid64 deleted the tom/release branch July 9, 2026 21:43
norrietaylor added a commit that referenced this pull request Jul 9, 2026
Resolves against #692, which introduced the materialize composite
(channel-released prebuilt mip; no source build) for the guest
kernel/rootfs pulls — superseding this branch's guest-artifacts
composite, which wrapped the same call sites around
scripts/fetch-artifact.sh. Resolution: adopt materialize at every
conflicted call site (ci-macos artifacts, ci-linux-kvm, release
fetch-release-guest-artifacts, including main's removal of the now
unneeded toolchain/protoc/cargo-cache steps in the release fetch
job), delete the guest-artifacts composite, and point the VM lanes'
composite path filters at .github/actions/materialize/** instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
norrietaylor added a commit that referenced this pull request Jul 9, 2026
Base moved to main's materialize composite (#692); union the mac
lane's composite path filters (materialize replaces guest-artifacts,
the vendor/libkrun/** pin entry stays).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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