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
4 changes: 4 additions & 0 deletions .github/CI.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
# CI selection and acceptance ownership

GitHub-hosted jobs restore their event-specific dependency caches first. Trusted PRs also try the default branch's push caches, so a new PR can reuse installed dependencies before it has saved a cache of its own. The `node_modules` fallback requires the identical lockfile hash. Saves stay in the event-specific namespace, fork PRs do not receive the fallback, and push jobs never restore PR caches. Blacksmith sticky disks keep their existing event-scoped keys. Dependency installation still validates the frozen lockfile after every restore. Explicit save steps run immediately after installation, while the composite action's path inputs are available, so later test failures do not prevent dependency-cache population.

The `changes` job runs Turborepo 2.9.14's `affectedTasks` query before installing application dependencies or provisioning services. `turbo.json` records package dependency propagation; `apps/sim/turbo.json` partitions the app into shared runtime, server, workspace UI, and acceptance tasks. `.github/ci-suites.json` turns those tasks into job matrices. The uploaded `ci-plan` artifact names changed files, selected tasks, attribution reasons, and any fallback.

The integration matrix's `push/db` job owns dependency-cache uploads; the other integration jobs only restore. Exact hits skip uploads. This avoids concurrently compressing the same dependency trees across all shards merely to lose the shared-key reservation race.

A PR compares its merge base with the checked-out merge commit. Main/staging pushes execute all checks; the parent `ci` workflow skips checks on `dev` pushes, while PRs targeting `dev` still run checks. A manual `checks` run executes all checks unless supplied a full base commit SHA to reproduce a scoped plan. Missing history, an empty diff, unknown files outside the workspace graph, root script/CI changes, or a planner error run every check. Missing selection outputs fail the aggregate gate. The gate also rejects an omitted dependency, any failed/cancelled job, and any skip that its explicit selection flag did not authorize.

| Change | Expensive checks selected |
Expand Down
57 changes: 53 additions & 4 deletions .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ inputs:
description: npm registry to write an .npmrc for, so `npm publish` reads NODE_AUTH_TOKEN. Empty writes none.
required: false
default: ''
save-dependency-cache:
description: Save GitHub dependency caches after installation. Parallel matrices can elect one writer.
required: false
default: 'true'

# Cache keys are scoped by event name, and fork PRs get their own namespace on
# top: untrusted fork runs must never share a cache with push runs (whose caches
# feed production image builds) or with trusted internal-PR runs.
# Writes stay scoped by event and fork status. Trusted GitHub PRs can read the
# default branch's push caches; push jobs never read PR caches.
#
# node_modules also keys on the lockfile hash: a sticky disk is a mutable volume,
# and `bun install --frozen-lockfile` adds what the lockfile needs without
Expand All @@ -45,27 +48,59 @@ runs:
registry-url: ${{ inputs.registry-url }}

- name: Mount Bun cache
if: inputs.provider == '' || inputs.provider == 'blacksmith'
uses: ./.github/actions/cache
with:
provider: ${{ inputs.provider }}
key: ${{ github.repository }}-bun-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}
path: ~/.bun/install/cache

- name: Mount node_modules
if: inputs.provider == '' || inputs.provider == 'blacksmith'
uses: ./.github/actions/cache
with:
provider: ${{ inputs.provider }}
key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }}
path: ./node_modules

- name: Restore Bun cache
id: bun-cache
if: inputs.provider != '' && inputs.provider != 'blacksmith'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
key: ${{ github.repository }}-bun-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ github.run_id }}
restore-keys: |
${{ github.repository }}-bun-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-
${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && format('{0}-bun-cache-push-', github.repository) || '' }}
path: ~/.bun/install/cache

- name: Restore node_modules
id: node-modules-cache
if: inputs.provider != '' && inputs.provider != 'blacksmith'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }}-${{ github.run_id }}
restore-keys: |
${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }}-
${{ github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && format('{0}-node-modules-push-{1}-', github.repository, hashFiles('bun.lock')) || '' }}
path: ./node_modules

- name: Mount Turbo cache
if: inputs.turbo-cache-key != ''
if: inputs.turbo-cache-key != '' && (inputs.provider == '' || inputs.provider == 'blacksmith')
uses: ./.github/actions/cache
with:
provider: ${{ inputs.provider }}
key: ${{ github.repository }}-${{ inputs.turbo-cache-key }}-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}
path: ./.turbo

- name: Restore and save Turbo cache
if: inputs.turbo-cache-key != '' && inputs.provider != '' && inputs.provider != 'blacksmith'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
key: ${{ github.repository }}-${{ inputs.turbo-cache-key }}-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ github.run_id }}
restore-keys: ${{ github.repository }}-${{ inputs.turbo-cache-key }}-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-
path: ./.turbo

# Bun retries a failed request itself, but a registry connection that stalls
# without failing leaves `bun install` waiting until the job's own timeout
# cancels it, the whole budget spent on one hung step. Healthy installs finish
Expand All @@ -83,3 +118,17 @@ runs:
done
echo "::error title=bun install stalled::both attempts ran past 3 minutes"
exit 1

- name: Save Bun cache
if: inputs.provider != '' && inputs.provider != 'blacksmith' && inputs.save-dependency-cache == 'true' && steps.bun-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
key: ${{ github.repository }}-bun-cache-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ github.run_id }}
path: ~/.bun/install/cache

- name: Save node_modules
if: inputs.provider != '' && inputs.provider != 'blacksmith' && inputs.save-dependency-cache == 'true' && steps.node-modules-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
key: ${{ github.repository }}-node-modules-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-${{ hashFiles('bun.lock') }}-${{ github.run_id }}
path: ./node_modules
1 change: 1 addition & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ jobs:
uses: ./.github/actions/setup
with:
provider: github
save-dependency-cache: ${{ matrix.provision == 'push' && matrix.shard == 'db' }}

- name: Provision a fresh database through the supported command
working-directory: packages/db
Expand Down
Loading