Skip to content

Commit 9ab24e9

Browse files
authored
ci: faster, cheaper, consistently named CI (#8750)
* ci: shard integration and unit tests, run e2e groups in parallel, add a ci gate The PR critical path was the PostgreSQL integration suite (~15 min), run in full on an 8 vCPU runner once per provisioning path. Its files run one at a time, so the runner sat mostly idle. - integration: each provisioning path (push, migrate) is split into 4 Vitest shards on 4 vCPU runners. Both paths keep the full suite: migrations add triggers, checks and NOT VALID constraints that db:push does not, so the schemas differ. - e2e: the four next-dev groups (scim, cli, stop-after, desktop-inbox) run as a matrix, each on its own database. The boot/wait/stop shell lives once in http-e2e.sh. - lint: lint, audits, type-check and schema sync split off from the tests. - test: apps/sim unit tests sharded 2 ways; shard 1 also runs root scripts and the other workspaces. Each shard has its own Turbo cache disk. - ci: one aggregate job that fails unless every check passed (skipped is allowed), so a ruleset can require a single stable check. Deploy gating is unchanged: migrate still requires the whole Test and Build workflow. * ci: short names, one setup action, aligned pins, explicit secrets Naming - Workflow files: test-build -> checks, migrations -> migrate, deploy-trigger-dev -> trigger-dev, docs-embeddings -> docs, companion-pr-check -> companion, stickydisk-gc -> disk-gc. ci.yml, helm.yml and codeql.yml keep their paths: they sign or analyze, and the path is part of the signer identity and code-scanning key. - Composite actions: setup-workspace -> setup, cache-mount -> cache, docker-build -> image. - Every workflow and job display name is a short lowercase id, matching the job id, with any matrix value in parentheses: ci / checks / integration (push, 1/4), image-amd64 (app). Duplicates - Nine hand-written Setup Bun + actions/cache + bun install blocks use the setup action. It gains node-version (empty keeps the runner's Node, as those jobs had) and registry-url (npm publishing). This also ends restoring node_modules from another lockfile through the `${runner.os}-bun-` prefix restore key. - The runner expression is anchored once per file and aliased after. Consistency - One SHA per action: checkout v6 (helm was on v4, codeql on v5), setup-node v6 (desktop on v4), cache v5 (desktop-release on v4), softprops/action-gh-release v3.0.3 (was v1, Node 16). Redis 8.2 everywhere. - secrets: inherit replaced by the secrets each callee reads; the checks workflow reads none. The dev migration gets only DEV_DATABASE_URL, and staging/production never see it. - Timeouts on the three macOS desktop-e2e jobs (none before, so a hang billed 6 hours), and a cache for their Electron, electron-builder and Playwright downloads. - Publish workflows: values moved from ${{ }} in run blocks to env, concurrency on the npm/PyPI publishers, persist-credentials: false on checkouts that never push. - Dependabot for github-actions (one grouped weekly PR), and actionlint in the lint job. Fixes - PyPI version check matched substrings (0.1.1 "existed" once 0.1.10 did) and treated a PyPI outage as "not published". It now asks PyPI for the exact version and fails on anything but 200 or 404. Job wiring (runner, if, needs, permissions, timeout, outputs) is unchanged: verified by loading the old and new ci.yml, checks.yml and helm.yml and comparing every job. * ci: run the ci gate on cancelled runs so a cancelled head never passes * docs(desktop): point the release notes at the renamed workflow and jobs
1 parent b4c38df commit 9ab24e9

30 files changed

Lines changed: 829 additions & 798 deletions

‎.agents/skills/ship/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ When the user runs `/ship`:
4747
- Run `/db-migrate` to review the migration for zero-downtime safety (expand/contract phasing, backward-compatibility with the deployed app version).
4848
- `(cd packages/db && bunx drizzle-kit generate && git status --porcelain ./migrations)` must print nothing (CI's schema/migration sync step).
4949
- `bun run check:migrations origin/staging` must pass (staging is the PR base). Do not silence a flagged statement with a `-- migration-safe:` annotation unless `/db-migrate` confirmed the old code no longer depends on it; otherwise split the destructive change into a later deploy.
50-
6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `Lint and Test` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed.
50+
6. **Run pre-ship checks** from the repo root before staging. This has two phases: first **regenerate** every committed artifact so generated files never drift into a CI failure (this is what catches things like `agent-stream-docs` going stale after a `models.ts` edit), then run the **full audit suite** CI's `lint` job enforces. Both phases parallelize — but only across commands that write **disjoint** outputs — and a bare `wait` swallows child exit codes, so both phases below explicitly collect each job's status and abort ship if any failed.
5151
5252
**Phase A — regenerate the always-in-repo committed artifacts (parallel), then let step 7 stage whatever changed.** Regenerate only the generators whose inputs live entirely in this repo and that any ordinary code change can drift — `agent-stream-docs:generate` (derives from the provider model registry), `docs-manifest:generate` (derives from docs page paths), and `skills:sync` (derives from `.agents/skills/**`). They write disjoint outputs (`apps/docs/…/agent.mdx`, `apps/sim/lib/mothership/generated/docs-manifest.ts`, and `.claude/skills` links), so they parallelize safely, and each is idempotent (a no-op when already in sync):
5353
```bash
@@ -66,7 +66,7 @@ When the user runs `/ship`:
6666
6767
**Do NOT blanket-run the domain generators here.** `mship:generate` (`generate-mship-contracts.ts`) is an **umbrella** that drives all nine mothership contract generators (`mship-contracts`, `billing-protocol-contract`, `mship-tools`, the four `trace-*`, `metrics-contract`, `vfs-snapshot-contract`) and biome-formats `apps/sim/lib/mothership/generated/` — never run it *and* its constituents (they write the same files and corrupt each other in parallel), and never run it on an ordinary ship: it reads an **external** copilot-contract source that isn't checked out in most worktrees, so it hard-fails with `ENOENT` and would abort ship for an unrelated reason. `generate:pi-model-catalog` (under `apps/sim`) likewise regenerates from the installed Pi package, not repo source. `scripts/generate-docs.ts` rewrites the integration docs and client-safe catalog; run it when this PR changes their block/icon/landing-content inputs or when `integration-catalog:check` reports drift, then review its broad generated diff. Only when **this PR's diff actually touches** a domain generator's input do you regenerate it deliberately and run its matching `:check` (`bun run mship:check` / the individual `*:check`) — with the external source present.
6868
69-
**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/test-build.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
69+
**Phase B — run lint + every audit CI enforces, in parallel, and abort ship if any fails.** Before running the commands, compare this list with `.github/workflows/checks.yml`; when CI adds an audit, run it and update this skill instead of trusting a stale snapshot. The env-flag audit is currently an inline workflow block rather than a package script: when `apps/sim/lib/core/config/env-flags.ts` changed, run that current workflow block verbatim instead of copying a second version into this skill. Run `bun run lint` first (it autofixes formatting and mutates files, so don't parallelize it with the read-only audits), then run the base-sensitive block-registry check, then fan the independent audits out and collect exit codes:
7070
```bash
7171
# autofix formatting first (mutating; not parallel-safe with the audits). Gate its exit too —
7272
# a non-zero lint (unfixable errors) must abort before the audits run, not be ignored.

‎.claude/rules/sim-testing.md‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@ contracts, and demonstrated regressions.
3232

3333
| Suffix | Needs | Run with | In CI |
3434
|--------|-------|----------|-------|
35-
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | Lint and Test job |
36-
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `PostgreSQL integration` job, by glob |
35+
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | `test` jobs (sharded) |
36+
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `integration` jobs, by glob (sharded per provisioning path) |
3737
| `*.live.test.ts` | provider APIs, hosted sandboxes, local runtimes, or sibling checkouts | `vitest run --mode live <file>` (apps/sim) | never |
3838
| `apps/desktop/e2e/*.spec.ts` | the packaged Electron app | Playwright | desktop E2E workflow |
39-
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | End-to-end over real HTTP job |
39+
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | `e2e` jobs (`.github/scripts/http-e2e.sh`) |
4040

4141
- A unit test lives next to its source: `feature.ts` → `feature.test.ts`. No network, no database,
4242
no real timers.

‎.cursor/rules/sim-testing.mdc‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ contracts, and demonstrated regressions.
3030

3131
| Suffix | Needs | Run with | In CI |
3232
|--------|-------|----------|-------|
33-
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | Lint and Test job |
34-
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `PostgreSQL integration` job, by glob |
33+
| `*.test.ts(x)` | nothing; global mocks from `vitest.setup.ts` | `vitest run` | `test` jobs (sharded) |
34+
| `*.integration.ts` | real PostgreSQL (`TEST_DATABASE_URL`), optionally Redis (`TEST_REDIS_URL`) | `vitest run --mode integration` | `integration` jobs, by glob (sharded per provisioning path) |
3535
| `*.live.test.ts` | provider APIs, hosted sandboxes, local runtimes, or sibling checkouts | `vitest run --mode live <file>` (apps/sim) | never |
3636
| `apps/desktop/e2e/*.spec.ts` | the packaged Electron app | Playwright | desktop E2E workflow |
37-
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | End-to-end over real HTTP job |
37+
| `apps/sim/scripts/test-*-e2e.ts` | a running app over HTTP | its `package.json` script when one exists (`bun run test:scim:e2e`; `test:workflow-version-compare:e2e` adds `--no-env-file`), else `bun scripts/test-<suite>-e2e.ts` from apps/sim | `e2e` jobs (`.github/scripts/http-e2e.sh`) |
3838

3939
- A unit test lives next to its source: `feature.ts` → `feature.test.ts`. No network, no database,
4040
no real timers.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Cache Mount
1+
name: cache
22
description: Mount a build cache directory using Blacksmith sticky disks, or the GitHub Actions cache when running on GitHub-hosted runners.
33

44
inputs:
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Docker Build and Push
1+
name: image
22
description: Set up a buildx builder and build/push an image, using Blacksmith's builder or the upstream Docker actions on GitHub-hosted runners.
33

44
inputs:
@@ -35,7 +35,7 @@ inputs:
3535
required: false
3636

3737
# Registry logins must precede this action. provenance/sbom stay off: attestation
38-
# manifests break `imagetools create` retagging in promote-images.
38+
# manifests break `imagetools create` retagging in the `promote` job of ci.yml.
3939
runs:
4040
using: composite
4141
steps:

.github/actions/setup-workspace/action.yml renamed to .github/actions/setup/action.yml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
name: Setup Workspace
1+
name: setup
22
description: Install the pinned Bun and Node toolchain, mount the dependency (and optionally Turbo) caches, and install workspace dependencies.
33

44
inputs:
55
provider:
6-
description: The CI_PROVIDER repo variable, forwarded to cache-mount.
6+
description: The CI_PROVIDER repo variable, forwarded to the cache action.
77
required: false
88
default: ''
99
turbo-cache-key:
1010
description: Suffix for a Turbo cache mounted at ./.turbo. Empty skips the mount. Jobs that write Turbo entries need distinct suffixes, or last-writer-wins commits evict each other's entries.
1111
required: false
1212
default: ''
13+
node-version:
14+
description: Node version to install. Empty keeps the runner's preinstalled Node, for jobs that only ever ran Bun.
15+
required: false
16+
default: '24'
17+
registry-url:
18+
description: npm registry to write an .npmrc for, so `npm publish` reads NODE_AUTH_TOKEN. Empty writes none.
19+
required: false
20+
default: ''
1321

1422
# Cache keys are scoped by event name, and fork PRs get their own namespace on
1523
# top: untrusted fork runs must never share a cache with push runs (whose caches
@@ -30,27 +38,29 @@ runs:
3038
bun-version: 1.4.2
3139

3240
- name: Setup Node
41+
if: inputs.node-version != ''
3342
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
3443
with:
35-
node-version: 24
44+
node-version: ${{ inputs.node-version }}
45+
registry-url: ${{ inputs.registry-url }}
3646

3747
- name: Mount Bun cache
38-
uses: ./.github/actions/cache-mount
48+
uses: ./.github/actions/cache
3949
with:
4050
provider: ${{ inputs.provider }}
4151
key: ${{ github.repository }}-bun-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}
4252
path: ~/.bun/install/cache
4353

4454
- name: Mount node_modules
45-
uses: ./.github/actions/cache-mount
55+
uses: ./.github/actions/cache
4656
with:
4757
provider: ${{ inputs.provider }}
4858
key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }}
4959
path: ./node_modules
5060

5161
- name: Mount Turbo cache
5262
if: inputs.turbo-cache-key != ''
53-
uses: ./.github/actions/cache-mount
63+
uses: ./.github/actions/cache
5464
with:
5565
provider: ${{ inputs.provider }}
5666
key: ${{ github.repository }}-${{ inputs.turbo-cache-key }}-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}

‎.github/dependabot.yml‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
version: 2
2+
3+
# GitHub Actions only: every `uses:` is pinned to a commit SHA, and without this the pins drift
4+
# apart (checkout had three different SHAs across workflows). One grouped PR a week keeps every
5+
# workflow and composite action on the same version of each action.
6+
updates:
7+
- package-ecosystem: github-actions
8+
directories:
9+
- /
10+
- /.github/actions/*
11+
schedule:
12+
interval: weekly
13+
target-branch: staging
14+
groups:
15+
actions:
16+
patterns:
17+
- '*'
18+
commit-message:
19+
prefix: ci

‎.github/scripts/http-e2e.sh‎

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#!/usr/bin/env bash
2+
# Runs one end-to-end suite group over real HTTP, each against its own `next dev` app.
3+
#
4+
# Usage: http-e2e.sh <scim|cli|stop-after|desktop-inbox> (run from apps/sim)
5+
#
6+
# The job provides DATABASE_URL, BETTER_AUTH_SECRET and ENCRYPTION_KEY; each group sets the rest of
7+
# its app's environment here. Reports and server logs land in $RUNNER_TEMP/e2e.
8+
#
9+
# The first request cold-compiles the app under Turbopack, which takes 42-150s on CI runners, so
10+
# the readiness deadline only has to catch a hung boot: an exited server fails immediately, and
11+
# either way the server log tail lands in the job log.
12+
#
13+
# Each app starts from an empty Turbopack dev cache: a cache written under other NEXT_PUBLIC_*
14+
# values, by a server that `next dev` SIGKILLs 100ms after SIGTERM, can panic Turbopack or wedge a
15+
# route compile on restore. It runs in its own session under an E2E_APP tag, and stop-session.sh
16+
# returns only once every process in that session or carrying that tag has exited (Next's
17+
# telemetry flush runs detached and still writes .next/dev).
18+
set -euo pipefail
19+
20+
group=${1:?usage: http-e2e.sh <scim|cli|stop-after|desktop-inbox>}
21+
report_dir="$RUNNER_TEMP/e2e"
22+
ready_timeout_seconds=300
23+
mkdir -p "$report_dir"
24+
25+
server_pid=''
26+
app_tag=''
27+
server_log=''
28+
status_log=''
29+
30+
finish() {
31+
local status=$?
32+
if [ -n "$server_pid" ]; then
33+
bash "$GITHUB_WORKSPACE/.github/scripts/stop-session.sh" "$server_pid" "$app_tag" || status=1
34+
wait "$server_pid" 2>/dev/null || true
35+
if [ -n "$status_log" ]; then
36+
awk '/^ (GET|POST|PUT|PATCH|DELETE|HEAD) \/api\// { print }' "$server_log" > "$status_log"
37+
fi
38+
if [ "$status" -ne 0 ]; then
39+
tail -n 200 "$server_log"
40+
fi
41+
fi
42+
exit "$status"
43+
}
44+
trap finish EXIT
45+
46+
# start_app <name> <port> <label> [record-http-status]
47+
start_app() {
48+
local name=$1 port=$2 label=$3
49+
server_log="$report_dir/$name-next.log"
50+
if [ "${4:-}" = record-http-status ]; then
51+
status_log="$report_dir/$name-http-status.log"
52+
fi
53+
app_tag="$name-$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT-$$"
54+
export NEXT_PUBLIC_APP_URL="http://127.0.0.1:$port"
55+
export BETTER_AUTH_URL="$NEXT_PUBLIC_APP_URL"
56+
export DISABLE_TELEMETRY=true NEXT_TELEMETRY_DISABLED=1
57+
rm -rf .next/dev
58+
E2E_APP="$app_tag" setsid node ../../node_modules/next/dist/bin/next dev --hostname 127.0.0.1 \
59+
--port "$port" > "$server_log" 2>&1 &
60+
server_pid=$!
61+
62+
local started=$SECONDS
63+
until curl --fail --silent --max-time 10 "$NEXT_PUBLIC_APP_URL/api/health" > /dev/null; do
64+
if ! kill -0 "$server_pid" 2>/dev/null; then
65+
echo "::error::Local $label app exited during startup."
66+
exit 1
67+
fi
68+
if [ $((SECONDS - started)) -ge "$ready_timeout_seconds" ]; then
69+
echo "::error::Local $label app did not become ready within $ready_timeout_seconds seconds."
70+
exit 1
71+
fi
72+
sleep 2
73+
done
74+
echo "Local $label app ready after $((SECONDS - started))s"
75+
}
76+
77+
case "$group" in
78+
scim)
79+
export NEXT_PUBLIC_FORCE_HOSTED=true
80+
export BILLING_ENABLED=true NEXT_PUBLIC_BILLING_ENABLED=true
81+
export ENTERPRISE_ENABLED=true NEXT_PUBLIC_ENTERPRISE_ENABLED=true
82+
export SCIM_ENABLED=true NEXT_PUBLIC_SCIM_ENABLED=true
83+
export SSO_ENABLED=true NEXT_PUBLIC_SSO_ENABLED=true
84+
export ORGANIZATIONS_ENABLED=true NEXT_PUBLIC_ORGANIZATIONS_ENABLED=true
85+
export INTERNAL_API_SECRET=scim-http-ci-local-secret-at-least-32-characters
86+
export DB_TX_TRIPWIRE=throw
87+
export NEXT_PUBLIC_CHAT_DISABLED=true
88+
start_app scim 3017 SCIM record-http-status
89+
SCIM_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
90+
SCIM_E2E_DATABASE_URL="$DATABASE_URL" \
91+
SCIM_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \
92+
SCIM_E2E_REPORT_PATH="$report_dir/scim-e2e-report.json" \
93+
bun run test:scim:e2e
94+
VERSION_COMPARE_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
95+
VERSION_COMPARE_E2E_DATABASE_URL="$DATABASE_URL" \
96+
VERSION_COMPARE_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \
97+
VERSION_COMPARE_E2E_REPORT_PATH="$report_dir/version-compare-http-report.json" \
98+
bun run test:workflow-version-compare:e2e
99+
;;
100+
101+
# The search suites serve their own fixtures in-process and need no app. They share this group
102+
# because they finish in seconds. Self-hosted without billing: hosted billing admits runs through
103+
# Redis, which the CLI app is not given.
104+
cli)
105+
for search in google-content lucid zoom google-meet; do
106+
report_var="SEARCH_$(echo "$search" | tr 'a-z-' 'A-Z_')_REPORT_PATH"
107+
env NEXT_PUBLIC_APP_URL=http://127.0.0.1:3040 NEXT_PUBLIC_FORCE_HOSTED=false \
108+
"$report_var=$report_dir/search-$search.json" \
109+
bun "scripts/test-search-$search-e2e.ts"
110+
done
111+
export NEXT_PUBLIC_FORCE_HOSTED=false
112+
export INTERNAL_API_SECRET=cli-http-ci-local-secret-at-least-32-characters
113+
start_app cli 3018 CLI
114+
CLI_LATENCY_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
115+
CLI_LATENCY_E2E_DATABASE_URL="$DATABASE_URL" \
116+
CLI_LATENCY_E2E_RUNS=3 \
117+
CLI_LATENCY_E2E_WARMUP=1 \
118+
CLI_LATENCY_E2E_REPORT_PATH="$report_dir/cli-run-latency-report.json" \
119+
bun run test:cli-run-latency:e2e
120+
;;
121+
122+
# Self-hosted: hosted billing admits a run only through a Redis usage reservation.
123+
stop-after)
124+
export NEXT_PUBLIC_FORCE_HOSTED=false
125+
export INTERNAL_API_SECRET=stop-after-http-ci-local-secret-at-least-32-characters
126+
export DB_TX_TRIPWIRE=throw
127+
export NEXT_PUBLIC_CHAT_DISABLED=true
128+
start_app stop-after 3018 workflow record-http-status
129+
STOP_AFTER_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
130+
STOP_AFTER_E2E_DATABASE_URL="$DATABASE_URL" \
131+
STOP_AFTER_E2E_REPORT_PATH="$report_dir/stop-after-http-report.json" \
132+
bun run test:workflow-stop-after:e2e
133+
;;
134+
135+
# The desktop background executor's protocol: device registration, the SSE doorbell over Redis
136+
# pub/sub, presence, leased claims, Stop and isolation. The only group whose app gets Redis.
137+
desktop-inbox)
138+
export REDIS_URL=redis://127.0.0.1:6379
139+
export NEXT_PUBLIC_FORCE_HOSTED=false
140+
export MSHIP_DESKTOP_BACKGROUND_EXECUTOR=true
141+
export COPILOT_TOOL_PERMISSIONS_ENABLED=true
142+
export INTERNAL_API_SECRET=desktop-inbox-http-ci-local-secret-at-least-32-characters
143+
export DB_TX_TRIPWIRE=throw
144+
start_app desktop-inbox 3019 'desktop executor' record-http-status
145+
DESKTOP_INBOX_E2E_BASE_URL="$NEXT_PUBLIC_APP_URL" \
146+
DESKTOP_INBOX_E2E_DATABASE_URL="$DATABASE_URL" \
147+
DESKTOP_INBOX_E2E_REDIS_URL="$REDIS_URL" \
148+
DESKTOP_INBOX_E2E_AUTH_SECRET="$BETTER_AUTH_SECRET" \
149+
DESKTOP_INBOX_E2E_REPORT_PATH="$report_dir/desktop-inbox-http-report.json" \
150+
bun run test:desktop-inbox:e2e
151+
;;
152+
153+
*)
154+
echo "::error::Unknown end-to-end group: $group" >&2
155+
exit 2
156+
;;
157+
esac

0 commit comments

Comments
 (0)