veilor-os/.github/workflows/build-bluebuild.yml
claude-veilor-bot f72569afcb
Some checks failed
Build veilor-os OCI (BlueBuild) / Build + push OCI (push) Failing after 18s
ci(bluebuild): port build to Forgejo runner (nullstone label)
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>
2026-05-06 16:44:52 +01:00

168 lines
6.5 KiB
YAML

name: Build veilor-os OCI (BlueBuild)
# v0.7 spike — builds the bootable OCI image used by the bootstrap
# 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/
on:
push:
branches: [v0.7-bluebuild-spike]
paths:
- 'bluebuild/**'
- 'overlay/**'
- 'assets/**'
- 'scripts/**'
- '.github/workflows/build-bluebuild.yml'
pull_request:
branches: [main, v0.7-bluebuild-spike]
schedule:
# Rebuild weekly so we pick up upstream secureblue + Fedora updates.
- cron: '0 6 * * 1'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
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
id-token: write # for GH-only cosign keyless (skipped on Forgejo)
attestations: write
env:
# 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.
uses: actions/checkout@v4.1.7
- name: Install build tooling (Fedora)
run: |
set -euxo pipefail
dnf -y upgrade --refresh
dnf -y install \
podman \
buildah \
skopeo \
jq \
git \
curl \
tar \
sudo \
cosign
- 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: |
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 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
'
# ── 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.GHCR_IMAGE }}:${{ env.OCI_TAG }}
format: spdx-json
output-file: veilor-os-oci.spdx.json
- 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.GHCR_IMAGE }}
subject-digest: ${{ steps.bluebuild.outputs.digest }}