From 9222d1849d676b23b6b4cef982e2082b59a9c471 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 12 Oct 2026 20:14:18 +0000 Subject: [PATCH] ci: report required checks on push, pull request, and merge queue Add merge_group triggers for the checks that gate pull requests, and move CodeQL to a workflow that keeps the existing Analyze check names. Release preview reports success outside pull requests. release.yml stays unchanged. Co-authored-by: Jonathan Beckman --- .github/codeql-notes.md | 31 ++++++++-- .github/workflows/codeql.yml | 76 +++++++++++++++++++++++++ .github/workflows/tegami-pr-preview.yml | 17 ++++++ .github/workflows/validate.yml | 11 +++- docs/e2e.md | 7 ++- docs/releasing.md | 28 +++++++++ 6 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/codeql-notes.md b/.github/codeql-notes.md index 4e203214..efa24c79 100644 --- a/.github/codeql-notes.md +++ b/.github/codeql-notes.md @@ -1,9 +1,32 @@ -# CodeQL notes +# CodeQL -Default GitHub CodeQL setup (`dynamic/github-code-scanning/codeql`) runs on master pushes. +Code scanning uses advanced setup in `.github/workflows/codeql.yml`. -On 2026-09-13 after #40 (`cc772d5`), Analyze (javascript-typescript) failed once with improved incremental analysis / possible disk space. GitHub records that failure in the Actions cache so the next analysis skips improved incremental. Analyze (actions) failed during SARIF upload on the same run with no open code-scanning alerts. +The workflow runs on: -`gh run rerun` for that run returned HTTP 500; default CodeQL has no `workflow_dispatch`. This no-op notes file exists to re-trigger a clean master CodeQL pass. +- `push` to `master` +- `pull_request` to `master` +- `merge_group` with type `checks_requested`, for base branch `master` +- a weekly schedule, `32 8 * * 1` + +Check contexts: + +- `Analyze (javascript-typescript)`, job `analyze-javascript-typescript` +- `Analyze (actions)`, job `analyze-actions` +- `CodeQL`, posted by the code scanning app when the analysis upload finishes + +The job names are fixed strings. They match the previous default-setup contexts. They do not come from a matrix value. + +Disable default setup (`dynamic/github-code-scanning/codeql`) before this workflow uploads results. Default setup has no `merge_group` trigger. GitHub rejects advanced setup uploads while default setup is enabled. + +```sh +gh api -X PATCH /repos/SolZeroAI/platform/code-scanning/default-setup -f state=not-configured +``` + +## Earlier default-setup failure + +Default setup ran on master pushes before this workflow. On 2026-09-13 after #40 (`cc772d5`), Analyze (javascript-typescript) failed once with improved incremental analysis / possible disk space. GitHub records that failure in the Actions cache so the next analysis skips improved incremental. Analyze (actions) failed during SARIF upload on the same run with no open code-scanning alerts. + +`gh run rerun` for that run returned HTTP 500; default setup has no `workflow_dispatch`. This notes file was used to re-trigger a clean master CodeQL pass. Second re-trigger 2026-09-13T09:56Z: prior master Push run 34748722747 cannot be rerun (SARIF upload Server Error on Analyze actions). diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..b024c0bd --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,76 @@ +# Advanced CodeQL setup. Job names are the required check contexts. +# Keep the name values literal so they stay Analyze (javascript-typescript) +# and Analyze (actions). Disable code scanning default setup when this file +# is on master. Default setup has no merge_group trigger, and it rejects +# advanced setup uploads while it remains enabled. +name: CodeQL + +on: + push: + branches: + - master + pull_request: + branches: + - master + merge_group: + types: [checks_requested] + branches: + - master + schedule: + - cron: "32 8 * * 1" + +permissions: + contents: read + +jobs: + analyze-javascript-typescript: + name: Analyze (javascript-typescript) + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + actions: read + contents: read + packages: read + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + languages: javascript-typescript + build-mode: none + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + category: /language:javascript-typescript + + analyze-actions: + name: Analyze (actions) + runs-on: ubuntu-latest + timeout-minutes: 30 + permissions: + actions: read + contents: read + packages: read + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 2 + + - name: Initialize CodeQL + uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + languages: actions + build-mode: none + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 + with: + category: /language:actions diff --git a/.github/workflows/tegami-pr-preview.yml b/.github/workflows/tegami-pr-preview.yml index 3db18cfd..1848c75b 100644 --- a/.github/workflows/tegami-pr-preview.yml +++ b/.github/workflows/tegami-pr-preview.yml @@ -8,6 +8,13 @@ on: - opened - reopened - synchronize + push: + branches: + - master + merge_group: + types: [checks_requested] + branches: + - master permissions: contents: read @@ -18,12 +25,18 @@ jobs: runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 10 steps: + - name: Report the required check outside pull requests + if: github.event_name != 'pull_request' + run: echo "Release preview is built for pull requests. This event reports the required check as success." + - name: Check out pull request + if: github.event_name == 'pull_request' uses: actions/checkout@v7 with: fetch-depth: 0 - name: Set up Nub + if: github.event_name == 'pull_request' uses: nubjs/setup-nub@v0.4.0 with: nub-version: 0.4.11 @@ -31,17 +44,21 @@ jobs: cache-dependency-path: nub.lock - name: Install native dependencies + if: github.event_name == 'pull_request' run: | sudo apt-get update sudo apt-get install --yes --no-install-recommends pkg-config liblzma-dev - name: Install dependencies + if: github.event_name == 'pull_request' run: nub install --frozen-lockfile - name: Build release preview + if: github.event_name == 'pull_request' run: nub run tegami pr preview --artifact tegami-pr-preview.md - name: Upload release preview + if: github.event_name == 'pull_request' uses: actions/upload-artifact@v7 with: name: tegami-pr-preview diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 54400c43..4ae56086 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -7,6 +7,10 @@ on: push: branches: - master + merge_group: + types: [checks_requested] + branches: + - master workflow_call: inputs: checkout_ref: @@ -35,7 +39,8 @@ jobs: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - ref: ${{ inputs.checkout_ref || github.event.pull_request.head.sha || github.ref }} + # Pull requests use the head SHA. Push, merge_group, and dispatch use github.sha. + ref: ${{ inputs.checkout_ref || github.event.pull_request.head.sha || github.sha }} - name: Set up Nub uses: nubjs/setup-nub@47e5e7393d50f4e9544ddaf756aa277972afba2d # v0.4.0 @@ -82,6 +87,7 @@ jobs: concurrency: group: solzero-e2e-cloudflare-${{ github.repository }} cancel-in-progress: false + # Fork pull requests skip this job. merge_group has no pull request payload and still runs. if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 45 @@ -96,7 +102,8 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: - ref: ${{ inputs.checkout_ref || github.event.pull_request.head.sha || github.ref }} + # Pull requests use the head SHA. Push, merge_group, and dispatch use github.sha. + ref: ${{ inputs.checkout_ref || github.event.pull_request.head.sha || github.sha }} - uses: nubjs/setup-nub@47e5e7393d50f4e9544ddaf756aa277972afba2d # v0.4.0 with: nub-version: 0.4.11 diff --git a/docs/e2e.md b/docs/e2e.md index 3699fcf4..276f7165 100644 --- a/docs/e2e.md +++ b/docs/e2e.md @@ -297,8 +297,9 @@ are deleted in cleanup; all mutations are limited to the isolated profile. ## CI and artifacts `Validate` runs static checks and discovers all e2e tests without secrets. Its dedicated -Cloudflare end-to-end job runs `nub run test` on trusted pull requests, pushes and manual -runs, including the canonical repository. Fork pull requests cannot access its credentials. +Cloudflare end-to-end job runs `nub run test` on trusted pull requests, pushes to `master`, +merge queue groups, and manual runs, including the canonical repository. A merge group +checks out `github.sha` for that queue commit. Fork pull requests cannot access its credentials. Configure repository secrets `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_TOKEN`, and `CF_AI_GATEWAY_E2E_TOKEN`; the workflow generates and masks a fresh disposable account password. Do not use production identity or integration secrets for tests. @@ -309,7 +310,7 @@ The default `test:e2e` command wraps the SDK and verifies recovery after exit. C Cleanup reconciles a token created before its state record was flushed by exact UUID name, account, permission policy and creation time. It verifies gateway/token HTTP 404 and owned Docker label absence before removing the run directory. The directory removal also clears every run-owned identity, auth session/API key, session/workspace/history, bot/routine, agent/skill/MCP definition, uploaded attachment, secret and runtime preference. Most tests also delete their entities or restore settings in `finally`; storage teardown recovers interrupted requests and APIs without individual delete endpoints. -`nub run test:e2e:lifecycle` exercises real success/failure recovery: launcher SIGTERM; SIGKILL with a real Codex container and missing token state; killed CLI leader with detached runtime descendants; an intentionally failing SDK suite; outer-command SIGTERM and SIGKILL after creating an authenticated session; a failed process inspector; and a genuine filesystem publication failure before Alchemy loads; and an official MCP open/observe/close session with valid JSON-RPC stdout and verified app teardown. It verifies receipts, state removal and idempotent recovery. These lifecycle fixtures are excluded from the ordinary core catalogue. To run them on the normal hosted validation job, dispatch `gh workflow run validate.yml --ref feat/e2e -f e2e_lifecycle=true`. The boolean defaults to false, so ordinary PR and push validation still runs only the core suite; an opt-in dispatch adds lifecycle cases after core. Lifecycle reports use `.e2e/cleanup-proof`; intentional inner failures use separate private report directories. +`nub run test:e2e:lifecycle` exercises real success/failure recovery: launcher SIGTERM; SIGKILL with a real Codex container and missing token state; killed CLI leader with detached runtime descendants; an intentionally failing SDK suite; outer-command SIGTERM and SIGKILL after creating an authenticated session; a failed process inspector; and a genuine filesystem publication failure before Alchemy loads; and an official MCP open/observe/close session with valid JSON-RPC stdout and verified app teardown. It verifies receipts, state removal and idempotent recovery. These lifecycle fixtures are excluded from the ordinary core catalogue. To run them on the normal hosted validation job, dispatch `gh workflow run validate.yml --ref feat/e2e -f e2e_lifecycle=true`. The boolean defaults to false, so ordinary pull request, push, and merge group validation still runs only the core suite; an opt-in dispatch adds lifecycle cases after core. Lifecycle reports use `.e2e/cleanup-proof`; intentional inner failures use separate private report directories. Sanitized CI diagnostics retain `cleanup-summary.json` (counts/types/verified status) for seven days. A separate `solzero-cleanup-ownership--` artifact retains only `cleanup-ownership.json` (repository/run/account hash/profile and exact run-owned resource metadata) for 30 days and uploads even on cancellation. Private state, credentials, logs and journals are never uploaded. Before new allocations, CI examines up to 10,000 repository artifact records and restores pending ownership from completed same-repository Validate attempts, including earlier attempts of the current run. It verifies original producer metadata and byte-equivalent pending rows in immutable dedicated archives. A newer empty or completed inventory does not discard older pending evidence; recovery verifies absence again. Active producers are preserved. Unavailable, conflicting or malformed claimed ownership evidence blocks recovery. Explicit manual recovery can also use a historical diagnostic archive containing the exact ownership file: `CI=1 nub exec tsx scripts/e2e/cleanup.ts /path/to/cleanup-ownership.json`, with the same isolated profile/account and an Actions-read token. Live token IDs are reconciled from exact UUID ownership; supplied IDs do not authorize deletion. Evidence beyond the retention and inventory bounds requires operator review; it is never replaced by a prefix sweep. diff --git a/docs/releasing.md b/docs/releasing.md index d4468361..afe8503d 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -77,6 +77,34 @@ combined version and release-note preview. A change with no observable effect ca Do not edit generated version files in a feature pull request. Review them in the version pull request before merge. +## Required checks + +These check contexts gate pull requests. The workflows also run on a push to `master` and on +`merge_group` with type `checks_requested`. + +| Check context | Workflow | Job | +| --- | --- | --- | +| `Repository validation` | Validate (`.github/workflows/validate.yml`) | `validate` | +| `Cloudflare end-to-end flows` | Validate (`.github/workflows/validate.yml`) | `e2e` | +| `Build release preview` | Tegami PR Preview (`.github/workflows/tegami-pr-preview.yml`) | `preview` | +| `Analyze (javascript-typescript)` | CodeQL (`.github/workflows/codeql.yml`) | `analyze-javascript-typescript` | +| `Analyze (actions)` | CodeQL (`.github/workflows/codeql.yml`) | `analyze-actions` | +| `actionlint` | Validate (`.github/workflows/validate.yml`) | `validate` (reviewdog check from the lint step) | +| `CodeQL` | Code scanning upload from the CodeQL workflow | Not a job. The code scanning app posts this context. | + +`Build release preview` builds the Tegami preview on `pull_request` only. On push and on a merge +group the same job reports success and does not read pull request fields. + +`Analyze (javascript-typescript)` and `Analyze (actions)` are fixed job names. They are the same +contexts as the previous default setup. Disable CodeQL default setup +(`dynamic/github-code-scanning/codeql`) when `.github/workflows/codeql.yml` is on `master`. +Default setup cannot run on `merge_group`, and GitHub rejects an advanced setup upload while +default setup stays enabled. See [`.github/codeql-notes.md`](../.github/codeql-notes.md). + +Release tags stay `vX.Y.Z`. GitHub Actions on SolZeroAI/platform do not promote a release to +production. `Deploy` and `Deploy Preview` stay disabled. Do not add a `prod` environment or a +`release: published` trigger. + ## Repository settings Enable **Allow GitHub Actions to create and approve pull requests** in the repository Actions