#[path = "support/python3.rs"]
mod python3;
use std::collections::BTreeSet;
use std::fs;
use std::path::PathBuf;
#[cfg(unix)]
use std::process::Command;
use std::time::{SystemTime, UNIX_EPOCH};
const DOWNSTREAM: &str = include_str!("../.github/workflows/release-downstream.yml");
const DOWNSTREAM_AUDIT: &str = include_str!("../.github/workflows/release-downstream-audit.yml");
const DOWNSTREAM_AUDIT_ACTION: &str =
include_str!("../.github/actions/release-downstream-audit/action.yml");
const DOWNSTREAM_AUTHORITY_PROOF: &str =
include_str!("../.github/actions/release-downstream-authority-proof/action.yml");
const DOWNSTREAM_PREPARE: &str =
include_str!("../.github/workflows/release-downstream-prepare.yml");
const RECEIPT: &str = include_str!("../.github/workflows/release-receipt.yml");
const CI: &str = include_str!("../.github/workflows/ci.yml");
const LINUX_REPOSITORY_BUILD: &str =
include_str!("../.github/workflows/release-linux-repository-build.yml");
const CHANNEL_RESULT_ACTION: &str =
include_str!("../.github/actions/release-channel-result/action.yml");
const RECEIPT_REFERENCE_BUILDER: &str =
include_str!("../scripts/release/build-downstream-receipt-reference.py");
fn repo_root() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
}
fn job<'a>(workflow: &'a str, id: &str, next: Option<&str>) -> &'a str {
let marker = format!("\n {id}:\n");
let tail = workflow
.split(&marker)
.nth(1)
.unwrap_or_else(|| panic!("missing job {id}"));
match next {
Some(next_id) => tail
.split(&format!("\n {next_id}:\n"))
.next()
.expect("job boundary"),
None => tail,
}
}
fn artifact_verification<'a>(workflow: &'a str, artifact_name: &str) -> &'a str {
let marker = format!("--name \"{artifact_name}\"");
workflow
.split(&marker)
.nth(1)
.unwrap_or_else(|| panic!("missing artifact verification for {artifact_name}"))
.split("--max-attempts 1")
.next()
.expect("artifact verification boundary")
}
fn assert_workflow_call_only(workflow: &str) {
assert!(workflow.contains("on:\n workflow_call:"));
assert_eq!(workflow.matches("permissions: {}").count(), 1);
for trigger in [
"\n push:",
"\n pull_request:",
"\n workflow_dispatch:",
"\n workflow_run:",
"\n repository_dispatch:",
"\n release:",
"\n schedule:",
] {
assert!(
!workflow.contains(trigger),
"downstream workflow gained trigger {trigger}"
);
}
for line in workflow.lines().map(str::trim) {
if let Some(target) = line.strip_prefix("uses: ") {
if target.starts_with("./") {
continue;
}
let (_, revision) = target.rsplit_once('@').expect("Action pin");
assert_eq!(revision.len(), 40, "Action is not pinned: {target}");
assert!(revision.bytes().all(|byte| byte.is_ascii_hexdigit()));
}
}
}
fn calls_downstream_workflow(line: &str, workflow_name: &str) -> bool {
let normalized = line.trim().strip_prefix("- ").unwrap_or(line.trim()).trim();
let Some(target) = normalized.strip_prefix("uses:") else {
return false;
};
let target = target
.split_whitespace()
.next()
.unwrap_or_default()
.trim_matches(|character| character == '\'' || character == '"')
.to_ascii_lowercase();
target == format!("./.github/workflows/{workflow_name}")
|| target.starts_with(&format!("helvesec/rmux/.github/workflows/{workflow_name}@"))
}
#[test]
fn downstream_workflow_is_receipt_gated_read_only_and_active() {
assert_workflow_call_only(DOWNSTREAM);
assert_eq!(DOWNSTREAM.matches("if: ${{ false }}").count(), 0);
assert!(!DOWNSTREAM.contains("contents: write"));
assert!(!DOWNSTREAM.contains("secrets: inherit"));
assert_eq!(
DOWNSTREAM
.matches("environment: release-publication")
.count(),
0
);
assert_eq!(DOWNSTREAM.matches("environment:").count(), 0);
assert!(!DOWNSTREAM.contains("self-hosted"));
assert!(!DOWNSTREAM.contains("larger-runner"));
let activation: serde_json::Value =
serde_json::from_str(include_str!("../.github/release/release-activation.json"))
.expect("activation ledger");
assert_eq!(activation["status"], "active");
assert_eq!(activation["runtime_override_allowed"], false);
assert_eq!(activation["capabilities"]["downstream_channels"], true);
let caller = job(RECEIPT, "downstream", None);
assert!(!caller.contains("if: ${{ false }}"));
assert!(caller.contains("uses: ./.github/workflows/release-downstream.yml"));
let workflows = repo_root().join(".github/workflows");
for entry in fs::read_dir(workflows).expect("list workflows") {
let path = entry.expect("workflow entry").path();
let text = fs::read_to_string(&path).expect("read workflow");
let calls_downstream = text
.lines()
.any(|line| calls_downstream_workflow(line, "release-downstream.yml"));
if path.ends_with("release-receipt.yml") {
assert!(
calls_downstream,
"receipt must retain the guarded downstream call"
);
assert!(!text.contains("if: ${{ false }}"));
continue;
}
assert!(
!calls_downstream,
"existing workflow {} calls the downstream workflow",
path.display()
);
}
}
#[test]
fn downstream_caller_guard_rejects_relative_and_absolute_targets() {
for line in [
" uses: ./.github/workflows/release-downstream.yml",
" uses: Helvesec/rmux/.github/workflows/release-downstream.yml@0123456789012345678901234567890123456789",
" uses: 'helvesec/RMUX/.github/workflows/release-downstream.yml@main'",
] {
assert!(calls_downstream_workflow(line, "release-downstream.yml"));
}
assert!(!calls_downstream_workflow(
" uses: Other/repo/.github/workflows/release-downstream.yml@main",
"release-downstream.yml"
));
}
#[cfg(unix)]
#[test]
fn downstream_workflow_entry_points_are_executable() {
use std::os::unix::fs::PermissionsExt;
for filename in [
"build-downstream-receipt-reference.py",
"channel-execution.py",
"channel-request.py",
"channel-summary.py",
"channel-target-evidence.py",
"collect-downstream-repository.py",
"downstream_payload.py",
"prepare-channel-retry.py",
"publish-crate-set.py",
"publish-linux-repository.py",
"publish-owned-repository.py",
"snap-candidate-status.py",
"stage-downstream-payloads.py",
"stage-rmux-io-payload.py",
"verify-exact-file-set.py",
"verify-receipt-attestation.py",
] {
let path = repo_root().join("scripts/release").join(filename);
let mode = fs::metadata(&path)
.unwrap_or_else(|error| panic!("read {filename} metadata: {error}"))
.permissions()
.mode();
assert_ne!(mode & 0o111, 0, "{filename} is not executable");
}
}
#[test]
fn downstream_authority_is_rechecked_live_before_payload_staging() {
assert!(DOWNSTREAM_AUDIT.contains("on:\n workflow_call:"));
assert!(DOWNSTREAM_AUDIT.contains(" workflow_dispatch:"));
assert!(DOWNSTREAM_AUDIT.contains("environment: release-publication"));
assert!(DOWNSTREAM_AUDIT.contains("uses: ./.github/actions/release-downstream-audit"));
assert!(!DOWNSTREAM_AUDIT.contains("secrets: inherit"));
assert!(DOWNSTREAM_AUDIT_ACTION.contains("permission-administration: write"));
assert!(DOWNSTREAM_AUDIT_ACTION.contains("permission-contents: read"));
assert!(!DOWNSTREAM_AUDIT_ACTION.contains("permission-administration: read"));
assert!(!DOWNSTREAM_AUDIT_ACTION.contains("permission-contents: write"));
assert!(DOWNSTREAM_AUDIT_ACTION.contains("collect-downstream-repository.py"));
assert!(DOWNSTREAM_AUDIT_ACTION.contains("verify-downstream-repository.py fixtures"));
assert_eq!(
DOWNSTREAM_AUDIT_ACTION
.matches("actions/create-github-app-token@fee1f7d63c2ff003460e3d139729b119787bc349")
.count(),
1
);
assert!(DOWNSTREAM_AUDIT_ACTION.contains("artifact-id:"));
assert!(DOWNSTREAM_AUDIT_ACTION.contains("artifact-digest:"));
assert!(!DOWNSTREAM.contains("uses: ./.github/workflows/release-downstream-audit.yml"));
assert!(!DOWNSTREAM.contains("uses: ./.github/actions/release-downstream-audit"));
assert!(!DOWNSTREAM.contains("RMUX_DOWNSTREAM_APP_PRIVATE_KEY"));
assert!(!DOWNSTREAM.contains("environment: release-publication"));
let audit = job(RECEIPT, "audit-downstream-authority", Some("downstream"));
assert!(audit.contains("environment: release-publication"));
assert!(audit.contains("app-private-key: ${{ secrets.RMUX_DOWNSTREAM_APP_PRIVATE_KEY }}"));
assert!(audit.contains("uses: ./.github/actions/release-downstream-audit"));
assert!(audit.contains("artifact_id: ${{ steps.audit.outputs.artifact-id }}"));
assert!(audit.contains("artifact_digest: ${{ steps.audit.outputs.artifact-digest }}"));
let downstream = job(RECEIPT, "downstream", None);
assert!(downstream.contains("needs: [receipt-only, audit-downstream-authority]"));
assert!(downstream.contains("downstream_audit_artifact_id:"));
assert!(downstream.contains("downstream_audit_artifact_digest:"));
let verification = job(
DOWNSTREAM,
"verify-downstream-authority",
Some("prepare-payloads"),
);
assert!(verification.contains("uses: ./.github/actions/release-downstream-authority-proof"));
assert!(verification.contains(
"test \"${{ inputs.downstream_audit_run_id }}\" = \"${{ inputs.receipt_run_id }}\""
));
assert!(DOWNSTREAM_AUTHORITY_PROOF.contains("actions-artifact.py verify"));
assert!(DOWNSTREAM_AUTHORITY_PROOF
.contains("--expected-workflow-path .github/workflows/release-receipt.yml"));
assert!(DOWNSTREAM_AUTHORITY_PROOF
.contains("test \"$RMUX_DOWNSTREAM_AUDIT_WORKFLOW_ID\" = 316435347"));
assert!(DOWNSTREAM_AUTHORITY_PROOF.contains("verify-exact-file-set.py"));
assert!(DOWNSTREAM_AUTHORITY_PROOF.contains("verify-downstream-repository.py fixtures"));
assert!(DOWNSTREAM_AUTHORITY_PROOF.contains("--allow-running-current-run"));
let payloads = job(
DOWNSTREAM,
"prepare-payloads",
Some("build-linux-repository"),
);
assert!(payloads.contains("needs: [prepare-plan, verify-downstream-authority]"));
}
#[test]
fn downstream_writers_keep_the_python_310_runtime_contract() {
assert!(CI.contains("actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0"));
assert!(CI.contains("python-version: \"3.10\""));
assert!(CI.contains("Validate release writers on Python 3.10"));
for filename in [
"channel-execution.py",
"prepare-channel-retry.py",
"publish-crate-set.py",
"publish-linux-repository.py",
"publish-owned-repository.py",
"snap-candidate-status.py",
] {
let source = fs::read_to_string(repo_root().join("scripts/release").join(filename))
.unwrap_or_else(|error| panic!("read {filename}: {error}"));
assert!(!source.contains("from datetime import UTC"));
assert!(!source.contains("datetime.now(UTC)"));
}
}
#[test]
fn linux_repository_build_retains_authenticated_previous_by_hash_indexes() {
let authenticated = LINUX_REPOSITORY_BUILD
.find("scripts/retain-linux-package-history.py")
.expect("authenticated package history");
let generated = LINUX_REPOSITORY_BUILD
.find("\"$apt_generator\"")
.expect("APT repository generator");
assert!(authenticated < generated);
assert!(LINUX_REPOSITORY_BUILD.contains("--previous-repository-dir \"$root/history/debian\""));
}
#[cfg(unix)]
#[test]
fn crates_writer_distinguishes_missing_versions_from_download_denials() {
let fixture = r#"
import importlib.util
import pathlib
import sys
import tempfile
import urllib.error
root = pathlib.Path.cwd()
scripts = root / "scripts" / "release"
sys.path.insert(0, str(scripts))
spec = importlib.util.spec_from_file_location(
"publish_crate_set", scripts / "publish-crate-set.py"
)
module = importlib.util.module_from_spec(spec)
assert spec.loader is not None
spec.loader.exec_module(module)
calls = []
class Response:
def __init__(self, body):
self.body = body
def __enter__(self):
return self
def __exit__(self, *_args):
return False
def read(self, _limit):
return self.body
def missing(request, timeout):
calls.append((request.full_url, timeout))
raise urllib.error.HTTPError(request.full_url, 404, "missing", {}, None)
module.urllib.request.urlopen = missing
assert module.registry_bytes("rmux", "0.9.1") is None
assert calls == [("https://crates.io/api/v1/crates/rmux/0.9.1", 30)]
def forbidden(request, timeout):
raise urllib.error.HTTPError(request.full_url, 403, "forbidden", {}, None)
module.urllib.request.urlopen = forbidden
try:
module.registry_bytes("rmux", "0.9.1")
except ValueError as error:
assert "lookup failed with HTTP 403" in str(error)
else:
raise AssertionError("metadata access denial was treated as a missing version")
with tempfile.TemporaryDirectory() as directory:
target = pathlib.Path(directory)
filename = "rmux-types-0.9.1.crate"
direct, temporary = module.generated_package_paths(target, filename)
temporary.parent.mkdir(parents=True)
temporary.write_bytes(b"canonical")
assert module.generated_package(target, filename) == temporary
direct.write_bytes(b"duplicate")
try:
module.generated_package(target, filename)
except ValueError as error:
assert "unexpected package set" in str(error)
else:
raise AssertionError("ambiguous Cargo package output was accepted")
module.remove_generated_package(target, filename)
assert not direct.exists() and not temporary.exists()
"#;
let output = Command::new("python3")
.args(["-c", fixture])
.current_dir(repo_root())
.output()
.expect("run crates.io metadata regression fixture");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn downstream_json_writer_uses_canonical_lf_bytes_on_every_platform() {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system time")
.as_nanos();
let root = std::env::temp_dir().join(format!(
"rmux-downstream-json-{}-{nonce}",
std::process::id()
));
fs::create_dir_all(&root).expect("create canonical JSON fixture directory");
let output_path = root.join("evidence.json");
let output = python3::command()
.args([
"-c",
"import pathlib,sys; sys.path.insert(0,'scripts/release'); \
from downstream_channels import write_object; \
write_object(pathlib.Path(sys.argv[1]), {'z': 1, 'a': 2})",
])
.arg(&output_path)
.current_dir(repo_root())
.output()
.expect("run canonical downstream JSON writer");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
let bytes = fs::read(&output_path).expect("read canonical downstream JSON");
fs::remove_dir_all(root).expect("remove canonical JSON fixture directory");
assert_eq!(bytes, b"{\n \"a\": 2,\n \"z\": 1\n}\n");
}
#[test]
fn downstream_result_digest_is_independent_of_windows_path_escaping() {
assert!(CHANNEL_RESULT_ACTION
.contains("digest=\"$(sha256sum < \"$RMUX_TARGET_EVIDENCE\" | cut -d' ' -f1)\""));
assert!(!CHANNEL_RESULT_ACTION.contains("sha256sum \"$RMUX_TARGET_EVIDENCE\""));
}
#[test]
fn downstream_rc_payloads_keep_stable_package_names() {
let staging = include_str!("../scripts/release/stage-downstream-payloads.py");
let snap = include_str!("../scripts/release/snap-candidate-status.py");
assert!(staging.contains("version = manifest[\"package_version\"]"));
assert!(!staging.contains("version = release_ref.removeprefix(\"v\")"));
assert!(snap.contains("version = package_version(args.release_ref)"));
}
#[test]
fn downstream_payloads_bind_the_complete_shadow_run_identity() {
let marker = "- name: Verify exact candidate manifest artifact identity";
let next_marker = "- name: Download only the exact candidate manifest artifact ID";
let verification = DOWNSTREAM_PREPARE
.split(marker)
.nth(1)
.expect("candidate manifest verification")
.split(next_marker)
.next()
.expect("candidate manifest verification boundary");
for expected in [
"--expected-workflow-id 316223904",
"--expected-workflow-path .github/workflows/release-shadow.yml",
"--expected-event workflow_dispatch",
"--expected-head-branch main",
] {
assert!(
verification.contains(expected),
"missing shadow run identity {expected}"
);
}
}
#[test]
fn exact_receipt_ids_digests_origin_and_documents_are_bound() {
let prepare = job(DOWNSTREAM, "prepare-plan", Some("prepare-payloads"));
for input in [
"receipt_run_id:",
"receipt_run_workflow_id:",
"receipt_workflow_id:",
"receipt_artifact_id:",
"receipt_artifact_digest:",
"receipt_envelope_artifact_id:",
"receipt_envelope_artifact_digest:",
"receipt_predicate_sha256:",
"receipt_envelope_sha256:",
"downstream_audit_run_id:",
"downstream_audit_workflow_id:",
"downstream_audit_artifact_id:",
"downstream_audit_artifact_digest:",
"expected_source_sha:",
"release_id:",
"release_ref:",
"release_kind:",
] {
assert!(DOWNSTREAM.contains(input), "missing exact input {input}");
}
assert_eq!(prepare.matches("actions-artifact.py verify").count(), 2);
for artifact_name in [
"rmux-publication-receipt-$RMUX_EXPECTED_SOURCE_SHA-$RMUX_RELEASE_ID",
"rmux-publication-receipt-envelope-$RMUX_EXPECTED_SOURCE_SHA-$RMUX_RELEASE_ID",
] {
let verification = artifact_verification(prepare, artifact_name);
assert!(
verification.contains("--expected-workflow-path .github/workflows/release-receipt.yml")
);
assert!(verification.contains("--allow-running-current-run"));
}
assert_eq!(
prepare
.matches("--expected-workflow-path .github/workflows/release-receipt.yml")
.count(),
2
);
assert!(!prepare.contains("--expected-workflow-path .github/workflows/release-promote.yml"));
assert!(
prepare.contains("test \"$RMUX_RECEIPT_RUN_WORKFLOW_ID\" = \"$RMUX_RECEIPT_WORKFLOW_ID\"")
);
assert!(prepare.contains("--expected-event workflow_dispatch"));
assert!(prepare.contains("--expected-head-branch \"$RMUX_RELEASE_REF\""));
assert_eq!(prepare.matches("artifact-ids:").count(), 2);
assert_eq!(
prepare
.matches("run-id: ${{ inputs.receipt_run_id }}")
.count(),
2
);
assert!(!prepare.contains("pattern:"));
assert_eq!(prepare.matches("merge-multiple: true").count(), 2);
assert!(prepare.contains("assert-release-capability.py downstream_channels"));
assert!(prepare.contains("build-downstream-receipt-reference.py"));
assert!(RECEIPT_REFERENCE_BUILDER.contains("receipt artifact contains a symlink"));
assert!(RECEIPT_REFERENCE_BUILDER.contains("receipt artifact file set differs"));
assert!(RECEIPT_REFERENCE_BUILDER.contains("publication receipt predicate identity differs"));
assert!(RECEIPT_REFERENCE_BUILDER.contains("publication receipt envelope identity differs"));
assert!(prepare.contains("release-state.json"));
assert!(prepare.contains("verify-receipt-attestation.py"));
assert!(prepare.contains("GH_TOKEN: ${{ github.token }}"));
assert!(prepare.contains("install-gh-2.93.0.sh"));
assert!(prepare.contains("RMUX_RECEIPT_PREDICATE_SHA256"));
assert!(prepare.contains("RMUX_RECEIPT_ENVELOPE_SHA256"));
assert!(prepare.contains("channel-policy.py create-plan"));
assert!(prepare.contains("channel-policy.py verify-plan"));
assert!(prepare.contains("--snap-candidate-opt-in"));
assert!(
prepare.contains("${{ runner.temp }}/rmux-downstream/publication-receipt-predicate.json")
);
assert!(!prepare
.contains("${{ runner.temp }}/rmux-downstream/receipt/publication-receipt-predicate.json"));
}
#[test]
fn all_eleven_channels_are_default_denied_and_rmux_io_is_last() {
let contract: serde_json::Value = serde_json::from_str(include_str!(
"../.github/release/downstream-channel-contract.json"
))
.expect("downstream contract");
assert_eq!(contract["status"], "atomic-authority-bound");
assert_eq!(contract["execution"]["only_trigger"], "workflow_call");
assert_eq!(contract["execution"]["public_callers"], 0);
assert_eq!(
contract["execution"]["required_caller_repository"],
"Helvesec/rmux"
);
assert_eq!(
contract["execution"]["required_caller_repository_id"],
1239918790
);
assert_eq!(
contract["execution"]["privileged_job_condition"],
"release-activation-ledger"
);
assert_eq!(contract["execution"]["maximum_parallel_channels"], 4);
assert_eq!(contract["execution"]["github_hosted_only"], true);
assert_eq!(contract["execution"]["native_rebuild_allowed"], false);
assert_eq!(contract["execution"]["rmux_io_last"], true);
assert_eq!(
contract["payload_evidence"]["canonical_provenance_ready"],
true
);
assert_eq!(contract["payload_evidence"]["actions_expiry_bound"], true);
assert_eq!(
contract["payload_evidence"]["producer_workflow_allowlist_ready"],
true
);
assert_eq!(
contract["payload_evidence"]["producer"],
serde_json::json!({
"workflow_id": 316435347,
"workflow_path": ".github/workflows/release-receipt.yml",
"job_workflow_paths": {
"default": ".github/workflows/release-downstream-prepare.yml",
"rmux_io": ".github/workflows/release-rmux-io-payload.yml"
},
"required_run_attempt": 1
})
);
assert_eq!(
contract["payload_evidence"]["activation_blockers"],
serde_json::json!([])
);
assert_eq!(contract["result_evidence"]["result_reference_ready"], true);
assert_eq!(
contract["result_evidence"]["result_reference_schema"],
".github/release/schemas/downstream-channel-result-reference.schema.json"
);
assert_eq!(
contract["result_evidence"]["attestation_verification_ready"],
true
);
assert_eq!(
contract["result_evidence"]["result_aggregation_ready"],
true
);
assert_eq!(
contract["result_evidence"]["aggregation_blockers"],
serde_json::json!([])
);
assert_eq!(
contract["result_evidence"]["summary_phases"],
serde_json::json!(["pre-site", "final"])
);
assert_eq!(contract["receipt_gate"]["attestation_required"], true);
assert_eq!(
contract["receipt_gate"]["attestation_subject_name"],
"release-state.json"
);
assert_eq!(
contract["receipt_gate"]["attestation_subject_in_bundle"],
true
);
assert_eq!(
contract["receipt_gate"]["workflow_id"],
serde_json::json!(316435347)
);
assert_eq!(
contract["receipt_gate"]["activation_blockers"],
serde_json::json!([])
);
let channels = contract["channels"].as_array().expect("channels");
assert_eq!(channels.len(), 11);
let names: BTreeSet<_> = channels
.iter()
.map(|channel| channel["name"].as_str().expect("channel name"))
.collect();
assert_eq!(
names,
BTreeSet::from([
"apt_rpm",
"chocolatey",
"crates_io",
"homebrew_core",
"homebrew_tap",
"rmux_io",
"scoop",
"snap_candidate",
"snap_stable",
"web_share",
"winget",
])
);
for ready in ["chocolatey", "crates_io", "snap_candidate", "web_share"] {
let channel = channels
.iter()
.find(|channel| channel["name"] == ready)
.expect("canonical payload channel");
assert_eq!(channel["payload_ready"], true, "{ready} lost its payload");
}
let web_share = channels
.iter()
.find(|channel| channel["name"] == "web_share")
.expect("web-share channel");
assert_eq!(web_share["blockers"], serde_json::json!([]));
let snap_stable = channels
.iter()
.find(|channel| channel["name"] == "snap_stable")
.expect("Snap stable channel");
assert_eq!(snap_stable["payload_ready"], true);
assert_eq!(
snap_stable["payload_roles"],
serde_json::json!(["policy-decision"])
);
assert_eq!(
snap_stable["blockers"],
serde_json::json!(["denied_until_support_decision"])
);
let canonical: serde_json::Value = serde_json::from_str(include_str!(
"../.github/release/canonical-build-contract.json"
))
.expect("canonical build contract");
let supplemental_roles: BTreeSet<_> = canonical["platforms"]
.as_array()
.expect("canonical platforms")
.iter()
.flat_map(|platform| {
platform["supplemental_roles"]
.as_array()
.expect("supplemental roles")
})
.map(|role| role.as_str().expect("supplemental role"))
.collect();
for role in [
"chocolatey-package",
"crate-package-set",
"snap-amd64",
"snap-arm64",
"wasm-byte-set",
"wasm-provenance",
] {
assert!(
supplemental_roles.contains(role),
"downstream payload role {role} is not sealed canonically"
);
}
let summary = job(
DOWNSTREAM,
"pre-site-summary",
Some("prepare-rmux-io-handoff"),
);
let rmux_io = job(
DOWNSTREAM,
"prepare-rmux-io-handoff",
Some("record-rmux-io-handoff"),
);
let rmux_io_result = job(
DOWNSTREAM,
"record-rmux-io-handoff",
Some("final-channel-summary"),
);
let final_summary = job(DOWNSTREAM, "final-channel-summary", None);
assert!(summary.contains("Aggregate ten exact pre-site results"));
assert!(summary.contains("release-channel-summary.yml"));
assert!(rmux_io.contains("needs: [prepare-plan, pre-site-summary]"));
assert!(rmux_io.contains("release-rmux-io-payload.yml"));
assert!(rmux_io_result.contains("release-rmux-io-channel.yml"));
assert!(final_summary.contains("Aggregate all eleven exact channel results"));
assert!(final_summary.contains("release-channel-summary.yml"));
assert_eq!(
DOWNSTREAM
.matches("release-owned-repository-channel.yml")
.count(),
3
);
assert_eq!(DOWNSTREAM.matches("release-policy-channel.yml").count(), 4);
assert_eq!(DOWNSTREAM.matches("release-channel-summary.yml").count(), 2);
assert_eq!(DOWNSTREAM.matches("if: ${{ false }}").count(), 0);
assert!(DOWNSTREAM.contains("test \"$GITHUB_REPOSITORY\" = \"Helvesec/rmux\""));
assert!(DOWNSTREAM.contains("test \"$GITHUB_REPOSITORY_ID\" = \"1239918790\""));
assert_eq!(DOWNSTREAM.matches("channel-summary.py create").count(), 0);
assert!(!RECEIPT.contains("if: ${{ false }}"));
}
#[test]
fn public_owned_downstream_protection_layers_are_recorded_and_active() {
let registry: serde_json::Value = serde_json::from_str(include_str!(
"../.github/release/downstream-repositories.json"
))
.expect("downstream repository registry");
assert_eq!(registry["writer_app"]["configured"], true);
assert_eq!(registry["writer_app"]["app_id"], 4352876);
assert_eq!(registry["writer_app"]["installation_id"], 147959477);
assert_eq!(registry["writer_app"]["repository_selection"], "selected");
assert_eq!(registry["writer_app"]["pat_fallback"], false);
assert_eq!(
registry["writer_app"]["required_permissions"]["administration"],
"write"
);
let repositories = registry["repositories"].as_array().expect("repositories");
for key in [
"homebrew-rmux",
"rmux-packages",
"rmux-web-share",
"scoop-rmux",
] {
let repository = repositories
.iter()
.find(|repository| repository["key"] == key)
.unwrap_or_else(|| panic!("missing downstream repository {key}"));
assert_eq!(repository["branch_protected"], true, "{key}");
assert_eq!(repository["ruleset_count"], 1, "{key}");
assert_eq!(repository["environment_count"], 1, "{key}");
let blockers = repository["blockers"].as_array().expect("blockers");
assert!(
blockers
.iter()
.all(|blocker| blocker != "environment_admin_bypass_enabled"),
"{key} still reports environment bypass"
);
assert!(
blockers
.iter()
.all(|blocker| blocker != "downstream_writer_app_missing"),
"{key} still reports a missing writer App"
);
assert!(
blockers
.iter()
.all(|blocker| blocker != "repository_protection_missing"),
"{key} still reports missing repository protection"
);
}
for key in [
"homebrew-rmux",
"rmux-packages",
"rmux-web-share",
"scoop-rmux",
] {
let repository = repositories
.iter()
.find(|repository| repository["key"] == key)
.unwrap_or_else(|| panic!("missing downstream repository {key}"));
assert_eq!(repository["activation_ready"], true, "{key}");
assert_eq!(repository["blockers"], serde_json::json!([]), "{key}");
}
let rmux_io = repositories
.iter()
.find(|repository| repository["key"] == "rmux.io")
.expect("missing downstream repository rmux.io");
assert_eq!(rmux_io["visibility"], "private");
assert_eq!(rmux_io["activation_ready"], false);
assert_eq!(
rmux_io["blockers"],
serde_json::json!([
"private_repository_protection_unavailable_on_current_plan",
"manual_site_update_required"
])
);
}
#[test]
fn downstream_repository_verifier_accepts_github_ruleset_arrays() {
let nonce = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("system time")
.as_nanos();
let root = std::env::temp_dir().join(format!(
"rmux-downstream-repository-{}-{nonce}",
std::process::id()
));
fs::create_dir_all(&root).expect("create fixture directory");
let write = |name: &str, value: serde_json::Value| {
let path = root.join(name);
fs::write(&path, serde_json::to_vec(&value).expect("encode fixture"))
.expect("write fixture");
path
};
let metadata = write(
"metadata.json",
serde_json::json!({
"id": 1259133629,
"full_name": "Helvesec/homebrew-rmux",
"visibility": "public",
"default_branch": "main",
"archived": false
}),
);
let protection = write(
"protection.json",
serde_json::json!({
"enforce_admins": {"enabled": true},
"allow_force_pushes": {"enabled": false},
"allow_deletions": {"enabled": false},
"required_signatures": {"enabled": true}
}),
);
let rulesets = write(
"rulesets.json",
serde_json::json!([{
"enforcement": "active",
"bypass_actors": [],
"conditions": {"ref_name": {"include": ["refs/heads/main"], "exclude": []}},
"rules": [{"type": "deletion"}, {"type": "non_fast_forward"}]
}]),
);
let environments = write(
"environments.json",
serde_json::json!({"environments": [{
"name": "release-homebrew-tap",
"can_admins_bypass": false,
"protection_rules": [{"type": "required_reviewers"}]
}]}),
);
let runners = write("runners.json", serde_json::json!({"total_count": 0}));
let installation = write(
"installation.json",
serde_json::json!({
"id": 147959477,
"app_id": 4352876,
"repository_selection": "selected",
"permissions": {"actions": "read", "administration": "write", "contents": "write", "metadata": "read"},
"events": [],
"repository_ids": [1249553407, 1258602064, 1259133629, 1259135161]
}),
);
let output = python3::command()
.arg(repo_root().join("scripts/release/verify-downstream-repository.py"))
.args(["fixtures", "--repository-key", "homebrew-rmux"])
.arg("--metadata")
.arg(metadata)
.arg("--protection")
.arg(protection)
.arg("--rulesets")
.arg(rulesets)
.arg("--environments")
.arg(environments)
.arg("--runners")
.arg(runners)
.arg("--installation")
.arg(installation)
.current_dir(repo_root())
.output()
.expect("run downstream repository verifier");
fs::remove_dir_all(root).expect("remove fixture directory");
assert!(
output.status.success(),
"{}",
String::from_utf8_lossy(&output.stderr)
);
}
#[test]
fn downstream_orchestrator_has_no_direct_mutation_primitive() {
for forbidden in [
"cargo publish",
"choco push",
"snapcore/action-publish",
"snapcraft upload",
"wrangler pages deploy",
"git push",
"gh release",
"gh pr create",
"curl -X POST",
"curl -X PUT",
"curl -X PATCH",
"curl -X DELETE",
"repository_dispatch",
] {
assert!(
!DOWNSTREAM.contains(forbidden),
"downstream orchestrator contains mutation primitive {forbidden}"
);
}
}