diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64399265fb1..b2bf69036a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,11 +80,7 @@ jobs: fi rm -f "$BUILD_LOG" if '[' '!' '-x' "$ROOT"'/target/release/claim_executor' ']'; then 'echo' '::error::build verification: declared artifact '\''claim_executor'\'' absent or not executable after a '\''successful'\'' build (sccache/cache corruption — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/claim_executor' >&2; exit 1; fi - GUNBC_BUILD_FRESHNESS_NEWER_SRC=$('find' "$ROOT"'/src/v1/stage0' "$ROOT"'/src/v1/stage0_core' "$ROOT"'/src/v1/stage0_emit_core' '(' '-name' '*.rs' '-o' '-name' 'Cargo.toml' '-o' '-name' 'Cargo.lock' ')' '-newer' "$ROOT"'/target/release/claim_executor' '-print' '-quit') - if '[' '-n' "$GUNBC_BUILD_FRESHNESS_NEWER_SRC" ']'; then 'echo' '::error::build verification: declared artifact '\''claim_executor'\'' is older than a source file (stale — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/claim_executor' >&2; exit 1; fi if '[' '!' '-x' "$ROOT"'/target/release/gunbc' ']'; then 'echo' '::error::build verification: declared artifact '\''gunbc'\'' absent or not executable after a '\''successful'\'' build (sccache/cache corruption — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/gunbc' >&2; exit 1; fi - GUNBC_BUILD_FRESHNESS_NEWER_SRC=$('find' "$ROOT"'/src/v1/stage0' "$ROOT"'/src/v1/stage0_core' "$ROOT"'/src/v1/stage0_emit_core' '(' '-name' '*.rs' '-o' '-name' 'Cargo.toml' '-o' '-name' 'Cargo.lock' ')' '-newer' "$ROOT"'/target/release/gunbc' '-print' '-quit') - if '[' '-n' "$GUNBC_BUILD_FRESHNESS_NEWER_SRC" ']'; then 'echo' '::error::build verification: declared artifact '\''gunbc'\'' is older than a source file (stale — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/gunbc' >&2; exit 1; fi sccache --show-stats 2>/dev/null || true git fetch --no-tags origin main 2>/dev/null || true "$ROOT/target/release/claim_executor" --source-root dsl --source-root src/v2 --plan-entry src/v2/workflow/ci_floor_plan.dag --plan-function gunbc_ci_floor_batches --notice-title "v2 claim corpus" @@ -160,11 +156,7 @@ jobs: fi rm -f "$BUILD_LOG" if '[' '!' '-x' "$ROOT"'/target/release/claim_executor' ']'; then 'echo' '::error::build verification: declared artifact '\''claim_executor'\'' absent or not executable after a '\''successful'\'' build (sccache/cache corruption — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/claim_executor' >&2; exit 1; fi - GUNBC_BUILD_FRESHNESS_NEWER_SRC=$('find' "$ROOT"'/src/v1/stage0' "$ROOT"'/src/v1/stage0_core' "$ROOT"'/src/v1/stage0_emit_core' '(' '-name' '*.rs' '-o' '-name' 'Cargo.toml' '-o' '-name' 'Cargo.lock' ')' '-newer' "$ROOT"'/target/release/claim_executor' '-print' '-quit') - if '[' '-n' "$GUNBC_BUILD_FRESHNESS_NEWER_SRC" ']'; then 'echo' '::error::build verification: declared artifact '\''claim_executor'\'' is older than a source file (stale — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/claim_executor' >&2; exit 1; fi if '[' '!' '-x' "$ROOT"'/target/release/gunbc' ']'; then 'echo' '::error::build verification: declared artifact '\''gunbc'\'' absent or not executable after a '\''successful'\'' build (sccache/cache corruption — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/gunbc' >&2; exit 1; fi - GUNBC_BUILD_FRESHNESS_NEWER_SRC=$('find' "$ROOT"'/src/v1/stage0' "$ROOT"'/src/v1/stage0_core' "$ROOT"'/src/v1/stage0_emit_core' '(' '-name' '*.rs' '-o' '-name' 'Cargo.toml' '-o' '-name' 'Cargo.lock' ')' '-newer' "$ROOT"'/target/release/gunbc' '-print' '-quit') - if '[' '-n' "$GUNBC_BUILD_FRESHNESS_NEWER_SRC" ']'; then 'echo' '::error::build verification: declared artifact '\''gunbc'\'' is older than a source file (stale — DESIGN §5 fail-open); failing closed: '"$ROOT"'/target/release/gunbc' >&2; exit 1; fi sccache --show-stats 2>/dev/null || true git fetch --no-tags origin main 2>/dev/null || true set -o pipefail diff --git a/dsl/gunbc/ci_spec.dag b/dsl/gunbc/ci_spec.dag index 3686be03cdb..ccf290edd38 100644 --- a/dsl/gunbc/ci_spec.dag +++ b/dsl/gunbc/ci_spec.dag @@ -5,7 +5,7 @@ import gunbc.ci_layer_roots { witness_layer_source_flags } import tools.build_step { BuildArtifact, verifications_script } -import extdeps.languages.bash.program { ShellWord, Concat, lit, var_ref } +import extdeps.languages.bash.program { Concat, lit, var_ref } type Gate = RustMonolithGate @@ -141,16 +141,8 @@ data ci_floor_required_artifacts: List = [ ci_release_artifact(name: "gunbc") ] -fn ci_build_source_roots() -> List { - [ - Concat { parts: [var_ref(name: "ROOT"), lit(text: "/src/v1/stage0")] }, - Concat { parts: [var_ref(name: "ROOT"), lit(text: "/src/v1/stage0_core")] }, - Concat { parts: [var_ref(name: "ROOT"), lit(text: "/src/v1/stage0_emit_core")] } - ] -} - fn ci_floor_build_verify_script() -> String { - verifications_script(produces: ci_floor_required_artifacts, roots: ci_build_source_roots(), patterns: ["*.rs", "Cargo.toml", "Cargo.lock"]) + verifications_script(produces: ci_floor_required_artifacts) } fn ci_release_build_script() -> String { diff --git a/dsl/test/claim/build_artifact_verification_witness_test.dag b/dsl/test/claim/build_artifact_verification_witness_test.dag index 8093ce065bb..c2511866be0 100644 --- a/dsl/test/claim/build_artifact_verification_witness_test.dag +++ b/dsl/test/claim/build_artifact_verification_witness_test.dag @@ -3,12 +3,12 @@ module test.claim.build_artifact_verification_witness import std.logic { Bool } import extdeps.languages.bash.program { ShellStmt, ShellWord, ShellProgram, - If, Assign, Command, Concat, VarRef, Lit, + If, Command, Concat, VarRef, Lit, lit, var_ref, serialize_bash } import tools.build_step { BuildArtifact, emit_verifications, verifications_script } import gunbc.ci_spec { - ci_floor_required_artifacts, ci_floor_build_verify_script, ci_build_source_roots + ci_floor_required_artifacts, ci_floor_build_verify_script } fn probe_artifact() -> BuildArtifact { @@ -18,12 +18,8 @@ fn probe_artifact() -> BuildArtifact { } } -fn probe_source_roots() -> List { - [Concat { parts: [var_ref(name: "ROOT"), lit(text: "/src")] }] -} - fn probe_stmts() -> List { - emit_verifications(produces: [probe_artifact()], roots: probe_source_roots(), patterns: ["*.rs", "Cargo.toml", "Cargo.lock"]) + emit_verifications(produces: [probe_artifact()]) } fn stmt_text(s: ShellStmt) -> String { @@ -37,58 +33,39 @@ fn is_if(s: ShellStmt) -> Bool { } } -fn is_assign(s: ShellStmt) -> Bool { - match s { - Assign { name: n, value: v } => true - _ => false - } -} - -fn witness_single_artifact_shape_exists_then_fresh() -> Bool { +fn witness_single_artifact_shape_exists_only() -> Bool { let stmts = probe_stmts() - stmts.length() == 3 - && is_if(s: stmts.first()) - && is_assign(s: stmts.skip(n: 1).first()) - && is_if(s: stmts.skip(n: 2).first()) + stmts.length() == 1 && is_if(s: stmts.first()) } -fn witness_existence_precedes_freshness() -> Bool { +fn witness_existence_check_no_mtime() -> Bool { let stmts = probe_stmts() let existence = stmt_text(s: stmts.first()) - let probe = stmt_text(s: stmts.skip(n: 1).first()) string_contains(s: existence, pattern: "-x") && !string_contains(s: existence, pattern: "-newer") - && string_contains(s: probe, pattern: "-newer") - && string_contains(s: probe, pattern: "-quit") } fn witness_serialized_conjuncts_and_teeth() -> Bool { - let script = verifications_script(produces: [probe_artifact()], roots: probe_source_roots(), patterns: ["*.rs", "Cargo.toml", "Cargo.lock"]) - string_contains(s: script, pattern: "-x") - && string_contains(s: script, pattern: "-newer") - && string_contains(s: script, pattern: "-print") - && string_contains(s: script, pattern: "-quit") - && string_contains(s: script, pattern: "'*.rs'") - && string_contains(s: script, pattern: "Cargo.toml") - && string_contains(s: script, pattern: "Cargo.lock") - && string_contains(s: script, pattern: "/target/release/probe_bin") - && string_contains(s: script, pattern: "/src") - && string_contains(s: script, pattern: "exit 1") + let script = verifications_script(produces: [probe_artifact()]) + string_contains(s: script, pattern: "-x") + && !string_contains(s: script, pattern: "-newer") + && string_contains(s: script, pattern: "/target/release/probe_bin") + && string_contains(s: script, pattern: "exit 1") } fn witness_floor_covers_both_release_bins() -> Bool { - let stmts = emit_verifications(produces: ci_floor_required_artifacts, roots: ci_build_source_roots(), patterns: ["*.rs", "Cargo.toml", "Cargo.lock"]) + let stmts = emit_verifications(produces: ci_floor_required_artifacts) let script = ci_floor_build_verify_script() - stmts.length() == 6 + stmts.length() == 2 && string_contains(s: script, pattern: "/target/release/claim_executor") && string_contains(s: script, pattern: "/target/release/gunbc") - && string_contains(s: script, pattern: "-newer") + && !string_contains(s: script, pattern: "-newer") && string_contains(s: script, pattern: "exit 1") } test fn build_artifact_verification_holds() -> Bool { - witness_single_artifact_shape_exists_then_fresh() - && witness_existence_precedes_freshness() + witness_single_artifact_shape_exists_only() + && witness_existence_check_no_mtime() && witness_serialized_conjuncts_and_teeth() && witness_floor_covers_both_release_bins() } diff --git a/dsl/tools/build_step.dag b/dsl/tools/build_step.dag index 8ea0463c0b1..92ca2a69466 100644 --- a/dsl/tools/build_step.dag +++ b/dsl/tools/build_step.dag @@ -2,9 +2,9 @@ module tools.build_step import extdeps.languages.bash.program { ShellStmt, ShellWord, ShellProgram, - Command, If, Exit, Assign, WithRedir, - Lit, VarRef, Concat, CmdSubst, StdoutToStderr, - lit, var_ref, command, assign, serialize_bash + Command, If, Exit, WithRedir, + Lit, Concat, StdoutToStderr, + lit, command, serialize_bash } type BuildArtifact { @@ -13,8 +13,6 @@ type BuildArtifact { name: String } -data build_freshness_probe_var: String = "GUNBC_BUILD_FRESHNESS_NEWER_SRC" - fn build_verify_echo(msg: ShellWord) -> ShellStmt { WithRedir { stmt: command(words: [lit(text: "echo"), msg]), @@ -35,62 +33,17 @@ fn verify_artifact_exists(art: BuildArtifact) -> ShellStmt { } } -fn name_predicate_words(patterns: List) -> List { - concat( - [lit(text: "(")], - concat( - fold(patterns, init: [], f: (acc, p) => - if acc.length() == 0 { - [lit(text: "-name"), lit(text: p)] - } else { - concat(acc, [lit(text: "-o"), lit(text: "-name"), lit(text: p)]) - } - ), - [lit(text: ")")] - ) - ) -} - -fn freshness_find_stmt(art: BuildArtifact, roots: List, patterns: List) -> ShellStmt { - command(words: concat( - concat([lit(text: "find")], roots), - concat( - name_predicate_words(patterns: patterns), - [lit(text: "-newer"), art.path, lit(text: "-print"), lit(text: "-quit")] - ) - )) -} - -fn verify_artifact_fresh(art: BuildArtifact, roots: List, patterns: List) -> List { - [ - Assign { - name: build_freshness_probe_var, - value: CmdSubst { body: freshness_find_stmt(art: art, roots: roots, patterns: patterns) } - }, - If { - cond: command(words: [lit(text: "["), lit(text: "-n"), var_ref(name: build_freshness_probe_var), lit(text: "]")]), - then: [ - build_verify_echo(msg: Concat { parts: [ - lit(text: concat("::error::build verification: declared artifact '", concat(art.name, "' is older than a source file (stale — DESIGN §5 fail-open); failing closed: "))), - art.path - ] }), - Exit { code: 1 } - ] - } - ] -} - -fn verify_artifact(art: BuildArtifact, roots: List, patterns: List) -> List { - concat([verify_artifact_exists(art: art)], verify_artifact_fresh(art: art, roots: roots, patterns: patterns)) +fn verify_artifact(art: BuildArtifact) -> List { + [verify_artifact_exists(art: art)] } -fn emit_verifications(produces: List, roots: List, patterns: List) -> List { - fold(produces, init: [], f: (acc, art) => concat(acc, verify_artifact(art: art, roots: roots, patterns: patterns))) +fn emit_verifications(produces: List) -> List { + fold(produces, init: [], f: (acc, art) => concat(acc, verify_artifact(art: art))) } -fn verifications_script(produces: List, roots: List, patterns: List) -> String { +fn verifications_script(produces: List) -> String { serialize_bash(p: ShellProgram { set_e: false, - statements: emit_verifications(produces: produces, roots: roots, patterns: patterns) + statements: emit_verifications(produces: produces) }) } diff --git a/dsl/tools/host_prelude.dag b/dsl/tools/host_prelude.dag index 7e0e3448e14..94afac9308a 100644 --- a/dsl/tools/host_prelude.dag +++ b/dsl/tools/host_prelude.dag @@ -11,10 +11,6 @@ import extdeps.languages.bash.program { } import tools.build_step { BuildArtifact, emit_verifications } -fn host_build_source_roots() -> List { - [Concat { parts: [var_ref(name: "ROOT"), lit(text: "/src")] }] -} - fn assign_root_stmt() -> ShellStmt { assign(name: "ROOT", value: CmdSubst { body: AndOr { left: WithRedir { @@ -58,9 +54,7 @@ fn ensure_bin_built_and_verified(var_name: String, bin_name: String) -> List