############################################################################### # Forgejo Actions - build, sign, and push the KAMOS Gaming OS image # # Configured for: cgi.medsys.cloud/mkm1971/kamos # Runner labels: ubuntu-latest / ubuntu-24.04 / ubuntu-22.04 (Forgejo runner v0.4.1) # # Prereqs in your Forgejo repo: # 1. Container Registry feature enabled on cgi.medsys.cloud. # 2. The runner host must be x86_64 (Bazzite NVIDIA is x86_64 only). # 3. Repository secrets at /mkm1971/kamos/settings/actions/secrets: # - SIGNING_SECRET contents of cosign.key (NOT the .pub) # - REGISTRY_USER mkm1971 # - REGISTRY_TOKEN Forgejo access token with `package` write scope ############################################################################### 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: workflow_dispatch: # push: # branches: [main] # pull_request: # branches: [main] # schedule: # - cron: "0 6 * * 1" env: IMAGE_NAME: kamos IMAGE_TAGS: "stable latest" # Override this in your Forgejo repo's variables to point at your instance. REGISTRY: ${{ vars.REGISTRY || 'cgi.medsys.cloud' }} REGISTRY_USER: ${{ secrets.REGISTRY_USER }} REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }} jobs: build: name: Build & push (${{ matrix.platform }}) # Matches your runner labels: ubuntu-latest / ubuntu-24.04 / ubuntu-22.04 # Assumes the runner host is x86_64 - if it's actually Apple Silicon, the # build will hit "exec format error" and we'll need to add binfmt qemu setup. runs-on: ubuntu-latest permissions: contents: read packages: write strategy: fail-fast: false matrix: platform: [linux/amd64] steps: # Manual checkout that bypasses the runner's broken internal URL. # The runner's `instance` is configured as http://forgejo:3000 which it # cannot resolve, so actions/checkout@v4 fails. We clone from the # public URL directly using REGISTRY_TOKEN for auth. - name: Checkout (manual workaround for runner internal URL) shell: bash env: TOKEN: ${{ secrets.REGISTRY_TOKEN }} REPO: ${{ gitea.repository }} SHA: ${{ gitea.sha }} run: | set -eo pipefail # Don't echo the token-bearing URL into logs set +x REMOTE="https://mkm1971:${TOKEN}@cgi.medsys.cloud/${REPO}.git" git init -q . git remote add origin "$REMOTE" git fetch --depth=1 origin "${SHA:-main}" git checkout -q FETCH_HEAD # Scrub the credential out of the remote so later steps can't leak it git remote set-url origin "https://cgi.medsys.cloud/${REPO}.git" set -x git log --oneline -1 - name: Compute tags id: tags shell: bash run: | DATE_TAG="$(date +%Y%m%d)" SHA_TAG="${GITHUB_SHA::7}" { echo "date_tag=${DATE_TAG}" echo "sha_tag=${SHA_TAG}" echo "image_ref=${REGISTRY}/${{ gitea.repository_owner }}/${IMAGE_NAME}" } >> "$GITHUB_OUTPUT" - name: Install build tooling shell: bash env: COSIGN_VERSION: v2.4.1 run: | set -euxo pipefail # podman, buildah, skopeo, jq come from Ubuntu repos. sudo apt-get update -y sudo apt-get install -y podman buildah skopeo jq curl ca-certificates # cosign is NOT in apt - install the official binary from sigstore. sudo curl -fsSL \ "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64" \ -o /usr/local/bin/cosign sudo chmod +x /usr/local/bin/cosign # Verify everything is callable. podman --version buildah --version skopeo --version cosign version jq --version # Build with buildah + vfs + chroot isolation. This combo avoids: # - user namespaces (which need newuidmap and aren't always allowed) # - overlay mounts (which need mount propagation) # - clone() with CLONE_NEW* flags (which seccomp may block) # Run with sudo so we already have full caps and don't need to unshare. - name: Build image id: build shell: bash env: IMAGE_REF: ${{ steps.tags.outputs.image_ref }} DATE_TAG: ${{ steps.tags.outputs.date_tag }} SHA_TAG: ${{ steps.tags.outputs.sha_tag }} BUILDAH_ISOLATION: chroot STORAGE_DRIVER: vfs run: | set -euxo pipefail sudo BUILDAH_ISOLATION=chroot STORAGE_DRIVER=vfs buildah \ --storage-driver=vfs \ bud \ --isolation=chroot \ --platform=${{ matrix.platform }} \ --pull-always \ --tag "${IMAGE_REF}:${DATE_TAG}" \ --tag "${IMAGE_REF}:${SHA_TAG}" \ $(for t in $IMAGE_TAGS; do echo --tag "${IMAGE_REF}:${t}"; done) \ . - name: Login to Forgejo container registry if: github.event_name != 'pull_request' shell: bash run: | echo "${REGISTRY_TOKEN}" | sudo buildah --storage-driver=vfs login \ --username "${REGISTRY_USER}" \ --password-stdin \ "${REGISTRY}" - name: Push image if: github.event_name != 'pull_request' shell: bash env: IMAGE_REF: ${{ steps.tags.outputs.image_ref }} DATE_TAG: ${{ steps.tags.outputs.date_tag }} SHA_TAG: ${{ steps.tags.outputs.sha_tag }} run: | set -euxo pipefail for tag in $DATE_TAG $SHA_TAG $IMAGE_TAGS; do sudo buildah --storage-driver=vfs push "${IMAGE_REF}:${tag}" done - name: Sign image with cosign if: github.event_name != 'pull_request' shell: bash env: COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }} COSIGN_PASSWORD: "" IMAGE_REF: ${{ steps.tags.outputs.image_ref }} run: | set -euxo pipefail for tag in $IMAGE_TAGS; do # skopeo inspect against private registry needs creds DIGEST=$(skopeo inspect \ --creds "${REGISTRY_USER}:${REGISTRY_TOKEN}" \ --format '{{.Digest}}' \ "docker://${IMAGE_REF}:${tag}") cosign sign --yes --key env://COSIGN_PRIVATE_KEY "${IMAGE_REF}@${DIGEST}" done - name: Summary shell: bash env: IMAGE_REF: ${{ steps.tags.outputs.image_ref }} run: | { echo "### Built image" echo "" echo "\`${IMAGE_REF}\` with tags: ${IMAGE_TAGS}" echo "" echo "Switch a target machine to this image with:" echo "" echo "\`\`\`" echo "sudo bootc switch ${IMAGE_REF}:stable" echo "\`\`\`" } >> "$GITHUB_STEP_SUMMARY"