diff --git a/.github/workflows/commercial-readiness-agent-coverage.yml b/.github/workflows/commercial-readiness-agent-coverage.yml index ff362412..680875e7 100644 --- a/.github/workflows/commercial-readiness-agent-coverage.yml +++ b/.github/workflows/commercial-readiness-agent-coverage.yml @@ -20,7 +20,6 @@ on: - ".github/workflows/commercial-readiness-loop.yml" - ".github/workflows/commercial-readiness-agent-coverage.yml" pull_request: - branches: [develop, main] paths: - "scripts/ci/commercial_readiness_loop.py" - "scripts/ci/commercial_readiness_reconcile.py" diff --git a/.github/workflows/controlplane-schema-coverage.yml b/.github/workflows/controlplane-schema-coverage.yml index 9059283f..22d3c15b 100644 --- a/.github/workflows/controlplane-schema-coverage.yml +++ b/.github/workflows/controlplane-schema-coverage.yml @@ -11,7 +11,6 @@ on: - "CHANGELOG.d/871-retention-schema-migration.md" - ".github/workflows/controlplane-schema-coverage.yml" pull_request: - branches: [develop, main] paths: - "appguardrail_core/controlplane_schema.py" - "appguardrail_core/__init__.py" diff --git a/.github/workflows/openssf-evidence-coverage.yml b/.github/workflows/openssf-evidence-coverage.yml index 782d7720..cc0de91c 100644 --- a/.github/workflows/openssf-evidence-coverage.yml +++ b/.github/workflows/openssf-evidence-coverage.yml @@ -2,7 +2,6 @@ name: OpenSSF Evidence Coverage on: pull_request: - branches: [develop, main] push: branches: [develop, main] diff --git a/.github/workflows/pinned-https-coverage.yml b/.github/workflows/pinned-https-coverage.yml index 6149a566..0003cc7f 100644 --- a/.github/workflows/pinned-https-coverage.yml +++ b/.github/workflows/pinned-https-coverage.yml @@ -2,7 +2,6 @@ name: Pinned HTTPS Coverage on: pull_request: - branches: [develop, main] push: branches: [develop, main] diff --git a/.github/workflows/retention-audit-coverage.yml b/.github/workflows/retention-audit-coverage.yml index 3c4d0f71..78619fcf 100644 --- a/.github/workflows/retention-audit-coverage.yml +++ b/.github/workflows/retention-audit-coverage.yml @@ -2,7 +2,6 @@ name: Retention Audit Coverage on: pull_request: - branches: [develop, main] push: branches: [develop, main] diff --git a/.github/workflows/scan-path-context-coverage.yml b/.github/workflows/scan-path-context-coverage.yml index 4cee4b8c..08e63bcd 100644 --- a/.github/workflows/scan-path-context-coverage.yml +++ b/.github/workflows/scan-path-context-coverage.yml @@ -4,7 +4,6 @@ on: push: branches: [develop, main] pull_request: - branches: [develop, main] permissions: contents: read diff --git a/.github/workflows/security-process.yml b/.github/workflows/security-process.yml index 46716c39..95dee869 100644 --- a/.github/workflows/security-process.yml +++ b/.github/workflows/security-process.yml @@ -4,7 +4,6 @@ on: push: branches: [develop, main, master] pull_request: - branches: [develop, main, master] schedule: - cron: "31 4 * * 1" workflow_dispatch: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8ce929df..eaeea17c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -4,7 +4,6 @@ on: push: branches: [develop, main] pull_request: - branches: [develop, main] permissions: contents: read diff --git a/tests/test_docs_only_workflow_filters.py b/tests/test_docs_only_workflow_filters.py new file mode 100644 index 00000000..893bda77 --- /dev/null +++ b/tests/test_docs_only_workflow_filters.py @@ -0,0 +1,61 @@ +"""Contracts preventing CI admission gaps for documentation and stacked pull requests.""" + +from pathlib import Path + +import pytest + + +CONTRACT_SENSITIVE_WORKFLOWS = ( + ".github/workflows/tests.yml", + ".github/workflows/openssf-evidence-coverage.yml", + ".github/workflows/pinned-https-coverage.yml", + ".github/workflows/retention-audit-coverage.yml", + ".github/workflows/scan-path-context-coverage.yml", +) + +STACKED_PR_WORKFLOWS = ( + ".github/workflows/tests.yml", + ".github/workflows/security-process.yml", + ".github/workflows/openssf-evidence-coverage.yml", + ".github/workflows/pinned-https-coverage.yml", + ".github/workflows/retention-audit-coverage.yml", + ".github/workflows/scan-path-context-coverage.yml", + ".github/workflows/controlplane-schema-coverage.yml", + ".github/workflows/commercial-readiness-agent-coverage.yml", +) + + +def _event_block(workflow: str, event: str) -> str: + """Return one peer event block from the workflow's top-level ``on`` mapping.""" + lines = workflow.splitlines() + marker = f" {event}:" + try: + start = lines.index(marker) + except ValueError as exc: + raise AssertionError(f"missing workflow event: {event}") from exc + + block: list[str] = [] + for line in lines[start + 1 :]: + if line.startswith(" ") and not line.startswith(" "): + break + block.append(line) + return "\n".join(block) + + +@pytest.mark.parametrize("workflow_path", CONTRACT_SENSITIVE_WORKFLOWS) +def test_contract_sensitive_workflows_do_not_skip_documentation( + workflow_path: str, +) -> None: + """Docs and policy Markdown remain covered until a dedicated contract lane exists.""" + workflow = Path(workflow_path).read_text(encoding="utf-8") + + for event in ("push", "pull_request"): + assert "paths-ignore:" not in _event_block(workflow, event) + + +@pytest.mark.parametrize("workflow_path", STACKED_PR_WORKFLOWS) +def test_pull_request_checks_admit_stacked_bases(workflow_path: str) -> None: + """PR checks must materialize when a reviewable stack targets another feature branch.""" + workflow = Path(workflow_path).read_text(encoding="utf-8") + + assert "branches:" not in _event_block(workflow, "pull_request")