a9403c9c99
lint-infisical-extractor / lint-infisical-extractor (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 6s
ci / lint (pull_request) Successful in 26s
consumer-drift / runtime-ssot-consumers (pull_request) Failing after 26s
ci / build (pull_request) Successful in 44s
ci / smoke-install (pull_request) Successful in 1m2s
ci / unit-tests (pull_request) Failing after 1m31s
ci / responsiveness-e2e (pull_request) Successful in 1m59s
consumer-drift checked runtime-consumer contract drift on a daily cron. Drift is best caught at change time: now runs as a per-PR gate (pull_request) + on push:main + workflow_dispatch. Schedule removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
104 lines
5.6 KiB
YAML
104 lines
5.6 KiB
YAML
name: consumer-drift
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
# Drift is best caught at change time: run as a per-PR gate (and on
|
|
# push:main) instead of a daily cron (no-nightly/no-cron CI policy).
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
runtime-ssot-consumers:
|
|
timeout-minutes: 10
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
|
|
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
|
with:
|
|
python-version: "3.11"
|
|
|
|
# CI bot-token consolidation (RFC: Gitea-Actions-secrets -> Infisical/KMS,
|
|
# mirrors #971 / #3274): source the molecule-runtime-release-bot token from
|
|
# the Infisical SSOT (/shared/runtime-bot, key RUNTIME_BOT_TOKEN) via the CI
|
|
# machine identity, instead of the per-repo Gitea Actions secret
|
|
# DISPATCH_TOKEN. The fetched value is exported to $GITHUB_ENV under
|
|
# GITEA_TOKEN — the exact env var name the two consumer steps below (and
|
|
# check_consumer_runtime_drift.py / check_platform_comm_contract.py) already
|
|
# read — so nothing downstream changes.
|
|
#
|
|
# ABSENT -> SKIP DEGRADE PRESERVED (runtime#83): a missing token is a config
|
|
# gap, not a runtime regression. If the bootstrap INFISICAL_CI_* creds are
|
|
# absent (the genuine config-gap scenario), this step warns and exports
|
|
# nothing, so the downstream `[ -z "${GITEA_TOKEN:-}" ]` checks SKIP the
|
|
# cross-repo work rather than painting runtime main red. But when the creds
|
|
# ARE present, Infisical is AUTHORITATIVE: a broken/empty/404 fetch
|
|
# hard-fails here so a broken migration can never masquerade as a green skip.
|
|
- name: Fetch RUNTIME_BOT_TOKEN from Infisical SSOT
|
|
id: runtime_bot_token
|
|
env:
|
|
INFISICAL_CI_CLIENT_ID: ${{ secrets.INFISICAL_CI_CLIENT_ID }}
|
|
INFISICAL_CI_CLIENT_SECRET: ${{ secrets.INFISICAL_CI_CLIENT_SECRET }}
|
|
INFISICAL_PROJECT_ID: ${{ secrets.INFISICAL_CI_PROJECT_ID }}
|
|
run: |
|
|
set -uo pipefail
|
|
if [ -z "${INFISICAL_CI_CLIENT_ID:-}" ] || [ -z "${INFISICAL_CI_CLIENT_SECRET:-}" ] || [ -z "${INFISICAL_PROJECT_ID:-}" ]; then
|
|
echo "::warning::INFISICAL_CI_* bootstrap creds absent; cannot fetch RUNTIME_BOT_TOKEN. Skipping cross-repo consumer-drift checks (config gap, runtime#83) rather than failing red. Provision INFISICAL_CI_CLIENT_ID/_CLIENT_SECRET/_PROJECT_ID to enable."
|
|
exit 0
|
|
fi
|
|
BASE="https://key.moleculesai.app"
|
|
TOK=$(curl -fsS -X POST "$BASE/api/v1/auth/universal-auth/login" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "{\"clientId\":\"$INFISICAL_CI_CLIENT_ID\",\"clientSecret\":\"$INFISICAL_CI_CLIENT_SECRET\"}" \
|
|
| python3 -c 'import sys,json;d=json.load(sys.stdin);v=d.get("accessToken");print(v if isinstance(v,str) and v else "")')
|
|
if [ -z "${TOK}" ]; then
|
|
echo "::error::Infisical universal-auth login returned no accessToken -- creds present but auth failed; this is a real infra fault, failing loudly instead of skipping." >&2
|
|
exit 1
|
|
fi
|
|
read_secret() {
|
|
curl -fsS "$BASE/api/v3/secrets/raw/$1?workspaceId=$INFISICAL_PROJECT_ID&environment=prod&secretPath=$2" \
|
|
-H "Authorization: Bearer $TOK" \
|
|
| python3 -c 'import sys,json;d=json.load(sys.stdin);v=(d.get("secret") or {}).get("secretValue");print(v if isinstance(v,str) and v else "")'
|
|
}
|
|
RUNTIME_BOT_TOKEN=$(read_secret RUNTIME_BOT_TOKEN %2Fshared%2Fruntime-bot)
|
|
if [ -z "${RUNTIME_BOT_TOKEN}" ]; then
|
|
echo "::error::Infisical returned empty for RUNTIME_BOT_TOKEN at /shared/runtime-bot (prod) -- creds present but authoritative fetch failed; failing loudly so a broken migration cannot masquerade as a green skip." >&2
|
|
exit 1
|
|
fi
|
|
echo "::add-mask::$RUNTIME_BOT_TOKEN"
|
|
# Export under GITEA_TOKEN — the name both consumer steps + scripts expect.
|
|
echo "GITEA_TOKEN=$RUNTIME_BOT_TOKEN" >> "$GITHUB_ENV"
|
|
echo "RUNTIME_BOT_TOKEN loaded from Infisical /shared/runtime-bot (non-empty, len=${#RUNTIME_BOT_TOKEN})"
|
|
|
|
- name: Check consumers do not vendor runtime source
|
|
env:
|
|
GITEA_TOKEN: ${{ env.GITEA_TOKEN }}
|
|
run: |
|
|
# runtime#83: a missing token is a config gap, not a runtime
|
|
# regression. Without the token we cannot clone the private consumer
|
|
# repos, so this cross-repo check is SKIPPED with a loud warning rather
|
|
# than painting runtime main red. When the token is present (now sourced
|
|
# from the Infisical SSOT /shared/runtime-bot by the fetch step above and
|
|
# exported to $GITHUB_ENV as GITEA_TOKEN), run it for real and let real
|
|
# drift fail the job.
|
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
|
echo "::warning::RUNTIME_BOT_TOKEN unavailable (Infisical fetch skipped on absent bootstrap creds); skipping cross-repo consumer drift check. Provision INFISICAL_CI_* to enable it (runtime#83)."
|
|
else
|
|
python scripts/check_consumer_runtime_drift.py
|
|
fi
|
|
|
|
- name: Check platform communication contract
|
|
env:
|
|
GITEA_TOKEN: ${{ env.GITEA_TOKEN }}
|
|
run: |
|
|
if [ -z "${GITEA_TOKEN:-}" ]; then
|
|
echo "::warning::RUNTIME_BOT_TOKEN unavailable (Infisical fetch skipped on absent bootstrap creds); skipping cross-repo communication contract check. Provision INFISICAL_CI_* to enable it (runtime#83)."
|
|
else
|
|
python scripts/check_platform_comm_contract.py
|
|
fi
|