Some checks failed
API and SemVer surface / api-surface (push) Failing after 1m28s
Native release artifact audit / audit (push) Failing after 1h6m34s
Native code generation / deterministic (push) Failing after 2m15s
Concurrency and resource soak audit / soak (push) Failing after 6m33s
Documentation / documentation (push) Failing after 2m0s
Imaging and meshing gate / native (push) Failing after 55s
JPEG 2000 feature / linux (push) Successful in 2m46s
performance evidence / audit (push) Failing after 13m45s
Release platform and feature matrix / audit (push) Successful in 1m3s
Native Rust workspace compile / compile (push) Failing after 55s
Skia feature / linux (push) Successful in 31m58s
Dependency and supply-chain audit / audit (push) Failing after 9m34s
Release platform and feature matrix / matrix (false, linux-stable-minimal, x86_64-unknown-linux-gnu, stable) (push) Failing after 10m2s
Release platform and feature matrix / matrix (false, macos-stable-portable, x86_64-apple-darwin, stable) (push) Failing after 2m0s
Release platform and feature matrix / matrix (false, windows-stable-portable, x86_64-pc-windows-gnu, stable) (push) Failing after 1m56s
Release platform and feature matrix / matrix (true, linux-msrv-portable, x86_64-unknown-linux-gnu, 1.96.0) (push) Failing after 6m19s
Release platform and feature matrix / matrix (true, linux-stable-default, x86_64-unknown-linux-gnu, stable) (push) Failing after 6m57s
Release platform and feature matrix / matrix (true, linux-stable-features, x86_64-unknown-linux-gnu, stable) (push) Failing after 7m6s
Release platform and feature matrix / matrix (true, linux-stable-release-surface, x86_64-unknown-linux-gnu, stable) (push) Failing after 8m8s
175 lines
6.9 KiB
Rust
175 lines
6.9 KiB
Rust
use metacrate_ci_matrix::{
|
|
audit, audit_api_surface, audit_artifacts, audit_dependencies, audit_documentation,
|
|
audit_provenance, load, run, workspace_root, write_api_baseline, write_documentation_report,
|
|
write_provenance_reports,
|
|
};
|
|
use std::path::{Path, PathBuf};
|
|
|
|
fn main() {
|
|
if let Err(error) = execute() {
|
|
eprintln!("ci-matrix: {error}");
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
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("audit") if arguments.next().is_none() => {
|
|
audit(&root, &matrix)?;
|
|
println!(
|
|
"release CI matrix: {} validated profiles; Linux, Windows, macOS, MSRV, stable, default/minimal/optional features, tests, examples, and docs covered",
|
|
matrix.profiles.len()
|
|
);
|
|
}
|
|
Some("run") => {
|
|
let profile = arguments.next().ok_or("run requires a profile")?;
|
|
let flag = arguments.next().ok_or("run requires --evidence FILE")?;
|
|
let evidence = arguments.next().ok_or("run requires --evidence FILE")?;
|
|
if flag != "--evidence" || arguments.next().is_some() {
|
|
return Err("usage: ci-matrix run PROFILE --evidence FILE".into());
|
|
}
|
|
let evidence = absolute_or_rooted(&root, &evidence);
|
|
run(&root, &matrix, &profile, &evidence)?;
|
|
println!("release CI profile {profile}: ok ({})", evidence.display());
|
|
}
|
|
Some("dependency-audit") => {
|
|
let flag = arguments
|
|
.next()
|
|
.ok_or("dependency-audit requires --evidence FILE")?;
|
|
let evidence = arguments
|
|
.next()
|
|
.ok_or("dependency-audit requires --evidence FILE")?;
|
|
if flag != "--evidence" || arguments.next().is_some() {
|
|
return Err("usage: ci-matrix dependency-audit --evidence FILE".into());
|
|
}
|
|
let evidence = absolute_or_rooted(&root, &evidence);
|
|
audit_dependencies(&root, &evidence)?;
|
|
println!("dependency policy: ok ({})", evidence.display());
|
|
}
|
|
Some("artifact-audit") => {
|
|
artifact_audit_command(&root, arguments)?;
|
|
}
|
|
Some("documentation-report") if arguments.next().is_none() => {
|
|
write_documentation_report(&root)?;
|
|
println!("documentation coverage report: updated");
|
|
}
|
|
Some("documentation-audit") => {
|
|
let flag = arguments
|
|
.next()
|
|
.ok_or("documentation-audit requires --evidence FILE")?;
|
|
let evidence = arguments
|
|
.next()
|
|
.ok_or("documentation-audit requires --evidence FILE")?;
|
|
if flag != "--evidence" || arguments.next().is_some() {
|
|
return Err("usage: ci-matrix documentation-audit --evidence FILE".into());
|
|
}
|
|
let evidence = absolute_or_rooted(&root, &evidence);
|
|
audit_documentation(&root, &evidence)?;
|
|
println!("documentation coverage: ok ({})", evidence.display());
|
|
}
|
|
Some("api-baseline-write") if arguments.next().is_none() => {
|
|
write_api_baseline(&root)?;
|
|
println!("API/SemVer baseline and report: updated");
|
|
}
|
|
Some("api-audit") => {
|
|
let flag = arguments
|
|
.next()
|
|
.ok_or("api-audit requires --evidence FILE")?;
|
|
let evidence = arguments
|
|
.next()
|
|
.ok_or("api-audit requires --evidence FILE")?;
|
|
if flag != "--evidence" || arguments.next().is_some() {
|
|
return Err("usage: ci-matrix api-audit --evidence FILE".into());
|
|
}
|
|
let evidence = absolute_or_rooted(&root, &evidence);
|
|
audit_api_surface(&root, &evidence)?;
|
|
println!("API/SemVer surface: ok ({})", evidence.display());
|
|
}
|
|
Some("provenance-report") if arguments.next().is_none() => {
|
|
write_provenance_reports(&root)?;
|
|
println!("provenance and distribution reports: updated");
|
|
}
|
|
Some("provenance-audit") => {
|
|
provenance_audit_command(&root, arguments)?;
|
|
}
|
|
_ => {
|
|
return Err(
|
|
"usage: ci-matrix audit | run PROFILE --evidence FILE | dependency-audit --evidence FILE | artifact-audit --artifact-dir DIR --package-dir DIR --evidence FILE | documentation-report | documentation-audit --evidence FILE | api-baseline-write | api-audit --evidence FILE | provenance-report | provenance-audit --evidence FILE"
|
|
.into(),
|
|
);
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn artifact_audit_command(
|
|
root: &Path,
|
|
mut arguments: impl Iterator<Item = String>,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
let artifact_dir = option(&mut arguments, "--artifact-dir")?;
|
|
let package_dir = option(&mut arguments, "--package-dir")?;
|
|
let evidence = option(&mut arguments, "--evidence")?;
|
|
if arguments.next().is_some() {
|
|
return Err(
|
|
"usage: ci-matrix artifact-audit --artifact-dir DIR --package-dir DIR --evidence FILE"
|
|
.into(),
|
|
);
|
|
}
|
|
let artifact_dir = absolute_or_rooted(root, &artifact_dir);
|
|
let package_dir = absolute_or_rooted(root, &package_dir);
|
|
let evidence = absolute_or_rooted(root, &evidence);
|
|
audit_artifacts(root, &artifact_dir, &package_dir, &evidence)?;
|
|
println!("native release artifacts: ok ({})", evidence.display());
|
|
Ok(())
|
|
}
|
|
|
|
fn option(
|
|
arguments: &mut impl Iterator<Item = String>,
|
|
expected: &str,
|
|
) -> Result<String, Box<dyn std::error::Error>> {
|
|
let flag = arguments
|
|
.next()
|
|
.ok_or_else(|| format!("missing {expected}"))?;
|
|
if flag != expected {
|
|
return Err(format!("expected {expected}, found {flag}").into());
|
|
}
|
|
arguments
|
|
.next()
|
|
.ok_or_else(|| format!("missing value for {expected}").into())
|
|
}
|
|
|
|
fn provenance_audit_command(
|
|
root: &Path,
|
|
mut arguments: impl Iterator<Item = String>,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
let flag = arguments
|
|
.next()
|
|
.ok_or("provenance-audit requires --evidence FILE")?;
|
|
let evidence = arguments
|
|
.next()
|
|
.ok_or("provenance-audit requires --evidence FILE")?;
|
|
if flag != "--evidence" || arguments.next().is_some() {
|
|
return Err("usage: ci-matrix provenance-audit --evidence FILE".into());
|
|
}
|
|
let evidence = absolute_or_rooted(root, &evidence);
|
|
audit_provenance(root, &evidence)?;
|
|
println!(
|
|
"license and provenance surface: ok ({})",
|
|
evidence.display()
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
fn absolute_or_rooted(root: &Path, value: &str) -> PathBuf {
|
|
let path = PathBuf::from(value);
|
|
if path.is_absolute() {
|
|
path
|
|
} else {
|
|
root.join(path)
|
|
}
|
|
}
|