44688ebabc
sop-checklist / all-items-acked (pull_request) acked: 0/9 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +6 — body-unfilled: comprehensive-testing, local-postgres-e2
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request_target) Successful in 4s
Block integration-tester contamination artifacts / Block staging-trigger / invalid manifest contamination (pull_request) Successful in 8s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 9s
CI / Python Lint & Test (pull_request) Successful in 7s
E2E Peer Visibility (literal MCP list_peers) / detect-changes (pull_request) Successful in 7s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 8s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 8s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 9s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 7s
Lint forbidden hand-written mcp__ tool-id literals / Scan for hand-written mcp__ tool-id literals (pull_request) Successful in 6s
E2E Workspace Lifecycle (staginge2e) / E2E Workspace Lifecycle (compile+skip) (pull_request) Successful in 20s
lint-bp-context-emit-match / lint-bp-context-emit-match (pull_request) Successful in 20s
lint-required-workflows-docker-host-pinned / Lint docker-host pin on docker-touching workflows (pull_request) Successful in 9s
Lint publish-runner timeout-minutes / Lint publish-runner timeout-minutes (pull_request) Successful in 18s
lint-no-coe-on-required / lint-no-coe-on-required (pull_request) Successful in 19s
lint-continue-on-error-tracking / lint-continue-on-error-tracking (pull_request) Successful in 30s
E2E API Smoke Test / detect-changes (pull_request) Successful in 39s
CI / Detect changes (pull_request) Successful in 39s
E2E Chat / detect-changes (pull_request) Successful in 37s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 37s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 20s
Lint schedule budget / Zero-cron ratchet (pull_request) Successful in 18s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 8s
lint-setup-go-cache / lint-setup-go-cache (pull_request) Successful in 14s
lint-staging-tenant-cd-gate-chain / lint-staging-tenant-cd-gate-chain (pull_request) Successful in 16s
gate-check-v3 / gate-check (pull_request_target) Successful in 11s
sop-checklist / review-refire (pull_request_target) Has been skipped
template-delivery-e2e / detect-changes (pull_request) Successful in 23s
PR Diff Guard / PR diff guard (pull_request) Successful in 24s
Lint workflow YAML (Gitea-1.22.6-hostile shapes) / Lint workflow YAML for Gitea-1.22.6-hostile shapes (pull_request) Successful in 27s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
CI / Platform (Go) (pull_request) Successful in 3s
Lint pre-flip continue-on-error / Verify continue-on-error flips have run-log proof (pull_request) Successful in 48s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 3s
CI / Canvas (Next.js) (pull_request) Successful in 3s
E2E Peer Visibility (literal MCP list_peers) / E2E Peer Visibility (pull_request) Successful in 5s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 4s
CI / Canvas Deploy Status (pull_request) Successful in 2s
E2E Chat / E2E Chat (pull_request) Successful in 4s
lint-required-context-exists-in-bp / lint-required-context-exists-in-bp (pull_request) Successful in 49s
template-delivery-e2e / Template-asset delivery (fresh seo-agent — config+prompts via asset channel, seo-all via plugin reconcile) (pull_request) Successful in 2s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 33s
CI / all-required (pull_request) Successful in 4s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 32s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Successful in 32s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
gitea-merge-queue / queue (pull_request_review) Successful in 7s
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
audit-force-merge / audit (pull_request_target) Successful in 13s
ci-required-drift / drift (pull_request) Waiting to run
Main-HEAD status coherence, three root fixes (no fake-green, no hacks): 1. e2e-workspace-lifecycle: the real staging job lived behind 'if: workflow_dispatch || schedule' inside a push/PR-triggered workflow, so Gitea auto-published a permanent SKIPPED commit status for it on every main push and every PR head. SPLIT: the job moves verbatim into the new dispatch-only e2e-workspace-lifecycle-staging.yml (no push/PR trigger -> no status at all on push; a real dispatch posts the REAL verdict). The per-PR compile+LOUD-skip gate stays where it was, unchanged. Zero-cron ratchet honored (no schedule; operator-config cron-bot dispatch is the cadence path, same as status-reaper). 2. staging-tenant-cd rollback-pin: the 'if: failure() && advance-pin success' job guard likewise posted SKIPPED on every green main push. The job is now 'if: always()' with an explicit in-job branch on the real upstream results: green roll -> loud no-op success; gate red / pin never advanced -> loud no-op success; roll FAILED after a pin advance -> the same revert as before (exact parity, incl. the cancelled-roll no-revert and empty-old_image cases). Gate chain untouched: lint_staging_tenant_cd_gate_chain passes (edges + no-coe). 3. sop-checklist OPERATOR RELAX (standing directive until the agent team exists): ack enforcement now keys on the org Actions variable MERGE_REQUIRE_SOP_ACK (already set org-wide, 'false'). Anything but 'true' => the gate still runs the FULL ack evaluation (nothing is short-circuited) but POSTs success with the exact description prefix 'ack advisory until agent-team' + the real would-be verdict, so the context reports without blocking. 'true' restores enforcement with no code change. Implemented as the pure, unit-tested apply_ack_enforcement_policy() (new TestApplyAckEnforcementPolicy in test_sop_checklist.py, runs in the test-ops-scripts pytest lane); also clears the stale-red 'sop-checklist / all-items-acked (pull_request)' sibling on PR heads on the next evaluation. Verified locally: yaml.safe_load OK on all 4 touched workflows; lint_staging_tenant_cd_gate_chain.py OK; py_compile OK on both python files; policy function truth-table exercised. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
103 lines
5.3 KiB
YAML
103 lines
5.3 KiB
YAML
name: E2E Workspace Lifecycle (staginge2e)
|
|
|
|
# core#2332 P1.10 — close the workspace-lifecycle coverage gap.
|
|
#
|
|
# soft-restart / pause / resume / hibernate were only unit-tested (httptest in
|
|
# workspace-server/internal/handlers/*_test.go) and never proven against a real
|
|
# container. This drives the Go staginge2e suite
|
|
# (workspace-server/internal/staginge2e/workspace_lifecycle_test.go) which
|
|
# provisions a REAL throwaway staging tenant, exercises each lifecycle endpoint,
|
|
# and asserts OBSERVABLE container state (status transitions + serve reachability
|
|
# + url-cleared-on-stop) — not just HTTP 200.
|
|
#
|
|
# ADVISORY-BY-INFRA. It needs a live staging tenant (a cold molecules-server / local-docker
|
|
# provision, was the ~30+ min cold EC2 path), so the real run is workflow_dispatch
|
|
# only — NOT per-PR and NOT a
|
|
# required check. Promotion to a required branch-protection context is a separate
|
|
# CTO decision (mirrors the cp internal/staginge2e suite, cp#386, and the
|
|
# peer-visibility flip-to-required pattern, molecule-core#1296).
|
|
#
|
|
# SPLIT (main-status coherence): the real staging job now lives in its own
|
|
# dispatch-only workflow, e2e-workspace-lifecycle-staging.yml. When it was a
|
|
# job HERE behind `if: workflow_dispatch || schedule`, every push/PR run of
|
|
# this workflow auto-published a `skipped` commit status for it
|
|
# (`E2E Workspace Lifecycle (staginge2e) / E2E Workspace Lifecycle (staging)
|
|
# (push)`) on every main HEAD — permanent skip-noise on the default branch's
|
|
# status surface. A dispatch-only workflow posts NO status on push/PR at all,
|
|
# and posts its REAL verdict when actually dispatched. Same trust model, same
|
|
# suite, zero behavior change for the compile gate below.
|
|
#
|
|
# HONEST GATE — NO continue-on-error mask (feedback_fix_root_not_symptom). The
|
|
# PR job validates that the suite COMPILES under -tags=staging_e2e and SKIPs LOUD
|
|
# without creds (the suite's contract) — a broken test file fails at PR time. The
|
|
# real assertion runs on dispatch/cron with staging creds.
|
|
#
|
|
# Gitea 1.22.6 / act_runner notes honored: no cross-repo uses (mirrored
|
|
# actions/checkout SHA), per-SHA concurrency, pinned GITHUB_SERVER_URL.
|
|
|
|
on:
|
|
# group A: staging added alongside main so the compile+skip PR gate runs on both protected
|
|
# branches. The real lifecycle-staging job (e2e-workspace-lifecycle-staging.yml) provisions on
|
|
# molecules-server (local-docker) via E2E_PROVIDER and stays dispatch-only — a 30-60 min cold
|
|
# provision is not a per-PR cost (the cheap per-PR coverage is the compile+skip gate here +
|
|
# local-provision-e2e).
|
|
push:
|
|
branches: [main, staging]
|
|
paths:
|
|
- 'workspace-server/internal/handlers/workspace_restart.go'
|
|
- 'workspace-server/internal/handlers/workspace_crud.go'
|
|
- 'workspace-server/internal/staginge2e/**'
|
|
- '.gitea/workflows/e2e-workspace-lifecycle.yml'
|
|
pull_request:
|
|
branches: [main, staging]
|
|
paths:
|
|
- 'workspace-server/internal/handlers/workspace_restart.go'
|
|
- 'workspace-server/internal/handlers/workspace_crud.go'
|
|
- 'workspace-server/internal/staginge2e/**'
|
|
- '.gitea/workflows/e2e-workspace-lifecycle.yml'
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
# Per-SHA (feedback_concurrency_group_per_sha).
|
|
group: e2e-workspace-lifecycle-${{ github.event.pull_request.head.sha || github.sha }}
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
GITHUB_SERVER_URL: https://git.moleculesai.app
|
|
|
|
jobs:
|
|
# PR / compile gate: prove the staginge2e suite compiles under the build tag
|
|
# and skips LOUD without creds. Cheap, honest, non-required. This is NOT a
|
|
# fake-green mask of the real assertion — it fails if the test file stops
|
|
# compiling. bp-required: pending CTO decision (see header).
|
|
lifecycle-compile-skip:
|
|
name: E2E Workspace Lifecycle (compile+skip)
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 10
|
|
steps:
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
|
|
with:
|
|
go-version: 'stable'
|
|
# cache:false — the self-hosted runner bind-mounts a persistent
|
|
# GOCACHE/GOMODCACHE (/var/cache/ci-go-{build,mod}); actions/cache is
|
|
# redundant and corrupts it by untarring over the bind mount ("File
|
|
# exists" -> "Failed to restore" -> partial cache -> linker/typecheck
|
|
# errors on heavy jobs, e.g. test -race link "too many errors" and
|
|
# go-arch-lint "without types"). Fleet sweep after the cp ci.yml find.
|
|
cache: false
|
|
cache-dependency-path: workspace-server/go.sum
|
|
- name: go vet (staging_e2e tag)
|
|
working-directory: workspace-server
|
|
run: go vet -tags staging_e2e ./internal/staginge2e/...
|
|
- name: Compile + skip-run (must SKIP LOUD without STAGING_E2E)
|
|
working-directory: workspace-server
|
|
run: |
|
|
# No STAGING_E2E / creds → the suite MUST skip (not pass-with-zero-
|
|
# assertions, not fail-open). `go test` exit 0 with a SKIP line is the
|
|
# contract. -run pins to the one test so this stays fast.
|
|
out=$(go test -tags staging_e2e ./internal/staginge2e/ -run TestWorkspaceLifecycle -count=1 -v 2>&1)
|
|
echo "$out"
|
|
echo "$out" | grep -q "SKIP: TestWorkspaceLifecycle_Staging" \
|
|
|| { echo "::error::expected a LOUD skip of TestWorkspaceLifecycle_Staging without creds"; exit 1; }
|