One job replaces the tarball pipeline. On a pull request it builds the Flatpak with flatpak-builder, which runs the bootstrap, the self-host build and the test suite inside the sandbox, and smoke-tests the result with `crafter-build --version` and the hello-world example. On a push to master it also bundles the build, promotes it into the live repo as the `beta` branch and refreshes the rolling `latest` prerelease. On a tag X.Y.Z it promotes as `stable`, refuses to proceed unless the metainfo's newest release is that version, and publishes a release whose notes are that entry's description. The job runs on the `flatpak` runner label: the privileged forgejo-runner on the Hetzner box, with the Sdk install, the flatpak-builder state and the repo's web root as volumes. The state volume is what keeps a normal run short: flatpak-builder rebuilds the LLVM and WASI modules only when their sources change. The live repo is canonical and never built into; builds are promoted with build-commit-from, then build-update-repo signs and prunes it and generates static deltas. The musl job, the per-march tarballs, the toolchain packages the runner used to install and the PKGBUILD go: the Flatpak is the one artifact. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
185 lines
7.8 KiB
YAML
185 lines
7.8 KiB
YAML
name: Flatpak
|
|
|
|
# One job, three outcomes:
|
|
# pull request -> build the Flatpak and run the suite inside it
|
|
# push master -> also publish the result as the `beta` branch of the
|
|
# Catcrafts repo and refresh the rolling `latest` release
|
|
# tag X.Y.Z -> publish as `stable` and create release X.Y.Z
|
|
#
|
|
# The `flatpak` runner label is the privileged runner on the Hetzner box
|
|
# (bubblewrap needs it) with three volumes allowed: the Sdk install, the
|
|
# flatpak-builder state (ccache and the LLVM module, so only crafter-build
|
|
# itself rebuilds on a normal run) and the published repo's web root.
|
|
on:
|
|
pull_request:
|
|
branches: [master]
|
|
push:
|
|
branches: [master]
|
|
tags: ['[0-9]+.[0-9]+.[0-9]+']
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
APP_ID: net.catcrafts.CrafterBuild
|
|
MANIFEST: packaging/flatpak/net.catcrafts.CrafterBuild.yaml
|
|
CI_MANIFEST: packaging/flatpak/ci-manifest.yaml
|
|
RUNTIME: org.freedesktop.Sdk//26.08
|
|
REPO_DIR: /srv/flatpak/repo
|
|
WEB_DIR: /srv/flatpak
|
|
|
|
jobs:
|
|
flatpak:
|
|
runs-on: flatpak
|
|
container:
|
|
image: archlinux:latest
|
|
options: >-
|
|
-v crafter-flatpak-system:/var/lib/flatpak
|
|
-v crafter-flatpak-builder:/root/.cache/flatpak-builder
|
|
-v /var/www/flatpak:/srv/flatpak
|
|
steps:
|
|
- name: Install tools
|
|
run: |
|
|
pacman-key --init
|
|
pacman-key --populate archlinux
|
|
pacman -Sy --noconfirm --needed archlinux-keyring
|
|
pacman -Syu --noconfirm --needed flatpak flatpak-builder ccache git nodejs jq gnupg go-yq ostree
|
|
git config --global --add safe.directory '*'
|
|
|
|
- name: Sdk
|
|
# A no-op once the volume is warm; `update` follows point releases.
|
|
run: |
|
|
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
flatpak install -y --noninteractive flathub "$RUNTIME"
|
|
flatpak update -y --noninteractive
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: true
|
|
|
|
- name: Version and channel
|
|
id: meta
|
|
run: |
|
|
set -eu
|
|
if [ "${GITHUB_REF_TYPE}" = tag ]; then
|
|
version="$GITHUB_REF_NAME"
|
|
branch=stable
|
|
# The metainfo's newest release is the release notes and must be
|
|
# the version being tagged.
|
|
top=$(grep -m1 -oP '<release version="\K[^"]+' packaging/flatpak/net.catcrafts.CrafterBuild.metainfo.xml)
|
|
if [ "$top" != "$version" ]; then
|
|
echo "metainfo lists $top as the newest release, but the tag is $version" >&2
|
|
exit 1
|
|
fi
|
|
else
|
|
version="0.0.0-dev+$(git rev-parse --short HEAD)"
|
|
branch=beta
|
|
fi
|
|
echo "version=$version" >> "$GITHUB_OUTPUT"
|
|
echo "branch=$branch" >> "$GITHUB_OUTPUT"
|
|
echo "version $version, flatpak branch $branch"
|
|
|
|
- name: Build
|
|
# The manifest is rewritten beside the original so its relative
|
|
# source paths still resolve. The suite runs inside this build.
|
|
env:
|
|
VERSION: ${{ steps.meta.outputs.version }}
|
|
run: |
|
|
set -eu
|
|
yq '."build-options".env.CRAFTER_BUILD_VERSION = strenv(VERSION)' "$MANIFEST" > "$CI_MANIFEST"
|
|
grep -n 'CRAFTER_BUILD_VERSION' "$CI_MANIFEST"
|
|
flatpak-builder --force-clean --ccache --disable-rofiles-fuse \
|
|
--state-dir=/root/.cache/flatpak-builder \
|
|
--repo=repo --default-branch="${{ steps.meta.outputs.branch }}" \
|
|
build-dir "$CI_MANIFEST"
|
|
|
|
- name: Smoke test
|
|
run: |
|
|
flatpak-builder --run build-dir "$CI_MANIFEST" crafter-build --version
|
|
flatpak-builder --run build-dir "$CI_MANIFEST" sh -c 'cd examples/hello-world && crafter-build && ls bin/*/hello*'
|
|
|
|
# Everything below publishes and only runs on master and on tags.
|
|
- name: Bundle
|
|
if: github.event_name != 'pull_request'
|
|
run: |
|
|
mkdir -p dist
|
|
flatpak build-bundle repo "dist/crafter-build-${{ steps.meta.outputs.version }}.flatpak" "$APP_ID" "${{ steps.meta.outputs.branch }}"
|
|
cp packaging/flatpak/net.catcrafts.CrafterBuild.flatpakref dist/
|
|
(cd dist && sha256sum * > SHA256SUMS)
|
|
ls -la dist
|
|
|
|
- name: Upload bundle
|
|
if: github.event_name != 'pull_request'
|
|
uses: actions/upload-artifact@v3
|
|
with:
|
|
name: crafter-build-${{ steps.meta.outputs.version }}
|
|
path: dist/*.flatpak
|
|
if-no-files-found: error
|
|
|
|
- name: Publish to the Catcrafts repo
|
|
if: github.event_name != 'pull_request'
|
|
env:
|
|
FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}
|
|
FLATPAK_GPG_KEY_ID: ${{ secrets.FLATPAK_GPG_KEY_ID }}
|
|
run: |
|
|
set -eu
|
|
export GNUPGHOME=$(mktemp -d)
|
|
printf '%s' "$FLATPAK_GPG_PRIVATE_KEY" | gpg --batch --quiet --import
|
|
# The live repo is the canonical copy; builds are promoted into it,
|
|
# never built into it.
|
|
[ -d "$REPO_DIR" ] || ostree init --repo="$REPO_DIR" --mode=archive
|
|
flatpak build-commit-from --src-repo=repo \
|
|
--gpg-sign="$FLATPAK_GPG_KEY_ID" --gpg-homedir="$GNUPGHOME" \
|
|
"$REPO_DIR" "app/$APP_ID/x86_64/${{ steps.meta.outputs.branch }}"
|
|
flatpak build-update-repo --gpg-sign="$FLATPAK_GPG_KEY_ID" --gpg-homedir="$GNUPGHOME" \
|
|
--generate-static-deltas --prune "$REPO_DIR"
|
|
# The repo description and the app ref carry the public key.
|
|
key=$(gpg --export "$FLATPAK_GPG_KEY_ID" | base64 --wrap=0)
|
|
sed "s|GPGKey=.*|GPGKey=$key|" packaging/flatpak/catcrafts.flatpakrepo > "$WEB_DIR/catcrafts.flatpakrepo"
|
|
sed "s|GPGKey=.*|GPGKey=$key|" packaging/flatpak/net.catcrafts.CrafterBuild.flatpakref > "$WEB_DIR/net.catcrafts.CrafterBuild.flatpakref"
|
|
|
|
- name: Rolling 'latest' release
|
|
if: github.event_name != 'pull_request' && github.ref_type != 'tag'
|
|
run: |
|
|
git config user.email "ci@catcrafts.net"
|
|
git config user.name "Crafter Build CI"
|
|
git tag -f latest
|
|
git push origin latest --force
|
|
- name: Publish rolling 'latest' release
|
|
if: github.event_name != 'pull_request' && github.ref_type != 'tag'
|
|
uses: https://code.forgejo.org/actions/forgejo-release@v2
|
|
with:
|
|
direction: upload
|
|
url: ${{ github.server_url }}
|
|
repo: ${{ github.repository }}
|
|
tag: latest
|
|
title: Latest master build
|
|
prerelease: true
|
|
override: true
|
|
release-dir: dist
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Release notes
|
|
if: github.ref_type == 'tag'
|
|
run: |
|
|
# The newest <release> block's description, as plain text.
|
|
python3 - > release-notes.md <<'EOF'
|
|
import re, html
|
|
text = open("packaging/flatpak/net.catcrafts.CrafterBuild.metainfo.xml").read()
|
|
block = re.search(r"<release [^>]*>(.*?)</release>", text, re.S).group(1)
|
|
paras = re.findall(r"<p>(.*?)</p>", block, re.S)
|
|
print("\n\n".join(html.unescape(" ".join(p.split())) for p in paras))
|
|
print("\nInstall:\n\n flatpak remote-add --if-not-exists catcrafts https://flatpak.catcrafts.net/catcrafts.flatpakrepo\n flatpak install catcrafts net.catcrafts.CrafterBuild\n")
|
|
EOF
|
|
- name: Publish release
|
|
if: github.ref_type == 'tag'
|
|
uses: https://code.forgejo.org/actions/forgejo-release@v2
|
|
with:
|
|
direction: upload
|
|
url: ${{ github.server_url }}
|
|
repo: ${{ github.repository }}
|
|
tag: ${{ github.ref_name }}
|
|
title: crafter-build ${{ github.ref_name }}
|
|
release-notes: release-notes.md
|
|
release-dir: dist
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|