Skip to content
Latchkey

Test & Deploy workflow (iterative/cml)

The Test & Deploy workflow from iterative/cml, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, 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: iterative/cml.github/workflows/test-deploy.ymlLicense Apache-2.0View source

What it does

This is the Test & Deploy workflow from the iterative/cml 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: Test & Deploy
on:
  pull_request_target:
  workflow_dispatch:
  workflow_call:
    inputs:
      release:
        required: true
        type: boolean
  schedule:
    - cron: '0 8 * * 1' # M H d m w (Mondays at 8:00)
jobs:
  authorize:
    environment:
      ${{ (github.event_name == 'pull_request_target' &&
      github.event.pull_request.head.repo.full_name != github.repository) &&
      'external' || 'internal' }}
    runs-on: ubuntu-latest
    steps:
      - run: echo ✓
  check-lock:
    needs: authorize
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - name: npm lock file is v2
        run: jq --exit-status .lockfileVersion==2 < package-lock.json
  lint:
    needs: authorize
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
      - run: npm ci
      - run: npm run lint
  test:
    needs: authorize
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
        with:
          node-version: 16
      - uses: actions/setup-python@v2
        with:
          python-version: 3.9
      - run: |
          pip install tensorboard
          pip install -I protobuf==3.20.1
      - run: npm ci && npm install --global
      - run: npm run test
        env:
          GITHUB_TOKEN: ${{ github.token }}
          TEST_GITHUB_TOKEN: ${{ secrets.TEST_GITHUB_TOKEN }}
          TEST_GITHUB_REPOSITORY: ${{ vars.TEST_GITHUB_REPOSITORY }}
          TEST_GITHUB_COMMIT: ${{ vars.TEST_GITHUB_COMMIT }}
          TEST_GITHUB_ISSUE: ${{ vars.TEST_GITHUB_ISSUE }}
          TEST_GITLAB_TOKEN: ${{ secrets.TEST_GITLAB_TOKEN }}
          TEST_GITLAB_REPOSITORY: ${{ vars.TEST_GITLAB_REPOSITORY }}
          TEST_GITLAB_COMMIT: ${{ vars.TEST_GITLAB_COMMIT }}
          TEST_GITLAB_ISSUE: ${{ vars.TEST_GITLAB_ISSUE }}
          TEST_BITBUCKET_TOKEN: ${{ secrets.TEST_BITBUCKET_TOKEN }}
          TEST_BITBUCKET_REPOSITORY: ${{ vars.TEST_BITBUCKET_REPOSITORY }}
          TEST_BITBUCKET_COMMIT: ${{ vars.TEST_BITBUCKET_COMMIT }}
          TEST_BITBUCKET_ISSUE: ${{ vars.TEST_BITBUCKET_ISSUE }}
  test-os:
    needs: authorize
    name: test-${{ matrix.system }}
    strategy:
      matrix:
        system: [ubuntu, macos, windows]
    runs-on: ${{ matrix.system }}-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - if: matrix.system == 'windows'
        uses: actions/setup-node@v3
      - name: install
        shell: bash
        run: |
          # https://github.com/npm/npm/issues/18503#issuecomment-347579469
          npm pack && npm install -g --no-save ./*cml*.tgz
          for cmd in '' runner publish pr; do
            cml $cmd --version
          done
      - if: matrix.system != 'windows'
        run: |
          for cmd in runner publish pr; do
            cml-$cmd --version
          done
  packages:
    needs: [lint, test, test-os]
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.publish.outputs.version }}
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
        with:
          registry-url: https://registry.npmjs.org
      - run: npm install
      - id: publish
        run: |
          VERSION=$(jq -r .version < package.json)
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          npm install --dry-run @dvcorg/cml@$VERSION ||
          npm ${{ inputs.release && 'publish' || 'publish --dry-run' }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      # Step required "thanks" to https://github.com/actions/runner-images/issues/6283
      - uses: Homebrew/actions/setup-homebrew@3040c87fbdd10e6ec48d90bd23cb0abb6d66152d
      - run: brew install ldid
      - run: |
          cp node_modules/@npcz/magic/dist/magic.mgc assets/magic.mgc
          npx --yes pkg --no-bytecode --public-packages "*" --public package.json
          for cmd in '' runner publish pr; do build/cml-linux-x64 $cmd --version; done
          cp build/cml-linux{-x64,}
          cp build/cml-macos{-x64,}
      - if: inputs.release
        run:
          find build -type f | xargs gh release upload
          "${GITHUB_HEAD_REF#bump/}"
        env:
          GITHUB_TOKEN: ${{ github.token }}
  images:
    needs: packages
    secrets: inherit
    uses: ./.github/workflows/images.yml
    with:
      release: ${{ inputs.release || false }}
      version: ${{ needs.packages.outputs.version }}

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: Test & Deploy
on:
  pull_request_target:
  workflow_dispatch:
  workflow_call:
    inputs:
      release:
        required: true
        type: boolean
  schedule:
    - cron: '0 8 * * 1' # M H d m w (Mondays at 8:00)
jobs:
  authorize:
    timeout-minutes: 30
    environment:
      ${{ (github.event_name == 'pull_request_target' &&
      github.event.pull_request.head.repo.full_name != github.repository) &&
      'external' || 'internal' }}
    runs-on: latchkey-small
    steps:
      - run: echo ✓
  check-lock:
    timeout-minutes: 30
    needs: authorize
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - name: npm lock file is v2
        run: jq --exit-status .lockfileVersion==2 < package-lock.json
  lint:
    timeout-minutes: 30
    needs: authorize
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
        with:
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
  test:
    timeout-minutes: 30
    needs: authorize
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
        with:
          cache: 'npm'
          node-version: 16
      - uses: actions/setup-python@v2
        with:
          python-version: 3.9
      - run: |
          pip install tensorboard
          pip install -I protobuf==3.20.1
      - run: npm ci && npm install --global
      - run: npm run test
        env:
          GITHUB_TOKEN: ${{ github.token }}
          TEST_GITHUB_TOKEN: ${{ secrets.TEST_GITHUB_TOKEN }}
          TEST_GITHUB_REPOSITORY: ${{ vars.TEST_GITHUB_REPOSITORY }}
          TEST_GITHUB_COMMIT: ${{ vars.TEST_GITHUB_COMMIT }}
          TEST_GITHUB_ISSUE: ${{ vars.TEST_GITHUB_ISSUE }}
          TEST_GITLAB_TOKEN: ${{ secrets.TEST_GITLAB_TOKEN }}
          TEST_GITLAB_REPOSITORY: ${{ vars.TEST_GITLAB_REPOSITORY }}
          TEST_GITLAB_COMMIT: ${{ vars.TEST_GITLAB_COMMIT }}
          TEST_GITLAB_ISSUE: ${{ vars.TEST_GITLAB_ISSUE }}
          TEST_BITBUCKET_TOKEN: ${{ secrets.TEST_BITBUCKET_TOKEN }}
          TEST_BITBUCKET_REPOSITORY: ${{ vars.TEST_BITBUCKET_REPOSITORY }}
          TEST_BITBUCKET_COMMIT: ${{ vars.TEST_BITBUCKET_COMMIT }}
          TEST_BITBUCKET_ISSUE: ${{ vars.TEST_BITBUCKET_ISSUE }}
  test-os:
    timeout-minutes: 30
    needs: authorize
    name: test-${{ matrix.system }}
    strategy:
      matrix:
        system: [ubuntu, macos, windows]
    runs-on: ${{ matrix.system }}-latest
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - if: matrix.system == 'windows'
        uses: actions/setup-node@v3
        with:
          cache: 'npm'
      - name: install
        shell: bash
        run: |
          # https://github.com/npm/npm/issues/18503#issuecomment-347579469
          npm pack && npm install -g --no-save ./*cml*.tgz
          for cmd in '' runner publish pr; do
            cml $cmd --version
          done
      - if: matrix.system != 'windows'
        run: |
          for cmd in runner publish pr; do
            cml-$cmd --version
          done
  packages:
    timeout-minutes: 30
    needs: [lint, test, test-os]
    runs-on: latchkey-small
    outputs:
      version: ${{ steps.publish.outputs.version }}
    steps:
      - uses: actions/checkout@v3
        with:
          ref: ${{ github.event.pull_request.head.sha || github.ref }}
      - uses: actions/setup-node@v3
        with:
          cache: 'npm'
          registry-url: https://registry.npmjs.org
      - run: npm install
      - id: publish
        run: |
          VERSION=$(jq -r .version < package.json)
          echo "version=$VERSION" >> $GITHUB_OUTPUT
          npm install --dry-run @dvcorg/cml@$VERSION ||
          npm ${{ inputs.release && 'publish' || 'publish --dry-run' }}
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
      # Step required "thanks" to https://github.com/actions/runner-images/issues/6283
      - uses: Homebrew/actions/setup-homebrew@3040c87fbdd10e6ec48d90bd23cb0abb6d66152d
      - run: brew install ldid
      - run: |
          cp node_modules/@npcz/magic/dist/magic.mgc assets/magic.mgc
          npx --yes pkg --no-bytecode --public-packages "*" --public package.json
          for cmd in '' runner publish pr; do build/cml-linux-x64 $cmd --version; done
          cp build/cml-linux{-x64,}
          cp build/cml-macos{-x64,}
      - if: inputs.release
        run:
          find build -type f | xargs gh release upload
          "${GITHUB_HEAD_REF#bump/}"
        env:
          GITHUB_TOKEN: ${{ github.token }}
  images:
    timeout-minutes: 30
    needs: packages
    secrets: inherit
    uses: ./.github/workflows/images.yml
    with:
      release: ${{ inputs.release || false }}
      version: ${{ needs.packages.outputs.version }}
 

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 7 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.

Actions used in this workflow