Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions .github/codeql-notes.md
Original file line number Diff line number Diff line change
@@ -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).
76 changes: 76 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -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@v7
with:
fetch-depth: 2

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: javascript-typescript
build-mode: none

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
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@v7
with:
fetch-depth: 2

- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: actions
build-mode: none

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: /language:actions
17 changes: 17 additions & 0 deletions .github/workflows/tegami-pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ on:
- opened
- reopened
- synchronize
push:
branches:
- master
merge_group:
types: [checks_requested]
branches:
- master

permissions:
contents: read
Expand All @@ -18,30 +25,40 @@ 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.6.0
with:
nub-version: 0.9.6
node-version-file: .nvmrc
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
Expand Down
11 changes: 9 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ on:
push:
branches:
- master
merge_group:
types: [checks_requested]
branches:
- master
workflow_call:
inputs:
checkout_ref:
Expand Down Expand Up @@ -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
# Allowlist accepts nubjs/setup-nub@v0* and the v0.4.0 SHA, not the v0.6.0 commit.
Expand Down Expand Up @@ -83,6 +88,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
Expand All @@ -97,7 +103,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 }}
# Allowlist accepts nubjs/setup-nub@v0* and the v0.4.0 SHA, not the v0.6.0 commit.
- uses: nubjs/setup-nub@v0.6.0
with:
Expand Down
7 changes: 4 additions & 3 deletions docs/e2e.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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-<run>-<attempt>` 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.

Expand Down
28 changes: 28 additions & 0 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,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

The release job mints a GitHub App installation token with `actions/create-github-app-token`. The
Expand Down
Loading