Crafter.Build/.forgejo/workflows/ci.yaml
Jorijn van der Graaf af41ee5084
Some checks failed
CI / build-test-release (pull_request) Failing after 14m50s
CI / build-test-release (push) Failing after 14m45s
ci: ship per-march variants (v2/v3/v4) as individual artifacts
Replaces the single Linux + single Windows tarball with six self-
contained variants — three µarch levels × two OSes. End users on the
Releases page see them as six individually-downloadable archives:

  crafter-build-{linux,windows}-x86_64-{v2,v3,v4}.{tar.gz,zip}

Pick the v-level your CPU supports:
  v2: SSE4.2 baseline (every x86_64 since ~2011)
  v3: AVX2 + FMA + BMI (Intel Haswell+, AMD Excavator+, ~2013+)
  v4: AVX-512 (Skylake-X+, recent server-class)

How: the bootstrap binary stays at v2 because the CI SBC (N5105 / Tremont,
no AVX) can't execute v3 or v4 instructions and would crash before it
could rebuild itself for higher levels. Once bootstrap's done, the same
v2 binary is re-invoked with CRAFTER_BUILD_MARCH overridden per variant
to produce v2/v3/v4 outputs. Same again with --target=x86_64-w64-mingw32
for the Windows variants. ExternalDependency cache keys on (url, target,
march) already so glslang gets built per variant; subsequent CI runs hit
the cache.

Also drops the wrapper zip from workflow artifacts: instead of one
upload-artifact call producing crafter-build.zip containing six archives,
there's now one call per archive. The PR / run page shows six small
downloads named for what they are.

forgejo-release continues to upload release-dir/* as individual assets,
so the Releases page already has the right shape — this just brings the
workflow artifact UX in line.

Bumped the glslang cache key to v2 (one-time invalidation) since the
cache layout now needs space for six glslang builds rather than two.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 02:29:50 +02:00

157 lines
7.2 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: CI
on:
pull_request:
branches: [master]
push:
branches: [master]
workflow_dispatch:
jobs:
build-test-release:
runs-on: arch-latest
env:
# x86-64-v2 = SSE4.2 baseline; runs on the CI SBC (Intel N5105 / Tremont,
# no AVX) and on essentially every x86_64 CPU since ~2011. The bootstrap
# MUST stay v2 — anything higher would emit instructions the SBC can't
# execute and the bootstrap binary itself would crash before it could
# rebuild for higher levels. v3/v4 variants are produced from this v2
# bootstrap by re-running it with CRAFTER_BUILD_MARCH overridden.
CRAFTER_BUILD_MARCH: x86-64-v2
CRAFTER_BUILD_MTUNE: generic
steps:
- name: Install build dependencies
run: |
# The slim archlinux:latest image arrives without a populated
# pacman keyring AND without a local pacman master key, so:
# 1. --init generates the local signing key (needed when pacman
# itself rewrites the keyring during package upgrades)
# 2. --populate archlinux imports the upstream master keys so
# currently-shipping signatures verify
# After that we can refresh archlinux-keyring to pick up keys for
# packagers added after the image's snapshot, then -Syu the rest.
pacman-key --init
pacman-key --populate archlinux
pacman -Sy --noconfirm --needed archlinux-keyring
pacman -Syu --noconfirm --needed \
base-devel git zip tar \
clang lld libc++ cmake \
mingw-w64-gcc \
wasi-libc wasi-libc++ wasi-libc++abi wasi-compiler-rt \
nodejs
# The container runs as root and the workspace may be owned by a
# different uid; tell git not to refuse operations on it.
git config --global --add safe.directory '*'
- name: Checkout
uses: actions/checkout@v4
with:
# Persist the auth token so the 'Update rolling latest tag' step
# below can push the tag back via the implicit GITHUB_TOKEN.
persist-credentials: true
- name: Cache glslang clone+build
# Cache covers crafter-build's per-(target, march) external dep cache.
# First run builds glslang up to 6 times (3 marches × 2 targets); the
# cache makes subsequent runs reuse those builds.
uses: actions/cache@v4
with:
path: |
~/.cache/crafter.build/external
key: glslang-${{ runner.os }}-v2
- name: Bootstrap (build.sh)
run: ./build.sh
- name: Run tests
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build ./bin/crafter-build test
- name: Build Linux x86-64-v2 (matches bootstrap)
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build ./bin/crafter-build
- name: Build Linux x86-64-v3
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build CRAFTER_BUILD_MARCH=x86-64-v3 ./bin/crafter-build
- name: Build Linux x86-64-v4
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build CRAFTER_BUILD_MARCH=x86-64-v4 ./bin/crafter-build
- name: Build Windows x86-64-v2 (mingw)
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build ./bin/crafter-build --target=x86_64-w64-mingw32
- name: Build Windows x86-64-v3 (mingw)
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build CRAFTER_BUILD_MARCH=x86-64-v3 ./bin/crafter-build --target=x86_64-w64-mingw32
- name: Build Windows x86-64-v4 (mingw)
run: CRAFTER_BUILD_HOME=$PWD/share/crafter-build CRAFTER_BUILD_MARCH=x86-64-v4 ./bin/crafter-build --target=x86_64-w64-mingw32
- name: Package artifacts
run: |
set -eux
mkdir -p dist
# 6 archives — 3 marches × 2 OSes. Each is self-contained: the
# Linux launcher is statically linked; the Windows launcher has
# crafter-build.dll + libcrafter-build.dll.a alongside the exe.
for march in x86-64-v2 x86-64-v3 x86-64-v4; do
stage_lin=$(mktemp -d)
mkdir -p "$stage_lin/bin" "$stage_lin/lib"
cp "bin/crafter.build-exe-x86_64-pc-linux-gnu-$march/crafter-build" "$stage_lin/bin/"
cp "bin/crafter.build-lib-x86_64-pc-linux-gnu-$march/libcrafter-build.a" "$stage_lin/lib/"
cp -r share "$stage_lin/"
tar czf "dist/crafter-build-linux-x86_64-$march.tar.gz" -C "$stage_lin" .
stage_win=$(mktemp -d)
mkdir -p "$stage_win/bin"
cp "bin/crafter.build-exe-x86_64-w64-mingw32-$march"/* "$stage_win/bin/"
cp -r share "$stage_win/"
(cd "$stage_win" && zip -r "$GITHUB_WORKSPACE/dist/crafter-build-windows-x86_64-$march.zip" .)
done
ls -la dist/
# Upload each archive as its own workflow artifact (one upload per file)
# so users browsing the PR / run page get six small, individually-named
# downloads instead of one wrapper zip containing the lot.
- name: Upload Linux v2 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-linux-x86_64-v2, path: dist/crafter-build-linux-x86_64-v2.tar.gz, if-no-files-found: error }
- name: Upload Linux v3 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-linux-x86_64-v3, path: dist/crafter-build-linux-x86_64-v3.tar.gz, if-no-files-found: error }
- name: Upload Linux v4 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-linux-x86_64-v4, path: dist/crafter-build-linux-x86_64-v4.tar.gz, if-no-files-found: error }
- name: Upload Windows v2 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-windows-x86_64-v2, path: dist/crafter-build-windows-x86_64-v2.zip, if-no-files-found: error }
- name: Upload Windows v3 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-windows-x86_64-v3, path: dist/crafter-build-windows-x86_64-v3.zip, if-no-files-found: error }
- name: Upload Windows v4 artifact
uses: actions/upload-artifact@v3
with: { name: crafter-build-windows-x86_64-v4, path: dist/crafter-build-windows-x86_64-v4.zip, if-no-files-found: error }
- name: Update rolling 'latest' tag
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/master'
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
# forgejo-release uploads each file in release-dir as a separate
# release asset, so the Releases page shows six individually
# downloadable archives — pick the v-level matching your CPU.
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/master'
uses: https://code.forgejo.org/actions/forgejo-release@v2
with:
direction: upload
url: ${{ github.server_url }}
repo: ${{ github.repository }}
tag: latest
title: Latest main build
prerelease: true
override: true
release-dir: dist
token: ${{ secrets.GITHUB_TOKEN }}