Files
codebase-memory-mcp/scripts/ci
Martin Vogel b67401a03b ci(dry-run): scan the archive artifacts with VirusTotal as the final step
Preparation for the next dry-run cycle. The release gate scans every shipped
artifact with VirusTotal and blocks on any detection; the dry run did not, so
the one question most likely to stop a release was the one a dry run could not
answer. v0.9.1-rc found that out the expensive way.

The scan mirrors the release job. The only difference is where the archives come
from: the release pulls them off a published release, a dry run has none, so
they come from the build job's artifacts — the same files, produced by the same
canonical package-release.sh, extracted the same way and scanned as the same
bytes a user would download and run. Same zero-tolerance gate
(scripts/ci/check-virustotal.sh), so a dry run now fails where the release would.

It runs LAST, after smoke and soak. It is the slowest job — polling can take two
hours — and its verdict does not depend on our code at all: the same unchanged
bytes can come back clean one day and flagged the next. That must not delay the
feedback that IS about our code.

Two independent skips, because they answer different questions:

  skip_builds      no artifacts at all          "do lint and tests pass?"
  skip_virustotal  build + smoke + soak, no scan "do the archives pass CI?"

The second is the one asked for: during a debug cycle, when the question is
whether the archives survive smoke and soak, a two-hour scan burning API quota
is pure noise. skip_builds implies no scan, since there is nothing to scan.

Extraction lives in scripts/ci/extract-release-archives.sh rather than inline in
the YAML because the venue-parity contract requires it — a venue may provision,
plumb artifacts, or call a canonical leg script, and this is leg logic. The
contract caught the inline version.

Two defects found by testing the script instead of trusting it:

  * The empty-input guard did not guard. It counted files in the output
    directory, but the install scripts are copied in unconditionally, so the
    count was never zero and an input with no archives reported success — a
    clean VirusTotal run over nothing, the exact false green the check exists to
    prevent. It now counts binaries recovered from archives, and exits 1 on
    zero.
  * The script was committed 100644 while the workflow invokes it directly as a
    command, which is the "Permission denied" failure
    test_script_exec_bit_contract.sh was written for. That contract scans
    scripts/ but not .github/workflows/, so it did not catch it here.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
2026-08-07 17:59:50 +02:00
..

scripts/ci/ — venue plumbing (single implementations)

Support scripts that keep the venues in the SAME shape. Each exists because the logic used to live inline in workflow YAML or was hand-duplicated between CI and the local infrastructure — both of which the venue-parity contract (tests/test_venue_parity_contract.sh) now forbids. Everything here answers --help (PowerShell: comment-based help, Get-Help <script>).

script job called by
new-protected-temp-root.ps1 Create the owner-stamped, inheritance-protected per-user TEMP root the daemon/install suites require (shared /tmp and default runner TEMP grant Authenticated-Users mutation rights, which the trust policy correctly refuses — running there produces security refusals, not signal). -ProtectDir stamps build dirs the same way. _test.yml, _soak.yml, vm-run-tests.sh
clean-test-residue.ps1 Sweep cbm-* residue from the Windows VM and assert runner-like free disk (default 14 GB — the GitHub runner's SSD). Long-path \\?\ fallback for the guard suites' adversarial trees; every removal VERIFIED (an earlier version counted attempts and reported 86 swept while 11 GB remained). BLOCKS below the floor: a disk that fills mid-run reads as a product bug. win.sh before every build/run
preflight-docker.sh Same idea for Colima/docker: prune runner-unlike residue, assert free space on the filesystem backing the docker data root (not the VM's /). Build cache + named volumes KEPT (the local analogue of actions/cache); --deep drops them. test-infrastructure/run.sh
check-glibc-compat.sh Run a linux binary in debian:bullseye (glibc 2.31) — the portable binary must start on old glibc. _smoke.yml portable legs
generate-sbom.py The release SPDX SBOM (vendored versions reviewable here, diffable by vendoring PRs — was inline YAML). release.yml
require-all-green.sh The aggregate gate: fail unless every needed job succeeded or legitimately skipped (was inline YAML). pr.yml ci-ok
verify-shard-union.sh Prove sharded test legs lost nothing: shard count agreement, indices 1..n, identical suite lists, union of slices == full list (was inline YAML). _test.yml shard-completeness
check-virustotal.sh Release-asset VirusTotal lookups. release.yml