diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12761f9..cac40bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -887,3 +887,28 @@ jobs: - name: Construct a loopback configuration without a request run: | "$RUNNER_TEMP/model-runtime-venv/bin/python" -I scripts/run_without_sockets.py scripts/smoke_model_runtime.py + + required-ci: + name: Required CI + if: ${{ always() }} + needs: + - test + - quality + - coverage + - shadow-benchmark-evidence + - capture-benchmark-contracts + - connectors + - capture-platform-contract + - build + - artifact-only-atif + - artifact-only-connectors + - installed-core-wheel + - installed-sdist + - installed-model-runtime + runs-on: ubuntu-24.04 + timeout-minutes: 5 + env: + CI_RESULTS: ${{ toJSON(needs) }} + steps: + - name: Require every CI job to succeed + run: jq -e 'all(.[]; .result == "success")' <<< "$CI_RESULTS" diff --git a/tests/test_ci_contract.py b/tests/test_ci_contract.py index 9e7efcc..0fec116 100644 --- a/tests/test_ci_contract.py +++ b/tests/test_ci_contract.py @@ -1948,6 +1948,25 @@ def test_ci_keeps_the_installed_model_runtime_smoke_config_only() -> None: assert "/chat/completions" not in runtime +def test_ci_exposes_one_fail_closed_required_gate() -> None: + text = _read(".github/workflows/ci.yml") + gate = _job_block(text, "required-ci") + + assert text.count("name: Required CI") == 1 + assert "if: ${{ always() }}" in gate + assert "runs-on: ubuntu-24.04" in gate + assert "timeout-minutes: 5" in gate + assert "CI_RESULTS: ${{ toJSON(needs) }}" in gate + assert 'run: jq -e \'all(.[]; .result == "success")\' <<< "$CI_RESULTS"' in gate + + needs = re.search(r"(?ms)^ needs:\n(?P.*?)(?=^ [a-z-]+:)", gate) + assert needs is not None + needed_jobs = re.findall(r"(?m)^ - ([a-z][a-z-]+)$", needs.group("body")) + declared_jobs = re.findall(r"(?m)^ ([a-z0-9][a-z0-9-]*):$", text.partition("jobs:\n")[2]) + assert declared_jobs[-1] == "required-ci" + assert needed_jobs == declared_jobs[:-1] + + def test_ci_installed_jobs_share_only_the_built_distributions() -> None: text = _read(".github/workflows/ci.yml") installed = tuple(