warriors/trisha/scripts/build-candidate.nu

# Build a coordinated local candidate entirely from an extracted source archive.
def executable [name: string] {
    if $nu.os-info.name == windows { $"($name).exe" } else { $name }
}
def build [manifest: path, package: string, log: path] {
    print $"Building ($package) from ($manifest)"
    let result = (^cargo build --manifest-path $manifest --release --locked -p $package | complete)
    $"($result.stdout)($result.stderr)" | save --force $log
    if $result.exit_code != 0 { error make {msg: $"build failed; see ($log)\n($result.stderr)"} }
    if ($result.stderr | lines | any {|line| $line | str starts-with 'warning:' }) {
        error make {msg: $"build emitted warnings; see ($log)"}
    }
}

def main [source: path, prefix: path] {
    let source = ($source | path expand)
    let verifier = ($env.FILE_PWD | path join verify-source.py)
    let checked_prefix = (^python3 $verifier --check-destination $source $prefix | complete)
    if $checked_prefix.exit_code != 0 { error make {msg: $checked_prefix.stderr} }
    let prefix = ($checked_prefix.stdout | str trim)
    if not ($source | path join sources.json | path exists) { error make {msg: "source provenance is missing"} }
    # Validate before creating any destination or invoking Cargo.
    let initial = (^python3 $verifier $source | complete)
    if $initial.exit_code != 0 { error make {msg: $initial.stderr} }
    let destination = $prefix
    let temporary = (if $nu.os-info.name == windows {
        {stdout: (mktemp -d --tmpdir-path ($destination | path dirname) $"(($destination | path basename)).building.XXXXXX"), stderr: '', exit_code: 0}
    } else { ^mktemp -d $"($destination).building.XXXXXX" | complete })
    let prefix = ($temporary.stdout | str trim)
    let owned_staging = (($prefix | str starts-with $"($destination).building.") and (($prefix | path dirname) == ($destination | path dirname)))
    try {
    if $temporary.exit_code != 0 { error make {msg: $"cannot create private candidate staging directory: ($temporary.stderr)"} }
    if not $owned_staging or ($prefix | path type) != dir { error make {msg: "mktemp did not return the expected staging directory"} }
    cd $source
    # A portable release must not inherit a caller's native CPU or cross target.
    hide-env -i CARGO_ENCODED_RUSTFLAGS CARGO_BUILD_TARGET
    $env.RUSTFLAGS = (if $nu.os-info.name == windows { '-C target-feature=+crt-static' } else { '' })
    $initial.stdout | save ($prefix | path join source-verification.json)
    mkdir ($prefix | path join bin)
    for project in [trident trisha joy] {
        let manifest = ($source | path join $project Cargo.toml)
        let metadata = (^cargo metadata --manifest-path $manifest --format-version 1 --all-features --locked | complete)
        if $metadata.exit_code != 0 { error make {msg: $metadata.stderr} }
        let packages = ($metadata.stdout | from json | get packages)
        if $project in [trisha joy] {
            for dependency in [triton-vm triton-air triton-isa triton-constraint-circuit triton-constraint-builder tasm-lib tasm-object-derive] {
                let versions = ($packages | where name == $dependency | get version | uniq)
                if $versions != ['7.0.0'] {
                    error make {msg: $"($project): release requires ($dependency)7.0.0; resolved ($versions | str join ', ')"}
                }
            }
        }
        let local = ($packages | where source == null | get manifest_path)
        let contained = (^python3 $verifier --check-contained $source ...$local | complete)
        if $contained.exit_code != 0 { error make {msg: $contained.stderr} }
    }
    for task in [
        {project: trident, package: trident-lang, binaries: [trident trident-lsp]}
        {project: trisha, package: trisha, binaries: [trisha]}
        {project: joy, package: cyber-joy, binaries: [joy]}
    ] {
        $env.CARGO_TARGET_DIR = ($prefix | path join build $task.project)
        build ($source | path join $task.project Cargo.toml) $task.package ($prefix | path join $"($task.project)-build.log")
        for name in $task.binaries {
            let file = (executable $name)
            cp ($env.CARGO_TARGET_DIR | path join release $file) ($prefix | path join bin $file)
        }
    }
    # A small fixture helper links to the archived BBG implementation. It creates
    # complete public certificates instead of embedding opaque stale state roots.
    let helper = ($source | path join trisha scripts fixtures Cargo.toml)
    $env.CARGO_TARGET_DIR = ($prefix | path join build fixtures)
    let fixtures = ($prefix | path join share trisha-release-smoke)
    let generated = (^cargo run --manifest-path $helper --release --locked --offline -- $fixtures | complete)
    $"($generated.stdout)($generated.stderr)" | save ($prefix | path join fixture-build.log)
    if $generated.exit_code != 0 { error make {msg: $generated.stderr} }
    if ($generated.stderr | lines | any {|line| $line | str starts-with 'warning:' }) { error make {msg: "fixture build emitted warnings"} }
    let binaries = ([trident trident-lsp trisha joy] | each {|name|
        let path = ($prefix | path join bin (executable $name))
        {name: $name, sha256: (open --raw $path | hash sha256)}
    })
    let final_check = (^python3 $verifier $source --expect ($prefix | path join source-verification.json) | complete)
    if $final_check.exit_code != 0 { error make {msg: $final_check.stderr} }
    if $final_check.stdout != $initial.stdout { error make {msg: "source provenance changed during build"} }
    let toolchain = (^rustc -vV | complete)
    if $toolchain.exit_code != 0 { error make {msg: $toolchain.stderr} }
    {schema_version: 2, platform: $nu.os-info, toolchain: $toolchain.stdout, rustflags: $env.RUSTFLAGS, source: $source, source_verified: true, source_verification_sha256: (open --raw ($prefix | path join source-verification.json) | hash sha256), provenance_sha256: (open --raw ($source | path join sources.json) | hash sha256), binaries: $binaries}
        | to json | save ($prefix | path join candidate.json)
    let publish_check = (^python3 $verifier --check-destination $source $destination | complete)
    if $publish_check.exit_code != 0 { error make {msg: $publish_check.stderr} }
    mv $prefix $destination
    } catch {|failure|
        if $owned_staging and ($prefix | path exists) { rm --recursive --force $prefix }
        error make {msg: $failure.msg}
    }
    print $"Candidate built: ($destination). Run smoke-release.nu against its bin directory. This does not publish a release."
}

Graph