diff --git a/.github/workflows/codeql-pr.yml b/.github/workflows/codeql-pr.yml index 710a82c45f..cc13d2d87e 100644 --- a/.github/workflows/codeql-pr.yml +++ b/.github/workflows/codeql-pr.yml @@ -237,17 +237,35 @@ jobs: ')" if [[ "$run_id" =~ ^[1-9][0-9]*$ ]]; then jobs_json="$(gh api --paginate --slurp "repos/ContextualWisdomLab/.github/actions/runs/${run_id}/jobs")" - job_conclusion="$(printf '%s' "$jobs_json" | jq -r --arg name "$expected_job" ' + dispatch_job="$(printf '%s' "$jobs_json" | jq -c --arg name "$expected_job" ' [.[] | .jobs[] | select(.name == $name)] - | if length == 1 then .[0].conclusion else empty end + | if length == 1 then .[0] else empty end ')" - case "$job_conclusion" in - success|failure) - echo "verdict=${job_conclusion}" >>"$GITHUB_OUTPUT" - echo "Found completed CodeQL dispatch scan job for ${LANGUAGE}: ${job_conclusion}." - exit 0 - ;; - esac + if [ -n "$dispatch_job" ]; then + gate_conclusion="$(printf '%s' "$dispatch_job" | jq -r ' + (.steps[]? | select(.name == "Enforce CodeQL Medium+ SARIF gate") | .conclusion) // empty + ')" + case "$gate_conclusion" in + success) + echo "verdict=success" >>"$GITHUB_OUTPUT" + echo "Found completed CodeQL dispatch scan gate for ${LANGUAGE}: success." + exit 0 + ;; + failure|cancelled|skipped) + echo "verdict=failure" >>"$GITHUB_OUTPUT" + echo "Found completed CodeQL dispatch scan gate for ${LANGUAGE}: failure." + exit 0 + ;; + esac + job_conclusion="$(printf '%s' "$dispatch_job" | jq -r '.conclusion // empty')" + case "$job_conclusion" in + success) + echo "verdict=success" >>"$GITHUB_OUTPUT" + echo "Found completed CodeQL dispatch scan job for ${LANGUAGE}: success." + exit 0 + ;; + esac + fi fi if [ "$RUN_ATTEMPT" != "1" ]; then diff --git a/tests/test_codeql_pr_workflow_contract.py b/tests/test_codeql_pr_workflow_contract.py index d5a54ccba5..ed632efa48 100644 --- a/tests/test_codeql_pr_workflow_contract.py +++ b/tests/test_codeql_pr_workflow_contract.py @@ -329,6 +329,41 @@ def test_codeql_pr_one_shot_read_accepts_the_opencode_agent_creator(tmp_path: Pa assert "Current-head CodeQL dispatch verdict for python: success." in verdict_result.stdout +def test_codeql_pr_one_shot_read_accepts_clean_gate_when_wake_step_failed_job( + tmp_path: Path, +) -> None: + """A clean SARIF gate must not inherit failure from a wake-only dispatch job (#2141).""" + head_sha = _TEST_HEAD_SHA + title = _dispatch_scan_title(head_sha=head_sha) + dispatch_result, verdict_result = _run_verdict_read( + tmp_path, + statuses=[], + dispatch_runs={"workflow_runs": [_completed_dispatch_run(title=title)]}, + dispatch_jobs={ + "jobs": [ + { + "name": "CodeQL dispatch scan (python)", + "conclusion": "failure", + "steps": [ + { + "name": "Enforce CodeQL Medium+ SARIF gate", + "conclusion": "success", + }, + { + "name": "Wake exact CodeQL required job", + "conclusion": "failure", + }, + ], + } + ] + }, + ) + assert dispatch_result.returncode == 0, dispatch_result.stderr + dispatch_result.stdout + assert verdict_result.returncode == 0, verdict_result.stderr + verdict_result.stdout + assert "completed CodeQL dispatch scan gate for python: success" in dispatch_result.stdout + assert "Current-head CodeQL dispatch verdict for python: success." in verdict_result.stdout + + def test_codeql_pr_one_shot_read_accepts_completed_dispatch_scan_job_when_status_unpublishable( tmp_path: Path, ) -> None: diff --git a/tests/test_organization_commercial_readiness_loop_receipt_contract.py b/tests/test_organization_commercial_readiness_loop_receipt_contract.py index ce0956bba5..6ae9dfa595 100644 --- a/tests/test_organization_commercial_readiness_loop_receipt_contract.py +++ b/tests/test_organization_commercial_readiness_loop_receipt_contract.py @@ -1,3 +1,4 @@ +import re from pathlib import Path from organization_commercial_readiness_fixtures import manual_workflow, workflow @@ -14,6 +15,21 @@ ) +def _harden_runner_allowed_endpoints(source: str) -> set[str]: + """Return the harden-runner allowlist entries without substring URL heuristics.""" + match = re.search( + r"(?m)^(?P[ \t]+)allowed-endpoints:[ \t]*>-[ \t]*\n" + r"(?P(?:(?P=indent) \S[^\n]*(?:\n|$))*)", + source, + ) + assert match is not None, "expected harden-runner allowed-endpoints block" + return { + line.strip() + for line in match.group("endpoints").splitlines() + if line.strip() + } + + def test_product_entrypoint_rejects_missing_model_key_or_manual_trigger() -> None: """Both the NVIDIA model boundary and manual opt-in trigger are mandatory.""" safe = manual_workflow() @@ -40,6 +56,8 @@ def test_json_receipt_is_retained_as_an_immutable_short_lived_artifact() -> None assert "path: ${{ runner.temp }}/organization-commercial-readiness-loop.json" in source assert "if-no-files-found: error" in source assert "retention-days: 3" in source - assert "results-receiver.actions.githubusercontent.com:443" in source - assert "*.actions.githubusercontent.com:443" in source - assert "*.blob.core.windows.net:443" in source + endpoints = _harden_runner_allowed_endpoints(source) + assert "results-receiver.actions.githubusercontent.com:443" in endpoints + assert "*.actions.githubusercontent.com:443" in endpoints + assert "*.blob.core.windows.net:443" in endpoints + assert "- name: Checkout exact trusted coordinator source" not in endpoints