name: Delta Gate # On-demand candidate-vs-control gate on the capped functional CI lane # (label: gate-functional). That lane is Bun-only host-mode — there is no # Node.js runtime available to it, so this workflow deliberately avoids every # JS-based action (checkout/setup-node/setup-bun/upload-artifact all require # one) and does everything with plain git + bun in shell steps instead. # # Verdict lines a caller should grep for in the run log: # COLLECTED patch= control= — collection-truncation guard inputs # NEW-RED-COUNT: — failures on candidate absent from control # DELTA-GATE: CLEAN | NEW REDS | INVALID | STOPPED-BY-REGISTRY-TRIPWIRE # # The lane's own housekeeping stops the runner and drops a marker file when # host pressure (I/O, registry latency, disk budget) trips — never ours to # interpret as a red or a green. The final step checks for that marker before # it says anything about pass/fail. on: workflow_dispatch: inputs: candidate: description: 'Candidate ref (branch or sha) to gate' required: true type: string control: description: 'Control sha to diff against' required: true type: string # workflow_dispatch needs Actions-unit write on the dispatching credential; # push does not (it runs from the pushed ref's own tree), so a plain push # to a release or CI branch is the fallback trigger while that grant is # outstanding — see the ref-resolution step below for what it gates against. push: branches: ['rel/**', 'ci/**'] concurrency: group: delta-gate cancel-in-progress: false jobs: delta-gate: name: Delta gate — candidate vs control runs-on: gate-functional timeout-minutes: 120 steps: - name: Resolve candidate/control refs id: refs run: | candidate="${{ github.event.inputs.candidate }}" control="${{ github.event.inputs.control }}" # workflow_dispatch supplies both explicitly; a push event carries # neither — fall back to the pushed commit as candidate and the # last released, known-good tip (10.4.9) as control, so a plain # push still produces a meaningful gate instead of an empty ref. if [ -z "$candidate" ]; then candidate="${{ github.sha }}"; fi if [ -z "$control" ]; then control="eec90bdd"; fi echo "candidate=$candidate" >> "$GITHUB_OUTPUT" echo "control=$control" >> "$GITHUB_OUTPUT" echo "Resolved (trigger=${{ github.event_name }}): candidate=$candidate control=$control" - name: Clean any residue from a prior run run: rm -rf "ob-cand-${{ github.run_id }}" "ob-ctrl-${{ github.run_id }}" "/tmp/ob-${{ github.run_id }}-"* - name: Clone + test — candidate id: patch run: | set -o pipefail git clone --quiet "https://source.soulcraft.com/soulcraftlabs/open-brainy.git" "ob-cand-${{ github.run_id }}" cd "ob-cand-${{ github.run_id }}" git checkout --quiet "${{ steps.refs.outputs.candidate }}" git log --oneline -1 bun install rc=0 bun x vitest run > "/tmp/ob-${{ github.run_id }}-patch.log" 2>&1 || rc=$? echo "PATCH-RC:$rc" grep -aE "Tests .*(passed|failed)" "/tmp/ob-${{ github.run_id }}-patch.log" | tail -1 grep -aE "^ FAIL |^\s+×" "/tmp/ob-${{ github.run_id }}-patch.log" | sed -E "s/ [0-9]+ms$//" | sed -E "s/^\s+//" | sort -u > "/tmp/ob-${{ github.run_id }}-patch.fail" echo "PATCH-FAILING:$(wc -l < "/tmp/ob-${{ github.run_id }}-patch.fail")" - name: Clone + test — control id: control run: | set -o pipefail git clone --quiet "https://source.soulcraft.com/soulcraftlabs/open-brainy.git" "ob-ctrl-${{ github.run_id }}" cd "ob-ctrl-${{ github.run_id }}" git checkout --quiet "${{ steps.refs.outputs.control }}" git log --oneline -1 bun install rc=0 bun x vitest run > "/tmp/ob-${{ github.run_id }}-control.log" 2>&1 || rc=$? echo "CONTROL-RC:$rc" grep -aE "Tests .*(passed|failed)" "/tmp/ob-${{ github.run_id }}-control.log" | tail -1 grep -aE "^ FAIL |^\s+×" "/tmp/ob-${{ github.run_id }}-control.log" | sed -E "s/ [0-9]+ms$//" | sed -E "s/^\s+//" | sort -u > "/tmp/ob-${{ github.run_id }}-control.fail" echo "CONTROL-FAILING:$(wc -l < "/tmp/ob-${{ github.run_id }}-control.fail")" - name: Delta gate verdict if: always() run: | set -o pipefail # The lane's own tripwire wins over anything we would otherwise say: # a bare failure/timeout above with this marker present is host # pressure, never a real red and never a real green. if [ -f /srv/gate-lane/TRIPWIRE-STOPPED ]; then echo "DELTA-GATE: STOPPED-BY-REGISTRY-TRIPWIRE" head -1 /srv/gate-lane/TRIPWIRE-STOPPED exit 3 fi patch_log="/tmp/ob-${{ github.run_id }}-patch.log" control_log="/tmp/ob-${{ github.run_id }}-control.log" patch_fail="/tmp/ob-${{ github.run_id }}-patch.fail" control_fail="/tmp/ob-${{ github.run_id }}-control.fail" if [ ! -s "$patch_log" ] || [ ! -s "$control_log" ]; then echo "DELTA-GATE: INVALID — a leg produced no log (see the two steps above for the real cause)" exit 2 fi pt=$(grep -aoE "\(([0-9]+)\)$" "$patch_log" | tail -1 | tr -d "()") ct=$(grep -aoE "\(([0-9]+)\)$" "$control_log" | tail -1 | tr -d "()") echo "COLLECTED patch=${pt:-0} control=${ct:-0}" if [ "${pt:-0}" -lt 3000 ] || [ "${ct:-0}" -lt 3000 ]; then echo "DELTA-GATE: INVALID — truncated collection" exit 2 fi echo "=== NEW REDS ===" comm -23 "$patch_fail" "$control_fail" new=$(comm -23 "$patch_fail" "$control_fail" | wc -l) echo "NEW-RED-COUNT:$new" echo "=== full candidate fail list ===" cat "$patch_fail" echo "=== full control fail list ===" cat "$control_fail" if [ "$new" -eq 0 ]; then echo "DELTA-GATE: CLEAN" else echo "DELTA-GATE: NEW REDS" exit 1 fi - name: Clean up (mind the lane's disk budget) if: always() run: rm -rf "ob-cand-${{ github.run_id }}" "ob-ctrl-${{ github.run_id }}" "/tmp/ob-${{ github.run_id }}-"*