ac55f43d8e
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 7s
CI / Python Lint & Test (pull_request) Successful in 6s
sop-checklist / all-items-acked (pull_request) ack advisory until agent-team — would be failure: acked: 0/10 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +7 — body
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request_target) Successful in 5s
Concierge Creates Workspace Hermetic / Concierge Creates Workspace Hermetic (pull_request) Successful in 18s
ci-required-drift / drift (pull_request) Successful in 18s
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Has been skipped
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Has been skipped
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
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 20s
CI / Detect changes (pull_request) Successful in 23s
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
Harness Replays / detect-changes (pull_request) Successful in 6s
E2E API Smoke Test / detect-changes (pull_request) Successful in 30s
E2E Chat / detect-changes (pull_request) Successful in 31s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 28s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 10s
E2E External Connect-Snippet + Leak-Lint / E2E External Connect-Snippet + Leak-Lint (pull_request) Successful in 34s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 10s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 8s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 8s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 9s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Successful in 21s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 30s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 20s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 22s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 14s
lint-phantom-gate / lint-phantom-gate (pull_request) Successful in 22s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 20s
lint-env-coupling-dismissal / lint-env-coupling-dismissal (pull_request) Successful in 33s
mcp-plugin-delivery-contract-drift / Compare MCP plugin delivery contract against template and runtime canonicals (pull_request) Successful in 12s
Lint schedule budget / Zero-cron ratchet (pull_request) Successful in 21s
lint-staging-tenant-cd-gate-chain / lint-staging-tenant-cd-gate-chain (pull_request) Successful in 21s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 22s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 43s
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-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 44s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 9s
nodup-lint / no-duplication (pull_request) Successful in 13s
mcp-verb-published-manifest / Published mcp-server manifest ⊇ contract required verbs (pull_request) Successful in 17s
PR Diff Guard / PR diff guard (pull_request) Successful in 15s
sync-providers-yaml / Verify SDK registry dependency (pull_request) Successful in 14s
template-delivery-e2e / detect-changes (pull_request) Successful in 21s
verify-providers-gen / Regenerate providers artifact and fail on drift (pull_request) Successful in 16s
gate-check-v3 / gate-check (pull_request_target) Successful in 14s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_target) Approved via pull_request_review trigger
security-review / approved (pull_request_target) Approved via pull_request_review trigger
qa-review / approved (pull_request_review) Successful in 7s
reserved-path-review / reserved-path-review (pull_request_review) Successful in 8s
security-review / approved (pull_request_review) Successful in 8s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 30s
E2E Chat / E2E Chat (pull_request) Successful in 4s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 8s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 5s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 1m1s
gitea-merge-queue / queue (pull_request_review) Successful in 47s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 38s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 54s
Harness Replays / Harness Replays (pull_request) Successful in 1m14s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 1m31s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m27s
CI / Platform (Go) (pull_request) Successful in 3m31s
CI / Canvas (Next.js) (pull_request) Successful in 4m31s
CI / Canvas Deploy Status (pull_request) Successful in 2s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 6m3s
CI / all-required (pull_request) Successful in 5s
sop-checklist / review-refire (pull_request_target) Compensating status: base workflow skipped review-refire; ac55f43 fixes future PRs. Real gates green; no refire requested.
audit-force-merge / audit (pull_request_target) Successful in 6s
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (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) / Prune stale e2e DNS records (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Waiting to run
306 lines
15 KiB
YAML
306 lines
15 KiB
YAML
# sop-checklist — peer-ack merge gate for SOP-checklist items.
|
|
#
|
|
# RFC#351 Step 2 of 6 (implementation MVP).
|
|
#
|
|
# === CONSOLIDATION (issue #1280) ===
|
|
#
|
|
# This workflow is the SINGLE `issue_comment` subscriber — the logic from
|
|
# `review-refire-comments.yml` has been merged in. Before this change:
|
|
# - sop-checklist.yml (pre-2026-05-16) → issue_comment:[created,edited,deleted] → runner slot used, job no-oped
|
|
# - review-refire-comments.yml → issue_comment:[created] → runner slot used, job no-oped
|
|
# → every non-refire comment occupied 2 runner slots for ~800 s each
|
|
# (~650 no-op runs/day, ~1,300 runner-slot-occupancy-hours/day).
|
|
#
|
|
# Fix (PR #1345 / issue #1280):
|
|
# - ONE workflow, ONE issue_comment:[created] subscription (no edited/deleted)
|
|
# - all-items-acked job: pull_request_target OR sop slash-command comments
|
|
# - review-refire job: qa/security refire slash commands
|
|
# → ~50% reduction in comment-triggered runner occupancy vs pre-fix.
|
|
#
|
|
# Trust boundary (mirrors RFC#324 §A4 + sop-checklist security note):
|
|
# `pull_request_target` (not `pull_request`) — workflow def is loaded
|
|
# from BASE branch, so a PR cannot rewrite this workflow to exfiltrate
|
|
# the token. The `actions/checkout` step pins `ref: base.sha` so the
|
|
# script ALSO comes from BASE. PR-HEAD code is never executed in the
|
|
# runner.
|
|
#
|
|
# Token scope:
|
|
# - read:repository, read:organization for PR + comments + team probes
|
|
# - write:repository for POST /statuses/{sha}
|
|
# - The token owner MUST be a member of every team referenced by the
|
|
# config's required_teams (else /teams/{id}/members/{login} returns
|
|
# 403 — see review-check.sh same-gotcha doc). For the MVP we use
|
|
# the dev-lead token (a member of engineers, managers, qa, security)
|
|
# via a repo secret `SOP_CHECKLIST_GATE_TOKEN`. Provisioning of that
|
|
# secret is a follow-up authorization step (separate from this PR).
|
|
#
|
|
# Slash-command contract (RFC#351 v1 + §A1.1-style notes from RFC#324):
|
|
#
|
|
# /sop-ack <slug-or-numeric-alias> [optional note]
|
|
# — register a peer-ack for one checklist item.
|
|
# — slug accepts kebab-case, snake_case, or natural-spaces
|
|
# (all normalized to canonical kebab-case).
|
|
# — numeric 1..7 maps via config.items[*].numeric_alias.
|
|
# — most-recent (user, slug) directive wins.
|
|
#
|
|
# /sop-revoke <slug-or-numeric-alias> [reason]
|
|
# — invalidate the commenter's own prior /sop-ack for this slug.
|
|
# — does NOT affect other peers' acks on the same slug.
|
|
# — most-recent (user, slug) directive wins, so a later /sop-ack
|
|
# re-restores the ack.
|
|
#
|
|
# /sop-n/a <gate> [reason]
|
|
# — declare a gate (qa-review, security-review) N/A.
|
|
# — see sop-checklist-config.yaml n/a_gates section.
|
|
#
|
|
# /qa-recheck /security-recheck
|
|
# — refire the corresponding status check on the PR head.
|
|
#
|
|
# The eval is read-only + idempotent (read PR + comments + team
|
|
# membership, compute, post status). Re-running on any event is safe —
|
|
# the new status overwrites the previous one for the same context.
|
|
|
|
name: sop-checklist
|
|
|
|
# Concurrency: supersede only same-EVENT-TYPE in-progress runs for the same PR.
|
|
#
|
|
# `github.event_name` is part of the group key on purpose. This workflow runs
|
|
# on BOTH `pull_request_target` (posts the BP-required
|
|
# `sop-checklist / all-items-acked (pull_request_target)` context, from the
|
|
# trusted base ref) AND `issue_comment` (posts the non-required
|
|
# `(pull_request)` context on /sop-ack). Gitea auto-suffixes the status
|
|
# context from the trigger event, so the two event types write DIFFERENT
|
|
# contexts.
|
|
#
|
|
# Before this fix the group was keyed by PR number alone with
|
|
# cancel-in-progress: true, so a /sop-ack comment run would CANCEL an
|
|
# in-flight pull_request_target run — leaving the required
|
|
# `(pull_request_target)` context stuck at `failure: Has been cancelled`
|
|
# with no same-event trigger to re-post it (a permanent merge wedge;
|
|
# repro'd on #3392/#3393/docs#91 2026-07-02). Splitting the group by
|
|
# event_name keeps "newest run of the SAME event type wins" (older
|
|
# pull_request_target edits/labels still supersede correctly, older
|
|
# comment runs still supersede) while a comment can no longer strand the
|
|
# trusted required status. The gate eval is idempotent (reads live
|
|
# PR+comments, posts a per-SHA status), so the surviving run always posts
|
|
# the correct verdict.
|
|
concurrency:
|
|
group: ${{ github.repository }}-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.event.issue.number || github.ref }}
|
|
cancel-in-progress: true
|
|
|
|
# bp-required: yes ← emits sop-checklist / all-items-acked (pull_request)
|
|
|
|
on:
|
|
pull_request_target:
|
|
types: [opened, edited, synchronize, reopened, labeled, unlabeled]
|
|
issue_comment:
|
|
types: [created] # NOT [created, edited, deleted] — Gitea 1.22.6 holds a runner slot
|
|
# at job-parsing time, before job-level if: guards run. edited/deleted events
|
|
# occupied ~1,300 runner-slot-hours/day on this workflow alone during the
|
|
# 2026-05-16 freeze. Per PR #1345 fix.
|
|
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
statuses: write
|
|
secrets: read
|
|
|
|
jobs:
|
|
# sop-checklist gate: runs on PR lifecycle events OR sop slash commands.
|
|
# All other comment types (no-op text comments) no longer assign a runner
|
|
# because this job's if: guard short-circuits before runner assignment.
|
|
all-items-acked:
|
|
if: |
|
|
github.event_name == 'pull_request_target' ||
|
|
(github.event_name == 'issue_comment' &&
|
|
github.event.issue.pull_request != null &&
|
|
(contains(github.event.comment.body, '/sop-ack') ||
|
|
contains(github.event.comment.body, '/sop-revoke') ||
|
|
contains(github.event.comment.body, '/sop-n/a')))
|
|
# Completes eb18297b: the gate calls Gitea over the INTERNAL docker-network
|
|
# address (GITEA_API_BASE_URL=http://molecule-gitea-local:3000, set below),
|
|
# which resolves ONLY from a runner on `molecule-net`. `ubuntu-latest` is
|
|
# advertised by the REMOTE robot-1 pool (host-network / off-net), where
|
|
# `molecule-gitea-local` does not resolve — the job died with
|
|
# `socket.gaierror: Temporary failure in name resolution` before it could
|
|
# evaluate (e.g. #3446 head, 2026-07-05). Pin to `ci-meta`, the local
|
|
# molecule-net runner that serves molecule-ai repos (GITHUB_SERVER_URL is
|
|
# http://molecule-gitea-local:3000 there), so the internal host is always
|
|
# reachable and the gate never touches the CF edge (WAF-1010). Verified live:
|
|
# a molecule-core job on `ci-meta` reaches molecule-gitea-local:3000 (HTTP
|
|
# 200). This gate is bp-exempt, so if the runner is briefly offline the
|
|
# status is simply not posted (no merge is blocked).
|
|
runs-on: ci-meta
|
|
steps:
|
|
- name: Check out BASE ref (trust boundary — never PR-head)
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
# For pull_request_target, the default branch is the trust
|
|
# anchor. For issue_comment the PR base may differ from the
|
|
# default branch (PR targeting `staging`), so we use the
|
|
# default-branch ref explicitly — same approach as
|
|
# qa-review.yml so the script source is always trusted.
|
|
ref: ${{ github.event.repository.default_branch }}
|
|
|
|
- name: Run sop-checklist
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.SOP_CHECKLIST_GATE_TOKEN }}
|
|
PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }}
|
|
OWNER: ${{ github.repository_owner }}
|
|
REPO_NAME: ${{ github.event.repository.name }}
|
|
# OPERATOR RELAX (standing directive, until the agent team exists):
|
|
# peer-ack ENFORCEMENT is gated on the org Actions variable
|
|
# MERGE_REQUIRE_SOP_ACK (currently 'false'). Anything but 'true' =>
|
|
# the gate still runs the FULL ack evaluation but POSTs success with
|
|
# the 'ack advisory until agent-team' description prefix (see
|
|
# apply_ack_enforcement_policy in sop-checklist.py — unit-tested).
|
|
# Set the org var to 'true' to restore enforcement, no code change.
|
|
MERGE_REQUIRE_SOP_ACK: ${{ vars.MERGE_REQUIRE_SOP_ACK }}
|
|
# CF-1010 fix: call Gitea over the INTERNAL docker-network address, not
|
|
# the public CF edge. The gate script uses urllib, whose `Python-urllib/*`
|
|
# User-Agent Cloudflare bans with WAF error 1010 (browser_signature_banned);
|
|
# that killed the gate before it could evaluate whenever the job landed on
|
|
# a molecule-net (local) runner — a non-deterministic org-wide RED that was
|
|
# being worked around by routing jobs to the remote robot-1 pool + repo-admin
|
|
# elevation. This is the internal service address the runners already use for
|
|
# checkout/control (GITHUB_SERVER_URL). The status link stays on the public
|
|
# host via --public-host. Auth is unchanged (same Gitea, same token).
|
|
GITEA_API_BASE_URL: http://molecule-gitea-local:3000
|
|
GITEA_PUBLIC_HOST: git.moleculesai.app
|
|
run: |
|
|
set -euo pipefail
|
|
python3 .gitea/scripts/sop-checklist.py \
|
|
--owner "$OWNER" \
|
|
--repo "$REPO_NAME" \
|
|
--pr "$PR_NUMBER" \
|
|
--config .gitea/sop-checklist-config.yaml \
|
|
--gitea-host "$GITEA_API_BASE_URL" \
|
|
--public-host "$GITEA_PUBLIC_HOST"
|
|
|
|
# bp-exempt: informational refire handler, not a merge gate. Emits
|
|
# qa-review/security-review status updates on /qa-recheck et al slash commands.
|
|
#
|
|
# Keep this job free of a job-level `if:`. `main` currently uses wildcard
|
|
# branch protection (`status_check_contexts: ["*"]`), so a skipped job still
|
|
# publishes a blocking commit status. Running the job and letting the steps
|
|
# no-op on pull_request_target gives that lifecycle context a real success
|
|
# while slash-command refires remain guarded below.
|
|
review-refire:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Classify comment
|
|
id: classify
|
|
env:
|
|
COMMENT_BODY: ${{ github.event.comment.body }}
|
|
run: |
|
|
set -euo pipefail
|
|
{
|
|
echo "run_qa=false"
|
|
echo "run_security=false"
|
|
} >> "$GITHUB_OUTPUT"
|
|
first_line=$(printf '%s\n' "$COMMENT_BODY" | sed -n '1p')
|
|
case "$first_line" in
|
|
/qa-recheck*)
|
|
echo "run_qa=true" >> "$GITHUB_OUTPUT"
|
|
;;
|
|
/security-recheck*)
|
|
echo "run_security=true" >> "$GITHUB_OUTPUT"
|
|
;;
|
|
*)
|
|
echo "::notice::no supported review refire slash command; no-op"
|
|
;;
|
|
esac
|
|
|
|
- name: Check out BASE ref for trusted scripts
|
|
if: |
|
|
steps.classify.outputs.run_qa == 'true' ||
|
|
steps.classify.outputs.run_security == 'true'
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: ${{ github.event.repository.default_branch }}
|
|
|
|
# KMS consolidation (#971/#3274 pattern): the two refire steps below
|
|
# previously read the per-bot Gitea Actions secret `STATUS_POST_TOKEN`
|
|
# for their explicit POST /statuses. We now fetch the consolidated
|
|
# CI_STATUS_TOKEN from the Infisical SSOT (prod /shared/ci-status) via
|
|
# the CI machine identity and export it to $GITHUB_ENV. Each refire step
|
|
# keeps reading it under the STATUS_POST_TOKEN env var name the
|
|
# review-refire-status.sh script already expects, so the script is
|
|
# unchanged. The old STATUS_POST_TOKEN Gitea secret is left in place
|
|
# until a green run validates this path (validate-before-delete).
|
|
#
|
|
# Trust boundary: this job runs on issue_comment with a BASE-ref checkout
|
|
# (trusted base context), so the INFISICAL_CI_* machine-identity secrets
|
|
# are available (same boundary that already gated STATUS_POST_TOKEN).
|
|
- name: Fetch CI_STATUS_TOKEN from Infisical SSOT
|
|
if: |
|
|
steps.classify.outputs.run_qa == 'true' ||
|
|
steps.classify.outputs.run_security == 'true'
|
|
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 "")'
|
|
}
|
|
CI_STATUS_TOKEN=$(read_secret CI_STATUS_TOKEN %2Fshared%2Fci-status)
|
|
echo "::add-mask::$CI_STATUS_TOKEN"
|
|
if [ -z "$CI_STATUS_TOKEN" ]; then
|
|
echo "::error::Infisical returned empty CI_STATUS_TOKEN at prod /shared/ci-status — failing closed."
|
|
exit 1
|
|
fi
|
|
echo "CI_STATUS_TOKEN=$CI_STATUS_TOKEN" >> "$GITHUB_ENV"
|
|
echo "CI_STATUS_TOKEN loaded from Infisical (len=${#CI_STATUS_TOKEN})"
|
|
|
|
- name: Refire qa-review status
|
|
if: steps.classify.outputs.run_qa == 'true'
|
|
env:
|
|
# Evaluator (review-check.sh + GET /pulls) stays on read-scoped token.
|
|
GITEA_TOKEN: ${{ secrets.SOP_CHECKLIST_GATE_TOKEN }}
|
|
# Explicit POST /statuses uses narrow-scoped write:repository token,
|
|
# now sourced from Infisical SSOT via $GITHUB_ENV (was
|
|
# secrets.STATUS_POST_TOKEN) — same env var name for the script.
|
|
STATUS_POST_TOKEN: ${{ env.CI_STATUS_TOKEN }}
|
|
GITEA_HOST: git.moleculesai.app
|
|
REPO: ${{ github.repository }}
|
|
PR_NUMBER: ${{ github.event.issue.number }}
|
|
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
TEAM: qa
|
|
TEAM_ID: '20'
|
|
REVIEW_CHECK_DEBUG: '0'
|
|
REVIEW_CHECK_STRICT: '0'
|
|
run: |
|
|
set -euo pipefail
|
|
.gitea/scripts/review-refire-status.sh
|
|
|
|
- name: Refire security-review status
|
|
if: steps.classify.outputs.run_security == 'true'
|
|
env:
|
|
# Evaluator (review-check.sh + GET /pulls) stays on read-scoped token.
|
|
GITEA_TOKEN: ${{ secrets.SOP_CHECKLIST_GATE_TOKEN }}
|
|
# Explicit POST /statuses uses narrow-scoped write:repository token,
|
|
# now sourced from Infisical SSOT via $GITHUB_ENV (was
|
|
# secrets.STATUS_POST_TOKEN) — same env var name for the script.
|
|
STATUS_POST_TOKEN: ${{ env.CI_STATUS_TOKEN }}
|
|
GITEA_HOST: git.moleculesai.app
|
|
REPO: ${{ github.repository }}
|
|
PR_NUMBER: ${{ github.event.issue.number }}
|
|
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
|
|
TEAM: security
|
|
TEAM_ID: '21'
|
|
REVIEW_CHECK_DEBUG: '0'
|
|
REVIEW_CHECK_STRICT: '0'
|
|
run: |
|
|
set -euo pipefail
|
|
.gitea/scripts/review-refire-status.sh
|