CI workflow (sveltejs/svelte)
The CI workflow from sveltejs/svelte, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get run de-duplication, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the sveltejs/svelte repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: CI
on:
push:
branches: [main]
pull_request:
permissions:
contents: read # to fetch code (actions/checkout)
env:
# We only install Chromium manually
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
jobs:
Tests:
permissions: {}
runs-on: ${{ matrix.os }}
timeout-minutes: 15
strategy:
matrix:
include:
# Vitest 4 requires Node 20+, so tests run on 20/22/24. The published
# Svelte package still supports Node >=18 (see packages/svelte/package.json).
- node-version: 20
os: windows-latest
- node-version: 20
os: macOS-latest
- node-version: 20
os: ubuntu-latest
- node-version: 22
os: ubuntu-latest
- node-version: 24
os: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm playwright install chromium
- run: pnpm test
env:
CI: true
TestNoAsync:
permissions: {}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm playwright install chromium
- run: pnpm test runtime-runes
env:
CI: true
SVELTE_NO_ASYNC: true
TSGo:
permissions: {}
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
- name: install
run: pnpm install --frozen-lockfile
- name: install tsgo
run: cd packages/svelte && pnpm i -D @typescript/native-preview
- name: type check
run: cd packages/svelte && pnpm check:tsgo
Lint:
permissions: {}
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
- name: install
run: pnpm install --frozen-lockfile
- name: type check
run: pnpm check
- name: lint
if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail (avoids multiple runs uncovering different issues at different steps)
run: pnpm lint
- name: build and check generated types
if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail
run: pnpm build && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed - please regenerate types locally with `cd packages/svelte && pnpm generate:types` and commit the changes after you have reviewed them"; git diff; exit 1); }
- name: check browser-support docs page is up to date
run: '{ [ "`git status --porcelain=v1 documentation/docs/07-misc/.generated/`" == "" ] || (echo "The browser-support docs page is out of date - please regenerate it locally with \`cd packages/svelte && pnpm generate:browser-support\` and commit the changes"; git diff documentation/docs/07-misc/.generated/; exit 1); }'
Benchmarks:
permissions: {}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v6
- uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4
- uses: actions/setup-node@v6
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm bench
env:
CI: true
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI on: push: branches: [main] pull_request: permissions: contents: read # to fetch code (actions/checkout) env: # We only install Chromium manually PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: Tests: permissions: {} runs-on: ${{ matrix.os }} timeout-minutes: 15 strategy: matrix: include: # Vitest 4 requires Node 20+, so tests run on 20/22/24. The published # Svelte package still supports Node >=18 (see packages/svelte/package.json). - node-version: 20 os: windows-latest - node-version: 20 os: macOS-latest - node-version: 20 os: ubuntu-latest - node-version: 22 os: ubuntu-latest - node-version: 24 os: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm playwright install chromium - run: pnpm test env: CI: true TestNoAsync: permissions: {} runs-on: latchkey-small timeout-minutes: 10 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@v6 with: node-version: 22 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm playwright install chromium - run: pnpm test runtime-runes env: CI: true SVELTE_NO_ASYNC: true TSGo: permissions: {} runs-on: latchkey-small timeout-minutes: 5 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm - name: install run: pnpm install --frozen-lockfile - name: install tsgo run: cd packages/svelte && pnpm i -D @typescript/native-preview - name: type check run: cd packages/svelte && pnpm check:tsgo Lint: permissions: {} runs-on: latchkey-small timeout-minutes: 10 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm - name: install run: pnpm install --frozen-lockfile - name: type check run: pnpm check - name: lint if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail (avoids multiple runs uncovering different issues at different steps) run: pnpm lint - name: build and check generated types if: (${{ success() }} || ${{ failure() }}) # ensures this step runs even if previous steps fail run: pnpm build && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed - please regenerate types locally with `cd packages/svelte && pnpm generate:types` and commit the changes after you have reviewed them"; git diff; exit 1); } - name: check browser-support docs page is up to date run: '{ [ "`git status --porcelain=v1 documentation/docs/07-misc/.generated/`" == "" ] || (echo "The browser-support docs page is out of date - please regenerate it locally with \`cd packages/svelte && pnpm generate:browser-support\` and commit the changes"; git diff documentation/docs/07-misc/.generated/; exit 1); }' Benchmarks: permissions: {} runs-on: latchkey-small timeout-minutes: 15 steps: - uses: actions/checkout@v6 - uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v4 - uses: actions/setup-node@v6 with: node-version: 24 cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm bench env: CI: true
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
What Latchkey heals here
This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:
- Dependency installs
- End-to-end and browser tests
This workflow runs 5 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.