DevTools workflow (GoogleChrome/lighthouse)
The DevTools workflow from GoogleChrome/lighthouse, explained and optimized by Latchkey.
CI health: D - needs work
Point runs-on at Latchkey and get caching, run de-duplication, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the DevTools workflow from the GoogleChrome/lighthouse 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
name: DevTools
on:
push:
branches: [main]
pull_request: # run on all PRs, not just PRs to a particular branch
env:
DEPOT_TOOLS_PATH: ${{ github.workspace }}/depot-tools
DEVTOOLS_PATH: ${{ github.workspace }}/devtools-frontend
PUPPETEER_SKIP_DOWNLOAD: 1
jobs:
build:
runs-on: ubuntu-latest
env:
FORCE_COLOR: true
steps:
- name: Set $PATH
run: echo "$DEPOT_TOOLS_PATH" >> $GITHUB_PATH
- name: git clone
uses: actions/checkout@v4
with:
path: lighthouse
- name: Use Node.js 22.19
uses: actions/setup-node@v4
with:
node-version: '22.19'
- name: Generate cache hash
run: bash $GITHUB_WORKSPACE/lighthouse/.github/scripts/generate-devtools-hash.sh > cdt-test-hash.txt
- name: Set week of the year
run: echo "WEEK_OF_THE_YEAR=$(date +%V)" >> $GITHUB_ENV
# Caches are invalidated at least once a week, so that's the max time between testing
# with the latest dependencies. Any commit to the DevTools repo touching Lighthouse
# code will invalidate the cache sooner.
- name: Cache depot tools and devtools
id: devtools-cache
uses: actions/cache@v3
with:
path: |
${{ env.DEPOT_TOOLS_PATH }}
${{ env.DEVTOOLS_PATH }}
${{ github.workspace }}/.gclient
${{ github.workspace }}/.gclient_entries
# This hash key changes:
# 1) every monday (so invalidates once a week)
# 2) every commit to CDT touching files important to Lighthouse web tests
# 3) every change to file in Lighthouse repo important to running these tests.
#
# The number is how many times this hash key was manually updated to break the cache.
key: ${{ runner.os }}-15-${{ env.WEEK_OF_THE_YEAR }}-${{ hashFiles('cdt-test-hash.txt') }}
restore-keys: ${{ runner.os }}-15
- name: Set GHA_DEVTOOLS_CACHE_HIT
if: steps.devtools-cache.outputs.cache-hit == 'true'
run: echo "GHA_DEVTOOLS_CACHE_HIT=1" >> $GITHUB_ENV
- run: yarn --frozen-lockfile --network-timeout 1000000
working-directory: ${{ github.workspace }}/lighthouse
- name: Download depot tools
run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-depot-tools.sh
- name: Download DevTools Frontend
run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-devtools.sh
- name: Roll Lighthouse + build DevTools
run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/roll-devtools.sh
- name: Cache build artifacts
id: devtools-build-artifacts
uses: actions/cache@v3
with:
path: |
${{ env.DEVTOOLS_PATH }}
${{ github.workspace }}/.gclient
${{ github.workspace }}/.gclient_entries
key: devtools-build-artifacts-${{ github.run_id }}
e2e:
needs: [build]
runs-on: ubuntu-latest
env:
FORCE_COLOR: true
steps:
- name: git clone
uses: actions/checkout@v4
with:
path: lighthouse
- name: Use Node.js 22.19
uses: actions/setup-node@v4
with:
node-version: '22.19'
- run: yarn --frozen-lockfile --network-timeout 1000000
working-directory: ${{ github.workspace }}/lighthouse
- name: Set $PATH
run: echo "$DEPOT_TOOLS_PATH" >> $GITHUB_PATH
# For vpython.
- name: Download depot tools
run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-depot-tools.sh
# Since Ubuntu 23, dev builds of Chromium need this.
# https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Load build artifacts
id: devtools-build-artifacts
uses: actions/cache@v3
with:
path: |
${{ env.DEVTOOLS_PATH }}
${{ github.workspace }}/.gclient
${{ github.workspace }}/.gclient_entries
key: devtools-build-artifacts-${{ github.run_id }}
- name: Run e2e tests
run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/run-e2e-tests.sh
smoke:
needs: [build]
strategy:
matrix:
smoke-test-shard: [1, 2, 3]
# e.g. if set 1 fails, continue with set 2 anyway
fail-fast: false
runs-on: ubuntu-latest
env:
CHROME_PATH: ${{ github.workspace }}/lighthouse/.tmp/chrome-tot/chrome
FORCE_COLOR: true
name: DevTools smoke ${{ matrix.smoke-test-shard }}/${{ strategy.job-total }}
steps:
- name: git clone
uses: actions/checkout@v4
with:
path: lighthouse
- name: Use Node.js 22.19
uses: actions/setup-node@v4
with:
node-version: '22.19'
- name: Load build artifacts
id: devtools-build-artifacts
uses: actions/cache@v3
with:
path: |
${{ env.DEVTOOLS_PATH }}
${{ github.workspace }}/.gclient
${{ github.workspace }}/.gclient_entries
key: devtools-build-artifacts-${{ github.run_id }}
- run: yarn --frozen-lockfile --network-timeout 1000000
working-directory: ${{ github.workspace }}/lighthouse
# This is only done because the import of `parseChromeFlags` in pptr-run-devtool.js triggers imports that eventually
# fail because of how report-assets.js reads generated files.
- run: yarn build-report
working-directory: ${{ github.workspace }}/lighthouse
# Since Ubuntu 23, dev builds of Chromium need this.
# https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md
- run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
- name: Install Chrome ToT
run: bash ${{ github.workspace }}/lighthouse/core/scripts/download-chrome.sh
- run: mkdir latest-run
working-directory: ${{ github.workspace }}/lighthouse
- name: yarn smoke --runner devtools
run: yarn smoke --runner devtools --shard=${{ matrix.smoke-test-shard }}/${{ strategy.job-total }} --jobs=3 --retries=2 --debug
working-directory: ${{ github.workspace }}/lighthouse
- name: Upload failures
if: failure()
uses: actions/upload-artifact@v7
with:
name: Smokehouse (devtools smoke)
path: ${{ github.workspace }}/lighthouse/.tmp/smokehouse-failures/
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: DevTools on: push: branches: [main] pull_request: # run on all PRs, not just PRs to a particular branch env: DEPOT_TOOLS_PATH: ${{ github.workspace }}/depot-tools DEVTOOLS_PATH: ${{ github.workspace }}/devtools-frontend PUPPETEER_SKIP_DOWNLOAD: 1 concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: timeout-minutes: 30 runs-on: latchkey-small env: FORCE_COLOR: true steps: - name: Set $PATH run: echo "$DEPOT_TOOLS_PATH" >> $GITHUB_PATH - name: git clone uses: actions/checkout@v4 with: path: lighthouse - name: Use Node.js 22.19 uses: actions/setup-node@v4 with: cache: 'npm' node-version: '22.19' - name: Generate cache hash run: bash $GITHUB_WORKSPACE/lighthouse/.github/scripts/generate-devtools-hash.sh > cdt-test-hash.txt - name: Set week of the year run: echo "WEEK_OF_THE_YEAR=$(date +%V)" >> $GITHUB_ENV # Caches are invalidated at least once a week, so that's the max time between testing # with the latest dependencies. Any commit to the DevTools repo touching Lighthouse # code will invalidate the cache sooner. - name: Cache depot tools and devtools id: devtools-cache uses: actions/cache@v3 with: path: | ${{ env.DEPOT_TOOLS_PATH }} ${{ env.DEVTOOLS_PATH }} ${{ github.workspace }}/.gclient ${{ github.workspace }}/.gclient_entries # This hash key changes: # 1) every monday (so invalidates once a week) # 2) every commit to CDT touching files important to Lighthouse web tests # 3) every change to file in Lighthouse repo important to running these tests. # # The number is how many times this hash key was manually updated to break the cache. key: ${{ runner.os }}-15-${{ env.WEEK_OF_THE_YEAR }}-${{ hashFiles('cdt-test-hash.txt') }} restore-keys: ${{ runner.os }}-15 - name: Set GHA_DEVTOOLS_CACHE_HIT if: steps.devtools-cache.outputs.cache-hit == 'true' run: echo "GHA_DEVTOOLS_CACHE_HIT=1" >> $GITHUB_ENV - run: yarn --frozen-lockfile --network-timeout 1000000 working-directory: ${{ github.workspace }}/lighthouse - name: Download depot tools run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-depot-tools.sh - name: Download DevTools Frontend run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-devtools.sh - name: Roll Lighthouse + build DevTools run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/roll-devtools.sh - name: Cache build artifacts id: devtools-build-artifacts uses: actions/cache@v3 with: path: | ${{ env.DEVTOOLS_PATH }} ${{ github.workspace }}/.gclient ${{ github.workspace }}/.gclient_entries key: devtools-build-artifacts-${{ github.run_id }} e2e: timeout-minutes: 30 needs: [build] runs-on: latchkey-small env: FORCE_COLOR: true steps: - name: git clone uses: actions/checkout@v4 with: path: lighthouse - name: Use Node.js 22.19 uses: actions/setup-node@v4 with: cache: 'npm' node-version: '22.19' - run: yarn --frozen-lockfile --network-timeout 1000000 working-directory: ${{ github.workspace }}/lighthouse - name: Set $PATH run: echo "$DEPOT_TOOLS_PATH" >> $GITHUB_PATH # For vpython. - name: Download depot tools run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/download-depot-tools.sh # Since Ubuntu 23, dev builds of Chromium need this. # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - name: Load build artifacts id: devtools-build-artifacts uses: actions/cache@v3 with: path: | ${{ env.DEVTOOLS_PATH }} ${{ github.workspace }}/.gclient ${{ github.workspace }}/.gclient_entries key: devtools-build-artifacts-${{ github.run_id }} - name: Run e2e tests run: bash $GITHUB_WORKSPACE/lighthouse/core/test/devtools-tests/run-e2e-tests.sh smoke: timeout-minutes: 30 needs: [build] strategy: matrix: smoke-test-shard: [1, 2, 3] # e.g. if set 1 fails, continue with set 2 anyway fail-fast: false runs-on: latchkey-small env: CHROME_PATH: ${{ github.workspace }}/lighthouse/.tmp/chrome-tot/chrome FORCE_COLOR: true name: DevTools smoke ${{ matrix.smoke-test-shard }}/${{ strategy.job-total }} steps: - name: git clone uses: actions/checkout@v4 with: path: lighthouse - name: Use Node.js 22.19 uses: actions/setup-node@v4 with: cache: 'npm' node-version: '22.19' - name: Load build artifacts id: devtools-build-artifacts uses: actions/cache@v3 with: path: | ${{ env.DEVTOOLS_PATH }} ${{ github.workspace }}/.gclient ${{ github.workspace }}/.gclient_entries key: devtools-build-artifacts-${{ github.run_id }} - run: yarn --frozen-lockfile --network-timeout 1000000 working-directory: ${{ github.workspace }}/lighthouse # This is only done because the import of `parseChromeFlags` in pptr-run-devtool.js triggers imports that eventually # fail because of how report-assets.js reads generated files. - run: yarn build-report working-directory: ${{ github.workspace }}/lighthouse # Since Ubuntu 23, dev builds of Chromium need this. # https://chromium.googlesource.com/chromium/src/+/main/docs/security/apparmor-userns-restrictions.md - run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 - name: Install Chrome ToT run: bash ${{ github.workspace }}/lighthouse/core/scripts/download-chrome.sh - run: mkdir latest-run working-directory: ${{ github.workspace }}/lighthouse - name: yarn smoke --runner devtools run: yarn smoke --runner devtools --shard=${{ matrix.smoke-test-shard }}/${{ strategy.job-total }} --jobs=3 --retries=2 --debug working-directory: ${{ github.workspace }}/lighthouse - name: Upload failures if: failure() uses: actions/upload-artifact@v7 with: name: Smokehouse (devtools smoke) path: ${{ github.workspace }}/lighthouse/.tmp/smokehouse-failures/
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.
- Cache dependency installs on the setup step so they are served from cache.
- 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 3 jobs (5 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.