mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-14 11:35:19 +08:00
Merge pull request #1282 from DeusData/feat/local-remote-parity
ci: revert runner-side Defender gating (RTP policy-locked off on hosted images)
This commit is contained in:
@@ -172,10 +172,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
msystem: ${{ matrix.arch == 'arm64' && 'CLANGARM64' || 'CLANG64' }}
|
||||
@@ -258,9 +254,7 @@ jobs:
|
||||
if ($code -eq 2) {
|
||||
Write-Host "BLOCKED: Windows Defender flagged $binary!"; exit 1
|
||||
} elseif ($code -ne 0) {
|
||||
# ensure-defender gates this job earlier, so the engine MUST be
|
||||
# available here: an engine failure is a red gate, never a skip.
|
||||
Write-Host "BLOCKED: Defender scan engine could not run for $binary (exit $code) - Defender-ON parity violated"; exit 1
|
||||
Write-Host "::warning::Windows Defender scan could not run for $binary (exit $code) - skipping AV gate on this runner"
|
||||
} else {
|
||||
Write-Host "=== Windows Defender: $binary clean ==="
|
||||
}
|
||||
|
||||
@@ -93,9 +93,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
@@ -153,9 +150,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
msystem: CLANGARM64
|
||||
@@ -271,9 +265,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
|
||||
+18
-11
@@ -154,7 +154,12 @@ jobs:
|
||||
with:
|
||||
name: shard-manifest-${{ matrix.os }}-${{ matrix.cc }}-${{ strategy.job-index }}
|
||||
path: build/c/test-logs/shard-manifest.txt
|
||||
if-no-files-found: error
|
||||
# The harness writes the manifest BEFORE any suite runs, so a
|
||||
# missing file here means the job died before the harness started
|
||||
# (contract step / build) — that failure is already the job's red;
|
||||
# warn instead of stacking a second error on top of it. The
|
||||
# shard-completeness job still gates the cross-shard union.
|
||||
if-no-files-found: warn
|
||||
|
||||
- name: Compiler cache (save)
|
||||
if: always() && (matrix.shard == null || startsWith(matrix.shard, '1/'))
|
||||
@@ -247,11 +252,12 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
# Defender parity: every Windows venue (local VM and runner alike) tests
|
||||
# with real-time protection ACTIVE — enabled + verified, never skipped.
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
# Defender posture: real-time protection is POLICY-LOCKED OFF on hosted
|
||||
# Windows images (verified 2026-07-27: WinDefend starts and
|
||||
# Set-MpPreference accepts, but RTP stays off — untamperable from the
|
||||
# job). The local VM leg enforces Defender-ON via the canonical Defender
|
||||
# preflight script, so AV-interaction coverage lives there; runners run
|
||||
# without RTP by platform constraint.
|
||||
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
@@ -329,7 +335,12 @@ jobs:
|
||||
with:
|
||||
name: shard-manifest-${{ matrix.os }}-${{ matrix.msystem }}-${{ strategy.job-index }}
|
||||
path: build/c/test-logs/shard-manifest.txt
|
||||
if-no-files-found: error
|
||||
# The harness writes the manifest BEFORE any suite runs, so a
|
||||
# missing file here means the job died before the harness started
|
||||
# (contract step / build) — that failure is already the job's red;
|
||||
# warn instead of stacking a second error on top of it. The
|
||||
# shard-completeness job still gates the cross-shard union.
|
||||
if-no-files-found: warn
|
||||
|
||||
# Shard 1 (or the unsharded job) saves the compiler cache; every shard
|
||||
# builds the identical runner, so one cache carries the full object set.
|
||||
@@ -381,10 +392,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
|
||||
- uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2
|
||||
with:
|
||||
msystem: CLANG64
|
||||
|
||||
@@ -84,11 +84,6 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Ensure Windows Defender is active (venue parity)
|
||||
if: matrix.os == 'windows-latest'
|
||||
shell: pwsh
|
||||
run: scripts/ci/ensure-defender.ps1
|
||||
|
||||
- name: Install deps (Ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: sudo apt-get update && sudo apt-get install -y zlib1g-dev ccache
|
||||
|
||||
@@ -66,3 +66,7 @@ graph-ui/.npm-cache-local/
|
||||
# Python bytecode from tests/windows/ harness
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Local soak-leg outputs (uploaded as CI artifacts, never committed)
|
||||
soak-results/
|
||||
soak-results-query-leak/
|
||||
|
||||
@@ -195,6 +195,22 @@ shard_filter < "$SER_FILE" > "$SER_FILE.shard" && mv "$SER_FILE.shard" "$SER_FIL
|
||||
SHARD_EXPECT="$LOGDIR/suites-shard.txt"
|
||||
cat "$PAR_FILE" "$SER_FILE" > "$SHARD_EXPECT"
|
||||
NSHARD=$(wc -l < "$SHARD_EXPECT" | tr -d ' ')
|
||||
|
||||
# Machine-checkable manifest for CI's cross-shard completeness job: it
|
||||
# proves at runtime that the shards of one leg agree on N and on the full
|
||||
# suite list, and that the union of their slices IS that list — the guard
|
||||
# against a mis-plumbed CBM_TEST_SHARD (two jobs running the same slice
|
||||
# passes every per-shard check but silently drops a slice; only a
|
||||
# cross-shard view catches it). Written BEFORE any suite runs: the slice is
|
||||
# fully determined here, and a red run's manifest is exactly as load-bearing
|
||||
# as a green one's — CI uploads it if: always().
|
||||
{
|
||||
echo "leg=${CBM_TEST_LEG:-local}"
|
||||
echo "shard=${SHARD_INDEX}/${SHARD_TOTAL}"
|
||||
echo "list_sha256=$(sort "$SUITES_FILE" | { sha256sum 2>/dev/null || shasum -a 256; } | awk '{print $1}')"
|
||||
echo "--- slice ---"
|
||||
cat "$SHARD_EXPECT"
|
||||
} > "$LOGDIR/shard-manifest.txt"
|
||||
echo "=== parallel test run: $NSHARD of $NSUITES suites (shard ${SHARD_INDEX}/${SHARD_TOTAL}, $(wc -l < "$SER_FILE" | tr -d ' ') serial-tail), $JOBS jobs ==="
|
||||
|
||||
# Per-suite wall-clock ceilings make a wedged child fail loudly. The
|
||||
@@ -255,20 +271,6 @@ stamp_windows_build_dir pre-tail
|
||||
run_wave "$FLEX_FILE" "${CBM_TAIL_JOBS:-2}"
|
||||
run_wave "$EXCL_FILE" 1
|
||||
|
||||
# Machine-checkable manifest for CI's cross-shard completeness job: it
|
||||
# proves at runtime that the shards of one leg agree on N and on the full
|
||||
# suite list, and that the union of their slices IS that list — the guard
|
||||
# against a mis-plumbed CBM_TEST_SHARD (two jobs running the same slice
|
||||
# passes every per-shard check but silently drops a slice; only a
|
||||
# cross-shard view catches it).
|
||||
{
|
||||
echo "leg=${CBM_TEST_LEG:-local}"
|
||||
echo "shard=${SHARD_INDEX}/${SHARD_TOTAL}"
|
||||
echo "list_sha256=$(sort "$SUITES_FILE" | { sha256sum 2>/dev/null || shasum -a 256; } | awk '{print $1}')"
|
||||
echo "--- slice ---"
|
||||
cat "$SHARD_EXPECT"
|
||||
} > "$LOGDIR/shard-manifest.txt"
|
||||
|
||||
# ── Union guard: every suite in this shard's slice produced exactly one
|
||||
# result. The slice is deterministic, so N green shard jobs = full coverage;
|
||||
# a shard that ran anything more, less, or twice fails here. ──
|
||||
|
||||
@@ -119,10 +119,12 @@ documented honestly where not:
|
||||
|
||||
- **Preflight, every venue-grade command:** `clean-test-residue.ps1` sweeps
|
||||
temp roots/staged binaries and asserts a runner-like free-disk floor, then
|
||||
`scripts/ci/ensure-defender.ps1` (the SAME script every Windows CI job runs)
|
||||
enables + verifies Defender real-time protection. Defender posture is
|
||||
matched ON on all venues — the runners enable it too; a venue where it
|
||||
cannot be activated goes red, never silently tests a different OS shape.
|
||||
`scripts/ci/ensure-defender.ps1` enables + verifies Defender real-time
|
||||
protection ON THIS VM (fail-closed: a drifted-off Defender goes red).
|
||||
Hosted GitHub runners CANNOT match this posture — RTP is policy-locked off
|
||||
on their images (verified 2026-07-27: WinDefend starts, Set-MpPreference
|
||||
accepts, RTP stays off) — so AV-interaction coverage is a deliberate LOCAL
|
||||
superset, and runner release scans stay on-demand (MpCmdRun, fail-soft).
|
||||
- **Snapshot-revert is NOT scriptable via utmctl** (its verb set is
|
||||
version/list/status/start/suspend/stop — no snapshot support), so per-run
|
||||
revert-to-clean is not wired. The honest fallback is the sweep preflight
|
||||
|
||||
@@ -249,32 +249,24 @@ REQUIRED = [
|
||||
("pr.yml", r"vm-smoke\.sh", "PR CI smokes through the shared wrapper"),
|
||||
("_build.yml", r"scripts/package-release\.sh",
|
||||
"release archives are produced by the canonical packaging entry"),
|
||||
("_test.yml", r"scripts/ci/ensure-defender\.ps1",
|
||||
"Windows test legs enable+verify Defender (venue parity)"),
|
||||
("_smoke.yml", r"scripts/ci/ensure-defender\.ps1",
|
||||
"Windows release smoke enables+verifies Defender (venue parity)"),
|
||||
("_soak.yml", r"scripts/ci/ensure-defender\.ps1",
|
||||
"Windows soak legs enable+verify Defender (venue parity)"),
|
||||
("pr.yml", r"scripts/ci/ensure-defender\.ps1",
|
||||
"PR Windows smoke enables+verifies Defender (venue parity)"),
|
||||
]
|
||||
for name, pattern, why in REQUIRED:
|
||||
path = workflows / name
|
||||
if path.exists() and not re.search(pattern, path.read_text()):
|
||||
failures.append(f"{name}: missing required `{pattern}` — {why}")
|
||||
|
||||
# Defender-ON parity: EVERY Windows job in every venue workflow enables and
|
||||
# verifies real-time protection — a single job dropping the step must fail,
|
||||
# so the expectation is an exact per-file count, not mere presence.
|
||||
DEFENDER_STEPS = {"_test.yml": 2, "_soak.yml": 3, "_smoke.yml": 1, "pr.yml": 1}
|
||||
for name, expected in DEFENDER_STEPS.items():
|
||||
# Defender posture: hosted Windows runners have real-time protection
|
||||
# POLICY-LOCKED OFF (verified 2026-07-27: WinDefend starts, Set-MpPreference
|
||||
# accepts, RTP stays off), so runner jobs must NOT gate on enabling it; the
|
||||
# LOCAL VM leg enforces Defender-ON via the same canonical script in its
|
||||
# preflight (see LOCAL_REQUIRED below) — superset coverage where the platform
|
||||
# allows it.
|
||||
for name in ("_test.yml", "_soak.yml", "_smoke.yml", "pr.yml"):
|
||||
path = workflows / name
|
||||
if path.exists():
|
||||
got = path.read_text().count("scripts/ci/ensure-defender.ps1")
|
||||
if got != expected:
|
||||
failures.append(
|
||||
f"{name}: expected {expected} ensure-defender.ps1 step(s) "
|
||||
f"(one per Windows job), found {got}")
|
||||
if path.exists() and "ensure-defender.ps1" in path.read_text():
|
||||
failures.append(
|
||||
f"{name}: ensure-defender.ps1 must not gate hosted runners — RTP is "
|
||||
f"policy-locked off there; the VM preflight owns Defender-ON coverage")
|
||||
|
||||
# ── Layer 4: the local venues route through the same entries ──
|
||||
compose = root / "test-infrastructure" / "docker-compose.yml"
|
||||
|
||||
Reference in New Issue
Block a user