fix(agent99): bind check receipts to same-run identity
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 1m40s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 11s
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 1m40s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
AWOOOI Harbor 110 Local Repair / workflow-shape (push) Successful in 1s
AWOOOI Harbor 110 Local Repair / harbor-110-local-repair (push) Successful in 11s
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
@@ -55,9 +56,9 @@ def test_sender_is_valid_shell_with_check_as_the_default() -> None:
|
||||
assert 'MODE="check"' in source
|
||||
assert "--apply" in source
|
||||
assert 'MODE="apply"' in source
|
||||
assert "apply_trace_id_missing_or_invalid" in source
|
||||
assert "apply_run_id_missing_or_invalid" in source
|
||||
assert "apply_work_item_id_missing_or_invalid" in source
|
||||
assert 'fail "${MODE}_trace_id_missing_or_invalid"' in source
|
||||
assert 'fail "${MODE}_run_id_missing_or_invalid"' in source
|
||||
assert 'fail "${MODE}_work_item_id_missing_or_invalid"' in source
|
||||
assert 'MODE_SELECTION="default"' in source
|
||||
assert 'REMOTE_EXECUTION_TIMEOUT_SECONDS="180"' in source
|
||||
assert 'REMOTE_EXECUTION_TIMEOUT_SECONDS="2400"' in source
|
||||
@@ -291,6 +292,34 @@ def test_receiver_has_single_flight_idempotency_and_no_secret_receipt_boundary()
|
||||
assert "[bool]$prior.relayReload.newGenerationVerified" in source
|
||||
|
||||
|
||||
def test_check_and_apply_receipts_project_the_same_run_identity() -> None:
|
||||
sender = SENDER.read_text(encoding="utf-8")
|
||||
projector = sender[
|
||||
sender.index("project_check_receipt_identity()") : sender.index(
|
||||
'if [[ "${MODE}" == "check" ]]'
|
||||
)
|
||||
]
|
||||
assert '"traceId": trace_id' in projector
|
||||
assert '"runId": run_id' in projector
|
||||
assert '"workItemId": work_item_id' in projector
|
||||
assert "receipt[field] != expected" in projector
|
||||
assert "raise SystemExit(65)" in projector
|
||||
|
||||
receiver = RECEIVER.read_text(encoding="utf-8")
|
||||
success_receipt = receiver[
|
||||
receiver.index("$successReceipt = [pscustomobject]@{") : receiver.index(
|
||||
"Write-AgentRemoteDeployReceipt $receiptPath $successReceipt"
|
||||
)
|
||||
]
|
||||
assert "traceId = $traceId" in success_receipt
|
||||
assert "runId = $runId" in success_receipt
|
||||
assert "workItemId = $workItemId" in success_receipt
|
||||
assert "secretValueRead = $false" in success_receipt
|
||||
assert "privateKeyValueRead = $false" in success_receipt
|
||||
assert "tokenValueRead = $false" in success_receipt
|
||||
assert "environmentSecretRead = $false" in success_receipt
|
||||
|
||||
|
||||
def test_receiver_creates_canonical_success_receipt_once_with_atomic_no_replace() -> None:
|
||||
source = RECEIVER.read_text(encoding="utf-8")
|
||||
writer = source[
|
||||
@@ -586,6 +615,39 @@ def test_apply_without_all_three_identities_fails_before_ssh() -> None:
|
||||
assert "known_hosts_file_missing" not in result.stderr
|
||||
|
||||
|
||||
def test_check_requires_complete_safe_same_run_identity_before_ssh() -> None:
|
||||
cases = (
|
||||
((), "check_trace_id_missing_or_invalid"),
|
||||
(("--trace-id", "trace-fixture"), "check_run_id_missing_or_invalid"),
|
||||
(
|
||||
("--trace-id", "trace-fixture", "--run-id", "run-fixture"),
|
||||
"check_work_item_id_missing_or_invalid",
|
||||
),
|
||||
(
|
||||
(
|
||||
"--trace-id",
|
||||
"trace fixture",
|
||||
"--run-id",
|
||||
"run-fixture",
|
||||
"--work-item-id",
|
||||
"AIA-SRE-P0-20260715",
|
||||
),
|
||||
"check_trace_id_missing_or_invalid",
|
||||
),
|
||||
)
|
||||
|
||||
for identity_args, expected_error in cases:
|
||||
result = subprocess.run(
|
||||
["bash", str(SENDER), "--check", *identity_args],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
assert result.returncode == 64
|
||||
assert expected_error in result.stderr
|
||||
assert "known_hosts_file_missing" not in result.stderr
|
||||
|
||||
|
||||
def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
@@ -610,7 +672,13 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
"#!/usr/bin/env bash\n"
|
||||
f"printf '%s\\n' \"$@\" >{shlex.quote(str(args_path))}\n"
|
||||
f"wc -c | tr -d ' ' >{shlex.quote(str(bytes_path))}\n"
|
||||
"printf '%s\\n' '{\"status\":\"check_ready\"}'\n",
|
||||
'if [[ -n "${FAKE_CHECK_RECEIPT:-}" ]]; then\n'
|
||||
" printf '%s\\n' \"$FAKE_CHECK_RECEIPT\"\n"
|
||||
"else\n"
|
||||
" printf '%s\\n' "
|
||||
'\'{"schemaVersion":"agent99_remote_atomic_deploy_receipt_v1",'
|
||||
'"status":"check_ready","mode":"check"}\'\n'
|
||||
"fi\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
fake_timeout = fake_bin / "timeout"
|
||||
@@ -647,6 +715,12 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
"bash",
|
||||
str(SENDER),
|
||||
"--check",
|
||||
"--trace-id",
|
||||
"trace-fixture",
|
||||
"--run-id",
|
||||
"run-fixture",
|
||||
"--work-item-id",
|
||||
"AIA-SRE-P0-20260715",
|
||||
"--known-hosts-file",
|
||||
str(known_hosts),
|
||||
"--identity-file",
|
||||
@@ -659,7 +733,11 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
)
|
||||
|
||||
assert result.returncode == 0, result.stderr
|
||||
assert '"status":"check_ready"' in result.stdout
|
||||
receipt = json.loads(result.stdout)
|
||||
assert receipt["status"] == "check_ready"
|
||||
assert receipt["traceId"] == "trace-fixture"
|
||||
assert receipt["runId"] == "run-fixture"
|
||||
assert receipt["workItemId"] == "AIA-SRE-P0-20260715"
|
||||
args = args_path.read_text(encoding="utf-8")
|
||||
remote_command = args.splitlines()[-1]
|
||||
assert "BatchMode=yes" in args
|
||||
@@ -673,6 +751,9 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
assert "agent99-contract-check.ps1" in check_script
|
||||
assert "Get-FileHash" in check_script
|
||||
assert "runtimeContract" in check_script
|
||||
assert "trace-fixture" not in check_script
|
||||
assert "run-fixture" not in check_script
|
||||
assert "AIA-SRE-P0-20260715" not in check_script
|
||||
assert "$ready=[bool]($c.executed-and$c.ok-and$c.exitCode-eq 0)" in check_script
|
||||
assert "'check_failed_no_apply'" in check_script
|
||||
assert "if(-not$ready){exit 65}" in check_script
|
||||
@@ -692,6 +773,30 @@ def test_check_mode_uses_bounded_control_command_without_ssh_stdin(
|
||||
stdin_bytes = int(bytes_path.read_text(encoding="utf-8"))
|
||||
assert stdin_bytes == 0
|
||||
|
||||
conflicting_environment = environment.copy()
|
||||
conflicting_environment["FAKE_CHECK_RECEIPT"] = json.dumps(
|
||||
{
|
||||
"schemaVersion": "agent99_remote_atomic_deploy_receipt_v1",
|
||||
"status": "check_ready",
|
||||
"mode": "check",
|
||||
"traceId": "different-trace",
|
||||
},
|
||||
separators=(",", ":"),
|
||||
)
|
||||
conflicting_result = subprocess.run(
|
||||
result.args,
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env=conflicting_environment,
|
||||
)
|
||||
assert conflicting_result.returncode == 65
|
||||
assert conflicting_result.stdout == ""
|
||||
assert (
|
||||
"agent99_transport_error=check_receipt_identity_projection_failed"
|
||||
in conflicting_result.stderr
|
||||
)
|
||||
|
||||
|
||||
def test_apply_uses_ephemeral_file_transport_and_cleans_up_without_ssh_stdin(
|
||||
tmp_path: Path,
|
||||
|
||||
Reference in New Issue
Block a user