diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 959d5cf..9afeef6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -160,6 +160,17 @@ jobs: shell: bash run: ${{ inputs.source-audit-command }} + - name: Reject an empty test-command + shell: bash + env: + TEST_COMMAND: ${{ inputs.test-command }} + run: | + set -euo pipefail + if [[ -z "${TEST_COMMAND// /}" ]]; then + echo "::error::test-command must not be empty or blank -- an empty run: step succeeds having tested nothing (FR-017: a gate must fail visibly, never pass silently)" + exit 1 + fi + - name: Run repository tests shell: bash run: ${{ inputs.test-command }} diff --git a/tests/workflows/reusable-workflow-contract.bats b/tests/workflows/reusable-workflow-contract.bats index 0261de2..76532fe 100755 --- a/tests/workflows/reusable-workflow-contract.bats +++ b/tests/workflows/reusable-workflow-contract.bats @@ -24,6 +24,8 @@ done # --- ci.yml: coverage gates, Sonar fail-closed, digest output, OIDC --------- have "$ci" "workflow_call" "ci.yml must be a reusable workflow" have "$ci" "test-command:" "ci.yml must take a required test-command gate" +have "$ci" "test-command must not be empty or blank" \ + "ci.yml must fail visibly on an empty test-command, never pass having tested nothing (FR-017, gitops spec 003 T024)" have "$ci" "contract-command:" "ci.yml must take a contract-command gate" have "$ci" "sonar-required:" "ci.yml must expose the Sonar fail-closed toggle (T102)" have "$ci" "the SonarQube quality gate is required but not configured" \