Run Tests workflow (google/closure-compiler)
The Run Tests workflow from google/closure-compiler, 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 Run Tests workflow from the google/closure-compiler 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
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Format reference: https://docs.github.com/en/actions/reference
name: Run Tests
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#on
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
schedule:
# Daily at 12pm UTC
- cron: '0 12 * * *'
# Can be called from other workflow to run the tests
workflow_call:
inputs:
ref:
description: 'Tag or commit to checkout'
required: false
type: string
permissions:
contents: read
env:
VERSION_NODEJS: '22'
UNSYMLINK_DIR: bazel-bin-unsymlink
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobs
jobs:
build-and-test:
name: Build and Test
runs-on: ubuntu-latest
steps:
- name: Setup Java
# https://github.com/marketplace/actions/setup-java-jdk
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: zulu
java-version: '21'
java-package: jdk
architecture: x64
# Clone closure-compiler repo from the commit under test into current directory.
- name: Checkout Current closure-compiler Commit
# https://github.com/marketplace/actions/checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false
# https://github.com/bazel-contrib/setup-bazel
- uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
with:
# Avoid downloading Bazel every time.
bazelisk-cache: true
# Store build cache per workflow.
disk-cache: ${{ github.workflow }}
# Share repository cache between workflows
repository-cache: true
- name: Build and Test
run: unset ANDROID_HOME && bazelisk test //:all
- name: Unsymlink Bazel Artifacts
# upload-artifact doesn't support paths with symlinks
run: |
mkdir -p ${{ env.UNSYMLINK_DIR }}
cp -t ${{ env.UNSYMLINK_DIR }} bazel-bin/compiler_uberjar_deploy.jar
cp -t ${{ env.UNSYMLINK_DIR }} bazel-bin/*_bundle.jar
# Share the following files with other jobs in this workflow. They can be grabbed using ID
# `unshaded_compiler`. This is made possible by uploading the files to GitHub controlled
# storage.
- name: Share Unshaded Compiler
# https://github.com/marketplace/actions/upload-a-build-artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: unshaded_compiler
path: ${{ env.UNSYMLINK_DIR }}/compiler_uberjar_deploy.jar
if-no-files-found: error
test-closure-compiler-npm:
name: Make Sure closure-compiler-npm is Compatible with this Compiler Build
runs-on: ubuntu-latest
needs:
- build-and-test
steps:
- name: Setup Java
# https://github.com/marketplace/actions/setup-java-jdk
uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0
with:
distribution: zulu
java-version: '21'
java-package: jdk
architecture: x64
- name: Setup Node.js
# https://github.com/marketplace/actions/setup-node-js-environment
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ env.VERSION_NODEJS }}
# Clone closure-compiler-npm repo from master into the current directory.
- name: Checkout Current closure-compiler-npm Commit
# https://github.com/marketplace/actions/checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: chadkillingsworth/closure-compiler-npm
ref: master
persist-credentials: false
# Clone closure-compiler repo from the commit under test into the npm repo compiler
# submodule
- name: Checkout Current closure-compiler Commit
# https://github.com/marketplace/actions/checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: compiler
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false
# Grab the compiler binary that was shared from `build-and-test` and put the file into
# ./compiler/bazel-bin.
- name: Grab Unshaded Compiler
# https://github.com/marketplace/actions/download-a-build-artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: unshaded_compiler
# Put the binary where bazel would have put it.
path: compiler/bazel-bin
- name: Test closure-compiler-npm
run: compiler/.github/ci_support/test_closure-compiler-npm.sh compiler/bazel-bin/compiler_uberjar_deploy.jar
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.
# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Format reference: https://docs.github.com/en/actions/reference name: Run Tests # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#on on: push: branches: [ master ] pull_request: branches: [ master ] schedule: # Daily at 12pm UTC - cron: '0 12 * * *' # Can be called from other workflow to run the tests workflow_call: inputs: ref: description: 'Tag or commit to checkout' required: false type: string permissions: contents: read env: VERSION_NODEJS: '22' UNSYMLINK_DIR: bazel-bin-unsymlink # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobs concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build-and-test: timeout-minutes: 30 name: Build and Test runs-on: latchkey-small steps: - name: Setup Java # https://github.com/marketplace/actions/setup-java-jdk uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 with: distribution: zulu java-version: '21' java-package: jdk architecture: x64 # Clone closure-compiler repo from the commit under test into current directory. - name: Checkout Current closure-compiler Commit # https://github.com/marketplace/actions/checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: ref: ${{ inputs.ref || github.sha }} persist-credentials: false # https://github.com/bazel-contrib/setup-bazel - uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0 with: # Avoid downloading Bazel every time. bazelisk-cache: true # Store build cache per workflow. disk-cache: ${{ github.workflow }} # Share repository cache between workflows repository-cache: true - name: Build and Test run: unset ANDROID_HOME && bazelisk test //:all - name: Unsymlink Bazel Artifacts # upload-artifact doesn't support paths with symlinks run: | mkdir -p ${{ env.UNSYMLINK_DIR }} cp -t ${{ env.UNSYMLINK_DIR }} bazel-bin/compiler_uberjar_deploy.jar cp -t ${{ env.UNSYMLINK_DIR }} bazel-bin/*_bundle.jar # Share the following files with other jobs in this workflow. They can be grabbed using ID # `unshaded_compiler`. This is made possible by uploading the files to GitHub controlled # storage. - name: Share Unshaded Compiler # https://github.com/marketplace/actions/upload-a-build-artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: unshaded_compiler path: ${{ env.UNSYMLINK_DIR }}/compiler_uberjar_deploy.jar if-no-files-found: error test-closure-compiler-npm: timeout-minutes: 30 name: Make Sure closure-compiler-npm is Compatible with this Compiler Build runs-on: latchkey-small needs: - build-and-test steps: - name: Setup Java # https://github.com/marketplace/actions/setup-java-jdk uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 with: distribution: zulu java-version: '21' java-package: jdk architecture: x64 - name: Setup Node.js # https://github.com/marketplace/actions/setup-node-js-environment uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: cache: 'npm' node-version: ${{ env.VERSION_NODEJS }} # Clone closure-compiler-npm repo from master into the current directory. - name: Checkout Current closure-compiler-npm Commit # https://github.com/marketplace/actions/checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: repository: chadkillingsworth/closure-compiler-npm ref: master persist-credentials: false # Clone closure-compiler repo from the commit under test into the npm repo compiler # submodule - name: Checkout Current closure-compiler Commit # https://github.com/marketplace/actions/checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: path: compiler ref: ${{ inputs.ref || github.sha }} persist-credentials: false # Grab the compiler binary that was shared from `build-and-test` and put the file into # ./compiler/bazel-bin. - name: Grab Unshaded Compiler # https://github.com/marketplace/actions/download-a-build-artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: unshaded_compiler # Put the binary where bazel would have put it. path: compiler/bazel-bin - name: Test closure-compiler-npm run: compiler/.github/ci_support/test_closure-compiler-npm.sh compiler/bazel-bin/compiler_uberjar_deploy.jar
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.
This workflow runs 2 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.