Consolidate required CI gate (#115)
All checks were successful
CI / required (push) Successful in 3m55s

This commit is contained in:
2026-08-12 16:46:45 +00:00
parent b9415bedaa
commit 27c860c225
47 changed files with 2506 additions and 1474 deletions

View File

@@ -1,90 +1,132 @@
# Release platform and feature CI matrix
# Consolidated CI and release matrix
The release matrix is declared in [`ci/release-matrix.json`](../ci/release-matrix.json)
and validated and executed by the native Rust `metacrate-ci-matrix` tool. The
manifest is the single reviewed inventory of toolchains, targets, feature sets,
native prerequisites, Cargo commands, and explicit manual gates. The runner
does not execute shell fragments from the manifest: every entry is an
allow-listed Cargo subcommand and argument list.
MetaCrate has one routine code-ready signal: the `required` job in
`.gitea/workflows/ci.yml`. It runs for every push and pull request on
`ubuntu-latest`, has a hard 15-minute timeout, and cancels an older run for the
same branch or pull request. `.gitea/workflows/release.yml` is the only other
workflow. It is manual, weekly, and tag-only; it never runs for an ordinary
source push or pull request.
## Platform boundary
The reviewed coverage map is `ci/ci-coverage.json`. It maps every responsibility
from the former 13 workflows to the required gate, the non-routine release
gate, or both, with a rationale. `metacrate-ci-matrix ci-audit` rejects missing
routes, additional workflow fan-out, non-Ubuntu jobs, Skia source-build
fallback, and changes to the 15-minute limit.
Repository policy requires every Gitea Actions job to use `ubuntu-latest`.
Accordingly, the matrix runs the complete default, minimal, optional-feature,
test, example, and documentation surfaces natively on Linux. Windows GNU and
macOS use their official Rust standard-library targets from the same Ubuntu
host to compile the portable public crates with default features disabled.
Those cross-target profiles cover code selected by `cfg` without pretending to
run Windows or macOS executables or to possess an Apple SDK.
## Required gate
Platform-native Skia, OpenJPEG, Opus, Vorbis, and CPAL adapters are exercised
in isolated Linux profiles with their versions recorded. WASAPI, CoreAudio,
platform packaging, and physical-device behavior remain explicit release/manual
gates; a successful Ubuntu cross check is never reported as a native runtime
test on another operating system.
The Rust `required-gate` command owns the command graph and records the elapsed
time and result of every stage. YAML performs checkout, one package install,
one coherent persistent-cache inspection, pinned toolchain/tool setup, and exact native-cache
preparation before invoking it. Fast-failure order is:
## Feature isolation
1. formatting, deterministic generators, API mappings, parity catalogs, and
milestone ownership checks;
2. regenerated API, documentation, dependency, and provenance evidence;
3. exact Skia ARM64 GNU binary installation proof;
4. all-feature workspace library/integration tests, minimal and JPEG 2000
feature isolation, compatibility tests, and concurrency regressions;
5. offline/fake program smoke and downstream API/SemVer consumers;
6. Clippy, warning-free documentation, dependency policy, unused dependency,
provenance, and committed performance-evidence audits.
`libremetaverse` defaults to the pure-Rust `dds-bc67` feature. OpenJPEG-backed
JPEG 2000 and Vorbis encoding are independently selectable as `jpeg2000` and
`vorbis`; neither native codec is discovered or linked for a default library
consumer. Skia and CPAL remain isolated in their existing `skia` and
`real-audio` features. The matrix validates each feature independently before
checking workspace-wide `--all-features` unification.
The driver stops starting work after its 12-minute internal target. This leaves
three minutes for shutdown and artifact upload beneath the workflow's hard
limit. `CARGO_BUILD_JOBS=2` is the bounded ARM64 setting; it permits useful
parallelism without the repeated high-memory compiles caused by the former
13-job fan-out. One feature-unified product/compatibility test graph uses a
single Cargo job, with package-qualified core features so unrelated consumer
options are not activated. This is the sole memory-safety exception, while
every other gate command retains the two-job bound.
The checked profiles cover:
- Rust 1.96.0 and current stable;
- native Linux default, no-default, individual optional features, and all
features;
- all targets, test compilation and execution, doctests, shipped
example-program binaries, and API documentation;
- portable Windows GNU and macOS cross-target compilation;
- exact OpenJPEG, Skia, Opus, ALSA, and Vorbis prerequisite declarations.
Dependency purpose, maintenance, license, advisory, source, and duplicate
review is the separate supply-chain gate documented in
[`dependency-policy.md`](dependency-policy.md). Changes to manifests or the
lockfile trigger both gates.
Release-file provenance, Linden CC BY-SA separation, complete locked package
notices, native redistribution obligations, and the source/binary notice set
are enforced by the companion
[`release provenance audit`](release-provenance.md). Its distribution manifest
hashes the full source tree, so the supply-chain workflow runs for every source
change rather than only dependency changes.
## Clean-build evidence
Each profile uses `target/ci/<profile>` and refuses to start if that directory
already exists. Incremental compilation is disabled. This makes an accidental
cache hit a hard failure instead of allowing it to hide a missing clean-build
dependency. Gitea may cache Cargo registry and Git downloads using a key derived
from the lockfile and toolchain; it never caches a `target` directory. Each
successful or failed run creates one JSON evidence file with the source commit,
requested toolchain and target, actual `rustc` and Cargo versions, feature sets,
native prerequisite versions, exact Cargo commands, completion count,
timestamp, and final status.
Run the audit locally with:
Run the structural audit locally on Linux, Windows, or macOS with:
```sh
cargo run --locked -p metacrate-ci-matrix -- audit
cargo run --locked -p metacrate-ci-matrix -- ci-audit
```
Run one clean profile with:
The full required graph expects the CI native-cache environment. On an ARM64
GNU Linux host with OpenJPEG installed by `tools/install_openjpeg_2_5_4.sh` and
the pinned Skia archive available, reproduce it with:
```sh
OPENJPEG_PREFIX=/path/to/openjpeg \
METACRATE_EXPECTED_HOST=aarch64-unknown-linux-gnu \
METACRATE_SKIA_ARCHIVE=/path/to/skia-binaries-a25a0fdb7d90429aa2d1-aarch64-unknown-linux-gnu-jpegd-jpege-pdf-svg-textlayout-vulkan-webpd-webpe.tar.gz \
cargo run --locked -p metacrate-ci-matrix -- \
run linux-stable-minimal \
--evidence /tmp/metacrate-linux-stable-minimal.json
required-gate --evidence artifacts/ci/local-required.json
```
Before rerunning the same profile, use Cargo's scoped cleanup command:
The driver is shell-free and constructs child processes with argument arrays,
so command and path mappings are portable. Gitea jobs intentionally remain
Ubuntu-only. Windows GNU and macOS portable surfaces are cross-checked from
Ubuntu by the non-routine release graph; no native runtime claim is inferred.
## Cache identity and invalidation
The dedicated VPS runner's persisted tool-cache mount stores Cargo registry/git
downloads, the two pinned audit binaries, the routine target directory, and
native archives/installations. The target directory is content-keyed by Rust
1.97.1, `aarch64-unknown-linux-gnu`, `Cargo.lock`, the CI coverage and dependency
policies, the Skia feature manifest, and the OpenJPEG installer. Changing any of
these selects a new target generation. This avoids depending on an external
GitHub cache service that is unreachable from the isolated Gitea runner.
After checkout, a state file beside the keyed target cache binds every tracked
path's Git mode and actual-content digest to the exact mtime used for its last
build. Unchanged files recover that mtime across commits and retain valid Cargo
fingerprints. A content or executable-mode change receives the current time, so
it is newer than cached outputs and invalidates the affected graph. The state is
written before compilation, so completed work remains reusable after a timeout,
and the workflow immediately verifies every applied mtime.
The manual `cold_cache` dispatch input clears the Cargo registry/git dependency
cache, pinned tools, and exact native paths before setup; it intentionally keeps
the separately keyed compiled target cache. This is the acceptance test's cold
dependency/native-cache case. Ordinary pushes and dispatches reuse all validated
cache layers.
OpenJPEG caches include a three-line identity containing version 2.5.4, commit
`6c4a29b00211eb0430fa0e5e890f1ce5c80f409f`, and runner architecture. The
installer checks this identity and `pkg-config --exact-version` before reuse.
The Skia cache is the exact 0.99.0 ARM64 GNU feature archive with SHA-256
`dd127f458a5e67a79f3936a8aa19f822fe90a1d6a11b50b5f84df2b0519d909c`.
The workflow never sets `FORCE_SKIA_BINARIES_DOWNLOAD`: rust-skia uses the
normal crates.io `.cargo_vcs_info.json` hash. The proof reads rust-skia's
persisted build-script output even on a cache hit and requires
`DOWNLOAD AND INSTALL SUCCEEDED`; the Rust driver rejects missing success output
or any `STARTING A FULL BUILD`. The adapter enables
rust-skia's `no-compile` feature on every target, making an unavailable or
incorrect binary a fast failure rather than a source build.
To invalidate local artifacts, remove only the relevant target directory or use:
```sh
cargo clean --target-dir target/ci/linux-stable-minimal
cargo clean --target-dir target/required
cargo clean --target-dir target/release-gate
```
Live-grid credentials, physical audio devices, and proprietary services remain
outside automatic CI and retain their dedicated opt-in gates.
## Non-routine release gate
The Rust `release-gate` command owns clean MSRV and portable cross-target
checks, benchmark compilation, the 16-cycle resource soak, all 16 source
packages, release binaries, native artifact inspection, and the aggregate
release-candidate audit. Reference C# performance regeneration and live-grid,
physical-audio, proprietary-service, signing, and platform-native installer
checks retain their documented credential/device/manual boundaries. Their
committed evidence and fast regression checks remain in routine CI.
## Troubleshooting and runtime evidence
- A host mismatch means the required runner label is not the documented ARM64
GNU VPS. Do not substitute a musl or x86 archive.
- An OpenJPEG identity failure requires deleting only its native cache entry and
rerunning the installer.
- A Skia hash/download failure indicates an upstream release-asset or redirect
reachability problem. Restore the exact archive in the configured cache; do
not enable source compilation.
- A 12-minute driver failure identifies the last completed stage in the uploaded
`required-gate.json`. Optimize or remove duplicate work only after updating
the coverage manifest; do not raise the 15-minute timeout.
The validation record and five qualifying ARM64 run links are maintained in
[`ci-runtime-evidence.md`](ci-runtime-evidence.md).