use std::fs;
use std::path::{Path, PathBuf};
fn workspace_root() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR")).join("..").join("..")
}
fn read_workspace_file(path: &str) -> String {
fs::read_to_string(workspace_root().join(path))
.unwrap()
.replace("\r\n", "\n")
}
fn assert_contains_in_order(text: &str, labels: &[&str]) {
let mut offset = 0usize;
for label in labels {
let relative = text[offset..]
.find(label)
.unwrap_or_else(|| panic!("missing {label:?} after byte offset {offset}"));
offset += relative + label.len();
}
}
#[test]
fn ci_workflow_has_cross_platform_matrix() {
let workflow = read_workspace_file(".github/workflows/ci.yml");
assert!(workflow.contains("include:"));
assert!(workflow.contains("os: ubuntu-22.04"));
assert!(workflow.contains("os: macos-15-intel"));
assert!(workflow.contains("os: macos-14"));
assert!(workflow.contains("os: windows-2022"));
assert!(workflow.contains("release-artifacts:"));
assert!(workflow.contains("Release artifact ${{ matrix.name }}"));
assert!(workflow.contains("x86_64-unknown-linux-musl"));
assert!(workflow.contains("aarch64-unknown-linux-musl"));
assert!(workflow.contains("x86_64-pc-windows-msvc"));
assert!(workflow.contains("aarch64-pc-windows-msvc"));
assert!(workflow.contains("Install musl tools"));
assert!(workflow.contains("CC_x86_64_unknown_linux_musl=musl-gcc"));
assert!(workflow.contains("Install QEMU"));
assert!(workflow.contains("qemu-aarch64-static"));
assert!(workflow.contains("Install cross"));
assert!(
workflow.contains("cross build --locked --release -p tzap --target ${{ matrix.target }}")
);
assert!(workflow.contains("Smoke test release binary"));
assert!(workflow.contains("matrix.run_fmt"));
assert!(workflow.contains("cargo fmt --all -- --check"));
assert!(workflow.contains("cargo check --workspace --all-targets --locked"));
assert!(workflow.contains("cargo test --workspace --locked"));
assert!(workflow.contains("cmp \"$WORKDIR/input.txt\" \"$WORKDIR/out/input.txt\""));
assert!(!workflow.contains("ubuntu-latest"));
assert!(!workflow.contains("macos-latest"));
assert!(!workflow.contains("windows-latest"));
}
#[test]
fn release_workflow_has_all_release_archives() {
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(workflow.contains("tzap-${{ github.ref_name }}-linux-x86_64-musl.tar.gz"));
assert!(workflow.contains("tzap-${{ github.ref_name }}-linux-aarch64-musl.tar.gz"));
assert!(workflow.contains("tzap-${{ github.ref_name }}-macos-x86_64.tar.gz"));
assert!(workflow.contains("tzap-${{ github.ref_name }}-macos-aarch64.tar.gz"));
assert!(workflow.contains("tzap-${{ github.ref_name }}-windows-x86_64.zip"));
assert!(workflow.contains("tzap-${{ github.ref_name }}-windows-aarch64.zip"));
assert!(!workflow.contains("tzap-${{ github.ref_name }}-linux-x86_64.tar.gz"));
}
#[test]
fn release_workflow_targets_distinct_build_triples() {
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(workflow.contains("x86_64-unknown-linux-musl"));
assert!(workflow.contains("aarch64-unknown-linux-musl"));
assert!(workflow.contains("x86_64-apple-darwin"));
assert!(workflow.contains("aarch64-apple-darwin"));
assert!(workflow.contains("x86_64-pc-windows-msvc"));
assert!(workflow.contains("aarch64-pc-windows-msvc"));
assert!(!workflow.contains("x86_64-unknown-linux-gnu"));
}
#[test]
fn release_workflow_uses_pinned_baseline_runners() {
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(workflow.contains("os: ubuntu-22.04"));
assert!(workflow.contains("os: macos-15-intel"));
assert!(workflow.contains("os: macos-14"));
assert!(workflow.contains("os: windows-2022"));
assert!(workflow.contains("runs-on: ubuntu-22.04"));
assert!(workflow.contains("MACOSX_DEPLOYMENT_TARGET"));
assert!(workflow.contains(r#"macosx_deployment_target: "10.12""#));
assert!(workflow.contains(r#"macosx_deployment_target: "11.0""#));
assert!(workflow.contains("musl-tools"));
assert!(workflow.contains("CC_x86_64_unknown_linux_musl=musl-gcc"));
assert!(workflow.contains("qemu-user-static"));
assert!(workflow.contains("cargo install cross --locked"));
assert!(workflow.contains("target-feature=+crt-static"));
assert!(!workflow.contains("ubuntu-latest"));
assert!(!workflow.contains("macos-latest"));
assert!(!workflow.contains("windows-latest"));
}
#[test]
fn release_workflow_has_smoke_checks() {
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(workflow.contains("preflight:"));
assert!(workflow.contains("needs: preflight"));
assert_eq!(workflow.matches("run_smoke: true").count(), 5);
for command in [
"cargo fmt --all -- --check",
"cargo check --workspace --all-targets --locked",
"cargo test --workspace --locked",
"cargo run --manifest-path fuzz/Cargo.toml --bin fuzz_smoke --locked",
"cargo check --manifest-path fuzz/Cargo.toml --bins --features libfuzzer --locked",
] {
assert!(
workflow.contains(command),
"release workflow missing preflight command {command:?}"
);
}
assert!(workflow.contains("Smoke test artifact (Unix)"));
assert!(workflow.contains("Smoke test artifact (Windows)"));
assert!(workflow.contains("--version"));
assert!(workflow.contains("--help"));
assert!(workflow.contains("tzap.exe"));
assert!(workflow.contains("tar -xzf \"dist/${{ matrix.archive }}\""));
assert!(workflow.contains("Expand-Archive -Path \"dist/${{ matrix.archive }}\""));
assert!(workflow.contains(
"create --password-stdin --argon2-t-cost 1 --argon2-m-cost-kib 8 --argon2-parallelism 1"
));
assert!(workflow.contains("list --password-stdin"));
assert!(workflow.contains("verify --password-stdin"));
assert!(workflow.contains("extract --password-stdin --directory"));
assert!(workflow.contains("grep -F \"input.txt\""));
assert!(workflow.contains("release smoke list output did not include input.txt"));
assert!(workflow.contains("cmp \"$WORKDIR/input.txt\" \"$WORKDIR/out/input.txt\""));
assert!(workflow.contains("release smoke payload mismatch"));
assert!(!workflow.contains("Smoke test build"));
assert_contains_in_order(
&workflow,
&[
"Package Unix",
"Smoke test artifact (Unix)",
"Generate checksum (Unix)",
"Package Windows",
"Smoke test artifact (Windows)",
"Generate checksum (Windows)",
"Upload asset",
],
);
}
#[test]
fn release_workflow_uploads_checksum_artifacts() {
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(workflow.contains("Generate checksum (Unix)"));
assert!(workflow.contains("Generate checksum (Windows)"));
assert!(workflow.contains("${{ matrix.archive }}.sha256"));
assert!(workflow.contains("dist/${{ matrix.archive }}.sha256"));
assert!(workflow.contains("Merge checksum manifest"));
assert!(workflow.contains("SHA256SUMS"));
assert_contains_in_order(
&workflow,
&["homebrew:", "needs: build", "brew install --formula"],
);
assert!(workflow.contains("HOMEBREW_NO_SANDBOX_LINUX: 1"));
assert_contains_in_order(
&workflow,
&[
"publish:",
"needs:",
"- build",
"- homebrew",
"Merge checksum manifest",
"Publish release",
],
);
}
#[test]
fn internal_docs_are_not_public_release_inputs() {
let gitignore = read_workspace_file(".gitignore");
let workflow = read_workspace_file(".github/workflows/release.yml");
assert!(gitignore.contains("/docs/"));
assert!(gitignore.contains("/implementation-docs/"));
assert!(!gitignore.contains("!/docs/"));
assert!(!workflow.contains("docs/tzap-"));
}