Skip to content
Latchkey

CI workflow (mui/material-ui)

The CI workflow from mui/material-ui, explained and optimized by Latchkey.

C

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.

Grade your own workflow free or run it on Latchkey →
Source: mui/material-ui.github/workflows/ci.ymlLicense MITView source

What it does

This is the CI workflow from the mui/material-ui 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

workflow (.yml)
name: CI

on:
  push:
    branches:
      # should sync with ci-check.yml as a workaround to bypass github checks
      - master
      - next
      - v*.x
  pull_request:
    paths-ignore:
      # should sync with ci-check.yml as a workaround to bypass github checks
      - 'docs/**'

permissions: {}

jobs:
  # Tests dev-only scripts across all supported dev environments
  test-dev:
    # l10nbot does not affect dev scripts.
    if: ${{ github.actor != 'l10nbot' }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, windows-latest, ubuntu-latest]
    permissions:
      contents: read
      pull-requests: write
    steps:
      - run: echo '${{ github.actor }}'
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          # fetch all tags which are required for `pnpm release:changelog`
          fetch-depth: 0
      - name: Set up pnpm
        uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
      - name: Use Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: '22.22.3'
          cache: 'pnpm' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-dependencies
      - run: pnpm install
      - name: Cache Next.js build
        uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
        with:
          path: docs/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('docs/**/*.js', 'docs/**/*.ts', 'docs/**/*.tsx', 'docs/**/*.jsx', 'docs/**/*.json', 'docs/**/*.md', 'docs/**/*.mdx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-
            ${{ runner.os }}-nextjs-
      - run: pnpm release:build
      - name: Publish packages to pkg.pr.new
        uses: mui/mui-public/.github/actions/ci-publish@9033c846aecf0e1454f13486af685d93269456e9 # master
        if: ${{ matrix.os == 'ubuntu-latest' }}
      - name: Build docs
        run: pnpm docs:build
        env:
          NODE_OPTIONS: --max_old_space_size=6144
          # macOS-latest has 3 CPUs, but we get "EMFILE: too many open files" errors with that parallelism
          # Limit Next.js to 2 CPUs to prevent file descriptor exhaustion. Empty string uses os.availableParallelism()
          NEXT_PARALLELISM: ${{ runner.os == 'macOS' && '2' || '' }}
          GITHUB_AUTH: Bearer ${{ secrets.GITHUB_TOKEN }}
      # - run: pnpm release:changelog
      #   env:
      #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Debug export-detail.json on when pnpm docs:build fails with EMFILE error
        if: failure()
        run: cat ./docs/.next/export-detail.json || true
      - name: Extract Vale version
        if: ${{ matrix.os == 'ubuntu-latest' }}
        id: vale-version
        run: |
          VERSION=$(node -p "(require('./package.json').config && require('./package.json').config.valeVersion) || ''")
          echo "vale_version=$VERSION" >> $GITHUB_OUTPUT
      - uses: vale-cli/vale-action@85f9f7f2c5f449ac0ae5b66662961bae3f77ca6a # 2.1.2
        continue-on-error: true # GitHub Action flag needed until https://github.com/errata-ai/vale-action/issues/89 is fixed
        if: ${{ matrix.os == 'ubuntu-latest' }}
        with:
          version: ${{ steps.vale-version.outputs.vale_version }}
          # Errors should be more visible
          fail_on_error: true
          # The other reports don't work, not really https://github.com/reviewdog/reviewdog#reporters
          reporter: github-pr-check
          # Required, set by GitHub actions automatically:
          # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret
          token: ${{secrets.GITHUB_TOKEN}}

  # Mirrors the real publish workflow environment (`publish.yml`) so an env
  # mismatch - e.g. the Node version pinned by `publish-prepare` violating our
  # engineStrict `engines` range - is caught here instead of during publishing.
  publish-dry-run:
    name: Publish Dry Run

    if: ${{ github.repository_owner == 'mui' }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
      - name: Prepare for publishing
        uses: mui/mui-public/.github/actions/publish-prepare@5a12855e473909291f8782c324f2c48983054337 # master
        with:
          node-version: '22.22.3'
      - name: Dry run npm publishing
        env:
          IS_PUBLISH_TEST: 'true'
        run: pnpm code-infra publish --ci --dry-run

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: CI
 
on:
  push:
    branches:
      # should sync with ci-check.yml as a workaround to bypass github checks
      - master
      - next
      - v*.x
  pull_request:
    paths-ignore:
      # should sync with ci-check.yml as a workaround to bypass github checks
      - 'docs/**'
 
permissions: {}
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  # Tests dev-only scripts across all supported dev environments
  test-dev:
    timeout-minutes: 30
    # l10nbot does not affect dev scripts.
    if: ${{ github.actor != 'l10nbot' }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [macos-latest, windows-latest, ubuntu-latest]
    permissions:
      contents: read
      pull-requests: write
    steps:
      - run: echo '${{ github.actor }}'
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          # fetch all tags which are required for `pnpm release:changelog`
          fetch-depth: 0
      - name: Set up pnpm
        uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
      - name: Use Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: '22.22.3'
          cache: 'pnpm' # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#caching-packages-dependencies
      - run: pnpm install
      - name: Cache Next.js build
        uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
        with:
          path: docs/.next/cache
          key: ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('docs/**/*.js', 'docs/**/*.ts', 'docs/**/*.tsx', 'docs/**/*.jsx', 'docs/**/*.json', 'docs/**/*.md', 'docs/**/*.mdx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('pnpm-lock.yaml') }}-
            ${{ runner.os }}-nextjs-
      - run: pnpm release:build
      - name: Publish packages to pkg.pr.new
        uses: mui/mui-public/.github/actions/ci-publish@9033c846aecf0e1454f13486af685d93269456e9 # master
        if: ${{ matrix.os == 'ubuntu-latest' }}
      - name: Build docs
        run: pnpm docs:build
        env:
          NODE_OPTIONS: --max_old_space_size=6144
          # macOS-latest has 3 CPUs, but we get "EMFILE: too many open files" errors with that parallelism
          # Limit Next.js to 2 CPUs to prevent file descriptor exhaustion. Empty string uses os.availableParallelism()
          NEXT_PARALLELISM: ${{ runner.os == 'macOS' && '2' || '' }}
          GITHUB_AUTH: Bearer ${{ secrets.GITHUB_TOKEN }}
      # - run: pnpm release:changelog
      #   env:
      #     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Debug export-detail.json on when pnpm docs:build fails with EMFILE error
        if: failure()
        run: cat ./docs/.next/export-detail.json || true
      - name: Extract Vale version
        if: ${{ matrix.os == 'ubuntu-latest' }}
        id: vale-version
        run: |
          VERSION=$(node -p "(require('./package.json').config && require('./package.json').config.valeVersion) || ''")
          echo "vale_version=$VERSION" >> $GITHUB_OUTPUT
      - uses: vale-cli/vale-action@85f9f7f2c5f449ac0ae5b66662961bae3f77ca6a # 2.1.2
        continue-on-error: true # GitHub Action flag needed until https://github.com/errata-ai/vale-action/issues/89 is fixed
        if: ${{ matrix.os == 'ubuntu-latest' }}
        with:
          version: ${{ steps.vale-version.outputs.vale_version }}
          # Errors should be more visible
          fail_on_error: true
          # The other reports don't work, not really https://github.com/reviewdog/reviewdog#reporters
          reporter: github-pr-check
          # Required, set by GitHub actions automatically:
          # https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret
          token: ${{secrets.GITHUB_TOKEN}}
 
  # Mirrors the real publish workflow environment (`publish.yml`) so an env
  # mismatch - e.g. the Node version pinned by `publish-prepare` violating our
  # engineStrict `engines` range - is caught here instead of during publishing.
  publish-dry-run:
    timeout-minutes: 30
    name: Publish Dry Run
 
    if: ${{ github.repository_owner == 'mui' }}
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
      - name: Prepare for publishing
        uses: mui/mui-public/.github/actions/publish-prepare@5a12855e473909291f8782c324f2c48983054337 # master
        with:
          node-version: '22.22.3'
      - name: Dry run npm publishing
        env:
          IS_PUBLISH_TEST: 'true'
        run: pnpm code-infra publish --ci --dry-run
 

What changed

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:

This workflow runs 2 jobs (4 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow