ci(bluebuild): port build to Forgejo runner (nullstone label)
Some checks failed
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 18s
Some checks failed
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 18s
A1 inline (agent failed on worktree base mismatch). Adapt build-bluebuild.yml to run on the Forgejo self-hosted runner using the same lessons from build-iso.yml debug: - runs-on: nullstone (resolves to veilor-build:43, fedora43+nodejs) - BlueBuild CLI installed in-job from upstream release tarball v0.9.10 - podman/buildah/skopeo/cosign installed via dnf - bluebuild build with podman driver + skopeo inspect + cosign signing - Push primary to Forgejo registry git.s8n.ru/veilor-org/veilor-os - GHCR push gated to github.server_url == 'https://github.com' only - SBOM + attest-build-provenance gated GH-only (Forgejo has no Fulcio) - All third-party actions remain pinned to node20-shipping versions Secrets needed in Forgejo repo settings: - FORGEJO_REGISTRY_TOKEN: PAT with package:write on veilor-org - FORGEJO_REGISTRY_USER: 's8n-ru' (or org member with write scope) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e485844dc4
commit
f72569afcb
1 changed files with 112 additions and 49 deletions
161
.github/workflows/build-bluebuild.yml
vendored
161
.github/workflows/build-bluebuild.yml
vendored
|
|
@ -1,16 +1,12 @@
|
|||
name: Build veilor-os OCI (BlueBuild)
|
||||
|
||||
# v0.7 spike — builds the bootable OCI image used by the bootstrap
|
||||
# kickstart's `ostreecontainer` directive. Active only on the
|
||||
# `v0.7-bluebuild-spike` branch until the spike passes success
|
||||
# criteria (see bluebuild/README.md).
|
||||
# kickstart's `ostreecontainer` directive. Runs on the Forgejo
|
||||
# self-hosted runner (label `nullstone`); GitHub-side cosign/SBOM/
|
||||
# attest steps are gated off because Forgejo has no Sigstore Fulcio-
|
||||
# trusted OIDC issuer (see docs/PROOF-OF-WORK.md, build-iso.yml fix).
|
||||
#
|
||||
# Reference: https://blue-build.org/how-to/setup-build-action/
|
||||
#
|
||||
# Security note: all `${{ }}` interpolations in this file are restricted
|
||||
# to vetted GitHub-controlled values (repository_owner, run number,
|
||||
# secrets, signed action outputs). No `github.event.issue.title` or
|
||||
# similar untrusted-user-input is read in run blocks.
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
@ -33,73 +29,140 @@ permissions:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
name: Build + sign + push OCI
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
name: Build + push OCI
|
||||
# nullstone label resolves to veilor-build:43 (fedora43 + nodejs)
|
||||
# via runner config. Privileged + userns=host + sock pass-through
|
||||
# already wired in the runner config (see infra/forgejo/).
|
||||
runs-on: nullstone
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # push to ghcr.io/veilor-org/veilor-os
|
||||
id-token: write # cosign keyless signing via Sigstore
|
||||
attestations: write # SLSA build provenance
|
||||
packages: write
|
||||
id-token: write # for GH-only cosign keyless (skipped on Forgejo)
|
||||
attestations: write
|
||||
|
||||
env:
|
||||
OCI_IMAGE: ghcr.io/${{ github.repository_owner }}/veilor-os
|
||||
OCI_TAG: latest
|
||||
# Forgejo container registry path. PAT in FORGEJO_REGISTRY_TOKEN
|
||||
# secret has package:write on veilor-org.
|
||||
FORGEJO_REGISTRY: git.s8n.ru
|
||||
FORGEJO_IMAGE: git.s8n.ru/veilor-org/veilor-os
|
||||
OCI_TAG: "43"
|
||||
# GH parallel target — only used when run on github.com.
|
||||
GHCR_IMAGE: ghcr.io/${{ github.repository_owner }}/veilor-os
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
# Pinned to last v4 tag confirmed to ship on node20. v4.2+ ships
|
||||
# node24 which forgejo-runner v6.4.0 (node20) cannot exec.
|
||||
# Pinned to last v4 tag confirmed to ship on node20.
|
||||
uses: actions/checkout@v4.1.7
|
||||
|
||||
- name: Free up disk
|
||||
- name: Install build tooling (Fedora)
|
||||
run: |
|
||||
sudo rm -rf /opt/hostedtoolcache /usr/share/dotnet /usr/local/lib/android
|
||||
sudo apt-get clean
|
||||
df -h
|
||||
set -euxo pipefail
|
||||
dnf -y upgrade --refresh
|
||||
dnf -y install \
|
||||
podman \
|
||||
buildah \
|
||||
skopeo \
|
||||
jq \
|
||||
git \
|
||||
curl \
|
||||
tar \
|
||||
sudo \
|
||||
cosign
|
||||
|
||||
# BlueBuild action wraps: image build, cosign sign (keyless via
|
||||
# Sigstore), GHCR push. Pinned to a commit SHA per CI hardening
|
||||
# agent 8 (2026-05-05 wave). The trailing comment records the
|
||||
# tag the SHA resolved from, so future bumps stay legible.
|
||||
- name: Build + push veilor-os OCI
|
||||
id: bluebuild
|
||||
uses: blue-build/github-action@24d146df25adc2cf579e918efe2d9bff6adea408 # v1
|
||||
with:
|
||||
recipe: bluebuild/recipe.yml
|
||||
registry_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
pr_event_number: ${{ github.event.number }}
|
||||
maximize_build_space: true
|
||||
- name: Install BlueBuild CLI
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
BB_VERSION="0.9.10"
|
||||
BB_URL="https://github.com/blue-build/cli/releases/download/v${BB_VERSION}/bluebuild-x86_64-unknown-linux-gnu.tar.gz"
|
||||
curl -fsSL "$BB_URL" -o /tmp/bb.tgz
|
||||
tar -xzf /tmp/bb.tgz -C /usr/local/bin/
|
||||
chmod +x /usr/local/bin/bluebuild
|
||||
bluebuild --version
|
||||
|
||||
- name: Build OCI image with BlueBuild
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
cd bluebuild
|
||||
# bluebuild build:
|
||||
# --recipe-path => path to recipe.yml
|
||||
# --tag => local tag, then we re-tag for registries
|
||||
# podman driver to avoid Docker socket coupling
|
||||
bluebuild build \
|
||||
--debug \
|
||||
--build-driver podman \
|
||||
--inspect-driver skopeo \
|
||||
--signing-driver cosign \
|
||||
recipe.yml
|
||||
# bluebuild tags as `<image-name>:latest` locally. Confirm it
|
||||
# lands and re-tag for both registries.
|
||||
podman images
|
||||
podman tag localhost/veilor-os:latest "${FORGEJO_IMAGE}:${OCI_TAG}"
|
||||
podman tag localhost/veilor-os:latest "${FORGEJO_IMAGE}:latest"
|
||||
|
||||
- name: Push to Forgejo registry (primary)
|
||||
if: success() && github.event_name != 'pull_request' && github.server_url != 'https://github.com'
|
||||
env:
|
||||
FORGEJO_REGISTRY_TOKEN: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
||||
FORGEJO_REGISTRY_USER: ${{ secrets.FORGEJO_REGISTRY_USER }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [ -z "${FORGEJO_REGISTRY_TOKEN:-}" ]; then
|
||||
echo "[WARN] FORGEJO_REGISTRY_TOKEN secret is empty; skipping push"
|
||||
exit 0
|
||||
fi
|
||||
echo "$FORGEJO_REGISTRY_TOKEN" | podman login \
|
||||
--username "${FORGEJO_REGISTRY_USER:-veilor-org}" \
|
||||
--password-stdin "$FORGEJO_REGISTRY"
|
||||
podman push "${FORGEJO_IMAGE}:${OCI_TAG}"
|
||||
podman push "${FORGEJO_IMAGE}:latest"
|
||||
echo "[OK] pushed ${FORGEJO_IMAGE}:{${OCI_TAG},latest}"
|
||||
|
||||
- name: Push to GHCR (mirror, GitHub-only)
|
||||
if: success() && github.event_name != 'pull_request' && github.server_url == 'https://github.com'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
podman tag localhost/veilor-os:latest "${GHCR_IMAGE}:${OCI_TAG}"
|
||||
podman tag localhost/veilor-os:latest "${GHCR_IMAGE}:latest"
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | podman login \
|
||||
--username "${{ github.repository_owner }}" \
|
||||
--password-stdin ghcr.io
|
||||
podman push "${GHCR_IMAGE}:${OCI_TAG}"
|
||||
podman push "${GHCR_IMAGE}:latest"
|
||||
|
||||
- name: Smoke-test OCI image
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
run: |
|
||||
podman pull "$OCI_IMAGE:$OCI_TAG"
|
||||
podman run --rm "$OCI_IMAGE:$OCI_TAG" /bin/bash -c '
|
||||
set -euxo pipefail
|
||||
podman run --rm "localhost/veilor-os:latest" /bin/bash -c '
|
||||
set -e
|
||||
echo "-- os-release"
|
||||
head -5 /etc/os-release
|
||||
echo "-- sudo present"; which sudo
|
||||
echo "-- mullvad-browser present"; which mullvad-browser
|
||||
echo "-- yggdrasil present"; which yggdrasil
|
||||
echo "-- tailscale present"; which tailscale
|
||||
echo "-- mullvad-browser path"; rpm -q mullvad-browser || echo "not installed"
|
||||
echo "-- yggdrasil"; rpm -q yggdrasil || echo "not installed"
|
||||
echo "-- tailscale"; rpm -q tailscale || echo "not installed"
|
||||
echo "-- veilor-firstboot unit"; ls -la /etc/systemd/system/veilor-firstboot.service 2>&1 || true
|
||||
'
|
||||
|
||||
- name: SBOM (SPDX)
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
# Pinned to last v0 tag confirmed to ship on node20. The `@v0`
|
||||
# floating tag rolls forward and will eventually pull a node24
|
||||
# release. TODO(infra): SHA pin in a follow-up sweep.
|
||||
# ── GitHub-only signing/SBOM/attest ────────────────────────────
|
||||
# cosign keyless needs Sigstore Fulcio-trusted OIDC. Forgejo
|
||||
# has none, so these are GH-only. v0.7+ TODO: cosign key-pair
|
||||
# signing for Forgejo using a stored secret.
|
||||
|
||||
- name: SBOM (SPDX, GitHub-only)
|
||||
if: github.event_name == 'push' && github.server_url == 'https://github.com'
|
||||
# Pinned to last v0.17 release that ships node20.
|
||||
uses: anchore/sbom-action@v0.17.2
|
||||
with:
|
||||
image: ${{ env.OCI_IMAGE }}:${{ env.OCI_TAG }}
|
||||
image: ${{ env.GHCR_IMAGE }}:${{ env.OCI_TAG }}
|
||||
format: spdx-json
|
||||
output-file: veilor-os-oci.spdx.json
|
||||
|
||||
- name: Build provenance attestation
|
||||
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
|
||||
# Pinned to last v2 tag confirmed to ship on node20.
|
||||
- name: Build provenance attestation (GitHub-only)
|
||||
if: github.event_name == 'push' && github.server_url == 'https://github.com'
|
||||
# Pinned to last v2.2 release that ships node20.
|
||||
uses: actions/attest-build-provenance@v2.2.3
|
||||
with:
|
||||
subject-name: ${{ env.OCI_IMAGE }}
|
||||
subject-name: ${{ env.GHCR_IMAGE }}
|
||||
subject-digest: ${{ steps.bluebuild.outputs.digest }}
|
||||
|
|
|
|||
Loading…
Reference in a new issue