Skip to content

Commit 8ba3d02

Browse files
committed
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.
1 parent 0e1d9c0 commit 8ba3d02

26 files changed

Lines changed: 554 additions & 495 deletions

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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.
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
Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Test and Build
1+
name: checks
22

33
on:
44
workflow_call:
@@ -8,7 +8,7 @@ permissions:
88
contents: read
99

1010
jobs:
11-
postgres-integration:
11+
integration:
1212
# Runs the real-infrastructure test layer: every `*.integration.ts` in packages/db and
1313
# apps/sim, discovered by glob (`vitest run --mode integration`), against the database each
1414
# provisioning path produces. A new integration suite needs no workflow change.
@@ -18,7 +18,7 @@ jobs:
1818
# suite's files across four shards; a shard runs its files one at a time against its own
1919
# database. Files run serially, so a shard barely uses more than one core: 4 vCPU is enough.
2020
name: integration (${{ matrix.provision }}, ${{ matrix.shard }}/4)
21-
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
21+
runs-on: &runner-4vcpu ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
2222
timeout-minutes: 20
2323
strategy:
2424
fail-fast: false
@@ -74,7 +74,7 @@ jobs:
7474
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
7575

7676
- name: Setup workspace
77-
uses: ./.github/actions/setup-workspace
77+
uses: ./.github/actions/setup
7878
with:
7979
provider: ${{ vars.CI_PROVIDER }}
8080

@@ -128,7 +128,7 @@ jobs:
128128
#
129129
# SCIM runs two suites against a hosted app and is the longest group, so it keeps the 8 vCPU
130130
# runner; the others boot a smaller self-hosted app and fit on 4.
131-
http-e2e:
131+
e2e:
132132
name: e2e (${{ matrix.group }})
133133
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && matrix.runner || 'ubuntu-latest' }}
134134
timeout-minutes: 20
@@ -160,7 +160,7 @@ jobs:
160160
--health-retries 10
161161
# Only the desktop executor's app is given REDIS_URL: its doorbell and presence live there.
162162
redis:
163-
image: redis:7-alpine
163+
image: redis:8.2-alpine
164164
ports:
165165
- 6379:6379
166166
options: >-
@@ -178,7 +178,7 @@ jobs:
178178
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
179179

180180
- name: Setup workspace
181-
uses: ./.github/actions/setup-workspace
181+
uses: ./.github/actions/setup
182182
with:
183183
provider: ${{ vars.CI_PROVIDER }}
184184

@@ -205,9 +205,9 @@ jobs:
205205
# Pull requests skip the live desktop suite only when every change is clearly unrelated to the
206206
# app it drives (docs, other apps, published content). Anything else, and any failure to work
207207
# out the diff, runs it: a pull request that skipped it wrongly would first fail on staging.
208-
desktop-live-changes:
209-
name: Detect desktop tool changes
210-
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
208+
desktop-changes:
209+
name: desktop-changes
210+
runs-on: &runner-2vcpu ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
211211
timeout-minutes: 5
212212
outputs:
213213
changed: ${{ github.event_name != 'pull_request' || steps.diff.outputs.changed != 'false' }}
@@ -224,11 +224,11 @@ jobs:
224224
run: bash .github/scripts/desktop-live-changes.sh "$BASE" >> "$GITHUB_OUTPUT"
225225

226226
# Desktop tools in the real Electron app against a local app, on its own runner: the
227-
# Electron app, the dev app and its realtime server together outgrow the http-e2e runner.
228-
desktop-live-e2e:
229-
name: Desktop tools against a local app
230-
needs: desktop-live-changes
231-
if: needs.desktop-live-changes.outputs.changed == 'true'
227+
# Electron app, the dev app and its realtime server together outgrow the e2e runner.
228+
desktop-live:
229+
name: desktop-live
230+
needs: desktop-changes
231+
if: needs.desktop-changes.outputs.changed == 'true'
232232
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-16vcpu-ubuntu-2404' || 'ubuntu-latest' }}
233233
timeout-minutes: 30
234234
services:
@@ -246,7 +246,7 @@ jobs:
246246
--health-timeout 5s
247247
--health-retries 10
248248
redis:
249-
image: redis:7-alpine
249+
image: redis:8.2-alpine
250250
ports:
251251
- 6379:6379
252252
options: >-
@@ -264,7 +264,7 @@ jobs:
264264
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
265265

266266
- name: Setup workspace
267-
uses: ./.github/actions/setup-workspace
267+
uses: ./.github/actions/setup
268268
with:
269269
provider: ${{ vars.CI_PROVIDER }}
270270

@@ -348,7 +348,7 @@ jobs:
348348
# kept off the test shards so neither waits on the other.
349349
lint:
350350
name: lint
351-
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-4vcpu-ubuntu-2404' || 'ubuntu-latest' }}
351+
runs-on: *runner-4vcpu
352352
timeout-minutes: 15
353353

354354
steps:
@@ -366,7 +366,7 @@ jobs:
366366
fetch-depth: 2
367367

368368
- name: Setup workspace
369-
uses: ./.github/actions/setup-workspace
369+
uses: ./.github/actions/setup
370370
with:
371371
provider: ${{ vars.CI_PROVIDER }}
372372
turbo-cache-key: turbo-cache
@@ -448,6 +448,20 @@ jobs:
448448
- name: Lint code
449449
run: bun run lint:check
450450

451+
# Workflow syntax, expressions, `needs` references and runner labels. ShellCheck stays off
452+
# here: the existing run blocks carry info-level findings that are their own cleanup.
453+
- name: Lint workflows
454+
env:
455+
ACTIONLINT_VERSION: 1.7.12
456+
ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
457+
run: |
458+
archive="$RUNNER_TEMP/actionlint.tar.gz"
459+
curl -fsSL -o "$archive" \
460+
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
461+
echo "${ACTIONLINT_SHA256} ${archive}" | sha256sum -c -
462+
tar -xzf "$archive" -C "$RUNNER_TEMP" actionlint
463+
"$RUNNER_TEMP/actionlint" -color -shellcheck= -pyflakes=
464+
451465
# Every zero-argument `check:*` script, run concurrently. The list is derived in
452466
# scripts/run-audits.ts, which also writes the per-audit timing table to the job
453467
# summary and annotates failures. Audits needing a base ref stay separate below.
@@ -463,7 +477,7 @@ jobs:
463477
# Every workspace, not just realtime. packages/emcn, packages/utils,
464478
# apps/desktop and apps/docs had no type check in CI at all; apps/sim's
465479
# source was covered only as a side effect of `next build` in the separate
466-
# Build App job. Note this does NOT cover apps/sim's tests — its tsconfig
480+
# `build` job. Note this does NOT cover apps/sim's tests — its tsconfig
467481
# excludes *.test.ts(x), and including them today surfaces ~2.2k errors,
468482
# so that is its own cleanup rather than a gate to switch on here.
469483
- name: Type-check all workspaces
@@ -502,7 +516,7 @@ jobs:
502516
fetch-depth: 2
503517

504518
- name: Setup workspace
505-
uses: ./.github/actions/setup-workspace
519+
uses: ./.github/actions/setup
506520
with:
507521
provider: ${{ vars.CI_PROVIDER }}
508522
turbo-cache-key: turbo-cache-test-${{ matrix.shard }}
@@ -530,7 +544,7 @@ jobs:
530544
# Next.js production build, in parallel with lint + tests. Sticky disks are
531545
# cloned from the last committed snapshot per job and committed last-writer-
532546
# wins, so concurrent mounts are safe. The bun/node_modules disks are shared
533-
# with test-build (the lockfile-hashed key means they only ever share when the
547+
# with the test jobs (the lockfile-hashed key means they only ever share when the
534548
# dependency tree really is identical, so LWW loss is harmless), but the Turbo
535549
# cache gets its own key: with a shared key, only the last committer's new
536550
# entries survive each run, so the test and build Turbo entries would evict
@@ -541,7 +555,7 @@ jobs:
541555
# peaked 51 GB. NODE_OPTIONS' --max-old-space-size caps only Node's JS heap,
542556
# not the native Turbopack workers that dominate, so it cannot prevent this.
543557
build:
544-
name: Build App
558+
name: build
545559
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-16vcpu-ubuntu-2404' || 'linux-x64-8-core' }}
546560
# Build durations crossed 15 minutes as the app grew (10m02 on Jul 29 AM,
547561
# 14m44 after the folders/desktop/library merges, then two straight
@@ -554,7 +568,7 @@ jobs:
554568
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
555569

556570
- name: Setup workspace
557-
uses: ./.github/actions/setup-workspace
571+
uses: ./.github/actions/setup
558572
with:
559573
provider: ${{ vars.CI_PROVIDER }}
560574
turbo-cache-key: turbo-cache-build
@@ -599,9 +613,9 @@ jobs:
599613
# suite skips on pull requests that cannot affect it); a failure or a cancellation is not.
600614
ci:
601615
name: ci
602-
needs: [postgres-integration, http-e2e, desktop-live-changes, desktop-live-e2e, lint, test, build]
616+
needs: [integration, e2e, desktop-changes, desktop-live, lint, test, build]
603617
if: ${{ !cancelled() }}
604-
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-2vcpu-ubuntu-2404' || 'ubuntu-latest' }}
618+
runs-on: *runner-2vcpu
605619
timeout-minutes: 5
606620
steps:
607621
- name: Require every check to pass

0 commit comments

Comments
 (0)