CI workflow (stylelint/stylelint)
The CI workflow from stylelint/stylelint, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, 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 stylelint/stylelint 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:
merge_group:
env:
FORCE_COLOR: 2
permissions:
contents: read
jobs:
lint:
uses: stylelint/.github/.github/workflows/call-lint.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1
permissions:
contents: read
test:
uses: stylelint/.github/.github/workflows/call-test.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1
with:
node-version: '["20", "22", "24", "26"]'
os: '["ubuntu-latest", "windows-latest", "macos-latest"]'
exclude: '[{"node-version": "24", "os": "ubuntu-latest"}]' # for coverage
permissions:
contents: read
test-coverage:
name: Test on Node.js 24 and ubuntu-latest with coverage
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: '24'
cache: npm
- name: Install latest npm
run: npm install --global npm
- name: Install dependencies
run: npm ci
- name: Test with coverage
run: npm run test-coverage
env:
# https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes
NODE_OPTIONS: '--max-old-space-size=4096'
- name: Upload coverage to Codecov
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
files: ./.coverage/lcov.info
fail_ci_if_error: true
# This test is only enabled when the relevant environment variable is set,
# so it is run here, separately from the main test matrix.
- name: Run test for Yarn PnP
run: |
npm install --global corepack
npm run test-node
env:
STYLELINT_TEST_YARN_PNP: 'true'
YARN_ENABLE_HARDENED_MODE: 0 # https://yarnpkg.com/features/security#hardened-mode
- name: Verify changeset
# Skip fork PRs due to GitHub token permissions.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
run: |
npm run changeset
npm run lint:md
git checkout -- CHANGELOG.md
env:
GITHUB_TOKEN: ${{ github.token }} # required by Changeset
spellcheck:
runs-on: ubuntu-slim
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Install codespell
run: pip install codespell
- name: Spellcheck
# Ignore a CI failure because there are false positives.
run: codespell || echo 'Fix misspells via "codespell" on your console, or ignore false positives.'
dependency-review:
if: github.event_name == 'pull_request'
uses: stylelint/.github/.github/workflows/call-dependency-review.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1
permissions:
contents: read
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: merge_group: env: FORCE_COLOR: 2 permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: lint: timeout-minutes: 30 uses: stylelint/.github/.github/workflows/call-lint.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1 permissions: contents: read test: timeout-minutes: 30 uses: stylelint/.github/.github/workflows/call-test.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1 with: node-version: '["20", "22", "24", "26"]' os: '["ubuntu-latest", "windows-latest", "macos-latest"]' exclude: '[{"node-version": "24", "os": "ubuntu-latest"}]' # for coverage permissions: contents: read test-coverage: name: Test on Node.js 24 and ubuntu-latest with coverage runs-on: latchkey-small timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Set up Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: node-version: '24' cache: npm - name: Install latest npm run: npm install --global npm - name: Install dependencies run: npm ci - name: Test with coverage run: npm run test-coverage env: # https://nodejs.org/api/cli.html#--max-old-space-sizesize-in-megabytes NODE_OPTIONS: '--max-old-space-size=4096' - name: Upload coverage to Codecov uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: files: ./.coverage/lcov.info fail_ci_if_error: true # This test is only enabled when the relevant environment variable is set, # so it is run here, separately from the main test matrix. - name: Run test for Yarn PnP run: | npm install --global corepack npm run test-node env: STYLELINT_TEST_YARN_PNP: 'true' YARN_ENABLE_HARDENED_MODE: 0 # https://yarnpkg.com/features/security#hardened-mode - name: Verify changeset # Skip fork PRs due to GitHub token permissions. if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository run: | npm run changeset npm run lint:md git checkout -- CHANGELOG.md env: GITHUB_TOKEN: ${{ github.token }} # required by Changeset spellcheck: runs-on: ubuntu-slim timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 - name: Install codespell run: pip install codespell - name: Spellcheck # Ignore a CI failure because there are false positives. run: codespell || echo 'Fix misspells via "codespell" on your console, or ignore false positives.' dependency-review: timeout-minutes: 30 if: github.event_name == 'pull_request' uses: stylelint/.github/.github/workflows/call-dependency-review.yml@de22fededfbe64a953912f8306e71923d7a503d3 # 1.0.1 permissions: contents: read
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.
- 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
This workflow runs 5 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.