The tagged ISO workflow fetched bos-settings/src/Cargo.toml from the dev branch (404 after the Tauri split) and cargo-built bread-theme. bread-theme 0.7.1 is already on the stable index. Stage required bins, units, breadhelp content, and desktop/license files from the minisign-verified index instead; optional bread-emit/module-host skip until bread publishes them. Fail the bake if a required bin is missing.
203 lines
8.6 KiB
YAML
203 lines
8.6 KiB
YAML
name: Build and release ISO
|
|
|
|
# Builds the BOS ISO on the hestia self-hosted runner (native Arch container).
|
|
# Stages bakery desktop apps from the *minisign-verified* stable index at
|
|
# https://dl.breadway.dev/index.json (see iso/bread-lockfile.toml), then runs
|
|
# build-local.sh and uploads the ISO to a Forgejo release. A matching GitHub
|
|
# release is created best-effort and points at Forgejo for the download
|
|
# (GitHub releases cannot host files larger than 2 GB).
|
|
#
|
|
# Required secrets:
|
|
# RELEASE_TOKEN — Forgejo API token with write:repository scope
|
|
# MIRROR_TOKEN — GitHub personal access token with repo scope
|
|
# GPG_PRIVATE_KEY — armoured secret key for the dedicated "BOS Release Signing"
|
|
# identity (releases@breadway.dev); public half is committed
|
|
# at KEYS.asc for verifying ISO SHA256SUMS only. That key
|
|
# does not sign the [breadway] pacman repo. No passphrase
|
|
# (CI-only key, access controlled via the Forgejo secret
|
|
# store).
|
|
|
|
on:
|
|
push:
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: 'Git tag to build (e.g. v0.4.0)'
|
|
required: true
|
|
|
|
jobs:
|
|
release-iso:
|
|
runs-on: [self-hosted, hestia]
|
|
container:
|
|
# Floating tag: this environment cannot pin a reproducible digest of
|
|
# archlinux:latest. Do not invent one.
|
|
image: archlinux:latest
|
|
# --privileged: mkarchiso needs CAP_SYS_ADMIN for loop mounts + mknod
|
|
# --network=host: gives localhost:3002 access to Forgejo (avoids the
|
|
# public git.breadway.dev → Aegis → Tailscale round-trip for pacman)
|
|
options: --privileged --network=host
|
|
|
|
steps:
|
|
- name: Install build dependencies
|
|
run: |
|
|
pacman -Syu --noconfirm archiso curl python git minisign
|
|
|
|
- name: Determine tag and version
|
|
id: vars
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
|
TAG="${{ github.event.inputs.tag }}"
|
|
else
|
|
TAG="${{ github.ref_name }}"
|
|
fi
|
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Clone repository at tag
|
|
run: |
|
|
git clone --branch "${{ steps.vars.outputs.tag }}" --depth 1 \
|
|
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /bos
|
|
|
|
- name: Stage bakery ecosystem from signed stable index
|
|
run: |
|
|
set -euo pipefail
|
|
cd /bos
|
|
LAPTOP_HOME=/build-home python3 scripts/ci-stage-bakery.py
|
|
|
|
- name: Verify staged bakery bake inputs
|
|
run: |
|
|
set -euo pipefail
|
|
cd /bos
|
|
LAPTOP_HOME=/build-home bash scripts/ci-verify-bake.sh
|
|
|
|
- name: Build ISO
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p /bos-work /bos-out
|
|
cd /bos
|
|
LAPTOP_HOME=/build-home \
|
|
WORK=/bos-work \
|
|
OUT=/bos-out \
|
|
CI_BUILD=1 \
|
|
bash build-local.sh
|
|
ls -lh /bos-out/*.iso
|
|
|
|
- name: Checksum and sign
|
|
env:
|
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
VERSION="${{ steps.vars.outputs.version }}"
|
|
ISO=$(ls /bos-out/*.iso | head -1)
|
|
ISO_NAME="bos-${VERSION}-x86_64.iso"
|
|
cd /bos-out
|
|
mv "$(basename "$ISO")" "$ISO_NAME"
|
|
|
|
sha256sum "$ISO_NAME" > SHA256SUMS
|
|
cat SHA256SUMS
|
|
|
|
pacman -S --noconfirm --needed gnupg
|
|
export GNUPGHOME=/tmp/gnupg-release
|
|
mkdir -m 700 -p "$GNUPGHOME"
|
|
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
|
|
gpg --batch --yes --local-user releases@breadway.dev \
|
|
--detach-sign --armor -o SHA256SUMS.asc SHA256SUMS
|
|
echo "Signed SHA256SUMS -> SHA256SUMS.asc"
|
|
|
|
- name: Create Forgejo release and upload assets
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
TAG="${{ steps.vars.outputs.tag }}"
|
|
VERSION="${{ steps.vars.outputs.version }}"
|
|
ISO_NAME="bos-${VERSION}-x86_64.iso"
|
|
|
|
# Use an existing release for this tag if one exists (e.g. created
|
|
# manually or by a prior re-run), otherwise create a fresh one.
|
|
EXISTING=$(curl -sf \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
|
|
2>/dev/null || true)
|
|
RELEASE_ID=$(echo "${EXISTING}" | python3 -c \
|
|
"import json,sys; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
|
|
|
|
if [ -z "${RELEASE_ID}" ]; then
|
|
RELEASE=$(curl -fsS -X POST \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases" \
|
|
-d "{
|
|
\"tag_name\": \"${TAG}\",
|
|
\"name\": \"BOS ${TAG}\",
|
|
\"prerelease\": false,
|
|
\"body\": \"ISO image attached below. Verify with SHA256SUMS + SHA256SUMS.asc (signed by the BOS Release Signing key — see KEYS.asc in the repo).\\n\\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.\"
|
|
}")
|
|
RELEASE_ID=$(echo "${RELEASE}" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")
|
|
fi
|
|
echo "Using release ID: ${RELEASE_ID}"
|
|
|
|
upload_asset() {
|
|
local file="$1" name
|
|
name="$(basename "$file")"
|
|
local asset_id
|
|
asset_id=$(curl -sf \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets" \
|
|
| python3 -c "
|
|
import json,sys
|
|
assets=json.load(sys.stdin)
|
|
match=[a['id'] for a in assets if a['name']=='${name}']
|
|
print(match[0] if match else '')
|
|
" 2>/dev/null || true)
|
|
if [ -n "${asset_id}" ]; then
|
|
curl -fsS -X DELETE \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets/${asset_id}"
|
|
echo "Removed existing ${name} asset"
|
|
fi
|
|
curl -fsS -X POST \
|
|
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
|
-F "attachment=@${file};filename=${name}" \
|
|
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets"
|
|
echo "Uploaded: ${name}"
|
|
}
|
|
|
|
upload_asset "/bos-out/${ISO_NAME}"
|
|
upload_asset "/bos-out/SHA256SUMS"
|
|
upload_asset "/bos-out/SHA256SUMS.asc"
|
|
|
|
- name: Create GitHub release
|
|
env:
|
|
GH_TOKEN: ${{ secrets.MIRROR_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
TAG="${{ steps.vars.outputs.tag }}"
|
|
VERSION="${{ steps.vars.outputs.version }}"
|
|
FORGEJO_URL="https://git.breadway.dev/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
|
|
|
|
printf '**Download ISO:** %s\n\nGitHub releases cannot host files >2 GB; the `bos-%s-x86_64.iso` (~2.5 GB), SHA256SUMS, and SHA256SUMS.asc (signed by the BOS Release Signing key — public half at [KEYS.asc](https://github.com/Breadway/bos/blob/main/KEYS.asc)) are all on Forgejo.\n\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.' \
|
|
"${FORGEJO_URL}" "${VERSION}" > /tmp/gh-release-notes.md
|
|
|
|
gh release create "${TAG}" \
|
|
--repo "Breadway/bos" \
|
|
--title "BOS ${TAG}" \
|
|
--notes-file /tmp/gh-release-notes.md \
|
|
|| echo "skip: GitHub release failed (MIRROR_TOKEN historically broken)"
|
|
|
|
# `stable` is a marker branch only — CI fast-forwards it to whatever
|
|
# commit the latest real (non-RC) release tag points at. Never merged
|
|
# into by hand, so unlike the old dev/beta/main model it can't rot:
|
|
# nobody has to remember to move it, a bot always does. Lets you
|
|
# `git diff stable..main` before a build to see what's new since the
|
|
# last release, without a human-maintained promotion step.
|
|
- name: Fast-forward stable branch to this tag
|
|
if: ${{ !contains(steps.vars.outputs.tag, '-rc.') }}
|
|
env:
|
|
FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
cd /bos
|
|
git push "https://oauth2:${FORGEJO_TOKEN}@git.breadway.dev/${GITHUB_REPOSITORY}.git" \
|
|
"HEAD:refs/heads/stable" --force
|