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 jq \ 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 # Short suffix (v2/v3/v4) for archive filenames; the upload-artifact # steps below reference these short names. short=${march##*-} # VariantId is "----"; CI pins # mtune=generic so each (target, march) resolves to a single subdir # but the trailing hash isn't known to the workflow, hence the glob. 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-$short.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-$short.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 }}