CI workflow (sveltejs/kit)
The CI workflow from sveltejs/kit, explained and optimized by Latchkey.
CI health: A - excellent
Point runs-on at Latchkey and get job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the CI workflow from the sveltejs/kit 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
paths-ignore: &paths_ignore
- '.changeset/**'
- '.githooks/**'
- '.github/ISSUE_TEMPLATE/**'
- '.github/copilot-instructions.md'
- '.github/FUNDING.yml'
- '.github/PULL_REQUEST_TEMPLATE.md'
- 'documentation/**'
- 'packages/*/CHANGELOG*.md'
- 'packages/kit/src/types/synthetic/**'
- 'AGENTS.md'
- 'CLAUDE.md'
- 'CONTRIBUTING.md'
- 'FUNDING.json'
- 'LICENSE'
- 'README.md'
pull_request:
paths-ignore: *paths_ignore
env:
# we call `pnpm playwright install` instead
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
# cancel in-progress runs on new commits to same PR (gitub.event.number)
concurrency:
group: ${{ github.workflow }}-${{ github.event.number || github.sha }}
cancel-in-progress: true
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
lint-all:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
- run: pnpm run lint
- run: cd packages/kit && pnpm prepublishOnly && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed - please run prepublishOnly locally and commit the changes after you have reviewed them"; git diff; exit 1); }
- run: pnpm run check
test-kit:
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- node-version: 18
os: ubuntu-latest
e2e-browser: 'chromium'
vite: 'baseline'
- node-version: 20
os: ubuntu-latest
e2e-browser: 'chromium'
vite: 'current'
- node-version: 22
os: ubuntu-latest
e2e-browser: 'chromium'
vite: 'current'
- node-version: 24
os: ubuntu-latest
e2e-browser: 'chromium'
vite: 'current'
- node-version: 24
os: ubuntu-latest
e2e-browser: 'chromium'
vite: 'beta'
env:
KIT_E2E_BROWSER: ${{matrix.e2e-browser}}
MATRIX_VITE: ${{matrix.vite}}
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
with:
node-version: ${{ matrix.node-version }}
- name: setup overrides for matrix.vite
if: matrix.vite != 'current'
run:
| # copies catalogs.vite-xxx to overrides in pnpm-workspace.yaml so the subsequent `pnpm install` enforces them
yq -i '.overrides =.catalogs."vite-${{matrix.vite}}"' pnpm-workspace.yaml
pnpm install --no-frozen-lockfile
git checkout pnpm-lock.yaml pnpm-workspace.yaml # revert changes to pnpm files to avoid cache key changes
pnpm --dir packages/kit ls vite
- run: pnpm playwright install ${{ matrix.e2e-browser }}
- run: pnpm run sync-all
- run: pnpm test:kit
env:
NODE_OPTIONS: ${{matrix.node-version == 22 && '--experimental-strip-types' || ''}} # allows loading svelte.config.ts
- name: Print flaky test report
run: node scripts/print-flaky-test-report.js
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
retention-days: 3
name: test-failure-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }}-vite-${{matrix.vite}}
path: test-results.tar.gz
test-kit-cross-browser:
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- node-version: 24
os: windows-latest
e2e-browser: 'chromium'
mode: 'dev'
- node-version: 24
os: ubuntu-latest
e2e-browser: 'firefox'
mode: 'dev'
- node-version: 24
os: macOS-latest
e2e-browser: 'webkit'
mode: 'dev'
- node-version: 24
os: windows-latest
e2e-browser: 'chromium'
mode: 'build'
- node-version: 24
os: ubuntu-latest
e2e-browser: 'firefox'
mode: 'build'
- node-version: 24
os: macOS-latest
e2e-browser: 'webkit'
mode: 'build'
env:
KIT_E2E_BROWSER: ${{matrix.e2e-browser}}
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
with:
node-version: ${{ matrix.node-version }}
- run: pnpm playwright install ${{ matrix.e2e-browser }}
- run: pnpm run sync-all
- run: pnpm test:cross-platform:${{ matrix.mode }}
- name: Print flaky test report
run: node scripts/print-flaky-test-report.js
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results-cross-platform-${{ matrix.mode }}.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
retention-days: 3
name: test-failure-cross-platform-${{ matrix.mode }}-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }}
path: test-results-cross-platform-${{ matrix.mode }}.tar.gz
test-kit-server-side-route-resolution:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- mode: 'dev'
- mode: 'build'
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
- run: pnpm playwright install chromium --no-shell
- run: pnpm run sync-all
- run: pnpm test:server-side-route-resolution:${{ matrix.mode }}
- name: Print flaky test report
run: node scripts/print-flaky-test-report.js
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results-server-side-route-resolution-${{ matrix.mode }}.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
retention-days: 3
name: test-failure-server-side-route-resolution-${{ matrix.mode }}-${{ github.run_id }}
path: test-results-server-side-route-resolution-${{ matrix.mode }}.tar.gz
test-kit-svelte-async:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- mode: 'dev'
- mode: 'build'
steps:
- run: git config --global core.autocrlf false
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
with:
node-version: ${{ matrix.node-version }}
- run: pnpm playwright install chromium --no-shell
- run: pnpm run sync-all
- run: pnpm test:svelte-async:${{ matrix.mode }}
- name: Print flaky test report
run: node scripts/print-flaky-test-report.js
- name: Archive test results
if: failure()
shell: bash
run: find packages -type d -name test-results -not -empty | tar -czf test-results-svelte-async-${{ matrix.mode }}.tar.gz --files-from=-
- name: Upload test results
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
retention-days: 3
name: test-failure-svelte-async-${{ matrix.mode }}-${{ github.run_id }}
path: test-results-svelte-async-${{ matrix.mode }}.tar.gz
test-others:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20, 22, 24]
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: ./.github/actions/node-setup
with:
node-version: ${{ matrix.node-version }}
- run: pnpm playwright install chromium --no-shell
- run: cd packages/kit && pnpm prepublishOnly
- run: pnpm run test:others
env:
NODE_OPTIONS: ${{matrix.node-version == 22 && '--experimental-strip-types' || ''}} # allows loading svelte.config.ts
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: CI on: push: branches: - main paths-ignore: &paths_ignore - '.changeset/**' - '.githooks/**' - '.github/ISSUE_TEMPLATE/**' - '.github/copilot-instructions.md' - '.github/FUNDING.yml' - '.github/PULL_REQUEST_TEMPLATE.md' - 'documentation/**' - 'packages/*/CHANGELOG*.md' - 'packages/kit/src/types/synthetic/**' - 'AGENTS.md' - 'CLAUDE.md' - 'CONTRIBUTING.md' - 'FUNDING.json' - 'LICENSE' - 'README.md' pull_request: paths-ignore: *paths_ignore env: # we call `pnpm playwright install` instead PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1' # cancel in-progress runs on new commits to same PR (gitub.event.number) concurrency: group: ${{ github.workflow }}-${{ github.event.number || github.sha }} cancel-in-progress: true permissions: contents: read # to fetch code (actions/checkout) jobs: lint-all: timeout-minutes: 30 runs-on: latchkey-small steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup - run: pnpm run lint - run: cd packages/kit && pnpm prepublishOnly && { [ "`git status --porcelain=v1`" == "" ] || (echo "Generated types have changed - please run prepublishOnly locally and commit the changes after you have reviewed them"; git diff; exit 1); } - run: pnpm run check test-kit: runs-on: ${{ matrix.os }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: - node-version: 18 os: ubuntu-latest e2e-browser: 'chromium' vite: 'baseline' - node-version: 20 os: ubuntu-latest e2e-browser: 'chromium' vite: 'current' - node-version: 22 os: ubuntu-latest e2e-browser: 'chromium' vite: 'current' - node-version: 24 os: ubuntu-latest e2e-browser: 'chromium' vite: 'current' - node-version: 24 os: ubuntu-latest e2e-browser: 'chromium' vite: 'beta' env: KIT_E2E_BROWSER: ${{matrix.e2e-browser}} MATRIX_VITE: ${{matrix.vite}} steps: - run: git config --global core.autocrlf false - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup with: node-version: ${{ matrix.node-version }} - name: setup overrides for matrix.vite if: matrix.vite != 'current' run: | # copies catalogs.vite-xxx to overrides in pnpm-workspace.yaml so the subsequent `pnpm install` enforces them yq -i '.overrides =.catalogs."vite-${{matrix.vite}}"' pnpm-workspace.yaml pnpm install --no-frozen-lockfile git checkout pnpm-lock.yaml pnpm-workspace.yaml # revert changes to pnpm files to avoid cache key changes pnpm --dir packages/kit ls vite - run: pnpm playwright install ${{ matrix.e2e-browser }} - run: pnpm run sync-all - run: pnpm test:kit env: NODE_OPTIONS: ${{matrix.node-version == 22 && '--experimental-strip-types' || ''}} # allows loading svelte.config.ts - name: Print flaky test report run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash run: find packages -type d -name test-results -not -empty | tar -czf test-results.tar.gz --files-from=- - name: Upload test results if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: retention-days: 3 name: test-failure-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }}-vite-${{matrix.vite}} path: test-results.tar.gz test-kit-cross-browser: runs-on: ${{ matrix.os }} timeout-minutes: 30 strategy: fail-fast: false matrix: include: - node-version: 24 os: windows-latest e2e-browser: 'chromium' mode: 'dev' - node-version: 24 os: ubuntu-latest e2e-browser: 'firefox' mode: 'dev' - node-version: 24 os: macOS-latest e2e-browser: 'webkit' mode: 'dev' - node-version: 24 os: windows-latest e2e-browser: 'chromium' mode: 'build' - node-version: 24 os: ubuntu-latest e2e-browser: 'firefox' mode: 'build' - node-version: 24 os: macOS-latest e2e-browser: 'webkit' mode: 'build' env: KIT_E2E_BROWSER: ${{matrix.e2e-browser}} steps: - run: git config --global core.autocrlf false - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup with: node-version: ${{ matrix.node-version }} - run: pnpm playwright install ${{ matrix.e2e-browser }} - run: pnpm run sync-all - run: pnpm test:cross-platform:${{ matrix.mode }} - name: Print flaky test report run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash run: find packages -type d -name test-results -not -empty | tar -czf test-results-cross-platform-${{ matrix.mode }}.tar.gz --files-from=- - name: Upload test results if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: retention-days: 3 name: test-failure-cross-platform-${{ matrix.mode }}-${{ github.run_id }}-${{ matrix.os }}-${{ matrix.node-version }}-${{ matrix.e2e-browser }} path: test-results-cross-platform-${{ matrix.mode }}.tar.gz test-kit-server-side-route-resolution: runs-on: latchkey-small timeout-minutes: 30 strategy: fail-fast: false matrix: include: - mode: 'dev' - mode: 'build' steps: - run: git config --global core.autocrlf false - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup - run: pnpm playwright install chromium --no-shell - run: pnpm run sync-all - run: pnpm test:server-side-route-resolution:${{ matrix.mode }} - name: Print flaky test report run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash run: find packages -type d -name test-results -not -empty | tar -czf test-results-server-side-route-resolution-${{ matrix.mode }}.tar.gz --files-from=- - name: Upload test results if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: retention-days: 3 name: test-failure-server-side-route-resolution-${{ matrix.mode }}-${{ github.run_id }} path: test-results-server-side-route-resolution-${{ matrix.mode }}.tar.gz test-kit-svelte-async: runs-on: latchkey-small timeout-minutes: 30 strategy: fail-fast: false matrix: include: - mode: 'dev' - mode: 'build' steps: - run: git config --global core.autocrlf false - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup with: node-version: ${{ matrix.node-version }} - run: pnpm playwright install chromium --no-shell - run: pnpm run sync-all - run: pnpm test:svelte-async:${{ matrix.mode }} - name: Print flaky test report run: node scripts/print-flaky-test-report.js - name: Archive test results if: failure() shell: bash run: find packages -type d -name test-results -not -empty | tar -czf test-results-svelte-async-${{ matrix.mode }}.tar.gz --files-from=- - name: Upload test results if: failure() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: retention-days: 3 name: test-failure-svelte-async-${{ matrix.mode }}-${{ github.run_id }} path: test-results-svelte-async-${{ matrix.mode }}.tar.gz test-others: timeout-minutes: 30 runs-on: latchkey-small strategy: matrix: node-version: [18, 20, 22, 24] steps: - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - uses: ./.github/actions/node-setup with: node-version: ${{ matrix.node-version }} - run: pnpm playwright install chromium --no-shell - run: cd packages/kit && pnpm prepublishOnly - run: pnpm run test:others env: NODE_OPTIONS: ${{matrix.node-version == 22 && '--experimental-strip-types' || ''}} # allows loading svelte.config.ts
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. - Add a job timeout so a hung step cannot burn hours of runner time.
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 6 jobs (9 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.