diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 7345440..def7a4b 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -15,15 +15,20 @@ name: build-image +# DISABLED for now — the Forgejo runner sandbox blocks unshare(CLONE_NEWUSER) +# which all container build tools require. See ./kamos-build.sh for the +# replacement: a local Mac-based build script that pushes to this same +# Forgejo registry. Re-enable this workflow once the runner config is updated +# to allow privileged containers (container.privileged: true in act_runner +# config.yaml). on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - # Rebuild weekly so we pick up base-image security updates. - - cron: "0 6 * * 1" workflow_dispatch: + # push: + # branches: [main] + # pull_request: + # branches: [main] + # schedule: + # - cron: "0 6 * * 1" env: IMAGE_NAME: kamos diff --git a/kamos-build.sh b/kamos-build.sh new file mode 100755 index 0000000..5460726 --- /dev/null +++ b/kamos-build.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# ============================================================================= +# kamos-build.sh +# +# Build the KAMOS Gaming OS image directly on this Mac, push to Forgejo, +# and sign it. Replaces the broken Forgejo CI workflow. +# +# Usage: +# chmod +x kamos-build.sh +# ./kamos-build.sh +# +# What it does: +# 1. Checks Podman + cosign are installed (offers to install if not) +# 2. Starts the Podman virtual machine (Linux env on macOS) +# 3. Builds linux/amd64 image (uses QEMU emulation on Apple Silicon - slow +# first time, ~30-60 min; faster afterwards because layers cache) +# 4. Logs into your Forgejo registry +# 5. Pushes the image +# 6. Signs it with cosign +# ============================================================================= + +set -euo pipefail + +# ---- config ---------------------------------------------------------------- +REGISTRY="cgi.medsys.cloud" +NAMESPACE="mkm1971" +IMAGE_NAME="kamos" +IMAGE_REF="${REGISTRY}/${NAMESPACE}/${IMAGE_NAME}" +TAGS=("stable" "latest" "$(date +%Y%m%d)") + +GREEN="\033[0;32m" +YELLOW="\033[1;33m" +RED="\033[0;31m" +NC="\033[0m" + +log() { echo -e "${GREEN}==>${NC} $*"; } +warn() { echo -e "${YELLOW}!! ${NC} $*"; } +err() { echo -e "${RED}!! ${NC} $*" >&2; } + +# ---- preflight ------------------------------------------------------------- +log "Pre-flight checks" + +if ! command -v brew >/dev/null 2>&1; then + err "Homebrew is not installed. Install it first from https://brew.sh" + exit 1 +fi + +for tool in podman cosign; do + if ! command -v "$tool" >/dev/null 2>&1; then + warn "$tool not found. Installing via brew..." + brew install "$tool" + fi +done + +# ---- podman machine -------------------------------------------------------- +log "Ensure podman machine is running" + +if ! podman machine list --format '{{.Name}} {{.Running}}' | grep -q "true"; then + if ! podman machine list --format '{{.Name}}' | grep -q .; then + log "No podman machine yet - creating one (8 GB RAM, 80 GB disk)" + podman machine init --cpus 6 --memory 8192 --disk-size 80 + fi + log "Starting podman machine" + podman machine start +fi + +# ---- build ---------------------------------------------------------------- +log "Build linux/amd64 image (this is the slow step on Apple Silicon)" + +build_args=() +for t in "${TAGS[@]}"; do + build_args+=(--tag "${IMAGE_REF}:${t}") +done + +podman build \ + --platform=linux/amd64 \ + --pull=newer \ + "${build_args[@]}" \ + . + +log "Build complete" +podman images | grep "${IMAGE_NAME}" || true + +# ---- login ---------------------------------------------------------------- +log "Login to Forgejo registry at ${REGISTRY}" +warn "When prompted: username = ${NAMESPACE}, password = your REGISTRY_TOKEN" + +podman login "${REGISTRY}" --username "${NAMESPACE}" + +# ---- push ----------------------------------------------------------------- +log "Push image with all tags" + +for t in "${TAGS[@]}"; do + log " pushing ${IMAGE_REF}:${t}" + podman push "${IMAGE_REF}:${t}" +done + +# ---- sign ----------------------------------------------------------------- +if [ -f cosign.key ]; then + log "Sign image with cosign" + for t in "${TAGS[@]}"; do + digest=$(podman image inspect "${IMAGE_REF}:${t}" --format '{{.Digest}}' 2>/dev/null || true) + if [ -z "$digest" ]; then + digest=$(skopeo inspect --format '{{.Digest}}' "docker://${IMAGE_REF}:${t}" 2>/dev/null || true) + fi + if [ -n "$digest" ]; then + log " signing ${IMAGE_REF}@${digest}" + COSIGN_PASSWORD="" cosign sign --yes --key cosign.key "${IMAGE_REF}@${digest}" + else + warn "Could not get digest for tag ${t} - skipping sign" + fi + done +else + warn "cosign.key not found in repo - skipping image signing" +fi + +# ---- done ----------------------------------------------------------------- +echo +log "All done." +echo +echo " Image: ${IMAGE_REF}" +echo " Tags: ${TAGS[*]}" +echo +echo " Switch your NVIDIA PC to it with:" +echo +echo " sudo bootc switch ${IMAGE_REF}:stable" +echo " sudo systemctl reboot" +echo