From b058ed7333a26cbb6d80cbbee2fbd6c81e9ef3bb Mon Sep 17 00:00:00 2001 From: rogu3bear Date: Thu, 4 Jun 2026 03:28:27 -0500 Subject: [PATCH] ci: skip scheduled live contract when secrets are absent --- .github/workflows/cfctl-contract.yml | 24 ++++++++++++++++++------ scripts/verify_static_contract.sh | 3 ++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cfctl-contract.yml b/.github/workflows/cfctl-contract.yml index 5ac968e..d7acaa2 100644 --- a/.github/workflows/cfctl-contract.yml +++ b/.github/workflows/cfctl-contract.yml @@ -40,7 +40,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Require live credentials + - name: Detect live contract configuration + id: live-config run: | set -euo pipefail shared_env_file="${RUNNER_TEMP}/cfctl-empty.env" @@ -55,24 +56,35 @@ jobs: export CFCTL_PUBLIC_CONTRACT_ZONE echo "CFCTL_PUBLIC_CONTRACT_ZONE=${CFCTL_PUBLIC_CONTRACT_ZONE}" >> "${GITHUB_ENV}" fi + missing=() if [[ -z "${CF_DEV_TOKEN:-}" ]]; then - echo "::error::CF_DEV_TOKEN secret is required for the live Cloudflare contract job." - exit 1 + missing+=("CF_DEV_TOKEN") fi if [[ -z "${CLOUDFLARE_ACCOUNT_ID:-}" ]]; then - echo "::error::CLOUDFLARE_ACCOUNT_ID secret is required for the live Cloudflare contract job." - exit 1 + missing+=("CLOUDFLARE_ACCOUNT_ID") fi if [[ -z "${CFCTL_PUBLIC_CONTRACT_ZONE:-}" ]]; then - echo "::error::CFCTL_PUBLIC_CONTRACT_ZONE variable or secret is required for live DNS/token smoke tests." + missing+=("CFCTL_PUBLIC_CONTRACT_ZONE") + fi + if (( ${#missing[@]} > 0 )); then + missing_list="${missing[*]}" + if [[ "${GITHUB_EVENT_NAME:-}" == "schedule" ]]; then + echo "::notice::Skipping scheduled live Cloudflare contract; missing: ${missing_list}. Configure the cfctl-live environment or run workflow_dispatch after setting secrets." + echo "configured=false" >> "${GITHUB_OUTPUT}" + exit 0 + fi + echo "::error::Live Cloudflare contract requires: ${missing_list}." exit 1 fi + echo "configured=true" >> "${GITHUB_OUTPUT}" - name: Verify permission catalog against live groups + if: steps.live-config.outputs.configured == 'true' run: | set -euo pipefail ./cfctl token permission-groups > "${RUNNER_TEMP}/permission-groups.json" python3 scripts/verify_permission_catalog.py --permission-groups "${RUNNER_TEMP}/permission-groups.json" - name: Verify public contract + if: steps.live-config.outputs.configured == 'true' run: ./scripts/verify_public_contract.sh diff --git a/scripts/verify_static_contract.sh b/scripts/verify_static_contract.sh index 01fbf3a..f70883b 100755 --- a/scripts/verify_static_contract.sh +++ b/scripts/verify_static_contract.sh @@ -593,7 +593,8 @@ assert_contains "docs bank audit logs" "Audit Logs v2" "${ROOT_DIR}/docs/cloudfl assert_contains "public contract live verifier note" "This is a live account smoke test." "${ROOT_DIR}/scripts/verify_public_contract.sh" assert_contains "contract workflow static gate" "python3 scripts/verify_permission_catalog.py --cfctl ./cfctl" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" assert_contains "contract workflow live gate" "./scripts/verify_public_contract.sh" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" -assert_contains "contract workflow secret gate" "CF_DEV_TOKEN secret is required" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" +assert_contains "contract workflow manual secret gate" "Live Cloudflare contract requires:" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" +assert_contains "contract workflow scheduled secret skip" "Skipping scheduled live Cloudflare contract" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" assert_contains "contract workflow protected environment" "environment: cfctl-live" "${ROOT_DIR}/.github/workflows/cfctl-contract.yml" assert_contains "public contract inactive legacy preview cleanup" "previews purge-inactive-legacy" "${ROOT_DIR}/scripts/verify_public_contract.sh" assert_contains "permission doctrine source" "Cloudflare API token permissions are resource-scoped" "${ROOT_DIR}/docs/permission-doctrine.md"