mirror of
https://github.com/hanzoai/visor.git
synced 2026-09-24 17:04:14 +00:00
`runsc --version` prints two lines, and -visor is in neither:
runsc version <STABLE_VERSION>
spec: <OCI spec version>
STABLE_VERSION is `git describe --always --tags` — tools/workspace_status.sh,
wired by .bazelrc, substituted through runsc/BUILD's x_defs. The spec line is
opencontainers/runtime-spec's. The -visor suffix lives in
pkg/sentry/kernel/version/version.go: it is the release the sandbox advertises
through uname(2), which only a process inside a running sandbox can read. Its
own comment says as much — the two builds "are told apart by asking the guest".
So the gate fails for every build that can exist. visor-20260919.0 is queued and
has never run; it would have compiled all of gVisor and died on the last line
before creating the release, reading as a broken fork rather than a bad grep.
Assert what the binary does report, and what a release needs anyway: that the
bytes carry the tag being published. At a tag, describe returns the tag name, so
the line is exactly `runsc version $TAG`. Everything that should be rejected
still is — VERSION_MISSING with no stamp, 0.0.0 or a bare commit with no tag in
reach, -dirty from a modified tree, and upstream, whose tags are release-*.
The bazelisk asset now names the pool it runs on. bazelisk publishes <os>-<arch>
with exactly the labels our runners carry, so the arm64 row cannot come back
downloading an amd64 bazel.
Co-authored-by: Hanzo Dev <[email protected]>
136 lines
6.3 KiB
YAML
136 lines
6.3 KiB
YAML
name: publish
|
|
|
|
# A node must install the sandbox boundary from a VERIFIED artifact: every
|
|
# binary ships beside its sha512, and universe's install.sh pins those digests,
|
|
# so a tampered or truncated download aborts instead of running an unverified
|
|
# boundary.
|
|
#
|
|
# Until this lane existed, the visor on each node was built by hand from a
|
|
# working tree — 102MB nobody could reproduce, attribute to a commit, or check.
|
|
#
|
|
# It runs on OUR self-hosted pools, not GitHub's machines, and publishes with
|
|
# the token every run is given, so there is no credential here that can rot.
|
|
#
|
|
# IT LIVES IN .hanzo/workflows FOR THAT REASON. Under .github/ it is a workflow
|
|
# only GitHub Actions would run, and this estate has no runners there: the lane
|
|
# sat at .github/workflows/publish.yml, tag visor-20260911.0 was pushed at a
|
|
# commit that already carried it, and no release was ever created. A workflow in
|
|
# the wrong directory does not fail — it waits, which reads exactly like a lane
|
|
# nobody triggered.
|
|
on:
|
|
push:
|
|
tags: ['visor-*']
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: An existing visor-* tag to publish
|
|
required: true
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
binaries:
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- arch: x86_64
|
|
runs-on: linux-amd64
|
|
# aarch64 is NOT here yet, and that is a measurement: the runner image
|
|
# oci.hanzo.ai/hanzoai/git-runner:5 is a single manifest, so an arm64
|
|
# node cannot start it — its pods StartError and the job then sits
|
|
# queued forever, which looks like nothing happening. Add this arch
|
|
# back in the same commit that publishes a multi-arch runner image.
|
|
#
|
|
# - arch: aarch64
|
|
# runs-on: linux-arm64
|
|
runs-on: ${{ matrix.runs-on }}
|
|
env:
|
|
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
|
|
|
|
# ONE bazel invocation for both, so the shim and the runtime it execs are
|
|
# always the same build. A shim paired with a runtime it was not built
|
|
# against fails at container start, after admission.
|
|
# bazel DIRECTLY, not `make copy`: the Makefile wraps bazel in a container
|
|
# and pushes to an upstream registry, so it needs a docker socket our
|
|
# runners do not have — it failed with `dial unix /var/run/docker.sock`
|
|
# before building anything.
|
|
#
|
|
# bazelisk rather than a pinned bazel, because the repo states its own
|
|
# version in .bazelversion and bazelisk is the one thing that reads it.
|
|
#
|
|
# Installed WITHOUT sudo, into a directory this job already owns. Runners
|
|
# execute inside the visor sandbox, where setuid is not honoured — sudo
|
|
# there fails with "nosuid", so any step that reaches for root fails
|
|
# before it does anything.
|
|
- name: Install bazelisk
|
|
run: |
|
|
set -eu
|
|
mkdir -p "$HOME/.local/bin"
|
|
# The RELEASE is pinned; no digest is asserted, because a checksum
|
|
# nobody verified out-of-band is theatre. What this lane actually
|
|
# proves is the binary it produces — the version gate below rejects
|
|
# anything not stamped with the tag being published.
|
|
#
|
|
# The asset is named after the pool: bazelisk publishes <os>-<arch>
|
|
# with exactly the labels our runners carry, so the download cannot
|
|
# be a different architecture from the machine that runs it.
|
|
curl -fsSL -o "$HOME/.local/bin/bazel" \
|
|
"https://github.com/bazelbuild/bazelisk/releases/download/v1.25.0/bazelisk-${{ matrix.runs-on }}"
|
|
chmod 0755 "$HOME/.local/bin/bazel"
|
|
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
"$HOME/.local/bin/bazel" version
|
|
|
|
- name: Build
|
|
run: |
|
|
set -eu
|
|
bazel build //runsc:runsc //shim:containerd-shim-runsc-v1
|
|
mkdir -p bin
|
|
cp -L "$(find -L bazel-bin/runsc -type f -name runsc | head -1)" bin/runsc
|
|
cp -L "$(find -L bazel-bin -type f -name containerd-shim-runsc-v1 | head -1)" bin/containerd-shim-runsc-v1
|
|
|
|
# The runtime installs as `visor` — the name the containerd handler and the
|
|
# RuntimeClass both use. Asking it for its version is the cheapest proof the
|
|
# bytes are this tag: .bazelrc stamps STABLE_VERSION from
|
|
# `git describe --always --tags` through runsc/BUILD's x_defs, and cli.go
|
|
# prints it as `runsc version <stamp>`. At a tag, describe returns the tag
|
|
# name — so an unstamped build (VERSION_MISSING), a build with no tag in
|
|
# reach (0.0.0 or a bare commit) and a modified tree (-dirty) all fail here.
|
|
#
|
|
# It does NOT print -visor. That suffix is the guest kernel's uname release
|
|
# in pkg/sentry/kernel/version/version.go, which only a process inside a
|
|
# running sandbox can read, so grepping the runtime's own --version for it
|
|
# could never pass: the gate burned a whole gVisor build to fail on its
|
|
# last line, having published nothing.
|
|
- name: Name the bytes and prove they are this tag
|
|
run: |
|
|
set -eu
|
|
cd bin
|
|
mv runsc visor
|
|
chmod 0755 visor containerd-shim-runsc-v1
|
|
./visor --version | tee version.txt
|
|
grep -qx "runsc version $TAG" version.txt || { echo "FATAL: this binary is stamped $(head -1 version.txt), not $TAG"; exit 1; }
|
|
for f in visor containerd-shim-runsc-v1; do
|
|
sha512sum "$f" | awk '{print $1}' > "$f-${{ matrix.arch }}.sha512"
|
|
mv "$f" "$f-${{ matrix.arch }}"
|
|
done
|
|
ls -l
|
|
|
|
- name: Publish to the release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -eu
|
|
gh release view "$TAG" >/dev/null 2>&1 || gh release create "$TAG" --title "$TAG" --notes "Verified visor binaries, built on our own runners."
|
|
cd bin
|
|
gh release upload "$TAG" \
|
|
"visor-${{ matrix.arch }}" "visor-${{ matrix.arch }}.sha512" \
|
|
"containerd-shim-runsc-v1-${{ matrix.arch }}" "containerd-shim-runsc-v1-${{ matrix.arch }}.sha512" \
|
|
--clobber
|
|
echo "published $(ls | tr '\n' ' ')"
|