Skip to content

feat(update_page): make the concurrency guard say when it cannot guard #583

feat(update_page): make the concurrency guard say when it cannot guard

feat(update_page): make the concurrency guard say when it cannot guard #583

Workflow file for this run

name: CI
# Re-enabled at v1.0.0 (M6). During bootstrap CI was paused
# (`workflow_dispatch` only) and the local four-command gate
# (`cargo fmt` / `clippy -D warnings` / `test` / `build --release`)
# was the merge gate per CLAUDE.md "How we work". With the workspace
# stabilised at v1 the GitHub Actions safety net is back on for
# every push to main and every PR.
#
# This is the correctness gate: fmt + clippy + test + build on Linux, on
# every PR, every push to main, and every release tag. The cross-platform
# RELEASE binaries (Windows + macOS + Linux packaging + GitHub Release)
# live in `release.yml`, which fires on `v*` tags only — PRs stay
# Linux-only.
on:
workflow_dispatch:
push:
branches: [main]
tags: ["v*"]
pull_request:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: "-D warnings"
RUST_BACKTRACE: short
# The workspace statically links libduckdb into ~15 test
# binaries. Linking them with full debuginfo, in parallel, blows
# past the 7 GB on a GitHub-hosted runner — the first re-enabled
# CI run got SIGTERM'd (exit 143) mid-link before any test ran.
# Drop test/dev debuginfo (duckdb's is enormous) and serialise
# build jobs to cap peak link memory. CI-only; the committed
# profiles and local dev builds are untouched.
CARGO_PROFILE_DEV_DEBUG: "0"
CARGO_PROFILE_TEST_DEBUG: "0"
CARGO_BUILD_JOBS: "1"
jobs:
ci:
name: fmt + clippy + test
runs-on: ubuntu-latest
# DuckDB is no longer compiled from source — libduckdb-sys downloads
# the precompiled libduckdb (see .cargo/config.toml: DUCKDB_DOWNLOAD_LIB).
# `CARGO_BUILD_JOBS=1` (the link-memory cap, see env above) still
# serialises linking, so keep generous headroom for the release stage.
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
# rust-toolchain.toml drives the channel + components; rustup
# honours it automatically on first invocation.
- name: Install Rust toolchain
run: |
rustup show active-toolchain || rustup toolchain install
rustup component add rustfmt clippy
- uses: Swatinem/rust-cache@v2
with:
# Bumped from `workspace` to invalidate caches that hold the
# libduckdb-sys build-script fingerprint but NOT the downloaded
# libduckdb (the old caches link-fail with `cannot find -lduckdb`).
shared-key: workspace-duckdb-dl
# The build script downloads libduckdb into this custom dir and
# bakes its path into the cached link-search output. It is NOT a
# standard cargo artifact, so cache it explicitly — otherwise a
# cache hit restores the fingerprint (script does not re-run) but
# not the .so, and the final test/release link fails.
cache-directories: target/duckdb-download
# Save the cache even when a later step fails — without this, a
# single test failure throws away the warm cache and every push
# re-pays the cold dependency build.
cache-on-failure: true
# Safety net for cache restores that lack the downloaded libduckdb
# (e.g. an older cache, or a partial restore): the libduckdb-sys
# build script only re-downloads when it actually re-runs, so force
# that by cleaning just that crate when the .so is absent.
- name: Ensure libduckdb is present (cache-restore safety)
run: |
if ! ls target/duckdb-download/*/*/libduckdb.so >/dev/null 2>&1; then
echo "libduckdb not in restored cache — forcing libduckdb-sys rebuild"
cargo clean -p libduckdb-sys || true
fi
- name: cargo fmt --check
run: cargo fmt --all -- --check
- name: cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings
- name: cargo test
run: cargo test --workspace --all-targets
# `cargo build --release` in its OWN job.
#
# It was the last step of `ci` and the first thing to die: exit 143
# mid-link on a cold cache. One `target/` was holding check, test AND
# release artifacts for a workspace that statically links libduckdb —
# which is why this file already carries CARGO_BUILD_JOBS=1 and
# *_DEBUG=0. Its own runner gets its own memory, disk and cache key.
#
# This matters more than a slow build: a cancelled job SKIPS the
# cache-save step, so a run that dies leaves no warm cache and the next
# run starts cold and dies in the same place. Splitting breaks that
# loop.
build:
name: build --release
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
run: |
rustup show active-toolchain || rustup toolchain install
rustup component add rustfmt clippy
# NO rust-cache here — deliberately, and NOT an oversight. libduckdb-sys
# (DUCKDB_DOWNLOAD_LIB, see .cargo/config.toml) downloads the shared
# libduckdb into target/duckdb-download and links against it.
# Swatinem/rust-cache PRUNES that downloaded .so when it saves the cache,
# so a *restored* cache link-fails with `rust-lld: unable to find library
# -lduckdb` — the build-script fingerprint is restored (so the script
# does NOT re-run and re-download) but the .so it points at is gone. The
# prior `cache-directories: target/duckdb-download` + conditional
# `cargo clean -p libduckdb-sys` safety step did NOT close this (the
# release job stayed red on main), so we do what release.yml already
# proved correct on all three platforms: no cache → the build script
# always runs → libduckdb is always freshly downloaded → the link always
# resolves. A cold release build per PR is the price of a green gate;
# libduckdb is a precompiled download (no C++ compile), and this job has
# its own 90-minute budget. See release.yml's "NOTE: deliberately NO
# rust-cache here" for the same reasoning on the tag-release path.
- name: cargo build --release
run: cargo build --workspace --release
# The SHIPPED feature set, in its OWN job.
#
# Without this, `s3.rs` and `gcs.rs` are never compiled on the merge
# path — they sit behind optional features and the job above passes no
# `--features`. That is how the S3 backend reached production
# unbuildable: the Dockerfile selected a feature CI had never once
# compiled.
#
# Why a separate job rather than another step in `ci`: the AWS and
# Google SDK dependency trees are large, and the main job already runs
# `CARGO_BUILD_JOBS=1` with a 90-minute budget because this workspace
# statically links libduckdb and sits near the runner's memory ceiling.
# Adding those trees to the same `target/` pushed `cargo build
# --release` into a SIGTERM (exit 143). Its own runner keeps that
# budget intact.
#
# clippy without `--all-targets`: the backends' own integration tests
# need real containers and run in `live.yml`. This job's job is to
# prove the library code still compiles and lints under the flags the
# release artifacts actually use.
features:
name: clippy (shipped features)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: Install Rust toolchain
run: |
rustup show active-toolchain || rustup toolchain install
rustup component add clippy
- uses: Swatinem/rust-cache@v2
with:
shared-key: features-s3-gcs
cache-directories: target/duckdb-download
cache-on-failure: true
- name: Ensure libduckdb is present (cache-restore safety)
run: |
if ! ls target/duckdb-download/*/*/libduckdb.so >/dev/null 2>&1; then
echo "libduckdb not in restored cache — forcing libduckdb-sys rebuild"
cargo clean -p libduckdb-sys || true
fi
- name: cargo clippy --features s3,gcs
run: cargo clippy -p escurel-server -p escurel-storage --features s3,gcs -- -D warnings