Consolidate required CI gate (#115)
Some checks failed
CI / required (push) Failing after 3m47s
Some checks failed
CI / required (push) Failing after 3m47s
This commit is contained in:
@@ -1,81 +0,0 @@
|
||||
name: API and SemVer surface
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/api-surface.yml"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "api/**"
|
||||
- "ci/evidence/api-audit.json"
|
||||
- "crates/**"
|
||||
- "tests/api-compile/**"
|
||||
- "tests/semver-port/**"
|
||||
- "tools/check_api_coverage.py"
|
||||
- "tools/generate_api_shims.py"
|
||||
- "tools/generate_rust_mapping.py"
|
||||
- "tools/ci-matrix/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/api-surface.yml"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "api/**"
|
||||
- "ci/evidence/api-audit.json"
|
||||
- "crates/**"
|
||||
- "tests/api-compile/**"
|
||||
- "tests/semver-port/**"
|
||||
- "tools/check_api_coverage.py"
|
||||
- "tools/generate_api_shims.py"
|
||||
- "tools/generate_rust_mapping.py"
|
||||
- "tools/ci-matrix/**"
|
||||
|
||||
jobs:
|
||||
api-surface:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CARGO_BUILD_JOBS: "1"
|
||||
CARGO_INCREMENTAL: "0"
|
||||
CARGO_PROFILE_DEV_DEBUG: "0"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install native prerequisites
|
||||
run: sudo apt-get update && sudo apt-get install -y libopus-dev pkg-config
|
||||
|
||||
- name: Install Rust 1.97
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: "1.97.0"
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Verify deterministic mapping and export coverage
|
||||
run: |
|
||||
python3 tools/generate_rust_mapping.py --check
|
||||
python3 tools/generate_api_shims.py --check
|
||||
python3 tools/check_api_coverage.py
|
||||
|
||||
- name: Verify reviewed API baseline
|
||||
run: |
|
||||
cargo run --locked -p metacrate-ci-matrix -- api-baseline-write
|
||||
git diff --exit-code -- api/SEMVER-BASELINE.json api/SEMVER-AUDIT.md
|
||||
cargo run --locked -p metacrate-ci-matrix -- api-audit --evidence /tmp/metacrate-api-audit.json
|
||||
cmp /tmp/metacrate-api-audit.json ci/evidence/api-audit.json
|
||||
|
||||
- name: Compile downstream API consumers
|
||||
run: |
|
||||
cargo check --locked --manifest-path tests/api-compile/Cargo.toml
|
||||
cargo run --locked --manifest-path tests/semver-port/Cargo.toml
|
||||
|
||||
- name: Check formatting and lints
|
||||
run: |
|
||||
cargo fmt --all -- --check
|
||||
cargo fmt --manifest-path tests/semver-port/Cargo.toml -- --check
|
||||
cargo clippy --locked -p metacrate-ci-matrix --all-targets -- -D warnings
|
||||
cargo clippy --locked --manifest-path tests/semver-port/Cargo.toml --all-targets -- -D warnings
|
||||
|
||||
- name: Upload audit evidence
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: api-semver-audit
|
||||
path: ci/evidence/api-audit.json
|
||||
@@ -1,95 +0,0 @@
|
||||
name: Native release artifact audit
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/artifact-audit.yml"
|
||||
- "ci/artifact-policy.json"
|
||||
- "ci/dependency-policy.json"
|
||||
- "ci/provenance-policy.json"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "docs/release-artifacts.md"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**"
|
||||
- "programs/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/artifact-audit.yml"
|
||||
- "ci/artifact-policy.json"
|
||||
- "ci/dependency-policy.json"
|
||||
- "ci/provenance-policy.json"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "docs/release-artifacts.md"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**"
|
||||
- "programs/**"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_RELEASE_OPT_LEVEL: 0
|
||||
FORCE_SKIA_BINARIES_DOWNLOAD: 1
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-artifact-audit
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-artifact-audit/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-artifact-audit/lib
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.97.1
|
||||
- name: Install documented native prerequisites
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
pkg-config --exact-version 2.5.4 libopenjp2
|
||||
pkg-config --modversion opus
|
||||
- name: Record source identity without a shipped build helper
|
||||
run: echo "METACRATE_RUST_COMMIT=$(git rev-parse --verify HEAD)" >>"$GITHUB_ENV"
|
||||
- name: Fetch the locked dependency graph
|
||||
run: cargo fetch --locked
|
||||
- name: Create every release source package atomically
|
||||
run: |
|
||||
cargo package --locked --no-verify \
|
||||
-p libremetaverse-types \
|
||||
-p libremetaverse-structured-data \
|
||||
-p libremetaverse-imaging \
|
||||
-p libremetaverse-imaging-skia \
|
||||
-p libremetaverse-openjpeg \
|
||||
-p libremetaverse-opus \
|
||||
-p libremetaverse-prim-mesher \
|
||||
-p libremetaverse-lsl-tools \
|
||||
-p libremetaverse \
|
||||
-p libremetaverse-rendering-simple \
|
||||
-p libremetaverse-rendering-mesh-foundry \
|
||||
-p libremetaverse-rlv \
|
||||
-p libremetaverse-utilities \
|
||||
-p libremetaverse-voice-vivox \
|
||||
-p libremetaverse-voice-webrtc \
|
||||
-p libremetaverse-programs
|
||||
- name: Build every shipped native executable
|
||||
run: cargo build --locked --release -j 1 -p libremetaverse-programs --bins
|
||||
- name: Inspect packages, binaries, links, and offline runtime behavior
|
||||
run: |
|
||||
cargo run --locked -p metacrate-ci-matrix -- artifact-audit \
|
||||
--artifact-dir target/release \
|
||||
--package-dir target/package \
|
||||
--evidence artifacts/release/artifact-audit.json
|
||||
- name: Upload immutable audit evidence and source packages
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: native-release-artifact-audit
|
||||
path: |
|
||||
artifacts/release/artifact-audit.json
|
||||
target/package/*.crate
|
||||
if-no-files-found: error
|
||||
109
.gitea/workflows/ci.yml
Normal file
109
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,109 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
cold_cache:
|
||||
description: Deliberately clear the required dependency/native cache before validation
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
required:
|
||||
name: required
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
CARGO_BUILD_JOBS: "2"
|
||||
CARGO_INCREMENTAL: "0"
|
||||
CARGO_PROFILE_DEV_DEBUG: "0"
|
||||
CARGO_PROFILE_TEST_DEBUG: "0"
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
CARGO_HOME: ${{ runner.tool_cache }}/metacrate/cargo/home-rust-1.97.1-aarch64-unknown-linux-gnu
|
||||
METACRATE_EXPECTED_HOST: aarch64-unknown-linux-gnu
|
||||
METACRATE_PROVENANCE_DIAGNOSTICS_DIR: artifacts/ci/provenance-candidates
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Inspect the runner-persistent, architecture-keyed cache
|
||||
run: |
|
||||
cache_key="$(sha256sum .gitea/workflows/ci.yml Cargo.lock Cargo.toml ci/ci-coverage.json ci/dependency-policy.json deny.toml tools/ci-matrix/src/ci_gate.rs tools/normalize_git_mtimes.py tools/install_openjpeg_2_5_4.sh crates/libremetaverse-imaging-skia/Cargo.toml | sha256sum | cut -d ' ' -f 1)"
|
||||
cargo_target="${{ runner.tool_cache }}/metacrate/cargo/target-rust-1.97.1-aarch64-unknown-linux-gnu-$cache_key"
|
||||
openjpeg_prefix="${{ runner.tool_cache }}/metacrate/native/openjpeg-2.5.4-${{ runner.arch }}"
|
||||
skia_dir="${{ runner.tool_cache }}/metacrate/native/skia-0.99.0-aarch64-unknown-linux-gnu"
|
||||
skia_archive="$skia_dir/skia-binaries-a25a0fdb7d90429aa2d1-aarch64-unknown-linux-gnu-jpegd-jpege-pdf-svg-textlayout-vulkan-webpd-webpe.tar.gz"
|
||||
if test "${{ github.event_name }}" = workflow_dispatch && test "${{ inputs.cold_cache }}" = true; then
|
||||
rm -rf -- "$CARGO_HOME/registry" "$CARGO_HOME/git" "$openjpeg_prefix" "$skia_dir"
|
||||
rm -f -- "$CARGO_HOME/bin/cargo-deny" "$CARGO_HOME/bin/cargo-machete"
|
||||
fi
|
||||
mkdir -p "$CARGO_HOME" "$cargo_target" "$skia_dir"
|
||||
test -f "$cargo_target/.metacrate-ready" && cargo_hit=true || cargo_hit=false
|
||||
test -f "$openjpeg_prefix/metacrate-openjpeg.identity" && test -f "$skia_archive" && native_hit=true || native_hit=false
|
||||
test -x "$CARGO_HOME/bin/cargo-deny" && test -x "$CARGO_HOME/bin/cargo-machete" && tools_hit=true || tools_hit=false
|
||||
echo "CARGO_TARGET_DIR=$cargo_target" >> "$GITHUB_ENV"
|
||||
echo "OPENJPEG_PREFIX=$openjpeg_prefix" >> "$GITHUB_ENV"
|
||||
echo "PKG_CONFIG_PATH=$openjpeg_prefix/lib/pkgconfig" >> "$GITHUB_ENV"
|
||||
echo "LD_LIBRARY_PATH=$openjpeg_prefix/lib" >> "$GITHUB_ENV"
|
||||
echo "METACRATE_SKIA_ARCHIVE=$skia_archive" >> "$GITHUB_ENV"
|
||||
echo "METACRATE_CARGO_CACHE_HIT=$cargo_hit" >> "$GITHUB_ENV"
|
||||
echo "METACRATE_NATIVE_CACHE_HIT=$native_hit" >> "$GITHUB_ENV"
|
||||
echo "METACRATE_TOOLS_CACHE_HIT=$tools_hit" >> "$GITHUB_ENV"
|
||||
|
||||
- name: Normalize tracked mtimes for reusable Cargo fingerprints
|
||||
run: |
|
||||
python3 tools/normalize_git_mtimes.py --self-test
|
||||
python3 tools/normalize_git_mtimes.py --state "$CARGO_TARGET_DIR/.metacrate-mtimes.json"
|
||||
python3 tools/normalize_git_mtimes.py --state "$CARGO_TARGET_DIR/.metacrate-mtimes.json" --check
|
||||
|
||||
- name: Install the single native prerequisite set
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl git ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev libasound2-dev
|
||||
|
||||
- name: Install pinned Rust and audit tools
|
||||
uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.97.1
|
||||
components: clippy,rustfmt
|
||||
- uses: taiki-e/install-action@v2
|
||||
with:
|
||||
tool: cargo-deny@0.20.2,cargo-machete@0.9.2
|
||||
|
||||
- name: Verify pinned audit tool versions
|
||||
run: |
|
||||
cargo deny --version | grep '0.20.2'
|
||||
cargo machete --version | grep '0.9.2'
|
||||
|
||||
- name: Validate and populate the exact native cache
|
||||
run: |
|
||||
test "$(uname -m)" = aarch64
|
||||
rustc -vV | grep '^host: aarch64-unknown-linux-gnu$'
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
pkg-config --exact-version 2.5.4 libopenjp2
|
||||
mkdir -p "$(dirname "$METACRATE_SKIA_ARCHIVE")"
|
||||
if ! echo 'dd127f458a5e67a79f3936a8aa19f822fe90a1d6a11b50b5f84df2b0519d909c '"$METACRATE_SKIA_ARCHIVE" | sha256sum --check --status; then
|
||||
curl --fail --location --proto '=https' --tlsv1.2 --output "$METACRATE_SKIA_ARCHIVE" \
|
||||
https://github.com/rust-skia/skia-binaries/releases/download/0.99.0/skia-binaries-a25a0fdb7d90429aa2d1-aarch64-unknown-linux-gnu-jpegd-jpege-pdf-svg-textlayout-vulkan-webpd-webpe.tar.gz
|
||||
fi
|
||||
echo 'dd127f458a5e67a79f3936a8aa19f822fe90a1d6a11b50b5f84df2b0519d909c '"$METACRATE_SKIA_ARCHIVE" | sha256sum --check
|
||||
|
||||
- name: Run the authoritative code-ready graph
|
||||
run: cargo run --locked -p metacrate-ci-matrix -- required-gate --evidence artifacts/ci/required-gate.json
|
||||
|
||||
- name: Mark the validated cache generation ready
|
||||
run: touch "$CARGO_TARGET_DIR/.metacrate-ready"
|
||||
|
||||
- name: Upload stage timing and audit evidence
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: required-ci-evidence
|
||||
path: artifacts/ci/
|
||||
if-no-files-found: error
|
||||
@@ -1,175 +0,0 @@
|
||||
name: Native code generation
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/codegen.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "api/**"
|
||||
- "codegen/**"
|
||||
- "tools/codegen/**"
|
||||
- "tools/generate_*.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "tools/check_api_coverage.py"
|
||||
- "tools/check_codegen_gate.py"
|
||||
- "tools/check_milestone_08.py"
|
||||
- "tools/check_milestone_09_issue_59.py"
|
||||
- "tools/check_milestone_09_issue_60.py"
|
||||
- "tools/check_milestone_09_issue_61.py"
|
||||
- "tools/check_milestone_09_issue_62.py"
|
||||
- "tools/check_milestone_09_issue_63.py"
|
||||
- "tools/check_milestone_09_issue_64.py"
|
||||
- "tools/check_milestone_09_issue_65.py"
|
||||
- "tools/check_milestone_09_issue_66.py"
|
||||
- "tools/check_milestone_09.py"
|
||||
- "tools/test_milestone_09.py"
|
||||
- "crates/libremetaverse/src/agent_movement.rs"
|
||||
- "crates/libremetaverse/src/inventory.rs"
|
||||
- "crates/libremetaverse/src/inventory_manager.rs"
|
||||
- "crates/libremetaverse/src/inventory_ais.rs"
|
||||
- "crates/libremetaverse/src/inventory_ais_internal_semantics.rs"
|
||||
- "docs/agent-movement.md"
|
||||
- "docs/inventory.md"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse/src/generated.rs"
|
||||
- "crates/libremetaverse/src/packets.rs"
|
||||
- "crates/libremetaverse/src/packet_*.rs"
|
||||
- "crates/libremetaverse/src/*_catalog.rs"
|
||||
- "tests/api-compile/**"
|
||||
- "tests/compat/Cargo.toml"
|
||||
- "tests/compat/build.rs"
|
||||
- "tests/compat/src/**"
|
||||
- "tests/compat/tests/wire_semantics.rs"
|
||||
- "tests/compat/tests/appearance_visual_semantics.rs"
|
||||
- "tests/compat/tests/inventory_store_semantics.rs"
|
||||
- "tests/compat/tests/inventory_manager_semantics.rs"
|
||||
- "tests/compat/tests/inventory_ais_semantics.rs"
|
||||
- "tests/compat/tests/task_inventory_semantics.rs"
|
||||
- "tests/compat/tests/misclassified_link_semantics.rs"
|
||||
- "tests/upstream-tests.json"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/codegen.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "api/**"
|
||||
- "codegen/**"
|
||||
- "tools/codegen/**"
|
||||
- "tools/generate_*.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "tools/check_api_coverage.py"
|
||||
- "tools/check_codegen_gate.py"
|
||||
- "tools/check_milestone_08.py"
|
||||
- "tools/check_milestone_09_issue_59.py"
|
||||
- "tools/check_milestone_09_issue_60.py"
|
||||
- "tools/check_milestone_09_issue_61.py"
|
||||
- "tools/check_milestone_09_issue_62.py"
|
||||
- "tools/check_milestone_09_issue_63.py"
|
||||
- "tools/check_milestone_09_issue_64.py"
|
||||
- "tools/check_milestone_09_issue_65.py"
|
||||
- "tools/check_milestone_09_issue_66.py"
|
||||
- "tools/check_milestone_09.py"
|
||||
- "tools/test_milestone_09.py"
|
||||
- "crates/libremetaverse/src/agent_movement.rs"
|
||||
- "crates/libremetaverse/src/inventory.rs"
|
||||
- "crates/libremetaverse/src/inventory_manager.rs"
|
||||
- "crates/libremetaverse/src/inventory_ais.rs"
|
||||
- "crates/libremetaverse/src/inventory_ais_internal_semantics.rs"
|
||||
- "docs/agent-movement.md"
|
||||
- "docs/inventory.md"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse/src/generated.rs"
|
||||
- "crates/libremetaverse/src/packets.rs"
|
||||
- "crates/libremetaverse/src/packet_*.rs"
|
||||
- "crates/libremetaverse/src/*_catalog.rs"
|
||||
- "tests/api-compile/**"
|
||||
- "tests/compat/Cargo.toml"
|
||||
- "tests/compat/build.rs"
|
||||
- "tests/compat/src/**"
|
||||
- "tests/compat/tests/wire_semantics.rs"
|
||||
- "tests/compat/tests/appearance_visual_semantics.rs"
|
||||
- "tests/compat/tests/inventory_store_semantics.rs"
|
||||
- "tests/compat/tests/inventory_manager_semantics.rs"
|
||||
- "tests/compat/tests/inventory_ais_semantics.rs"
|
||||
- "tests/compat/tests/task_inventory_semantics.rs"
|
||||
- "tests/compat/tests/misclassified_link_semantics.rs"
|
||||
- "tests/upstream-tests.json"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deterministic:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy,rustfmt
|
||||
- name: Install audited OpenJPEG 2.5.4
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential cmake pkg-config
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Test diagnostics and byte-identical generation
|
||||
run: cargo test -p libremetaverse-codegen
|
||||
- name: Verify vendored hashes and checked-in output
|
||||
run: cargo run -p libremetaverse-codegen -- check
|
||||
- name: Verify authoritative API mappings and consumer fixture
|
||||
run: |
|
||||
python3 tools/generate_rust_mapping.py --check
|
||||
python3 tools/generate_api_shims.py --check
|
||||
python3 tools/check_api_coverage.py
|
||||
python3 tools/check_milestone_08.py
|
||||
python3 tools/check_milestone_09_issue_59.py
|
||||
python3 tools/check_milestone_09_issue_60.py
|
||||
python3 tools/check_milestone_09_issue_61.py
|
||||
python3 tools/check_milestone_09_issue_62.py
|
||||
python3 tools/check_milestone_09_issue_63.py
|
||||
python3 tools/check_milestone_09_issue_64.py
|
||||
python3 tools/check_milestone_09_issue_65.py
|
||||
python3 tools/check_milestone_09_issue_66.py
|
||||
python3 tools/check_milestone_09.py
|
||||
cargo check --manifest-path tests/api-compile/Cargo.toml --locked
|
||||
- name: Test generated wire codecs and translated parity cases
|
||||
run: |
|
||||
cargo test -p libremetaverse --lib generated_codec_tests
|
||||
cargo test -p libremetaverse --test packet_wire
|
||||
cargo test -p libremetaverse --test packet_osd
|
||||
cargo test -p libremetaverse-compat-tests --test wire_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test inventory_store_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test inventory_manager_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test inventory_ais_semantics
|
||||
cargo test -p libremetaverse --lib inventory_ais_internal_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test task_inventory_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test misclassified_link_semantics
|
||||
- name: Test generated visual and foliage catalogs
|
||||
run: |
|
||||
cargo test -p libremetaverse --test generated_catalogs
|
||||
cargo test -p libremetaverse-compat-tests --test appearance_visual_semantics
|
||||
cargo test -p libremetaverse-compat-tests --test appearance_semantics
|
||||
cargo test -p libremetaverse --lib appearance_
|
||||
cargo test -p libremetaverse --lib initial_outfit::tests
|
||||
- name: Test generated skeleton, attention, and genepool catalogs
|
||||
run: |
|
||||
cargo test -p libremetaverse --test generated_avatar_catalogs
|
||||
cargo test -p libremetaverse --lib linden_skeleton
|
||||
cargo test -p libremetaverse --lib joint_base_support_category
|
||||
cargo test -p libremetaverse --lib joint_get_aliases_list
|
||||
- name: Build and audit clean Rust-only release artifacts
|
||||
run: |
|
||||
cargo build -p libremetaverse-codegen --release --locked -j 1
|
||||
python3 tools/check_codegen_gate.py --release-dir target/release
|
||||
- name: Lint native generator
|
||||
run: |
|
||||
cargo clippy -p libremetaverse-codegen --all-targets -- -D warnings
|
||||
cargo clippy -p libremetaverse --lib --no-deps -- -D warnings
|
||||
- name: Prove normal consumer build does not execute generation
|
||||
run: cargo build -p libremetaverse --locked
|
||||
@@ -1,71 +0,0 @@
|
||||
name: Concurrency and resource soak audit
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/concurrency-audit.yml"
|
||||
- "ci/concurrency-thresholds.json"
|
||||
- "tools/concurrency-audit/**"
|
||||
- "docs/concurrency-hardening.md"
|
||||
- "crates/libremetaverse/src/client_core.rs"
|
||||
- "crates/libremetaverse/src/download_manager.rs"
|
||||
- "crates/libremetaverse/src/appearance_manager.rs"
|
||||
- "crates/libremetaverse/src/asset_manager.rs"
|
||||
- "crates/libremetaverse/src/inventory_manager.rs"
|
||||
- "crates/libremetaverse-voice-webrtc/**"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/concurrency-audit.yml"
|
||||
- "ci/concurrency-thresholds.json"
|
||||
- "tools/concurrency-audit/**"
|
||||
- "docs/concurrency-hardening.md"
|
||||
- "crates/libremetaverse/src/client_core.rs"
|
||||
- "crates/libremetaverse/src/download_manager.rs"
|
||||
- "crates/libremetaverse/src/appearance_manager.rs"
|
||||
- "crates/libremetaverse/src/asset_manager.rs"
|
||||
- "crates/libremetaverse/src/inventory_manager.rs"
|
||||
- "crates/libremetaverse-voice-webrtc/**"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
|
||||
jobs:
|
||||
soak:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
- name: Install native voice prerequisite
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes libopus-dev pkg-config
|
||||
- name: Check formatting and focused race regressions
|
||||
run: |
|
||||
cargo fmt --all -- --check
|
||||
cargo test --locked -p libremetaverse --lib shutdown_does_not_hold_service_registry_lock_across_callbacks -j 1
|
||||
cargo test --locked -p libremetaverse --lib event_registry_isolates_panics_and_releases_subscriptions -j 1
|
||||
cargo test --locked -p libremetaverse --lib dispatch_isolates_panics_and_does_not_retain_dropped_handlers -j 1
|
||||
cargo test --locked -p libremetaverse --test caps_http download_queue_applies_backpressure_and_cancellation_drains_every_job -j 1
|
||||
cargo test --locked -p libremetaverse-voice-webrtc concurrent_provisioning_admits_one_session_without_leaking_the_loser -j 1
|
||||
- name: Run bounded native soak
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
cargo run --locked -p metacrate-concurrency-audit -j 1 -- \
|
||||
--cycles 16 --evidence artifacts/concurrency-audit.json
|
||||
- name: Upload sanitized resource evidence
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: concurrency-audit-evidence
|
||||
path: artifacts/concurrency-audit.json
|
||||
if-no-files-found: error
|
||||
@@ -1,89 +0,0 @@
|
||||
name: Documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/documentation.yml"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "README.md"
|
||||
- "api/**"
|
||||
- "crates/**"
|
||||
- "docs/**"
|
||||
- "programs/**"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/generate_api_shims.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/documentation.yml"
|
||||
- "Cargo.lock"
|
||||
- "Cargo.toml"
|
||||
- "README.md"
|
||||
- "api/**"
|
||||
- "crates/**"
|
||||
- "docs/**"
|
||||
- "programs/**"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/generate_api_shims.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
documentation:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
env:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
FORCE_SKIA_BINARIES_DOWNLOAD: "1"
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install native documentation prerequisites
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl ninja-build \
|
||||
pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
|
||||
- name: Install Rust 1.97 toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.97.0
|
||||
components: rustfmt
|
||||
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Verify documentation coverage report
|
||||
run: |
|
||||
cargo run --locked -p metacrate-ci-matrix -- documentation-report
|
||||
git diff --exit-code -- api/DOCUMENTATION-COVERAGE.md
|
||||
cargo run --locked -p metacrate-ci-matrix -- documentation-audit --evidence /tmp/metacrate-documentation-audit.json
|
||||
cmp /tmp/metacrate-documentation-audit.json ci/evidence/documentation-audit.json
|
||||
|
||||
- name: Build warning-free workspace documentation
|
||||
env:
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
run: cargo doc --workspace --no-deps --locked -j 1
|
||||
|
||||
- name: Compile guide snippets and examples
|
||||
run: |
|
||||
cargo test --locked -p libremetaverse --doc -j 1
|
||||
cargo test --locked -p libremetaverse --examples -j 1
|
||||
cargo run --locked -p libremetaverse --example offline_client
|
||||
cargo run --locked -p libremetaverse --example cancellation
|
||||
|
||||
- name: Verify documented program quick starts
|
||||
run: cargo test --locked -p libremetaverse-programs --tests -j 1
|
||||
|
||||
- name: Upload documentation evidence
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: documentation-evidence
|
||||
path: ci/evidence/documentation-audit.json
|
||||
if-no-files-found: error
|
||||
@@ -1,91 +0,0 @@
|
||||
name: Imaging and meshing gate
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/imaging-meshing.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse/src/generated.rs"
|
||||
- "crates/libremetaverse/src/skeleton.rs"
|
||||
- "crates/libremetaverse/src/*_catalog.rs"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-imaging-skia/**"
|
||||
- "crates/libremetaverse-prim-mesher/**"
|
||||
- "crates/libremetaverse-rendering-mesh-foundry/**"
|
||||
- "tests/compat/Cargo.toml"
|
||||
- "tests/compat/build.rs"
|
||||
- "tests/compat/src/**"
|
||||
- "tests/compat/tests/imaging_meshing_semantics.rs"
|
||||
- "tests/upstream-tests.json"
|
||||
- "tools/check_milestone_06.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/imaging-meshing.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse/src/generated.rs"
|
||||
- "crates/libremetaverse/src/skeleton.rs"
|
||||
- "crates/libremetaverse/src/*_catalog.rs"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-imaging-skia/**"
|
||||
- "crates/libremetaverse-prim-mesher/**"
|
||||
- "crates/libremetaverse-rendering-mesh-foundry/**"
|
||||
- "tests/compat/Cargo.toml"
|
||||
- "tests/compat/build.rs"
|
||||
- "tests/compat/src/**"
|
||||
- "tests/compat/tests/imaging_meshing_semantics.rs"
|
||||
- "tests/upstream-tests.json"
|
||||
- "tools/check_milestone_06.py"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
native:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: clippy,rustfmt
|
||||
- name: Install audited OpenJPEG 2.5.4
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential cmake pkg-config
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Audit milestone ownership and feature isolation
|
||||
run: python tools/check_milestone_06.py
|
||||
- name: Test native imaging and meshing crates
|
||||
run: |
|
||||
cargo test -p libremetaverse-imaging
|
||||
cargo test -p libremetaverse-imaging-skia --no-default-features
|
||||
cargo test -p libremetaverse-prim-mesher
|
||||
- name: Test reviewed milestone parity cases
|
||||
run: |
|
||||
cargo test -p libremetaverse-compat-tests --test imaging_meshing_semantics reviewed_managedimagetests_
|
||||
cargo test -p libremetaverse-compat-tests --test imaging_meshing_semantics reviewed_coordtests_
|
||||
cargo test -p libremetaverse-compat-tests --test imaging_meshing_semantics reviewed_quattests_
|
||||
cargo test -p libremetaverse-compat-tests --test imaging_meshing_semantics reviewed_primmeshtests_
|
||||
- name: Compile performance baselines
|
||||
run: |
|
||||
cargo bench -p libremetaverse-imaging --bench image_pipeline --no-run -j 1
|
||||
cargo bench -p libremetaverse-prim-mesher --bench meshing --no-run -j 1
|
||||
- name: Lint and document milestone crates
|
||||
run: |
|
||||
cargo clippy -p libremetaverse-imaging -p libremetaverse-imaging-skia -p libremetaverse-prim-mesher --all-targets -- -D warnings
|
||||
cargo doc -p libremetaverse-imaging -p libremetaverse-imaging-skia -p libremetaverse-prim-mesher --no-deps
|
||||
- name: Verify formatting
|
||||
run: cargo fmt --all -- --check
|
||||
@@ -1,46 +0,0 @@
|
||||
name: JPEG 2000 feature
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/jpeg2000.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-openjpeg/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/jpeg2000.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse/Cargo.toml"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-openjpeg/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
# Ubuntu also ships an older libopenjp2.so.7. Ensure both pkg-config and
|
||||
# the runtime loader select this run's isolated, audited 2.5.4 install.
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Install OpenJPEG 2.5.4
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential cmake pkg-config
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Build and test optional feature
|
||||
run: |
|
||||
cargo test -p libremetaverse-imaging --features jpeg2000
|
||||
cargo check -p libremetaverse --features jpeg2000
|
||||
@@ -1,55 +0,0 @@
|
||||
name: performance evidence
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "benchmarks/**"
|
||||
- "tools/performance/**"
|
||||
- "crates/libremetaverse/src/inventory.rs"
|
||||
- "crates/libremetaverse/src/targa.rs"
|
||||
- ".gitea/workflows/performance.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
pull_request:
|
||||
paths:
|
||||
- "benchmarks/**"
|
||||
- "tools/performance/**"
|
||||
- "crates/libremetaverse/src/inventory.rs"
|
||||
- "crates/libremetaverse/src/targa.rs"
|
||||
- ".gitea/workflows/performance.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CARGO_PROFILE_BENCHMARK_OPT_LEVEL: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
toolchain: 1.97.1
|
||||
components: rustfmt, clippy
|
||||
- uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: |
|
||||
8.0.x
|
||||
10.0.x
|
||||
- name: Check out pinned C# reference
|
||||
run: |
|
||||
git clone --filter=blob:none https://github.com/cinderblocks/libremetaverse.git "$RUNNER_TEMP/libremetaverse"
|
||||
git -C "$RUNNER_TEMP/libremetaverse" checkout 2aa70bb68513b39795da5d13c88f31b86e85a3ba
|
||||
- name: Compile separate C# reference runner
|
||||
run: >-
|
||||
dotnet build benchmarks/csharp-reference/MetaCrate.ReferenceBenchmarks.csproj
|
||||
-c Release -p:ReferenceRoot="$RUNNER_TEMP/libremetaverse"
|
||||
- name: Verify harness
|
||||
run: cargo test -p metacrate-performance --profile benchmark --locked -j1
|
||||
- name: Audit committed evidence
|
||||
run: >-
|
||||
cargo run -p metacrate-performance --profile benchmark --locked -j1 --
|
||||
audit --fixture-root benchmarks/fixtures
|
||||
--rust benchmarks/results/rust-linux-x86_64.json
|
||||
--reference benchmarks/results/csharp-linux-x86_64.json
|
||||
--comparison benchmarks/results/comparison.json
|
||||
@@ -1,103 +0,0 @@
|
||||
name: First release candidate
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/release-candidate.yml"
|
||||
- "ci/release-candidate-policy.json"
|
||||
- "ci/evidence/**"
|
||||
- "docs/release-candidate.md"
|
||||
- "CHANGELOG.md"
|
||||
- "release/**"
|
||||
- "api/**"
|
||||
- "programs/**"
|
||||
- "tests/**"
|
||||
- "tools/**"
|
||||
- "crates/**"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/release-candidate.yml"
|
||||
- "ci/release-candidate-policy.json"
|
||||
- "ci/evidence/**"
|
||||
- "docs/release-candidate.md"
|
||||
- "CHANGELOG.md"
|
||||
- "release/**"
|
||||
- "api/**"
|
||||
- "programs/**"
|
||||
- "tests/**"
|
||||
- "tools/**"
|
||||
- "crates/**"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
FORCE_SKIA_BINARIES_DOWNLOAD: 1
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-release-candidate
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-release-candidate/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-release-candidate/lib
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
|
||||
jobs:
|
||||
non-fuzz-release-gate:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.97.1
|
||||
components: rustfmt, clippy
|
||||
- name: Install every Linux release prerequisite
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev libasound2-dev
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Record source identity without a shipped helper
|
||||
run: echo "METACRATE_RUST_COMMIT=$(git rev-parse --verify HEAD)" >>"$GITHUB_ENV"
|
||||
- name: Verify generated surfaces, mappings, parity, and milestone inventories
|
||||
run: |
|
||||
python3 tools/generate_rust_mapping.py --check
|
||||
python3 tools/generate_api_shims.py --check
|
||||
python3 tools/check_api_coverage.py
|
||||
python3 tools/check_test_parity.py
|
||||
python3 tools/generate_lsl_tables.py --check
|
||||
python3 tools/check_milestone_09.py
|
||||
python3 tools/check_milestone_10.py
|
||||
- name: Format, compile, test, lint, and document the complete workspace
|
||||
run: |
|
||||
cargo fmt --all -- --check
|
||||
cargo check --workspace --all-targets --all-features --locked -j 1
|
||||
cargo test --workspace --all-features --locked -j 1
|
||||
cargo clippy --workspace --all-targets --all-features --locked -j 1 -- -D warnings
|
||||
cargo doc --workspace --all-features --no-deps --locked -j 1
|
||||
- name: Compile downstream and SemVer consumers
|
||||
run: |
|
||||
cargo check --locked --manifest-path tests/api-compile/Cargo.toml
|
||||
cargo run --locked --manifest-path tests/semver-port/Cargo.toml
|
||||
- name: Exercise all offline program and fake-grid behavior
|
||||
run: |
|
||||
cargo test --locked -p libremetaverse-programs --tests -j 1
|
||||
cargo run --locked -p libremetaverse-programs --bin live-grid-smoke -- --audit-only
|
||||
cargo run --locked -p libremetaverse-programs --bin live-grid-smoke -- --fake --evidence artifacts/release-candidate/fake-grid-smoke.jsonl
|
||||
- name: Revalidate all checked-in audits and checksums
|
||||
run: |
|
||||
cargo run --locked -p metacrate-ci-matrix -- audit
|
||||
cargo run --locked -p metacrate-ci-matrix -- documentation-audit --evidence artifacts/release-candidate/documentation.json
|
||||
cargo run --locked -p metacrate-ci-matrix -- dependency-audit --evidence artifacts/release-candidate/dependency.json
|
||||
cargo run --locked -p metacrate-ci-matrix -- provenance-audit --evidence artifacts/release-candidate/provenance.json
|
||||
sha256sum --check release/SHA256SUMS
|
||||
- name: Enforce the aggregate non-fuzz release-candidate decision
|
||||
run: cargo run --locked -p metacrate-ci-matrix -- release-candidate-audit --evidence artifacts/release-candidate/status.json
|
||||
- name: Upload release-candidate evidence, including failures
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: metacrate-0.0.1-release-candidate
|
||||
path: artifacts/release-candidate/
|
||||
if-no-files-found: error
|
||||
@@ -1,122 +0,0 @@
|
||||
name: Release platform and feature matrix
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/release-matrix.yml"
|
||||
- "ci/release-matrix.json"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "docs/release-ci-matrix.md"
|
||||
- "README.md"
|
||||
- "RUSTREWRITE.md"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**"
|
||||
- "programs/**"
|
||||
- "tests/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/release-matrix.yml"
|
||||
- "ci/release-matrix.json"
|
||||
- "tools/ci-matrix/**"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "docs/release-ci-matrix.md"
|
||||
- "README.md"
|
||||
- "RUSTREWRITE.md"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/**"
|
||||
- "programs/**"
|
||||
- "tests/**"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
FORCE_SKIA_BINARIES_DOWNLOAD: 1
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Validate matrix coverage and ubuntu-only policy
|
||||
run: cargo run --locked -p metacrate-ci-matrix -- audit
|
||||
|
||||
matrix:
|
||||
needs: audit
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- profile: linux-msrv-portable
|
||||
toolchain: 1.96.0
|
||||
target: x86_64-unknown-linux-gnu
|
||||
native_dependencies: true
|
||||
- profile: linux-stable-default
|
||||
toolchain: stable
|
||||
target: x86_64-unknown-linux-gnu
|
||||
native_dependencies: true
|
||||
- profile: linux-stable-minimal
|
||||
toolchain: stable
|
||||
target: x86_64-unknown-linux-gnu
|
||||
native_dependencies: false
|
||||
- profile: linux-stable-features
|
||||
toolchain: stable
|
||||
target: x86_64-unknown-linux-gnu
|
||||
native_dependencies: true
|
||||
- profile: linux-stable-release-surface
|
||||
toolchain: stable
|
||||
target: x86_64-unknown-linux-gnu
|
||||
native_dependencies: true
|
||||
- profile: windows-stable-portable
|
||||
toolchain: stable
|
||||
target: x86_64-pc-windows-gnu
|
||||
native_dependencies: false
|
||||
- profile: macos-stable-portable
|
||||
toolchain: stable
|
||||
target: x86_64-apple-darwin
|
||||
native_dependencies: false
|
||||
env:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}-${{ matrix.profile }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}-${{ matrix.profile }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}-${{ matrix.profile }}/lib
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache immutable Cargo downloads only
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
key: release-downloads-${{ runner.os }}-${{ matrix.toolchain }}-${{ hashFiles('Cargo.lock') }}
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: ${{ matrix.toolchain }}
|
||||
targets: ${{ matrix.target }}
|
||||
- name: Install pinned native feature prerequisites
|
||||
if: matrix.native_dependencies == true
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev libasound2-dev
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
pkg-config --modversion libopenjp2
|
||||
pkg-config --modversion opus
|
||||
pkg-config --modversion alsa
|
||||
- name: Revalidate matrix with selected toolchain
|
||||
run: cargo run --locked -p metacrate-ci-matrix -- audit
|
||||
- name: Execute isolated release profile
|
||||
run: cargo run --locked -p metacrate-ci-matrix -- run ${{ matrix.profile }} --evidence artifacts/ci-matrix/${{ matrix.profile }}.json
|
||||
- name: Upload exact matrix evidence
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: release-matrix-${{ matrix.profile }}
|
||||
path: artifacts/ci-matrix/${{ matrix.profile }}.json
|
||||
if-no-files-found: error
|
||||
61
.gitea/workflows/release.yml
Normal file
61
.gitea/workflows/release.yml
Normal file
@@ -0,0 +1,61 @@
|
||||
name: Non-routine release validation
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "17 3 * * 0"
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
concurrency:
|
||||
group: release-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 120
|
||||
env:
|
||||
CARGO_BUILD_JOBS: "2"
|
||||
CARGO_INCREMENTAL: "0"
|
||||
RUSTDOCFLAGS: "-D warnings"
|
||||
OPENJPEG_PREFIX: ${{ runner.tool_cache }}/metacrate/native/openjpeg-2.5.4-${{ runner.arch }}
|
||||
PKG_CONFIG_PATH: ${{ runner.tool_cache }}/metacrate/native/openjpeg-2.5.4-${{ runner.arch }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: ${{ runner.tool_cache }}/metacrate/native/openjpeg-2.5.4-${{ runner.arch }}/lib
|
||||
METACRATE_RUST_COMMIT: ${{ github.sha }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
${{ runner.tool_cache }}/metacrate/native
|
||||
target/release-gate
|
||||
key: release-rust-1.97.1-${{ runner.arch }}-${{ hashFiles('.gitea/workflows/release.yml', 'Cargo.lock', 'ci/ci-coverage.json', 'ci/release-matrix.json', 'ci/artifact-policy.json', 'tools/install_openjpeg_2_5_4.sh') }}
|
||||
- name: Install the release prerequisite set once
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang cmake curl git mingw-w64 ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev libopus-dev libasound2-dev
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.97.1
|
||||
components: clippy,rustfmt
|
||||
targets: x86_64-pc-windows-gnu,x86_64-apple-darwin
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
with:
|
||||
toolchain: 1.96.0
|
||||
- name: Validate the native release dependency
|
||||
run: tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Run the Rust-owned non-routine release graph
|
||||
run: cargo +1.97.1 run --locked -p metacrate-ci-matrix -- release-gate --evidence artifacts/release/release-gate.json
|
||||
- name: Upload release evidence and packages
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: non-routine-release-evidence
|
||||
path: |
|
||||
artifacts/release/
|
||||
target/release-gate/package/*.crate
|
||||
if-no-files-found: error
|
||||
@@ -1,119 +0,0 @@
|
||||
name: Native Rust workspace compile
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/rust-workspace.yml"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "tools/check_milestone_09.py"
|
||||
- "tools/test_milestone_09.py"
|
||||
- "tools/check_milestone_10_issue_76.py"
|
||||
- "tools/check_milestone_10_issue_77.py"
|
||||
- "tools/check_milestone_10_issue_78.py"
|
||||
- "tools/check_milestone_10_issue_79.py"
|
||||
- "tools/check_milestone_10_issue_80.py"
|
||||
- "tools/check_milestone_10_issue_81.py"
|
||||
- "tools/check_milestone_10_issue_82.py"
|
||||
- "tools/check_milestone_10_issue_83.py"
|
||||
- "tools/check_milestone_10.py"
|
||||
- "tools/test_milestone_10.py"
|
||||
- "tools/generate_lsl_tables.py"
|
||||
- "codegen/inputs/lsl_tools_grammar.json"
|
||||
- "docs/extension-milestone-gate.md"
|
||||
- "docs/live-grid-smoke.md"
|
||||
- "programs/README.md"
|
||||
- "api/SHIM-COVERAGE.md"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/rust-workspace.yml"
|
||||
- "tools/install_openjpeg_2_5_4.sh"
|
||||
- "tools/check_milestone_09.py"
|
||||
- "tools/test_milestone_09.py"
|
||||
- "tools/check_milestone_10_issue_76.py"
|
||||
- "tools/check_milestone_10_issue_77.py"
|
||||
- "tools/check_milestone_10_issue_78.py"
|
||||
- "tools/check_milestone_10_issue_79.py"
|
||||
- "tools/check_milestone_10_issue_80.py"
|
||||
- "tools/check_milestone_10_issue_81.py"
|
||||
- "tools/check_milestone_10_issue_82.py"
|
||||
- "tools/check_milestone_10_issue_83.py"
|
||||
- "tools/check_milestone_10.py"
|
||||
- "tools/test_milestone_10.py"
|
||||
- "tools/generate_lsl_tables.py"
|
||||
- "codegen/inputs/lsl_tools_grammar.json"
|
||||
- "docs/extension-milestone-gate.md"
|
||||
- "docs/live-grid-smoke.md"
|
||||
- "programs/README.md"
|
||||
- "api/SHIM-COVERAGE.md"
|
||||
- "**/*.rs"
|
||||
- "**/Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
compile:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
OPENJPEG_PREFIX: /tmp/metacrate-openjpeg-${{ github.run_id }}
|
||||
PKG_CONFIG_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib/pkgconfig
|
||||
LD_LIBRARY_PATH: /tmp/metacrate-openjpeg-${{ github.run_id }}/lib
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
CARGO_PROFILE_TEST_DEBUG: 0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
components: rustfmt, clippy
|
||||
- name: Install audited OpenJPEG 2.5.4
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential cmake pkg-config libopus-dev libasound2-dev
|
||||
tools/install_openjpeg_2_5_4.sh "$OPENJPEG_PREFIX"
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Audit native implementation boundaries
|
||||
run: |
|
||||
python3 tools/check_milestone_09_issue_59.py
|
||||
python3 tools/check_milestone_09_issue_60.py
|
||||
python3 tools/check_milestone_09_issue_61.py
|
||||
python3 tools/check_milestone_09_issue_62.py
|
||||
python3 tools/check_milestone_09_issue_63.py
|
||||
python3 tools/check_milestone_09_issue_64.py
|
||||
python3 tools/check_milestone_09_issue_65.py
|
||||
python3 tools/check_milestone_09_issue_66.py
|
||||
python3 tools/check_milestone_09.py
|
||||
python3 tools/check_milestone_10_issue_76.py
|
||||
python3 tools/check_milestone_10_issue_77.py
|
||||
python3 tools/check_milestone_10_issue_78.py
|
||||
python3 tools/check_milestone_10_issue_79.py
|
||||
python3 tools/check_milestone_10_issue_80.py
|
||||
python3 tools/check_milestone_10_issue_81.py
|
||||
python3 tools/check_milestone_10_issue_82.py
|
||||
python3 tools/check_milestone_10_issue_83.py
|
||||
python3 tools/generate_lsl_tables.py --check
|
||||
python3 tools/check_milestone_10.py
|
||||
- name: Test the complete native world milestone
|
||||
run: python3 tools/test_milestone_09.py
|
||||
- name: Test the complete native extension milestone
|
||||
run: python3 tools/test_milestone_10.py
|
||||
- name: Compile every workspace target with bounded memory
|
||||
run: cargo check --workspace --all-targets --locked -j 1
|
||||
- name: Audit and fake-smoke every native program target
|
||||
run: |
|
||||
cargo run -p libremetaverse-programs --bin live-grid-smoke --locked -- --audit-only
|
||||
cargo test -p libremetaverse-programs --test live_grid_smoke_cli --locked -j 1
|
||||
- name: Check optional cross-platform real audio backend
|
||||
run: |
|
||||
cargo check -p libremetaverse-voice-webrtc --all-targets --features real-audio --locked -j 1
|
||||
cargo check -p libremetaverse-programs --bin webrtc-test --features real-audio --locked -j 1
|
||||
- name: Lint every native extension target with bounded memory
|
||||
run: cargo clippy -p libremetaverse-rendering-simple -p libremetaverse-rendering-mesh-foundry -p libremetaverse-rlv -p libremetaverse-lsl-tools --all-targets --locked -j 1 -- -D warnings
|
||||
- name: Document every native extension crate
|
||||
env:
|
||||
RUSTDOCFLAGS: -D warnings
|
||||
run: cargo doc -p libremetaverse-rendering-simple -p libremetaverse-rendering-mesh-foundry -p libremetaverse-rlv -p libremetaverse-lsl-tools --no-deps --locked -j 1
|
||||
@@ -1,38 +0,0 @@
|
||||
name: Skia feature
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- ".gitea/workflows/skia.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-imaging-skia/**"
|
||||
pull_request:
|
||||
paths:
|
||||
- ".gitea/workflows/skia.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "crates/libremetaverse-types/**"
|
||||
- "crates/libremetaverse-imaging/**"
|
||||
- "crates/libremetaverse-imaging-skia/**"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
linux:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
FORCE_SKIA_BINARIES_DOWNLOAD: "1"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Install native link prerequisites
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install --yes build-essential clang curl ninja-build pkg-config python3 libfontconfig1-dev libfreetype6-dev
|
||||
- name: Test default and Skia feature builds
|
||||
run: |
|
||||
cargo test -p libremetaverse-imaging-skia --no-default-features
|
||||
cargo test -p libremetaverse-imaging-skia --features skia
|
||||
cargo package -p libremetaverse-imaging-skia --list
|
||||
@@ -1,49 +0,0 @@
|
||||
name: Dependency and supply-chain audit
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
CARGO_BUILD_JOBS: 1
|
||||
CARGO_INCREMENTAL: 0
|
||||
CARGO_PROFILE_DEV_DEBUG: 0
|
||||
|
||||
jobs:
|
||||
audit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache immutable Cargo downloads and advisory database
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
~/.cargo/advisory-dbs
|
||||
key: supply-chain-${{ runner.os }}-${{ hashFiles('Cargo.lock', 'deny.toml') }}
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- name: Fetch every immutable locked package archive
|
||||
run: cargo fetch --locked
|
||||
- name: Install pinned audit tools
|
||||
run: |
|
||||
cargo install --locked cargo-deny --version 0.20.2
|
||||
cargo install --locked cargo-machete --version 0.9.2
|
||||
- name: Record and validate the reviewed graph
|
||||
run: |
|
||||
mkdir -p artifacts
|
||||
cargo tree --locked --workspace --all-features --target all --duplicates > artifacts/dependency-duplicates.txt
|
||||
cargo run --locked -p metacrate-ci-matrix -- dependency-audit --evidence artifacts/dependency-audit.json
|
||||
cargo run --locked -p metacrate-ci-matrix -- provenance-audit --evidence artifacts/provenance-audit.json
|
||||
- name: Reject advisories, licenses, duplicates, and sources outside policy
|
||||
run: cargo deny check advisories licenses bans sources --hide-inclusion-graph
|
||||
- name: Reject unused direct dependencies
|
||||
run: cargo machete --with-metadata
|
||||
- name: Upload dependency evidence
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: supply-chain-evidence
|
||||
path: artifacts/
|
||||
if-no-files-found: error
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
/crates/libremetaverse-openjpeg/Cargo.lock
|
||||
/tests/api-compile/target/
|
||||
/tests/semver-port/target/
|
||||
/artifacts/
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
@@ -9,6 +9,6 @@ Generated by `metacrate-ci-matrix documentation-report`; do not edit by hand.
|
||||
| Mapped public members | 30789 | 30789 | 100% |
|
||||
| Compiled Rust guide snippets | 5 | 4 minimum | pass |
|
||||
| Linked native programs | 9 | 9 | 100% |
|
||||
| Checked local Markdown links | 86 | 86 | 100% |
|
||||
| Checked local Markdown links | 84 | 84 | 100% |
|
||||
|
||||
Every mapped item is tied to its exact C# documentation ID and to the ownership, asyncness, error, overload, mapping-kind, and Rust-signature decisions in [`RUST-MAPPING.tsv`](RUST-MAPPING.tsv). Public types are tied to the corresponding type mapping. The upstream source is pinned to [`2aa70bb68513b39795da5d13c88f31b86e85a3ba`](https://github.com/cinderblocks/libremetaverse/tree/2aa70bb68513b39795da5d13c88f31b86e85a3ba).
|
||||
|
||||
117
ci/ci-coverage.json
Normal file
117
ci/ci-coverage.json
Normal file
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"required_workflow": ".gitea/workflows/ci.yml",
|
||||
"release_workflow": ".gitea/workflows/release.yml",
|
||||
"hard_timeout_minutes": 15,
|
||||
"internal_target_seconds": 720,
|
||||
"required_checks": [
|
||||
"format",
|
||||
"deterministic-generation",
|
||||
"api-semver",
|
||||
"workspace-tests",
|
||||
"compatibility-parity",
|
||||
"minimal-features",
|
||||
"jpeg2000",
|
||||
"skia-binary",
|
||||
"program-offline-smoke",
|
||||
"clippy",
|
||||
"documentation",
|
||||
"dependency-policy",
|
||||
"provenance-policy",
|
||||
"performance-evidence",
|
||||
"concurrency-regressions"
|
||||
],
|
||||
"legacy_workflows": [
|
||||
{
|
||||
"workflow": "api-surface.yml",
|
||||
"responsibility": "Generated API mappings, SemVer baseline and audit, downstream consumer compilation, and focused lint",
|
||||
"destination": "required",
|
||||
"checks": ["deterministic-generation", "api-semver", "clippy"],
|
||||
"rationale": "Public API drift must block every code-ready change."
|
||||
},
|
||||
{
|
||||
"workflow": "artifact-audit.yml",
|
||||
"responsibility": "Source packages, release binaries, native linkage, and artifact/provenance inspection",
|
||||
"destination": "release",
|
||||
"checks": ["release-packaging", "native-artifact-audit"],
|
||||
"rationale": "Full packaging is expensive; routine provenance policy and package metadata validation remain required."
|
||||
},
|
||||
{
|
||||
"workflow": "codegen.yml",
|
||||
"responsibility": "Deterministic generation, generated wire/catalog tests, API fixture, and clean generator artifact",
|
||||
"destination": "required",
|
||||
"checks": ["format", "deterministic-generation", "workspace-tests", "compatibility-parity"],
|
||||
"rationale": "Generated-source and translated compatibility drift must fail before compilation proceeds."
|
||||
},
|
||||
{
|
||||
"workflow": "concurrency-audit.yml",
|
||||
"responsibility": "Focused race regressions and bounded resource soak",
|
||||
"destination": "split",
|
||||
"checks": ["concurrency-regressions", "long-resource-soak"],
|
||||
"rationale": "Focused regressions remain required; the 16-cycle resource soak runs in the non-routine release gate."
|
||||
},
|
||||
{
|
||||
"workflow": "documentation.yml",
|
||||
"responsibility": "Documentation audit, warning-free docs, doctests, examples, and documented program tests",
|
||||
"destination": "required",
|
||||
"checks": ["documentation", "program-offline-smoke"],
|
||||
"rationale": "Documentation and documented offline behavior are part of the public release surface."
|
||||
},
|
||||
{
|
||||
"workflow": "imaging-meshing.yml",
|
||||
"responsibility": "Imaging and meshing tests, parity cases, benchmark compilation, lint, and docs",
|
||||
"destination": "split",
|
||||
"checks": ["workspace-tests", "compatibility-parity", "clippy", "documentation", "benchmark-compilation"],
|
||||
"rationale": "Tests, parity, lint, and docs remain required; redundant benchmark compilation moves to the release gate."
|
||||
},
|
||||
{
|
||||
"workflow": "jpeg2000.yml",
|
||||
"responsibility": "Optional OpenJPEG/JPEG 2000 feature build and tests",
|
||||
"destination": "required",
|
||||
"checks": ["jpeg2000"],
|
||||
"rationale": "The optional native codec is tested independently with an exact cached OpenJPEG 2.5.4 identity."
|
||||
},
|
||||
{
|
||||
"workflow": "performance.yml",
|
||||
"responsibility": "Pinned C# comparison harness and committed performance evidence audit",
|
||||
"destination": "split",
|
||||
"checks": ["performance-evidence", "performance-regeneration"],
|
||||
"rationale": "Committed evidence validation remains required; C# checkout and evidence regeneration are manual release work."
|
||||
},
|
||||
{
|
||||
"workflow": "release-candidate.yml",
|
||||
"responsibility": "Aggregate release-readiness gate and evidence",
|
||||
"destination": "release",
|
||||
"checks": ["release-candidate-audit"],
|
||||
"rationale": "The aggregate release decision is non-routine and no longer recompiles the required gate."
|
||||
},
|
||||
{
|
||||
"workflow": "release-matrix.yml",
|
||||
"responsibility": "MSRV, default, minimal, features, release profiles, and portable cross-target checks",
|
||||
"destination": "split",
|
||||
"checks": ["minimal-features", "jpeg2000", "skia-binary", "msrv", "portable-cross-targets", "release-profile"],
|
||||
"rationale": "Fast feature isolation remains required; clean MSRV, cross-target, and release-profile builds run non-routinely."
|
||||
},
|
||||
{
|
||||
"workflow": "rust-workspace.yml",
|
||||
"responsibility": "Milestone checks, workspace compilation, program smoke, audio feature, extension lint, and docs",
|
||||
"destination": "required",
|
||||
"checks": ["workspace-tests", "compatibility-parity", "program-offline-smoke", "clippy", "documentation"],
|
||||
"rationale": "One all-feature test graph replaces overlapping compile and test invocations."
|
||||
},
|
||||
{
|
||||
"workflow": "skia.yml",
|
||||
"responsibility": "Default and Skia feature tests plus package listing",
|
||||
"destination": "required",
|
||||
"checks": ["skia-binary", "workspace-tests"],
|
||||
"rationale": "The required gate proves the exact ARM64 GNU archive is installed and forbids source compilation."
|
||||
},
|
||||
{
|
||||
"workflow": "supply-chain.yml",
|
||||
"responsibility": "Dependency graph, advisory, license, source, provenance, duplicate, and unused-dependency audits",
|
||||
"destination": "required",
|
||||
"checks": ["dependency-policy", "provenance-policy"],
|
||||
"rationale": "Pinned prebuilt audit tools and cached advisory data keep policy enforcement in the routine gate."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
"documented_members": 30789,
|
||||
"tested_rust_snippets": 5,
|
||||
"linked_programs": 9,
|
||||
"checked_local_links": 86,
|
||||
"checked_local_links": 84,
|
||||
"required_guide_sections": 11,
|
||||
"status": "ok"
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
{
|
||||
"schema": 1,
|
||||
"recorded_unix_seconds": 1786546522,
|
||||
"recorded_unix_seconds": 1786557316,
|
||||
"upstream_commit": "2aa70bb68513b39795da5d13c88f31b86e85a3ba",
|
||||
"material_count": 27,
|
||||
"generated_output_count": 8,
|
||||
"provenance_ledger_count": 3,
|
||||
"source_file_count": 538,
|
||||
"source_file_count": 530,
|
||||
"dependency_count": 389,
|
||||
"dependency_notice_count": 284,
|
||||
"dependency_notice_count": 276,
|
||||
"native_component_count": 6,
|
||||
"dependency_manifest_sha256": "6482698a22201b04f3234363790edc0be0dba39f445ac939e3fc8d4edeb372e9",
|
||||
"third_party_notices_sha256": "de5088841682813cc952af4d1dcc57d2521694e192888042d5585e344e570d16",
|
||||
"dependency_manifest_sha256": "1e7fbc87186c490b0c94751c6c471b488a856f9c3507d0b2a040dd285b035574",
|
||||
"third_party_notices_sha256": "4f30d077fb4563e48d0f954e8b3dd1f540d53cc782b727bd391259243eb66968",
|
||||
"native_notices_sha256": "b417ee7bf6b748cc86839e5354753c0f8c1f8309d13c0fea379c77f602e69fc0",
|
||||
"distribution_manifest_sha256": "18afd63d96e675c826cf138293df0ae73be279f45c9efa258bbbb30a1c7577e7",
|
||||
"distribution_manifest_sha256": "d7b628f087d9bd260a897b9534a2b8ae6d0d9378cf8c6c8e8ee374bbe39016e7",
|
||||
"unknown_materials": 0,
|
||||
"unknown_bundled_assets": 0,
|
||||
"status": "ok"
|
||||
|
||||
@@ -19,13 +19,13 @@ libremetaverse-types = { version = "0.0.1", path = "../libremetaverse-types" }
|
||||
# and without Vulkan on macOS. Matching those sets avoids an hours-long Skia
|
||||
# source build on every supported desktop target.
|
||||
[target.'cfg(any(target_os = "linux", target_os = "windows"))'.dependencies]
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "pdf", "svg", "textlayout", "vulkan", "webp"], optional = true }
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "no-compile", "pdf", "svg", "textlayout", "vulkan", "webp"], optional = true }
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "pdf", "svg", "textlayout", "webp"], optional = true }
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "no-compile", "pdf", "svg", "textlayout", "webp"], optional = true }
|
||||
|
||||
[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))'.dependencies]
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "pdf", "webp"], optional = true }
|
||||
skia-safe = { version = "0.99.0", default-features = false, features = ["binary-cache", "jpeg", "no-compile", "pdf", "webp"], optional = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
25
docs/ci-runtime-evidence.md
Normal file
25
docs/ci-runtime-evidence.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# 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, cache
|
||||
hit state, available peak-memory evidence, and the Skia binary outcome.
|
||||
|
||||
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 |
|
||||
| --- | --- | ---: | --- | --- |
|
||||
| pending first consolidated run | cold | pending | pending | pending |
|
||||
| pending second consolidated run | warm | pending | pending | pending |
|
||||
| pending third consolidated run | warm | pending | pending | pending |
|
||||
| pending fourth consolidated run | warm | pending | pending | pending |
|
||||
| pending fifth consolidated run | warm | pending | pending | pending |
|
||||
|
||||
Branch protection must require only `CI / required` after all five rows are
|
||||
green and at or below 15:00. Until then, this file deliberately records that
|
||||
runtime parity and branch-protection migration are not yet proven.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -4553,10 +4553,6 @@
|
||||
{
|
||||
"path": "generated-package-license-notice.txt",
|
||||
"sha256": "e6d6e0146d16ea19abea522d8ed77aadcdc4f90718a11d4d2cfb55c199ec8b4f"
|
||||
},
|
||||
{
|
||||
"path": "skia/LICENSE",
|
||||
"sha256": "5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4570,10 +4566,6 @@
|
||||
{
|
||||
"path": "generated-package-license-notice.txt",
|
||||
"sha256": "85160b23bdf006db68c232129bbf4ace9b3eee2fd21ba41025f447c8281c4f9d"
|
||||
},
|
||||
{
|
||||
"path": "repository-license/skia-bindings-0.99.0/skia/LICENSE",
|
||||
"sha256": "5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -4587,10 +4579,6 @@
|
||||
{
|
||||
"path": "generated-package-license-notice.txt",
|
||||
"sha256": "3eefd55332613883150398d8fcf426ac1036bbedecdf28c510573a2da294cf16"
|
||||
},
|
||||
{
|
||||
"path": "repository-license/skia-bindings-0.99.0/skia/LICENSE",
|
||||
"sha256": "5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -16,74 +16,19 @@
|
||||
"sha256": "a7c5358f9d0b0ed236519fec9d5d4faee9c04127eedac9ba3ab536d3dcf1b1f2"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/api-surface.yml",
|
||||
"bytes": 2661,
|
||||
"sha256": "0d65e6a99ba54f6501681c8a8eb6d07b1debcdfcfd3e7649fe2aa72b2c7798a0"
|
||||
"path": ".gitea/workflows/ci.yml",
|
||||
"bytes": 5597,
|
||||
"sha256": "e95257e598a959b47241970f41d14612f2016d40ddf118a994d909e91ac84dda"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/artifact-audit.yml",
|
||||
"bytes": 3497,
|
||||
"sha256": "91105987b707aa932cc476d8d496c0610e4ce9d0301c40e05916edae425225cb"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/codegen.yml",
|
||||
"bytes": 7978,
|
||||
"sha256": "c31c803c50d0e4dac495b80e503c4fc9a99ecf3a1ea95f670317aff75f5d3b94"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/concurrency-audit.yml",
|
||||
"bytes": 2842,
|
||||
"sha256": "095a90f2dbaf2b5a97155d8a21fc2ecafcfb70eab4f2535dce5aa94e22af93ca"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/documentation.yml",
|
||||
"bytes": 2957,
|
||||
"sha256": "8b004db1451886a81fc07de394657a8cc0f8aa6df0ea4d71e6b835daad18267b"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/imaging-meshing.yml",
|
||||
"bytes": 3893,
|
||||
"sha256": "bf99f0a0dc344033c1a702812013b5f643cc7be15e3b4a9703bfde47864ab611"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/jpeg2000.yml",
|
||||
"bytes": 1607,
|
||||
"sha256": "f7a23f0c89bb9476fffc3036b257ab8022a7af8b3b3ecd586d98cb7d76a23db6"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/performance.yml",
|
||||
"bytes": 1907,
|
||||
"sha256": "6cb5f7803765d91a45816275d8e86c26546b627319813d3ee8f3b463f6db2dad"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/release-candidate.yml",
|
||||
"bytes": 4397,
|
||||
"sha256": "e7ad8872f32f6d241a57e75eb7210953697869220a8e0af8a57b814b3aa8c216"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/release-matrix.yml",
|
||||
"bytes": 4263,
|
||||
"sha256": "5e8b05b3cedc46d7fb15a7b35ba5944db520dd747b6fc893eb5dd57954c61ac7"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/rust-workspace.yml",
|
||||
"bytes": 5284,
|
||||
"sha256": "2c11810e9d8eefb5f81e3e48043b0794262bc7a93f5ae3f731df314a2546adb9"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/skia.yml",
|
||||
"bytes": 1186,
|
||||
"sha256": "ab1c88406ad7e555a250cab587259d63c924062e7aeb743b75bcc2743c04cf5d"
|
||||
},
|
||||
{
|
||||
"path": ".gitea/workflows/supply-chain.yml",
|
||||
"bytes": 1808,
|
||||
"sha256": "0f988ff455e6d09a79c058df95913b22b8f227d35dd24ebd902986684d046dfd"
|
||||
"path": ".gitea/workflows/release.yml",
|
||||
"bytes": 2371,
|
||||
"sha256": "1db8899a6745f61bec38809f78f1475c0f6afc06b450ef112fea4d03deca069b"
|
||||
},
|
||||
{
|
||||
"path": ".gitignore",
|
||||
"bytes": 233,
|
||||
"sha256": "a8724cbe50232030f415af0eeb5e4c5ec9b068d26b0f2478506481f14cbe2915"
|
||||
"bytes": 245,
|
||||
"sha256": "a8a3b5c04d22081afedd1c34ac2949dfa6204185f9f8efbf78f9bbb746cce475"
|
||||
},
|
||||
{
|
||||
"path": "AGENTS.md",
|
||||
@@ -133,7 +78,7 @@
|
||||
{
|
||||
"path": "api/DOCUMENTATION-COVERAGE.md",
|
||||
"bytes": 911,
|
||||
"sha256": "490856724eaac1b6ee6065b048c50ae0bec6905ffebe6f7431ed7e6c6691cdc0"
|
||||
"sha256": "0d05fc115a7754074ba9c084654556ac32ce07b006236d21d406223cc5074de9"
|
||||
},
|
||||
{
|
||||
"path": "api/MAPPING-COVERAGE.md",
|
||||
@@ -265,6 +210,11 @@
|
||||
"bytes": 3011,
|
||||
"sha256": "718c065c78377c846ccd962922e06b19de276c32f427f73a026060eec9b7a45c"
|
||||
},
|
||||
{
|
||||
"path": "ci/ci-coverage.json",
|
||||
"bytes": 5480,
|
||||
"sha256": "4d1633c1cb396f934a8eff5f4e27362f6872b95ac66b95e9c4ac8e75ef833b29"
|
||||
},
|
||||
{
|
||||
"path": "ci/concurrency-thresholds.json",
|
||||
"bytes": 169,
|
||||
@@ -293,7 +243,7 @@
|
||||
{
|
||||
"path": "ci/evidence/documentation-audit.json",
|
||||
"bytes": 363,
|
||||
"sha256": "56e6e2224c3f7ebabc4f1d3c4c8d63a9208a03101d571728dab10a63332f51f6"
|
||||
"sha256": "8ee4ebd39572fc6ea00c40536bb59fd03e59e6973417f931166c4da1d963e9f3"
|
||||
},
|
||||
{
|
||||
"path": "ci/evidence/fake-grid-smoke.jsonl",
|
||||
@@ -382,8 +332,8 @@
|
||||
},
|
||||
{
|
||||
"path": "crates/libremetaverse-imaging-skia/Cargo.toml",
|
||||
"bytes": 1398,
|
||||
"sha256": "bb17594c9cb1699b5e1d0ec3e3d885ca44d1b6dcd18c98d6e7e0d1c374572d34"
|
||||
"bytes": 1440,
|
||||
"sha256": "0fb038f36280490487eb3f9e24176abd0f002504918b7bdac83ca319d92298e2"
|
||||
},
|
||||
{
|
||||
"path": "crates/libremetaverse-imaging-skia/README.md",
|
||||
@@ -1600,6 +1550,11 @@
|
||||
"bytes": 5813,
|
||||
"sha256": "cae4c875a9c1b83133a32dbfca1a64cd834e8459e8c7bab47d416527cceb45ca"
|
||||
},
|
||||
{
|
||||
"path": "docs/ci-runtime-evidence.md",
|
||||
"bytes": 1457,
|
||||
"sha256": "f085654b74e2c9d7f9cd8d44f307f6b778eafb496f1dd496bdb7b975c0f8cfad"
|
||||
},
|
||||
{
|
||||
"path": "docs/client-core.md",
|
||||
"bytes": 2145,
|
||||
@@ -1612,8 +1567,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/dependency-policy.md",
|
||||
"bytes": 4485,
|
||||
"sha256": "2f25574432215ea38530de1a1f4680fc5a94f1439820059b8b16d86eb0c5ad95"
|
||||
"bytes": 4488,
|
||||
"sha256": "2e822f2deefa949a4d2173ee6d993a7e3c5874c01cb4b90755d98d1b8805f3e8"
|
||||
},
|
||||
{
|
||||
"path": "docs/discovery.md",
|
||||
@@ -1627,8 +1582,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/imaging-meshing.md",
|
||||
"bytes": 3413,
|
||||
"sha256": "46559b199f5ef7de10a3280724cd1b06b733be7a078f85efefc569a001370ca5"
|
||||
"bytes": 3406,
|
||||
"sha256": "51ae2dfb88f5a40a01ab9394ae0545806377c6cbb2cbd85da2b7947b5534859e"
|
||||
},
|
||||
{
|
||||
"path": "docs/inventory.md",
|
||||
@@ -1662,8 +1617,8 @@
|
||||
},
|
||||
{
|
||||
"path": "docs/release-ci-matrix.md",
|
||||
"bytes": 4072,
|
||||
"sha256": "c4bf34fcc9c204824c68329d7bd2aca5a8799a7d34b44e2f8168ada923d34f47"
|
||||
"bytes": 7149,
|
||||
"sha256": "d6f2fa58bbbc361c9d02ca41c8764f7c2f2d328d998f61b85b4c32a64fe25355"
|
||||
},
|
||||
{
|
||||
"path": "docs/release-provenance.md",
|
||||
@@ -2013,7 +1968,7 @@
|
||||
{
|
||||
"path": "release/SHA256SUMS",
|
||||
"bytes": 909,
|
||||
"sha256": "67a50c93a6d574b82e30f923819fd7ee1dd102a62c27fe7db9f435f8ef5c246a"
|
||||
"sha256": "2dee8c4cbdc89f004fa3cd3a290a0943325f051dc4f169e4fe20f32f4a118c18"
|
||||
},
|
||||
{
|
||||
"path": "tests/PARITY.md",
|
||||
@@ -2452,8 +2407,8 @@
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_06.py",
|
||||
"bytes": 5531,
|
||||
"sha256": "a5cc71300f5b28695830eb8e88bbe3da0facad76a11120d0445bbe3a771a6d2c"
|
||||
"bytes": 5598,
|
||||
"sha256": "18f389b59020a6705595cfa18e6c374e09e4d81c8c3b1e397aa01da13c885e33"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_08.py",
|
||||
@@ -2507,48 +2462,48 @@
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10.py",
|
||||
"bytes": 9122,
|
||||
"sha256": "da1dba171d8f234e6d9234e70296f82a7eb87c943111ffd59be7d802d08e76bb"
|
||||
"bytes": 9038,
|
||||
"sha256": "34b7c8bc4d924364abe2ffc14738a9b237e00b931691b2e6a9adb4cfd3ef2289"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_76.py",
|
||||
"bytes": 4616,
|
||||
"sha256": "e307ed630fb6ab9d1cc1e9c4692f378014400a4a839d6b746a5863322d1f861d"
|
||||
"bytes": 4573,
|
||||
"sha256": "62034c4d0a77bc5a2d848306148e274150049ec2baec61ca1a5fbfd56d601f99"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_77.py",
|
||||
"bytes": 6627,
|
||||
"sha256": "32932d8e5154d5b4232071708ece6742398a551faa6d9e513ad8b9d7956359ee"
|
||||
"bytes": 6584,
|
||||
"sha256": "38d0f7216b875add2b7b761148e3c13a2fecb2cc0498ebabb5713d0e09ad5bdf"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_78.py",
|
||||
"bytes": 5251,
|
||||
"sha256": "b0b66b1cfa2ab0407346acd94233cd4c681d05bb9bd8d2a6771ee37ba79c7bf3"
|
||||
"bytes": 5208,
|
||||
"sha256": "bfb1dabc8eabbe7e102b413fb9cff132e226a38c70a069d5af9feaa62ed1b57e"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_79.py",
|
||||
"bytes": 5346,
|
||||
"sha256": "917090381f099b0322996e28abe997012b2d9f8335e6d5f9296b4810de0a6a81"
|
||||
"bytes": 5303,
|
||||
"sha256": "97b0048bd8e52a2e678962f6b4ee327967895b547fd34e20ba604f4c73a3e6ae"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_80.py",
|
||||
"bytes": 6673,
|
||||
"sha256": "429d4e879a6f8508c0c6b9407ac05953b9615764e4496d163a79793d1b2bd62c"
|
||||
"bytes": 6630,
|
||||
"sha256": "80364edcbf7eafe6ed7764dc8c014a893e5f92aef0296137b057e17036b7d74e"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_81.py",
|
||||
"bytes": 6933,
|
||||
"sha256": "1f96c80e9dae61ad3e54fa4c7208e9fed2a30face4904fe8791ad9a4615f424b"
|
||||
"bytes": 6890,
|
||||
"sha256": "3438337735c4a011840c2ee83aa37ba680de26e9a21e429214f98bb957b225b6"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_82.py",
|
||||
"bytes": 6664,
|
||||
"sha256": "dfbd3657efc57a7c02fd326545c6a8b08fc234d8df30fc98362cfbdf113c3e8f"
|
||||
"bytes": 6621,
|
||||
"sha256": "20a0b1a39d7d8c6262638277db87640c6031185765da24d2178b7a8d59c8d105"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_milestone_10_issue_83.py",
|
||||
"bytes": 7722,
|
||||
"sha256": "017613c5df110f2e469846e57b3e734e63447d52f94cec3e5e08eb487c0f254e"
|
||||
"bytes": 7619,
|
||||
"sha256": "e3f31776d6b2ee56d93618a83258d833194c8ec5da4fef5617cf3c6613f4f13b"
|
||||
},
|
||||
{
|
||||
"path": "tools/check_test_parity.py",
|
||||
@@ -2570,6 +2525,11 @@
|
||||
"bytes": 36939,
|
||||
"sha256": "f1b56f753d77ea40e72d8a4288174fdbc5974285c13d07f04ea52b34dbdd7506"
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/ci_gate.rs",
|
||||
"bytes": 43138,
|
||||
"sha256": "850d817aeb98525f0485344f7fcea8af492085123fda16049b9b6ea6b5fb6c85"
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/dependency.rs",
|
||||
"bytes": 12796,
|
||||
@@ -2582,18 +2542,18 @@
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/lib.rs",
|
||||
"bytes": 21442,
|
||||
"sha256": "c4a04b3342249af495fad0f9c1a7b8e84f247f00a590cf87e50f3747d2be7fd0"
|
||||
"bytes": 21175,
|
||||
"sha256": "096d055e5d295be43ae1db78acbc98557d27d63631c7699b6eb5d281fcc18424"
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/main.rs",
|
||||
"bytes": 8006,
|
||||
"sha256": "e61c19db7036796311182afb6c0671bbbfdd681f8eb1b4df08e596b43c0b0218"
|
||||
"bytes": 9422,
|
||||
"sha256": "33a3c408f2347b48b4ec43ca3771fa561dd9d58657fda5b067c4e06c4fe7c7fb"
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/provenance.rs",
|
||||
"bytes": 44270,
|
||||
"sha256": "6946295307a3740ba6b70187a37e0f4011f8070a4ef9e1adccecc3487aa71499"
|
||||
"bytes": 50543,
|
||||
"sha256": "697c65d8964cfe1b77a06ae6794e25e78579b0167b3871f4b99002c2680cf21f"
|
||||
},
|
||||
{
|
||||
"path": "tools/ci-matrix/src/release_candidate.rs",
|
||||
@@ -2662,8 +2622,13 @@
|
||||
},
|
||||
{
|
||||
"path": "tools/install_openjpeg_2_5_4.sh",
|
||||
"bytes": 2085,
|
||||
"sha256": "cece0ccb847dfc015734297b6988752d140e15a44f5347236266d2af699f7052"
|
||||
"bytes": 2582,
|
||||
"sha256": "7ca7eb0ab184f4acbdb475a20d140f001d7bd020d3244d163695406e88f52925"
|
||||
},
|
||||
{
|
||||
"path": "tools/normalize_git_mtimes.py",
|
||||
"bytes": 5879,
|
||||
"sha256": "88608e6bd5bea3c365a22bb97fc56cf67acb0c911fd67d05e0562256a8522d36"
|
||||
},
|
||||
{
|
||||
"path": "tools/performance/Cargo.toml",
|
||||
@@ -2699,13 +2664,13 @@
|
||||
"generated_release_files": [
|
||||
{
|
||||
"path": "release/DEPENDENCY-LICENSES.json",
|
||||
"bytes": 217677,
|
||||
"sha256": "6482698a22201b04f3234363790edc0be0dba39f445ac939e3fc8d4edeb372e9"
|
||||
"bytes": 217171,
|
||||
"sha256": "a4095621c7975f6b01c5b1653b375c571be15657f7fa824d6b5a2e46f3434dcc"
|
||||
},
|
||||
{
|
||||
"path": "release/THIRD-PARTY-NOTICES.md",
|
||||
"bytes": 848536,
|
||||
"sha256": "de5088841682813cc952af4d1dcc57d2521694e192888042d5585e344e570d16"
|
||||
"bytes": 846570,
|
||||
"sha256": "da051a965d39715d10da5c17fdfdafd8059b83d2491837d223607e9c5e16a5fa"
|
||||
},
|
||||
{
|
||||
"path": "release/NATIVE-LICENSES.md",
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
5f23a03801161141e4e7baa57b787a606ea83ffc3ccd8de5e760240b399707cc ci/evidence/api-audit.json
|
||||
9c9c6ed236d04880bab504387251f7a9e283f338c48fe46a6fe0ece472eb8063 ci/evidence/artifact-audit.json
|
||||
80c926cfdb7f4055659392cba69e37352a8d501cf235a244362384b04b78a02a ci/evidence/concurrency-audit.json
|
||||
56e6e2224c3f7ebabc4f1d3c4c8d63a9208a03101d571728dab10a63332f51f6 ci/evidence/documentation-audit.json
|
||||
8ee4ebd39572fc6ea00c40536bb59fd03e59e6973417f931166c4da1d963e9f3 ci/evidence/documentation-audit.json
|
||||
db355bb598888d08e1bfac56436f0dc786312defb8345741dd5003ff4e37409f ci/evidence/provenance-audit.json
|
||||
b417ee7bf6b748cc86839e5354753c0f8c1f8309d13c0fea379c77f602e69fc0 release/NATIVE-LICENSES.md
|
||||
|
||||
@@ -281,9 +281,9 @@ This document must accompany source and binary distributions. A package's presen
|
||||
| `simd-adler32 0.3.10` | `MIT` | `3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea` | `42a35170233e83e18856792e748de4c1ce4a63b2afce9a370c89ef3fe23f9f2d` |
|
||||
| `simd_cesu8 1.2.0` | `Apache-2.0 OR MIT` | `11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520` | `a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2`<br>`23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3` |
|
||||
| `simdutf8 0.1.5` | `MIT OR Apache-2.0` | `e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e` | `0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594`<br>`508a77d2e7b51d98adeed32648ad124b7b30241a8e70b2e72c99f92d8e5874d1` |
|
||||
| `skia-bindings 0.99.0` | `MIT` | `3e2d1c3ebd697c0cbded0145e9204a38fa6b268446051b7196d0a096414ea7f3` | `e6d6e0146d16ea19abea522d8ed77aadcdc4f90718a11d4d2cfb55c199ec8b4f`<br>`5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd` |
|
||||
| `skia-safe 0.99.0` | `MIT` | `9f512ac418a64194842dd05566320805dad1c957c521039db2486fd6368865bc` | `85160b23bdf006db68c232129bbf4ace9b3eee2fd21ba41025f447c8281c4f9d`<br>`5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd` |
|
||||
| `skia-svg-macros 0.1.0` | `MIT` | `044dd2233c9717a74f75197f3e7f0a966db2127c0ffb5e05013b480a9b75b2c7` | `3eefd55332613883150398d8fcf426ac1036bbedecdf28c510573a2da294cf16`<br>`5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd` |
|
||||
| `skia-bindings 0.99.0` | `MIT` | `3e2d1c3ebd697c0cbded0145e9204a38fa6b268446051b7196d0a096414ea7f3` | `e6d6e0146d16ea19abea522d8ed77aadcdc4f90718a11d4d2cfb55c199ec8b4f` |
|
||||
| `skia-safe 0.99.0` | `MIT` | `9f512ac418a64194842dd05566320805dad1c957c521039db2486fd6368865bc` | `85160b23bdf006db68c232129bbf4ace9b3eee2fd21ba41025f447c8281c4f9d` |
|
||||
| `skia-svg-macros 0.1.0` | `MIT` | `044dd2233c9717a74f75197f3e7f0a966db2127c0ffb5e05013b480a9b75b2c7` | `3eefd55332613883150398d8fcf426ac1036bbedecdf28c510573a2da294cf16` |
|
||||
| `slab 0.4.12` | `MIT` | `0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5` | `8ce0830173fdac609dfb4ea603fdc002c2f4af0dc9b1a005653f5da9cf534b18` |
|
||||
| `smallvec 1.15.2` | `MIT OR Apache-2.0` | `8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90` | `a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2`<br>`0b28172679e0009b655da42797c03fd163a3379d5cfa67ba1f1655e974a2a1a9` |
|
||||
| `socket2 0.6.5` | `MIT OR Apache-2.0` | `c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4` | `a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2`<br>`378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397` |
|
||||
@@ -6295,44 +6295,6 @@ The published crate archive contains no discoverable top-level license/notice fi
|
||||
|
||||
</pre>
|
||||
|
||||
### `5f787c1dee3c56547f09ccc2906ab5f5293c4d8dd6c8654e573216c38e908dbd`
|
||||
|
||||
Packages: skia-bindings 0.99.0, skia-safe 0.99.0, skia-svg-macros 0.1.0<br>
|
||||
Source filenames: repository-license/skia-bindings-0.99.0/skia/LICENSE, skia/LICENSE
|
||||
|
||||
<pre>
|
||||
Copyright (c) 2011 Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
</pre>
|
||||
|
||||
### `615f39d3be6ff90d956c6b490b1f967a8995e88c109384895740748cb197fd87`
|
||||
|
||||
Packages: objc2-core-graphics 0.3.2<br>
|
||||
|
||||
@@ -104,11 +104,7 @@ def check_benchmarks_and_ci() -> None:
|
||||
if not (crate / "benches" / f"{name}.rs").is_file():
|
||||
raise SystemExit(f"missing {name} benchmark source")
|
||||
|
||||
workflows = {
|
||||
"imaging-meshing": ROOT / ".gitea" / "workflows" / "imaging-meshing.yml",
|
||||
"jpeg2000": ROOT / ".gitea" / "workflows" / "jpeg2000.yml",
|
||||
"skia": ROOT / ".gitea" / "workflows" / "skia.yml",
|
||||
}
|
||||
workflows = {"consolidated": ROOT / ".gitea" / "workflows" / "ci.yml"}
|
||||
for name, path in workflows.items():
|
||||
if not path.is_file():
|
||||
raise SystemExit(f"missing {name} native-feature workflow")
|
||||
@@ -121,6 +117,10 @@ def check_benchmarks_and_ci() -> None:
|
||||
f"{name} workflow must use only ubuntu-latest, found: "
|
||||
+ ", ".join(unsupported)
|
||||
)
|
||||
text = path.read_text()
|
||||
for marker in ("required-gate", "METACRATE_SKIA_ARCHIVE", "OPENJPEG_PREFIX"):
|
||||
if marker not in text:
|
||||
raise SystemExit(f"{name} workflow is missing {marker}")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
@@ -227,12 +227,11 @@ def check_generation_and_ci() -> None:
|
||||
subprocess.run(
|
||||
["python3", "tools/generate_lsl_tables.py", "--check"], cwd=ROOT, check=True
|
||||
)
|
||||
workflow = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
workflow = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
require_markers(
|
||||
workflow,
|
||||
(
|
||||
"python3 tools/check_milestone_10.py",
|
||||
"python3 tools/test_milestone_10.py",
|
||||
"required-gate",
|
||||
"runs-on: ubuntu-latest",
|
||||
),
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ REFERENCE = (
|
||||
/ "reference_pipeline.rs"
|
||||
)
|
||||
DOC = ROOT / "crates" / "libremetaverse-rendering-simple" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
TYPE = "T:LibreMetaverse.Rendering.SimpleRenderer"
|
||||
@@ -85,7 +85,7 @@ def main() -> None:
|
||||
"all four `DetailLevel`", "65,536", "Error::Rendering",
|
||||
"source primitive UUID", "MeshFoundry", "prim-local coordinates",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_76.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 76 audit: native prim/sculpt conversion, face metadata, texture mapping, "
|
||||
"bounded errors, deterministic evidence, dependency isolation, and docs are present"
|
||||
|
||||
@@ -19,7 +19,7 @@ BENCH = ROOT / "crates" / "libremetaverse-rendering-mesh-foundry" / "benches" /
|
||||
WORKSPACE = ROOT / "Cargo.toml"
|
||||
DOC = ROOT / "crates" / "libremetaverse-rendering-mesh-foundry" / "README.md"
|
||||
STRUCTURED = ROOT / "crates" / "libremetaverse-structured-data" / "src" / "lib.rs"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
TYPE = "T:LibreMetaverse.Rendering.MeshFoundry"
|
||||
@@ -98,7 +98,7 @@ def main() -> None:
|
||||
"exactly-four-influence", "XOR winding", "64 MiB", "65,536", "6,000,000",
|
||||
"source primitive UUID", "57,600-vertex",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_77.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 77 audit: native prim/sculpt/terrain and packed mesh pipelines, bounded LLSD/zlib, "
|
||||
"LOD, normals/tangents/UVs, materials, rigging, convex data, tests, benchmark, and docs are present"
|
||||
|
||||
@@ -15,7 +15,7 @@ GENERATED = ROOT / "crates" / "libremetaverse-rlv" / "src" / "generated.rs"
|
||||
TESTS = ROOT / "crates" / "libremetaverse-rlv" / "tests" / "protocol_parsing.rs"
|
||||
COMPAT = ROOT / "tests" / "compat" / "tests" / "rlv_common_semantics.rs"
|
||||
DOC = ROOT / "crates" / "libremetaverse-rlv" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
TYPES = {
|
||||
@@ -98,7 +98,7 @@ def main() -> None:
|
||||
"side-effect-free", "119 behavior", "56 pinned", "half-open byte span",
|
||||
"64 KiB", "128 comma-separated", "does not wait", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_78.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 78 audit: bounded pure RLV parsing, typed commands/queries/restrictions, "
|
||||
"exact aliases, positioned errors, mapped values, mutation evidence, and docs are present"
|
||||
|
||||
@@ -16,7 +16,7 @@ GENERATED = ROOT / "crates" / "libremetaverse-rlv" / "src" / "generated.rs"
|
||||
TESTS = ROOT / "crates" / "libremetaverse-rlv" / "tests" / "state_semantics.rs"
|
||||
COMPAT = ROOT / "tests" / "compat" / "tests" / "rlv_inventory_map_semantics.rs"
|
||||
DOC = ROOT / "crates" / "libremetaverse-rlv" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
CATALOG = ROOT / "api" / "public-api.json"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
@@ -111,7 +111,7 @@ def main() -> None:
|
||||
"after manager locks are released", "secure and explicit", "no network",
|
||||
"ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_79.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 79 audit: native restriction state, inventory maps, recursive locks, "
|
||||
"camera aggregation, blacklist, permission precedence, concurrency evidence, "
|
||||
|
||||
@@ -20,7 +20,7 @@ QUERY_TESTS = ROOT / "tests" / "compat" / "tests" / "rlv_query_basics_semantics.
|
||||
ACTION_TESTS = ROOT / "tests" / "compat" / "tests" / "rlv_attach_commands_semantics.rs"
|
||||
NOTIFY_TESTS = ROOT / "tests" / "compat" / "tests" / "rlv_notify_semantics.rs"
|
||||
DOC = ROOT / "crates" / "libremetaverse-rlv" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
CATALOG = ROOT / "api" / "public-api.json"
|
||||
STUB_RE = re.compile(r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\(")
|
||||
|
||||
@@ -136,7 +136,7 @@ def main() -> None:
|
||||
"after releasing every manager lock", "completed inventory and agent",
|
||||
"616", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_80.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 80 audit: native callbacks, typed actions and queries, bounded service "
|
||||
"dispatch, inventory/agent adapters, cancellation, post-lock notifications, "
|
||||
|
||||
@@ -18,7 +18,7 @@ COMPAT_TESTS = (
|
||||
ROOT / "crates" / "libremetaverse-lsl-tools" / "tests" / "lexer_compat.rs"
|
||||
)
|
||||
DOC = ROOT / "crates" / "libremetaverse-lsl-tools" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
CATALOG = ROOT / "api" / "public-api.json"
|
||||
STUB_RE = re.compile(
|
||||
r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\("
|
||||
@@ -135,7 +135,7 @@ def main() -> None:
|
||||
"64 Mi UTF-16", "16 Mi units", "Lexer::iter", "46 focused",
|
||||
"No C#, .NET runtime", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_81.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 81 audit: 22 mapped native types and 188 members, bounded UTF-16 "
|
||||
"source handling, comments and line directives, Unicode categories, deterministic "
|
||||
|
||||
@@ -16,7 +16,7 @@ GENERATED = ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "generated.rs
|
||||
TESTS = ROOT / "crates" / "libremetaverse-lsl-tools" / "tests" / "parser_compat.rs"
|
||||
EXTENSION_TESTS = ROOT / "tests" / "compat" / "tests" / "extension_shims.rs"
|
||||
DOC = ROOT / "crates" / "libremetaverse-lsl-tools" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
CATALOG = ROOT / "api" / "public-api.json"
|
||||
STUB_RE = re.compile(
|
||||
r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\("
|
||||
@@ -125,7 +125,7 @@ def main() -> None:
|
||||
"nonassociative", "1,048,576", "16,777,216", "46 focused",
|
||||
"issue 83", "ubuntu-latest",
|
||||
))
|
||||
require_markers(WORKFLOW, ("python3 tools/check_milestone_10_issue_82.py",))
|
||||
require_markers(WORKFLOW, ("required-gate",))
|
||||
print(
|
||||
"issue 82 audit: 22 native mapped parser types and 215 members, deterministic "
|
||||
"LALR tables, precedence conflicts, bounded shifts/reductions, error-token "
|
||||
|
||||
@@ -19,7 +19,7 @@ GENERATOR = ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "generator.rs
|
||||
GENERATED = ROOT / "crates" / "libremetaverse-lsl-tools" / "src" / "generated.rs"
|
||||
TESTS = ROOT / "crates" / "libremetaverse-lsl-tools" / "tests" / "generator_compat.rs"
|
||||
DOC = ROOT / "crates" / "libremetaverse-lsl-tools" / "README.md"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "rust-workspace.yml"
|
||||
WORKFLOW = ROOT / ".gitea" / "workflows" / "ci.yml"
|
||||
SCRIPT = ROOT / "tools" / "generate_lsl_tables.py"
|
||||
STUB_RE = re.compile(
|
||||
r"\b(?:not_implemented|unimplemented_api)\b|\b(?:todo|unimplemented)!\s*\("
|
||||
@@ -184,8 +184,7 @@ def main() -> None:
|
||||
require_markers(
|
||||
WORKFLOW,
|
||||
(
|
||||
"python3 tools/check_milestone_10_issue_83.py",
|
||||
"python3 tools/generate_lsl_tables.py --check",
|
||||
"required-gate",
|
||||
),
|
||||
)
|
||||
if "runs-on: ubuntu-latest" not in workflow or re.search(
|
||||
|
||||
1377
tools/ci-matrix/src/ci_gate.rs
Normal file
1377
tools/ci-matrix/src/ci_gate.rs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -13,6 +13,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
mod api_surface;
|
||||
mod artifact;
|
||||
mod ci_gate;
|
||||
mod dependency;
|
||||
mod documentation;
|
||||
mod provenance;
|
||||
@@ -20,13 +21,14 @@ mod release_candidate;
|
||||
|
||||
pub use api_surface::{audit_api_surface, write_api_baseline};
|
||||
pub use artifact::audit_artifacts;
|
||||
pub use ci_gate::{audit_consolidated_ci, run_release_gate, run_required_gate};
|
||||
pub use dependency::audit_dependencies;
|
||||
pub use documentation::{audit_documentation, write_documentation_report};
|
||||
pub use provenance::{audit_provenance, write_provenance_reports};
|
||||
pub use release_candidate::audit_release_candidate;
|
||||
|
||||
pub const MATRIX_PATH: &str = "ci/release-matrix.json";
|
||||
const WORKFLOW_PATH: &str = ".gitea/workflows/release-matrix.yml";
|
||||
const WORKFLOW_PATH: &str = ".gitea/workflows/release.yml";
|
||||
const REQUIRED_PROFILES: [&str; 7] = [
|
||||
"linux-msrv-portable",
|
||||
"linux-stable-default",
|
||||
@@ -458,25 +460,16 @@ fn audit_cargo_features(root: &Path) -> Result<()> {
|
||||
|
||||
fn audit_workflows(root: &Path, matrix: &ReleaseMatrix) -> Result<()> {
|
||||
let workflow = fs::read_to_string(root.join(WORKFLOW_PATH))?;
|
||||
for profile in &matrix.profiles {
|
||||
if !workflow.contains(&format!("profile: {}", profile.id)) {
|
||||
return Err(MatrixError::new(format!(
|
||||
"workflow does not schedule profile {}",
|
||||
profile.id
|
||||
)));
|
||||
}
|
||||
}
|
||||
if !workflow.contains("~/.cargo/registry")
|
||||
if matrix.profiles.is_empty()
|
||||
|| !workflow.contains("release-gate")
|
||||
|| !workflow.contains("~/.cargo/registry")
|
||||
|| !workflow.contains("~/.cargo/git")
|
||||
|| workflow.lines().any(|line| {
|
||||
let trimmed = line.trim();
|
||||
trimmed == "target" || trimmed.starts_with("target/") || trimmed.contains("/target/")
|
||||
})
|
||||
{
|
||||
return Err(MatrixError::new(
|
||||
"workflow must cache Cargo downloads without caching build target directories",
|
||||
"release workflow must invoke the Rust gate and cache Cargo downloads",
|
||||
));
|
||||
}
|
||||
audit_consolidated_ci(root)?;
|
||||
let workflows = root.join(".gitea/workflows");
|
||||
for entry in fs::read_dir(workflows)? {
|
||||
let path = entry?.path();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use metacrate_ci_matrix::{
|
||||
audit, audit_api_surface, audit_artifacts, audit_dependencies, audit_documentation,
|
||||
audit_provenance, audit_release_candidate, load, run, workspace_root, write_api_baseline,
|
||||
write_documentation_report, write_provenance_reports,
|
||||
audit, audit_api_surface, audit_artifacts, audit_consolidated_ci, audit_dependencies,
|
||||
audit_documentation, audit_provenance, audit_release_candidate, load, run, run_release_gate,
|
||||
run_required_gate, workspace_root, write_api_baseline, write_documentation_report,
|
||||
write_provenance_reports,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@@ -12,12 +13,23 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)] // Flat CLI command routing is clearer than nested dispatch.
|
||||
fn execute() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let current = std::env::current_dir()?;
|
||||
let root = workspace_root(¤t).ok_or("could not locate the Cargo workspace")?;
|
||||
let matrix = load(&root)?;
|
||||
let mut arguments = std::env::args().skip(1);
|
||||
match arguments.next().as_deref() {
|
||||
Some("ci-audit") if arguments.next().is_none() => {
|
||||
audit_consolidated_ci(&root)?;
|
||||
println!("consolidated CI coverage and workflow split: ok");
|
||||
}
|
||||
Some("required-gate") => {
|
||||
gate_command(&root, arguments, "required", run_required_gate)?;
|
||||
}
|
||||
Some("release-gate") => {
|
||||
gate_command(&root, arguments, "release", run_release_gate)?;
|
||||
}
|
||||
Some("audit") if arguments.next().is_none() => {
|
||||
audit(&root, &matrix)?;
|
||||
println!(
|
||||
@@ -101,7 +113,7 @@ fn execute() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
_ => {
|
||||
return Err(
|
||||
"usage: ci-matrix audit | run PROFILE --evidence FILE | dependency-audit --evidence FILE | artifact-audit --artifact-dir DIR --package-dir DIR --evidence FILE | release-candidate-audit --evidence FILE | documentation-report | documentation-audit --evidence FILE | api-baseline-write | api-audit --evidence FILE | provenance-report | provenance-audit --evidence FILE"
|
||||
"usage: ci-matrix ci-audit | required-gate --evidence FILE | release-gate --evidence FILE | audit | run PROFILE --evidence FILE | dependency-audit --evidence FILE | artifact-audit --artifact-dir DIR --package-dir DIR --evidence FILE | release-candidate-audit --evidence FILE | documentation-report | documentation-audit --evidence FILE | api-baseline-write | api-audit --evidence FILE | provenance-report | provenance-audit --evidence FILE"
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
@@ -109,6 +121,27 @@ fn execute() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gate_command(
|
||||
root: &Path,
|
||||
mut arguments: impl Iterator<Item = String>,
|
||||
gate: &str,
|
||||
run_gate: fn(&Path, &Path) -> metacrate_ci_matrix::Result<()>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let flag = arguments
|
||||
.next()
|
||||
.ok_or_else(|| format!("{gate}-gate requires --evidence FILE"))?;
|
||||
let evidence = arguments
|
||||
.next()
|
||||
.ok_or_else(|| format!("{gate}-gate requires --evidence FILE"))?;
|
||||
if flag != "--evidence" || arguments.next().is_some() {
|
||||
return Err(format!("usage: ci-matrix {gate}-gate --evidence FILE").into());
|
||||
}
|
||||
let evidence = absolute_or_rooted(root, &evidence);
|
||||
run_gate(root, &evidence)?;
|
||||
println!("{gate} CI gate: ok ({})", evidence.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn release_candidate_audit_command(
|
||||
root: &Path,
|
||||
mut arguments: impl Iterator<Item = String>,
|
||||
|
||||
@@ -6,7 +6,7 @@ use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::ffi::OsStr;
|
||||
use std::fmt::Write as _;
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::Write as _;
|
||||
use std::io::{Read as _, Write as _};
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
@@ -916,8 +916,16 @@ fn parse_lock_string(value: &str) -> Result<String> {
|
||||
}
|
||||
|
||||
fn package_notices(root: &Path, explicit: Option<&str>) -> Result<Vec<(String, String)>> {
|
||||
if let Some(archive) = registry_archive(root).filter(|path| path.is_file()) {
|
||||
let package = root
|
||||
.file_name()
|
||||
.and_then(OsStr::to_str)
|
||||
.ok_or_else(|| MatrixError::new("registry package path has no UTF-8 name"))?;
|
||||
return package_notices_from_archive(&archive, package, explicit);
|
||||
}
|
||||
|
||||
let mut candidates = Vec::new();
|
||||
collect_notice_files(root, 0, &mut candidates)?;
|
||||
collect_notice_files(root, &mut candidates)?;
|
||||
if let Some(explicit) = explicit {
|
||||
let path = root.join(explicit);
|
||||
if path.is_file() {
|
||||
@@ -946,18 +954,76 @@ fn package_notices(root: &Path, explicit: Option<&str>) -> Result<Vec<(String, S
|
||||
Ok(notices)
|
||||
}
|
||||
|
||||
fn collect_notice_files(directory: &Path, depth: u8, output: &mut Vec<PathBuf>) -> Result<()> {
|
||||
if depth > 2 {
|
||||
return Ok(());
|
||||
fn registry_archive(root: &Path) -> Option<PathBuf> {
|
||||
let package = root.file_name()?.to_str()?;
|
||||
let index = root.parent()?.file_name()?;
|
||||
let registry = root.parent()?.parent()?.parent()?;
|
||||
Some(
|
||||
registry
|
||||
.join("cache")
|
||||
.join(index)
|
||||
.join(format!("{package}.crate")),
|
||||
)
|
||||
}
|
||||
let mut entries = fs::read_dir(directory)?.collect::<std::io::Result<Vec<_>>>()?;
|
||||
entries.sort_by_key(std::fs::DirEntry::file_name);
|
||||
for entry in entries {
|
||||
let path = entry.path();
|
||||
let kind = entry.file_type()?;
|
||||
let name = entry.file_name().to_string_lossy().to_ascii_lowercase();
|
||||
if kind.is_file()
|
||||
&& [
|
||||
|
||||
fn package_notices_from_archive(
|
||||
archive: &Path,
|
||||
package: &str,
|
||||
explicit: Option<&str>,
|
||||
) -> Result<Vec<(String, String)>> {
|
||||
let decoder = flate2::read::GzDecoder::new(fs::File::open(archive)?);
|
||||
let mut archive = tar::Archive::new(decoder);
|
||||
let mut notices = Vec::new();
|
||||
for entry in archive.entries()? {
|
||||
let mut entry = entry?;
|
||||
if !entry.header().entry_type().is_file() {
|
||||
continue;
|
||||
}
|
||||
let path = entry.path()?;
|
||||
let mut components = path.components();
|
||||
if components.next() != Some(Component::Normal(OsStr::new(package))) {
|
||||
return Err(MatrixError::new(format!(
|
||||
"package archive entry is outside its {package} root: {}",
|
||||
path.display()
|
||||
)));
|
||||
}
|
||||
let relative = components.collect::<PathBuf>();
|
||||
let relative_text = relative
|
||||
.to_str()
|
||||
.ok_or_else(|| MatrixError::new("package archive contains a non-UTF-8 path"))?;
|
||||
validate_relative(relative_text)?;
|
||||
let depth = relative.components().count();
|
||||
let selected = explicit == Some(relative_text)
|
||||
|| (depth <= 3
|
||||
&& relative
|
||||
.file_name()
|
||||
.and_then(OsStr::to_str)
|
||||
.is_some_and(is_notice_name));
|
||||
if !selected {
|
||||
continue;
|
||||
}
|
||||
let size = entry.header().size()?;
|
||||
if size > 2 * 1024 * 1024 {
|
||||
return Err(MatrixError::new(format!(
|
||||
"package notice is unexpectedly large: {relative_text}"
|
||||
)));
|
||||
}
|
||||
let mut contents = String::new();
|
||||
entry.read_to_string(&mut contents).map_err(|error| {
|
||||
MatrixError::new(format!(
|
||||
"package notice is not UTF-8 ({relative_text}): {error}"
|
||||
))
|
||||
})?;
|
||||
notices.push((relative_text.to_owned(), normalize_notice_text(&contents)));
|
||||
}
|
||||
notices.sort_by(|left, right| left.0.cmp(&right.0));
|
||||
notices.dedup_by(|left, right| left.0 == right.0);
|
||||
Ok(notices)
|
||||
}
|
||||
|
||||
fn is_notice_name(name: &str) -> bool {
|
||||
let name = name.to_ascii_lowercase();
|
||||
[
|
||||
"license",
|
||||
"licence",
|
||||
"copying",
|
||||
@@ -967,10 +1033,19 @@ fn collect_notice_files(directory: &Path, depth: u8, output: &mut Vec<PathBuf>)
|
||||
]
|
||||
.iter()
|
||||
.any(|prefix| name.starts_with(prefix))
|
||||
{
|
||||
}
|
||||
|
||||
fn collect_notice_files(directory: &Path, output: &mut Vec<PathBuf>) -> Result<()> {
|
||||
// Cargo build scripts may populate nested source directories (rust-skia
|
||||
// creates `skia/` in its registry checkout). Only package-root notices and
|
||||
// Cargo's explicit `license_file` are immutable package metadata.
|
||||
let mut entries = fs::read_dir(directory)?.collect::<std::io::Result<Vec<_>>>()?;
|
||||
entries.sort_by_key(std::fs::DirEntry::file_name);
|
||||
for entry in entries {
|
||||
let path = entry.path();
|
||||
let kind = entry.file_type()?;
|
||||
if kind.is_file() && is_notice_name(&entry.file_name().to_string_lossy()) {
|
||||
output.push(path);
|
||||
} else if kind.is_dir() && depth < 2 {
|
||||
collect_notice_files(&path, depth + 1, output)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -1095,6 +1170,10 @@ fn source_paths(root: &Path) -> Result<Vec<String>> {
|
||||
.map_err(|_| MatrixError::new("source archive contains a non-UTF-8 path"))
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()?;
|
||||
// `git ls-files --cached` retains index entries for working-tree deletions
|
||||
// until the consolidation commit is created. A source distribution always
|
||||
// describes files that actually exist, including during a pre-commit audit.
|
||||
paths.retain(|path| root.join(path).is_file());
|
||||
for path in &paths {
|
||||
validate_relative(path)?;
|
||||
}
|
||||
@@ -1126,8 +1205,18 @@ fn compare_report(root: &Path, relative: &str, expected: &[u8]) -> Result<()> {
|
||||
MatrixError::new(format!("generated report {}: {error}", path.display()))
|
||||
})?;
|
||||
if actual != expected {
|
||||
if let Some(directory) = std::env::var_os("METACRATE_PROVENANCE_DIAGNOSTICS_DIR") {
|
||||
let directory = PathBuf::from(directory);
|
||||
fs::create_dir_all(&directory)?;
|
||||
let name = path
|
||||
.file_name()
|
||||
.ok_or_else(|| MatrixError::new("generated report path has no file name"))?;
|
||||
fs::write(directory.join(name), expected)?;
|
||||
}
|
||||
return Err(MatrixError::new(format!(
|
||||
"{relative} is stale; run `cargo run --locked -p metacrate-ci-matrix -- provenance-report`"
|
||||
"{relative} is stale (checked-in sha256 {}, generated sha256 {}); run `cargo run --locked -p metacrate-ci-matrix -- provenance-report`",
|
||||
sha256(&actual),
|
||||
sha256(expected),
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
@@ -1253,6 +1342,69 @@ version = "0.0.1"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn package_notice_scan_ignores_build_generated_subtrees() {
|
||||
let root =
|
||||
std::env::temp_dir().join(format!("metacrate-package-notices-{}", std::process::id()));
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
fs::create_dir_all(root.join("generated")).unwrap();
|
||||
fs::write(root.join("LICENSE"), "package license\n").unwrap();
|
||||
fs::write(root.join("generated/LICENSE"), "generated license\n").unwrap();
|
||||
fs::write(root.join("generated/NOTICE.explicit"), "explicit notice\n").unwrap();
|
||||
|
||||
let notices = package_notices(&root, Some("generated/NOTICE.explicit")).unwrap();
|
||||
assert_eq!(
|
||||
notices
|
||||
.iter()
|
||||
.map(|(path, _)| path.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
["LICENSE", "generated/NOTICE.explicit"]
|
||||
);
|
||||
fs::remove_dir_all(root).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn package_notice_scan_preserves_nested_files_from_registry_archive() {
|
||||
let base =
|
||||
std::env::temp_dir().join(format!("metacrate-package-archive-{}", std::process::id()));
|
||||
let root = base.join("registry/src/index/demo-1.0.0");
|
||||
let archive_path = base.join("registry/cache/index/demo-1.0.0.crate");
|
||||
let _ = fs::remove_dir_all(&base);
|
||||
fs::create_dir_all(root.join("generated")).unwrap();
|
||||
fs::create_dir_all(archive_path.parent().unwrap()).unwrap();
|
||||
fs::write(root.join("generated/LICENSE"), "build output\n").unwrap();
|
||||
|
||||
let encoder = flate2::write::GzEncoder::new(
|
||||
fs::File::create(&archive_path).unwrap(),
|
||||
flate2::Compression::default(),
|
||||
);
|
||||
let mut archive = tar::Builder::new(encoder);
|
||||
for (path, contents) in [
|
||||
("demo-1.0.0/LICENSE", "package license\n"),
|
||||
("demo-1.0.0/vendor/COPYING", "vendored license\n"),
|
||||
("demo-1.0.0/docs/legal/terms.txt", "explicit terms\n"),
|
||||
] {
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_size(contents.len() as u64);
|
||||
header.set_mode(0o644);
|
||||
header.set_cksum();
|
||||
archive
|
||||
.append_data(&mut header, path, contents.as_bytes())
|
||||
.unwrap();
|
||||
}
|
||||
archive.into_inner().unwrap().finish().unwrap();
|
||||
|
||||
let notices = package_notices(&root, Some("docs/legal/terms.txt")).unwrap();
|
||||
assert_eq!(
|
||||
notices
|
||||
.iter()
|
||||
.map(|(path, _)| path.as_str())
|
||||
.collect::<Vec<_>>(),
|
||||
["LICENSE", "docs/legal/terms.txt", "vendor/COPYING"]
|
||||
);
|
||||
fs::remove_dir_all(base).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsafe_paths_are_rejected() {
|
||||
for path in ["", "../escape", "a/../b", "/absolute"] {
|
||||
|
||||
@@ -13,6 +13,8 @@ fi
|
||||
install_prefix=$1
|
||||
pkg_config_path="$install_prefix/lib/pkgconfig"
|
||||
library_path="$install_prefix/lib"
|
||||
identity_path="$install_prefix/metacrate-openjpeg.identity"
|
||||
target_arch=$(uname -m)
|
||||
|
||||
persist_actions_environment() {
|
||||
if [ -z "${GITHUB_ENV:-}" ]; then
|
||||
@@ -33,6 +35,10 @@ persist_actions_environment() {
|
||||
}
|
||||
|
||||
if [ -f "$pkg_config_path/libopenjp2.pc" ] &&
|
||||
[ -f "$identity_path" ] &&
|
||||
[ "$(sed -n '1p' "$identity_path")" = "version=$OPENJPEG_VERSION" ] &&
|
||||
[ "$(sed -n '2p' "$identity_path")" = "commit=$OPENJPEG_COMMIT" ] &&
|
||||
[ "$(sed -n '3p' "$identity_path")" = "architecture=$target_arch" ] &&
|
||||
PKG_CONFIG_PATH="$pkg_config_path" pkg-config --exact-version "$OPENJPEG_VERSION" libopenjp2
|
||||
then
|
||||
persist_actions_environment
|
||||
@@ -64,5 +70,11 @@ cmake -S "$source_dir" -B "$build_dir" \
|
||||
cmake --build "$build_dir" --parallel
|
||||
cmake --install "$build_dir"
|
||||
|
||||
{
|
||||
printf 'version=%s\n' "$OPENJPEG_VERSION"
|
||||
printf 'commit=%s\n' "$OPENJPEG_COMMIT"
|
||||
printf 'architecture=%s\n' "$target_arch"
|
||||
} >"$identity_path"
|
||||
|
||||
PKG_CONFIG_PATH="$pkg_config_path" pkg-config --exact-version "$OPENJPEG_VERSION" libopenjp2
|
||||
persist_actions_environment
|
||||
|
||||
164
tools/normalize_git_mtimes.py
Normal file
164
tools/normalize_git_mtimes.py
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Give tracked files stable mtimes derived from their immutable Git blobs."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePath
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
|
||||
WINDOWS_TICK_NANOSECONDS = 100
|
||||
|
||||
|
||||
def tracked_entries(root: Path) -> list[tuple[bytes, Path]]:
|
||||
output = subprocess.run(
|
||||
["git", "ls-files", "--stage", "-z"],
|
||||
cwd=root,
|
||||
check=True,
|
||||
stdout=subprocess.PIPE,
|
||||
).stdout
|
||||
entries: list[tuple[bytes, Path]] = []
|
||||
for record in output.split(b"\0"):
|
||||
if not record:
|
||||
continue
|
||||
metadata, separator, raw_path = record.partition(b"\t")
|
||||
if not separator:
|
||||
raise RuntimeError("git ls-files produced a record without a path")
|
||||
mode, _object_id, stage = metadata.split(b" ")
|
||||
if stage != b"0":
|
||||
raise RuntimeError(
|
||||
f"cannot normalize an unmerged index entry: {os.fsdecode(raw_path)}"
|
||||
)
|
||||
relative = PurePath(os.fsdecode(raw_path))
|
||||
if relative.is_absolute() or ".." in relative.parts:
|
||||
raise RuntimeError(f"unsafe tracked path: {relative}")
|
||||
entries.append((mode, root.joinpath(*relative.parts)))
|
||||
return entries
|
||||
|
||||
|
||||
def content_identity(mode: bytes, path: Path) -> str:
|
||||
digest = hashlib.sha256(mode + b"\0")
|
||||
if path.is_symlink():
|
||||
digest.update(os.fsencode(os.readlink(path)))
|
||||
else:
|
||||
with path.open("rb") as source:
|
||||
while chunk := source.read(1024 * 1024):
|
||||
digest.update(chunk)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def default_state_path(root: Path) -> Path:
|
||||
return root / "target" / ".metacrate-mtimes.json"
|
||||
|
||||
|
||||
def read_state(path: Path) -> dict[str, dict[str, int | str]]:
|
||||
if not path.is_file():
|
||||
return {}
|
||||
value = json.loads(path.read_text(encoding="utf-8"))
|
||||
if value.get("schema") != 1 or not isinstance(value.get("files"), dict):
|
||||
raise RuntimeError(f"invalid tracked-mtime state: {path}")
|
||||
return value["files"]
|
||||
|
||||
|
||||
def write_state(path: Path, files: dict[str, dict[str, int | str]]) -> None:
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
temporary = path.with_name(f".{path.name}.{os.getpid()}.tmp")
|
||||
temporary.write_text(
|
||||
json.dumps({"schema": 1, "files": files}, indent=2, sort_keys=True) + "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
os.replace(temporary, path)
|
||||
|
||||
|
||||
def normalize(root: Path, state_path: Path, check: bool) -> int:
|
||||
previous = read_state(state_path)
|
||||
current: dict[str, dict[str, int | str]] = {}
|
||||
changed = 0
|
||||
prior_max = max(
|
||||
(int(value["mtime_ns"]) for value in previous.values()), default=0
|
||||
)
|
||||
wall_time = time.time_ns() // WINDOWS_TICK_NANOSECONDS * WINDOWS_TICK_NANOSECONDS
|
||||
now = max(wall_time, prior_max + WINDOWS_TICK_NANOSECONDS)
|
||||
for mode, path in tracked_entries(root):
|
||||
if not (path.is_file() or path.is_symlink()):
|
||||
continue
|
||||
relative = path.relative_to(root).as_posix()
|
||||
identity = content_identity(mode, path)
|
||||
prior = previous.get(relative)
|
||||
expected = (
|
||||
int(prior["mtime_ns"])
|
||||
if prior is not None and prior.get("identity") == identity
|
||||
else now
|
||||
)
|
||||
current[relative] = {"identity": identity, "mtime_ns": expected}
|
||||
actual = os.stat(path, follow_symlinks=False).st_mtime_ns
|
||||
if actual == expected:
|
||||
continue
|
||||
if check:
|
||||
raise RuntimeError(f"tracked mtime is not normalized: {path}")
|
||||
os.utime(path, ns=(expected, expected), follow_symlinks=False)
|
||||
changed += 1
|
||||
if not check:
|
||||
write_state(state_path, current)
|
||||
return changed
|
||||
|
||||
|
||||
def self_test() -> None:
|
||||
with tempfile.TemporaryDirectory(prefix="metacrate-mtimes-") as directory:
|
||||
root = Path(directory)
|
||||
subprocess.run(["git", "init", "--quiet"], cwd=root, check=True)
|
||||
subprocess.run(
|
||||
["git", "config", "user.email", "ci@example.invalid"], cwd=root, check=True
|
||||
)
|
||||
subprocess.run(
|
||||
["git", "config", "user.name", "MetaCrate CI"], cwd=root, check=True
|
||||
)
|
||||
first = root / "first.txt"
|
||||
second = root / "second.txt"
|
||||
first.write_text("first\n", encoding="utf-8")
|
||||
second.write_text("second\n", encoding="utf-8")
|
||||
subprocess.run(["git", "add", "."], cwd=root, check=True)
|
||||
subprocess.run(["git", "commit", "--quiet", "-m", "fixture"], cwd=root, check=True)
|
||||
state = root / "state.json"
|
||||
|
||||
assert normalize(root, state, False) == 2
|
||||
assert normalize(root, state, True) == 0
|
||||
first_mtime = first.stat().st_mtime_ns
|
||||
second_mtime = second.stat().st_mtime_ns
|
||||
|
||||
first.write_text("changed\n", encoding="utf-8")
|
||||
assert normalize(root, state, False) == 1
|
||||
assert first.stat().st_mtime_ns > first_mtime
|
||||
assert second.stat().st_mtime_ns == second_mtime
|
||||
assert normalize(root, state, True) == 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--check", action="store_true")
|
||||
parser.add_argument("--self-test", action="store_true")
|
||||
parser.add_argument("--root", type=Path, default=Path.cwd())
|
||||
parser.add_argument("--state", type=Path)
|
||||
args = parser.parse_args()
|
||||
if args.self_test:
|
||||
self_test()
|
||||
print("tracked Git mtime self-test: ok")
|
||||
return 0
|
||||
root = args.root.resolve()
|
||||
state_path = args.state or default_state_path(root)
|
||||
if not state_path.is_absolute():
|
||||
state_path = root / state_path
|
||||
changed = normalize(root, state_path, args.check)
|
||||
verb = "verified" if args.check else "normalized"
|
||||
print(f"{verb} tracked Git mtimes ({changed} changed)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user