Files
molecule-core/.gitea/workflows/lint-no-coe-on-required.yml
T
hongming-personalandClaude Opus 4.8 b9af25f913
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 9s
CI / Python Lint & Test (pull_request) Successful in 9s
contract-ssot-sync / Verify core's contract mirror matches the molecule-contracts SSOT (pull_request) Successful in 10s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Has been skipped
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 12s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Has been skipped
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 18s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Plugin Install Lifecycle (pull_request) Has been skipped
E2E Workspace Lifecycle (staginge2e) / E2E Workspace Lifecycle (staging) (pull_request) Has been skipped
Handlers Postgres Integration / detect-changes (pull_request) Successful in 13s
E2E Workspace Lifecycle (staginge2e) / E2E Workspace Lifecycle (compile+skip) (pull_request) Successful in 21s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 13s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Failing after 17s
CI / Detect changes (pull_request) Successful in 57s
E2E API Smoke Test / detect-changes (pull_request) Successful in 54s
E2E Chat / detect-changes (pull_request) Successful in 55s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 52s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 21s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 6s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 7s
E2E Legacy Advisory / Legacy local-platform E2E (pull_request) Failing after 1m7s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 7s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 14s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 19s
lint-required-no-paths / lint-required-no-paths (pull_request) Failing after 15s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 15s
mcp-plugin-delivery-contract-drift / Compare MCP plugin delivery contract against template and runtime canonicals (pull_request) Failing after 10s
Railway pin audit (drift detection) / Audit Railway env vars for drift-prone pins (pull_request) Failing after 8s
mcp-verb-published-manifest / Published mcp-server manifest ⊇ contract required verbs (pull_request) Successful in 17s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 22s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 39s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
SECRET_PATTERNS drift lint / Detect SECRET_PATTERNS drift (pull_request) Successful in 15s
sync-providers-yaml / Compare synced providers.yaml against controlplane canonical (pull_request) Failing after 6s
gate-check-v3 / gate-check (pull_request_target) Failing after 7s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Failing after 44s
sop-checklist / review-refire (pull_request_target) Has been skipped
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 39s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (local) (pull_request) Has been skipped
sop-checklist / all-items-acked (pull_request_target) Failing after 7s
PR Diff Guard / PR diff guard (pull_request) Successful in 35s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 3s
CI / Canvas (Next.js) (pull_request) Successful in 3s
CI / Platform (Go) (pull_request) Successful in 3s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 6s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 3s
E2E Chat / E2E Chat (pull_request) Successful in 3s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
CI / Canvas Deploy Status (pull_request) Successful in 1s
template-delivery-e2e / detect-changes (pull_request) Successful in 26s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 2s
CI / all-required (pull_request) Successful in 5s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 48s
reserved-path-review / reserved-path-review (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_target) Review check failed via pull_request_review trigger
security-review / approved (pull_request_target) Review check failed via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_review) Successful in 10s
qa-review / approved (pull_request_review) Failing after 11s
security-review / approved (pull_request_review) Failing after 10s
audit-force-merge / audit (pull_request_target) Successful in 9s
ci-required-drift / drift (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / Prune stale e2e DNS records (pull_request) Waiting to run
ci: remove schedule/cron triggers — per-PR + prod-merge gating only (no nightly CI)
Per the principal's CI-gating discipline: every test/gate runs per-PR and/or as
the prod-merge gate (push:main/staging), never on a schedule. Scheduled runs are
how breakage reaches prod uncaught — nobody blocks on a nightly.

Strips the `schedule:` trigger from 21 non-AWS workflows and reclassifies each:

Already per-PR/push gated (schedule was redundant) — schedule deleted:
  contract-ssot-sync, e2e-chat, e2e-peer-visibility, e2e-staging-canvas,
  e2e-workspace-lifecycle, gate-check-v3, lint-continue-on-error-tracking,
  lint-no-coe-on-required, mcp-plugin-delivery-contract-drift,
  mcp-verb-published-manifest, sync-providers-yaml

Reaper/monitor crons → workflow_dispatch only (rely on in-CP reapers /
fold cleanup into e2e teardown; manual safety net retained):
  main-red-watchdog, sweep-cf-tunnels, sweep-stale-ws-orphans,
  weekly-platform-go, zone-count-drift

Schedule-only gates/lints → injected a real per-PR (and/or prod-merge) trigger:
  ci-required-drift     → pull_request + push:main/staging (paths .gitea/**)
  lint-bp-context-emit-match → pull_request + push (paths .gitea/**)
  railway-pin-audit     → pull_request + push (paths .gitea/**) + dispatch
  secret-pattern-drift  → pull_request (same paths as push) + dispatch
  e2e-legacy-advisory   → push:main/staging (prod-merge gate) + pull_request:main

None of the newly PR-triggered lints are in .gitea/required-contexts.txt, so the
merge queue is not wedged. The AWS-dead scheduled workflows (continuous-synth-e2e,
e2e-staging-*, staging-smoke, sweep-aws-secrets, sweep-cf-orphans,
sweep-stale-e2e-orgs, etc.) are handled by the open AWS-disable PR #3341 — this PR
is the complement; together they leave zero active schedule triggers in the repo.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 06:18:45 -07:00

118 lines
5.4 KiB
YAML

name: lint-no-coe-on-required
# Static workflow-shape lint: forbid `continue-on-error: true` on any job
# that emits a REQUIRED branch-protection status context. Makes SOP#765
# mechanical (the mc#1982 masking incident).
#
# Forbidden shape
# ---------------
# A job in `.gitea/workflows/*.yml` that is BOTH continue-on-error: true
# AND emits a context in `.gitea/required-contexts.txt` (the checked-in
# SSOT of merge-required contexts).
#
# Why this rule exists (mc#1982 / SOP#765)
# ----------------------------------------
# `continue-on-error: true` makes a failed step roll up to a SUCCESS job
# status (Gitea Quirk #10). On a REQUIRED context that silently converts
# a real failure into a green gate — continue-on-error on platform-build
# masked regressions for ~3 weeks before #656 surfaced them. SOP#765
# banned it on required jobs; this lint enforces it at PR time.
#
# Required-context SSOT + drift guard
# -----------------------------------
# `.gitea/required-contexts.txt` is authoritative (CI cannot always read
# branch_protections — cp returns 403). When a repo-admin token is
# present (DRIFT_BOT_TOKEN) the lint ALSO live-reads BP and fails if the
# checked-in allowlist has DRIFTED from live BP. A 403/absent token
# degrades gracefully to allowlist-only (warn, not fail).
#
# Not path-filtered on the required-contexts file because BP can change
# out-of-band; the live cross-check catches that on every run.
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- '.gitea/workflows/**'
- '.gitea/required-contexts.txt'
- '.gitea/scripts/lint_no_coe_on_required.py'
- 'tests/test_lint_no_coe_on_required.py'
push:
branches: [main, staging]
workflow_dispatch:
env:
GITHUB_SERVER_URL: https://git.moleculesai.app
permissions:
contents: read
concurrency:
group: lint-no-coe-on-required-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# bp-exempt: meta-lint guarding the required set; standalone red-status
# lint, not itself a branch-protection required context.
lint:
name: lint-no-coe-on-required
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: '3.12'
- name: Install PyYAML
run: python -m pip install --quiet 'PyYAML==6.0.2'
# KMS consolidation (#971/#3274 pattern): the lint below previously read
# the per-bot Gitea Actions secret `DRIFT_BOT_TOKEN`. We now fetch the
# consolidated DRIFT_BOT_TOKEN from the Infisical SSOT (prod
# /shared/drift-bot) via the CI machine identity and export it to
# $GITHUB_ENV. The lint keeps reading it under the GITEA_TOKEN env var
# name it already expects, so the script is unchanged. The old
# DRIFT_BOT_TOKEN Gitea secret is left in place until a green run
# validates this path (validate-before-delete).
#
# Trust boundary: molecule-core PRs are same-repo (not forks), so the
# INFISICAL_CI_* machine-identity secrets are present on pull_request /
# push — the same assumption the prior direct consumption made.
- name: Fetch DRIFT_BOT_TOKEN from Infisical SSOT
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
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; v=json.load(sys.stdin).get("accessToken"); sys.stdout.write(v if isinstance(v,str) else "")')
if [ -z "$TOK" ]; then echo "::error::Infisical accessToken empty - failing closed"; 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; v=json.load(sys.stdin).get("secret",{}).get("secretValue"); sys.stdout.write(v if isinstance(v,str) else "")'
}
DRIFT_BOT_TOKEN=$(read_secret DRIFT_BOT_TOKEN %2Fshared%2Fdrift-bot)
echo "::add-mask::$DRIFT_BOT_TOKEN"
if [ -z "$DRIFT_BOT_TOKEN" ]; then
echo "::error::Infisical returned empty DRIFT_BOT_TOKEN at prod /shared/drift-bot — failing closed."
exit 1
fi
echo "DRIFT_BOT_TOKEN=$DRIFT_BOT_TOKEN" >> "$GITHUB_ENV"
echo "DRIFT_BOT_TOKEN loaded from Infisical (len=${#DRIFT_BOT_TOKEN})"
- name: Run lint-no-coe-on-required
env:
# KMS consolidation: now arrives via $GITHUB_ENV from the fetch step
# above (was secrets.DRIFT_BOT_TOKEN).
GITEA_TOKEN: ${{ env.DRIFT_BOT_TOKEN }}
GITEA_HOST: git.moleculesai.app
REPO: ${{ github.repository }}
run: python3 .gitea/scripts/lint_no_coe_on_required.py
- name: Run unit tests
run: |
python -m pip install --quiet pytest
python3 -m pytest tests/test_lint_no_coe_on_required.py -q