Files
Skald-Circle/.gitea/workflows/release.yml
T
Daniele e0d75a8dc8
Nightly Build / build (push) Canceled after 6m16s
ci: stop rebuilding the whole workspace on every run
Cargo decides freshness by mtime, and the Gitea runner deletes the job
workspace after each run. So `actions/checkout` stamped every source file
with "now" and all 20 workspace crates recompiled regardless of what the
commit touched: measured on a JS-only commit, 20 of 722 rlibs rebuilt —
the ~700 third-party deps stayed cached, our own code never did. That,
not the size of skald-core, was the 4 minutes per architecture.

Restore mtimes from git history after checkout (needs the full history,
hence fetch-depth: 0 — cheap here, ~170 commits against a Gitea instance
on the same machine).

Also:

- nightly: CARGO_INCREMENTAL=1. Release builds have incremental off by
  default, the worst case for a 51k-line crate. The nightly trades a
  marginally less optimised binary for the rebuild time; release does not.
- nightly: concurrency with cancel-in-progress. The runner has capacity 1
  and the nightly publishes to a fixed filename, so a queued build was
  8 minutes spent on a tarball the next one overwrites.
- release: its own CARGO_TARGET_DIR. CARGO_INCREMENTAL is part of cargo's
  profile fingerprint, so one shared cache between a workflow that sets it
  and one that does not would have each invalidate the other's workspace
  crates — reintroducing the very rebuild this removes.
- packaging steps derive --target-dir from $CARGO_TARGET_DIR instead of
  repeating the path, so the two cannot drift.
2026-08-10 18:21:06 +01:00

140 lines
5.7 KiB
YAML

name: Release
on:
push:
branches:
- release
pull_request:
branches:
- release
jobs:
# ── PR check: verify the version is not already built ───────────────────────
verify-version:
if: github.event_name == 'pull_request'
runs-on: linux-amd64
steps:
- uses: actions/checkout@v4
- name: Verify version is new
run: ./ci/verify-version.sh --builds-dir /var/www/builds.skaldagent.net
# ── Push/merge: build, package, and deploy the release ──────────────────────
release:
if: github.event_name == 'push'
runs-on: linux-amd64
outputs:
version: ${{ steps.extract-version.outputs.version }}
env:
# Deliberately NOT the nightly's target dir. No CARGO_INCREMENTAL here —
# a release binary is the one people install, so it gets the fully
# optimised non-incremental build — and that flag is part of cargo's
# profile fingerprint. Sharing one cache between a workflow that sets it
# and one that doesn't would make each run invalidate the other's
# workspace crates, which is exactly the cost this whole change removes.
CARGO_TARGET_DIR: /home/dguiducci/.cache/skald-ci/target-release
steps:
- uses: actions/checkout@v4
with:
# Full history: `git restore-mtime` below dates each file from the
# last commit that touched it.
fetch-depth: 0
# See the long note in nightly.yml: the runner wipes the job workspace
# after every run, so without this every source file is stamped "now" on
# checkout and all 20 workspace crates rebuild from scratch regardless of
# what the commit changed. This is what lets CARGO_TARGET_DIR cache our
# own crates and not just the ~700 third-party deps.
- name: Restore source mtimes from git history
run: git restore-mtime
- name: Extract version from Cargo.toml
id: extract-version
run: |
VER="v$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')"
echo "version=$VER" >> "$GITHUB_OUTPUT"
echo "[release] Building version $VER"
# Also run verify-version on push to catch any race (belt-and-suspenders)
- name: Verify version is new
run: ./ci/verify-version.sh --builds-dir /var/www/builds.skaldagent.net
- name: Build native (linux/amd64)
run: |
RUSTFLAGS="-A warnings" cargo build --release --no-default-features
RUSTFLAGS="-A warnings" cargo build --release --no-default-features -p skald-setup
- name: Cross-compile (linux/arm64)
env:
CC_aarch64_unknown_linux_gnu: aarch64-linux-gnu-gcc
AR_aarch64_unknown_linux_gnu: aarch64-linux-gnu-ar
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
run: |
RUSTFLAGS="-A warnings" cargo build --release --no-default-features --target aarch64-unknown-linux-gnu
RUSTFLAGS="-A warnings" cargo build --release --no-default-features -p skald-setup --target aarch64-unknown-linux-gnu
- name: Package amd64
run: |
cd "${GITHUB_WORKSPACE:-.}"
./ci/package.sh \
--version "${{ steps.extract-version.outputs.version }}" \
--os linux \
--arch amd64 \
--target-dir "$CARGO_TARGET_DIR/release" \
--output dist/
- name: Package arm64
run: |
cd "${GITHUB_WORKSPACE:-.}"
./ci/package.sh \
--version "${{ steps.extract-version.outputs.version }}" \
--os linux \
--arch arm64 \
--target-dir "$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release" \
--output dist/
- name: Deploy to builds.skaldagent.net
run: |
cd "${GITHUB_WORKSPACE:-.}"
VERSION="${{ steps.extract-version.outputs.version }}"
TARGET="/var/www/builds.skaldagent.net/releases/${VERSION}"
mkdir -p "$TARGET"
# Publish each tarball atomically (temp name + rename) so a client can
# never fetch a half-written file.
for f in dist/*.tar.gz; do
name="$(basename "$f")"
cp "$f" "$TARGET/.$name.tmp"
mv -f "$TARGET/.$name.tmp" "$TARGET/$name"
done
echo "[release] Deployed $VERSION:"
ls -lh "$TARGET/"
- name: Update latest version pointer
run: |
VERSION="${{ steps.extract-version.outputs.version }}"
DEST=/var/www/builds.skaldagent.net/releases
# Flip LATEST atomically — install.sh/update.sh read it to decide
# whether to upgrade, so it must never be observed empty or partial.
printf '%s\n' "$VERSION" > "$DEST/.LATEST.tmp"
mv -f "$DEST/.LATEST.tmp" "$DEST/LATEST"
echo "[release] Updated releases/LATEST → $VERSION"
- name: Publish the release installer
run: |
cd "${GITHUB_WORKSPACE:-.}"
# install.sh is served straight from the web root
# (curl -fsSL https://builds.skaldagent.net/install.sh | bash), so
# without this it stays whatever was copied there by hand and drifts
# from the repo — a fix to the installer would reach every existing box
# through update.sh but never a new one. Published here rather than on
# every push so the served installer always matches a real release.
ROOT=/var/www/builds.skaldagent.net
cp install.sh "$ROOT/.install.sh.tmp"
chmod 644 "$ROOT/.install.sh.tmp"
mv -f "$ROOT/.install.sh.tmp" "$ROOT/install.sh"
echo "[release] Published install.sh"