PR: Run UNIT tests and Build artifacts for all platforms workflow (DNSControl/dnscontrol)
The PR: Run UNIT tests and Build artifacts for all platforms workflow from DNSControl/dnscontrol, explained and optimized by Latchkey.
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.
What it does
This is the PR: Run UNIT tests and Build artifacts for all platforms workflow from the DNSControl/dnscontrol 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
name: "PR: Run UNIT tests and Build artifacts for all platforms"
# When will this pipeline be activated?
# 1. On any pull-request, or if someone pushes to a branch called
# "tlim_testpr".
on:
pull_request:
workflow_dispatch:
# Want to trigger all the tests without making a PR?
# Run: git push origin main:tlim_testpr --force
# This will trigger a full PR test on the main branch.
# See https://github.com/DNSControl/dnscontrol/actions/workflows/pr_build.yml?query=branch%3Atlim_testpr
push:
branches:
- 'tlim_testpr'
permissions:
contents: read
# Environment Variables
env:
# cache-key: Change to force cache reset `pwsh > Get-Date -UFormat %s`
cache-key: 1639697695
# go-mod-path: Where go-mod writes temp files
go-mod-path: /go/pkg/mod
# BIND_DOMAIN: BIND is the one providers that we always test. By
# defining this here, we know it will always be set.
BIND_DOMAIN: example.com
jobs:
# Run unit tests:
build:
runs-on: ubuntu-latest
env:
TEST_RESULTS: "/tmp/test-results"
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: stable
- name: restore_cache
uses: actions/cache@v6.1.0
with:
key: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
restore-keys: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }}
path: ${{ env.go-mod-path }}
- run: mkdir -p "$TEST_RESULTS"
- name: Run unit tests
run: |
go install gotest.tools/gotestsum@latest
gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- $PACKAGE_NAMES
# - name: Enforce Go Formatted Code
# run: "[ `go fmt ./... | wc -l` -eq 0 ]"
- uses: actions/upload-artifact@v7.0.1
with:
name: unit-tests
path: ${{ env.TEST_RESULTS }}
# build: Use GoReleaser to build binaries for all platforms.
# Stringer is needed because .goreleaser includes "go generate ./..."
- name: Install stringer
run: |
go install golang.org/x/tools/cmd/stringer@latest
-
id: build_binaries_tagged
name: Build binaries (if tagged)
if: github.ref_type == 'tag'
uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser
version: latest
args: build
-
id: build_binaries_not_tagged
name: Build binaries (not tagged)
if: github.ref_type != 'tag'
uses: goreleaser/goreleaser-action@v7
with:
args: build --snapshot --single-target --skip=before
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: "PR: Run UNIT tests and Build artifacts for all platforms" # When will this pipeline be activated? # 1. On any pull-request, or if someone pushes to a branch called # "tlim_testpr". on: pull_request: workflow_dispatch: # Want to trigger all the tests without making a PR? # Run: git push origin main:tlim_testpr --force # This will trigger a full PR test on the main branch. # See https://github.com/DNSControl/dnscontrol/actions/workflows/pr_build.yml?query=branch%3Atlim_testpr push: branches: - 'tlim_testpr' permissions: contents: read # Environment Variables env: # cache-key: Change to force cache reset `pwsh > Get-Date -UFormat %s` cache-key: 1639697695 # go-mod-path: Where go-mod writes temp files go-mod-path: /go/pkg/mod # BIND_DOMAIN: BIND is the one providers that we always test. By # defining this here, we know it will always be set. BIND_DOMAIN: example.com concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # Run unit tests: build: timeout-minutes: 30 runs-on: latchkey-small env: TEST_RESULTS: "/tmp/test-results" steps: - uses: actions/checkout@v7 with: fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v6 with: go-version: stable - name: restore_cache uses: actions/cache@v6.1.0 with: key: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }} restore-keys: linux-go-${{ hashFiles('go.sum') }}-${{ env.cache-key }} path: ${{ env.go-mod-path }} - run: mkdir -p "$TEST_RESULTS" - name: Run unit tests run: | go install gotest.tools/gotestsum@latest gotestsum --junitfile ${TEST_RESULTS}/gotestsum-report.xml -- $PACKAGE_NAMES # - name: Enforce Go Formatted Code # run: "[ `go fmt ./... | wc -l` -eq 0 ]" - uses: actions/upload-artifact@v7.0.1 with: name: unit-tests path: ${{ env.TEST_RESULTS }} # build: Use GoReleaser to build binaries for all platforms. # Stringer is needed because .goreleaser includes "go generate ./..." - name: Install stringer run: | go install golang.org/x/tools/cmd/stringer@latest - id: build_binaries_tagged name: Build binaries (if tagged) if: github.ref_type == 'tag' uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: latest args: build - id: build_binaries_not_tagged name: Build binaries (not tagged) if: github.ref_type != 'tag' uses: goreleaser/goreleaser-action@v7 with: args: build --snapshot --single-target --skip=before
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.
- Add a job timeout so a hung step cannot burn hours of runner time.
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 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.