Skip to content
Latchkey

tests workflow (mujocolab/mjlab)

The tests workflow from mujocolab/mjlab, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: mujocolab/mjlab.github/workflows/ci.ymlLicense Apache-2.0View source

What it does

This is the tests workflow from the mujocolab/mjlab repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: tests

on:
  push:
    branches: [main]
    paths-ignore:
      - '**.md'
      - '**.rst'
      - 'docs/**'
      - 'Makefile'
      - 'LICENSE'
      - 'scripts/benchmarks/**'
  pull_request:
    branches: [main]
    paths-ignore:
      - '**.md'
      - '**.rst'
      - 'docs/**'
      - 'Makefile'
      - 'LICENSE'
      - 'scripts/benchmarks/**'

env:
  UV_FROZEN: "1"

jobs:
  lint-format:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Run lint
        run: uvx ruff@0.14.14 check --diff
      - name: Run format
        run: uvx ruff@0.14.14 format --diff

  tests:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
        resolution: ["locked"]
        # Also test against a fresh resolve of the latest compatible
        # dependencies so a new upstream release breaks a PR instead of a
        # release.
        include:
          - python-version: "3.13"
            resolution: "unlocked"
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Restore Warp kernel cache
        uses: actions/cache@v4
        with:
          path: ~/.cache/warp
          key: warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-${{ matrix.resolution }}-${{ hashFiles('uv.lock', 'mjlab/**/*.py') }}
          restore-keys: |
            warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-${{ matrix.resolution }}-
      - name: Test with python ${{ matrix.python-version }} (locked deps)
        if: matrix.resolution == 'locked'
        run: uv run --extra cpu pytest
      - name: Test with python ${{ matrix.python-version }} (latest deps)
        if: matrix.resolution == 'unlocked'
        env:
          UV_FROZEN: "0"
        run: uv run --extra cpu --upgrade pytest

  pyright:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Test with python ${{ matrix.python-version }}
        run: uv run --extra cpu pyright

  ty-check:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Type check with python ${{ matrix.python-version }}
        run: uv run --extra cpu ty check

  stubs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Sync environment
        run: uv sync --extra cpu
      - name: Regenerate MuJoCo stubs
        run: bash typings/generate_mujoco_stubs.sh
      - name: Verify stubs are up to date
        run: |
          if ! git diff --exit-code typings/mujoco; then
            echo "::error::MuJoCo type stubs are out of date. Run 'make stubs' and commit the result."
            exit 1
          fi

  # Mirrors the release smoke test: build the artifacts and import mjlab from an
  # isolated, freshly resolved install, so packaging and clean-install issues
  # surface on the PR instead of at publish time.
  smoke-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Install Python 3.13
        run: uv python install 3.13
      - name: Build
        run: uv build
      # MUJOCO_GL=disable so `import mujoco` skips its GL backend import; the
      # runner has no GL libraries and the smoke test does not render.
      - name: Smoke test (wheel)
        run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
        env:
          MUJOCO_GL: disable
      - name: Smoke test (source distribution)
        run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
        env:
          MUJOCO_GL: disable

The same workflow, on Latchkey

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

name: tests
 
on:
  push:
    branches: [main]
    paths-ignore:
      - '**.md'
      - '**.rst'
      - 'docs/**'
      - 'Makefile'
      - 'LICENSE'
      - 'scripts/benchmarks/**'
  pull_request:
    branches: [main]
    paths-ignore:
      - '**.md'
      - '**.rst'
      - 'docs/**'
      - 'Makefile'
      - 'LICENSE'
      - 'scripts/benchmarks/**'
 
env:
  UV_FROZEN: "1"
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  lint-format:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Run lint
        run: uvx ruff@0.14.14 check --diff
      - name: Run format
        run: uvx ruff@0.14.14 format --diff
 
  tests:
    timeout-minutes: 30
    runs-on: latchkey-small
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
        resolution: ["locked"]
        # Also test against a fresh resolve of the latest compatible
        # dependencies so a new upstream release breaks a PR instead of a
        # release.
        include:
          - python-version: "3.13"
            resolution: "unlocked"
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Restore Warp kernel cache
        uses: actions/cache@v4
        with:
          path: ~/.cache/warp
          key: warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-${{ matrix.resolution }}-${{ hashFiles('uv.lock', 'mjlab/**/*.py') }}
          restore-keys: |
            warp-kernels-${{ runner.os }}-${{ runner.arch }}-${{ matrix.python-version }}-${{ matrix.resolution }}-
      - name: Test with python ${{ matrix.python-version }} (locked deps)
        if: matrix.resolution == 'locked'
        run: uv run --extra cpu pytest
      - name: Test with python ${{ matrix.python-version }} (latest deps)
        if: matrix.resolution == 'unlocked'
        env:
          UV_FROZEN: "0"
        run: uv run --extra cpu --upgrade pytest
 
  pyright:
    timeout-minutes: 30
    runs-on: latchkey-small
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Test with python ${{ matrix.python-version }}
        run: uv run --extra cpu pyright
 
  ty-check:
    timeout-minutes: 30
    runs-on: latchkey-small
    strategy:
      matrix:
        python-version: ["3.10", "3.11", "3.12", "3.13"]
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          python-version: ${{ matrix.python-version }}
          enable-cache: true
          version: "0.9.27"
      - name: Type check with python ${{ matrix.python-version }}
        run: uv run --extra cpu ty check
 
  stubs:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Sync environment
        run: uv sync --extra cpu
      - name: Regenerate MuJoCo stubs
        run: bash typings/generate_mujoco_stubs.sh
      - name: Verify stubs are up to date
        run: |
          if ! git diff --exit-code typings/mujoco; then
            echo "::error::MuJoCo type stubs are out of date. Run 'make stubs' and commit the result."
            exit 1
          fi
 
  # Mirrors the release smoke test: build the artifacts and import mjlab from an
  # isolated, freshly resolved install, so packaging and clean-install issues
  # surface on the PR instead of at publish time.
  smoke-test:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v6
      - name: Setup uv
        uses: astral-sh/setup-uv@v7
        with:
          enable-cache: true
          version: "0.9.27"
      - name: Install Python 3.13
        run: uv python install 3.13
      - name: Build
        run: uv build
      # MUJOCO_GL=disable so `import mujoco` skips its GL backend import; the
      # runner has no GL libraries and the smoke test does not render.
      - name: Smoke test (wheel)
        run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
        env:
          MUJOCO_GL: disable
      - name: Smoke test (source distribution)
        run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
        env:
          MUJOCO_GL: disable
 

What changed

1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

This workflow runs 6 jobs (15 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