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

@@ -0,0 +1,56 @@
# Required CI runtime evidence
This record is populated from the consolidated `CI / required` Gitea job. A
qualifying sample consists of one deliberate cold native/dependency cache run
and four normal warm-cache runs on `aarch64-unknown-linux-gnu`. Each uploaded
`required-gate.json` contains per-stage elapsed time, Rust host/target, separate
compiled-Cargo, dependency-download, native, and tool cache hit state,
available peak-memory evidence, and the Skia binary outcome.
The compiled target key includes Rust 1.97.1, the ARM64 GNU target, every Cargo
manifest, `Cargo.lock`, required feature/policy configuration, and native
installer inputs. CI-driver-only changes reuse the newest generation through a
same-filesystem hard-link migration; Cargo still validates every fingerprint.
To invalidate compiled artifacts, change a keyed build input. A deliberate
`cold_cache` dispatch removes registry archives/index data, Git database data,
pinned audit tools, OpenJPEG, and Skia. It retains immutable extracted registry
sources and the compiled target so the cold dependency/native measurement does
not manufacture source-mtime rebuilds unrelated to cache correctness.
The pre-consolidation Gitea baseline was 13 automatic workflows and 333 runs.
Successful maxima included 22.9 minutes for the native workspace, 32.0 minutes
for Skia, 66.6 minutes for artifact audit, and 86.0 minutes for the release
matrix. Native code generation had a 13.2-minute median and 18.5-minute maximum;
even this one concern could exceed the new complete-gate budget.
| Run | Cache | Elapsed | Result | Evidence |
| --- | --- | ---: | --- | --- |
| [423](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/391) | cold (compiled hit; dependency/native/tool miss) | 4:24 | success | [required-ci-evidence](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/391/artifacts/required-ci-evidence) |
| [424](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/392) | warm | 3:56 | success | [required-ci-evidence](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/392/artifacts/required-ci-evidence) |
| [425](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/393) | warm | 3:56 | success | [required-ci-evidence](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/393/artifacts/required-ci-evidence) |
| [426](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/394) | warm | 3:55 | success | [required-ci-evidence](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/394/artifacts/required-ci-evidence) |
| [427](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/395) | warm | 4:12 | success | [required-ci-evidence](https://git.rfc1437.de/hugo/MetaCrate/actions/runs/395/artifacts/required-ci-evidence) |
The uploaded evidence reports the following internal gate timings. Warm values
are the observed minimum and maximum across the four warm runs.
| Stage | Cold seconds | Warm seconds |
| --- | ---: | ---: |
| static/generated/API | 119.200 | 118.291119.204 |
| reviewed reports | 0.000 | 0.000 |
| Skia binary proof | 0.343 | 0.2500.262 |
| compile/test/features | 38.429 | 37.03137.590 |
| program/API smoke | 2.876 | 2.4162.526 |
| clippy/docs | 1.243 | 1.0321.080 |
| policy/evidence | 7.669 | 7.2727.469 |
| complete internal gate | 201.202 | 197.423198.555 |
All five consecutive runs used commit `05af8d5edf566fb79770990153d8561a98718ec4`
on the ARM64 `ubuntu-latest` runner. The 4:24 maximum leaves 10:36 of headroom
under the 15-minute job timeout. Branch protection for `main` enables status
checks with `CI / required (push)` as its only required context; direct-push
behavior is unchanged. Every evidence record reports `aarch64` with Rust
host/target `aarch64-unknown-linux-gnu`; observed peak cgroup memory is
264,696264,712 KiB. Every Skia proof installed the pinned archive with SHA-256
`dd127f458a5e67a79f3936a8aa19f822fe90a1d6a11b50b5f84df2b0519d909c`
and records that no source build started.

View File

@@ -22,7 +22,7 @@ not raise it accidentally.
## Automated gates
The Ubuntu-only `supply-chain` Gitea workflow installs pinned versions of
The Ubuntu-only consolidated required Gitea gate installs pinned versions of
`cargo-deny` and `cargo-machete`, then runs:
```sh

View File

@@ -23,9 +23,9 @@ and [`MeshFoundry` guide](../crates/libremetaverse-rendering-mesh-foundry/README
OpenJPEG is a non-default workspace member so release tooling can package the
adapter explicitly, and imaging reaches it only through the optional
dependency. Skia is likewise an optional, target-specific dependency. The
dedicated Gitea workflows exercise both optional features on `ubuntu-latest`;
the default `imaging-meshing` workflow proves that no native codec is needed
for the owned Rust and translated compatibility tests.
consolidated required Gitea gate exercises both optional features on
`ubuntu-latest` while its minimal-feature check proves that no native codec is
needed for the owned Rust and translated compatibility tests.
## Bounds and rendering contract
@@ -50,10 +50,10 @@ python3 tools/check_milestone_06.py
The audit rejects owned Rust stubs, feature leakage, missing platform jobs,
missing performance targets, or drift in the 48 reviewed ManagedImage,
Coord/Quat, and PrimMesh compatibility cases. The cross-platform workflow also
runs each reviewed group explicitly, native crate tests, workspace test
compilation, Clippy with warnings denied, rustdoc with warnings denied, and
benchmark compilation.
Coord/Quat, and PrimMesh compatibility cases. The required gate runs the native
crate and reviewed parity tests, Clippy with warnings denied, and rustdoc with
warnings denied. Benchmark compilation is retained in the non-routine release
gate.
The focused performance baselines are executable Rust programs rather than
wall-clock assertions, so slower shared runners do not weaken or destabilize

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).