Skip to content
Latchkey

build workflow (goreleaser/goreleaser)

The build workflow from goreleaser/goreleaser, 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: goreleaser/goreleaser.github/workflows/build.ymlLicense MITView source

What it does

This is the build workflow from the goreleaser/goreleaser 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

workflow (.yml)
name: build
concurrency:
  group: ${{ github.head_ref || github.ref_name }}
  cancel-in-progress: true
on:
  push:
    branches:
      - "main"
  pull_request:
    paths:
      - "go.*"
      - "**/*.go"
      - "**/*.golden"
      - "Taskfile.yml"
      - "Dockerfile"
      - ".github/workflows/*.yml"
      # XXX: these dirs might have yml, txt, and golden files that when changed
      # need to trigger CI as well
      - "cmd/**/*"
      - "pkg/**/*"
      - "internal/**/*"
permissions:
  contents: read
jobs:
  license-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
        with:
          go-version: stable
      - uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
        with:
          version: 3.x
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - run: task licenses:check
  semgrep:
    uses: caarlos0/meta/.github/workflows/semgrep.yml@c7f17af352dac91fa6c785d06ebac8547f1abdd3 # v0.1.0
  ruleguard:
    uses: caarlos0/meta/.github/workflows/ruleguard.yml@c7f17af352dac91fa6c785d06ebac8547f1abdd3 # v0.1.0
    with:
      args: "-disable largeloopcopy"
  test:
    strategy:
      fail-fast: true
      matrix:
        os: [ubuntu-latest, windows-latest]
        include:
          # the race detector is OS-independent and coverage is only uploaded
          # from ubuntu, so skip both on windows to speed up the slowest job.
          - os: windows-latest
            test-args: RACE=false COVER=false
    runs-on: ${{ matrix.os }}
    env:
      DOCKER_CLI_EXPERIMENTAL: "enabled"
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          fetch-depth: 0
      - uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
        with:
          version: 3.x
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
        if: matrix.os == 'ubuntu-latest'
      - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
        if: matrix.os == 'ubuntu-latest'
        with:
          driver-opts: network=host
      - name: setup-snapcraft
        if: matrix.os == 'ubuntu-latest'
        run: sudo snap install snapcraft --classic
      - uses: crazy-max/ghaction-upx@c83f378efc804f828e988debb88ed6116feb2368 # v4.0.0
        with:
          install-only: true
      - name: install-flatpak-makeself
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt update -q
          sudo apt install -yq makeself flatpak flatpak-builder
      - name: cache-flatpak
        id: cache-flatpak
        if: matrix.os == 'ubuntu-latest'
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.local/share/flatpak
          key: flatpak-${{ runner.os }}-freedesktop-24.08
      - name: setup-flatpak
        # runtimes are installed --user so the cache (runner-owned) can restore
        # them without sudo; only download on a cache miss.
        if: matrix.os == 'ubuntu-latest' && steps.cache-flatpak.outputs.cache-hit != 'true'
        run: |
          flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
          flatpak install -y --user --noninteractive flathub org.freedesktop.Platform/x86_64/24.08 org.freedesktop.Sdk/x86_64/24.08 org.freedesktop.Platform/aarch64/24.08 org.freedesktop.Sdk/aarch64/24.08
      - uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7
        if: matrix.os == 'ubuntu-latest'
        with:
          github_access_token: ${{ secrets.GITHUB_TOKEN }}
      - run: nix profile add nixpkgs#pkgs.nixfmt nixpkgs#alejandra
        if: matrix.os == 'ubuntu-latest'
      - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
        with:
          go-version-file: go.mod
      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: "25"
      - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
      - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
      - uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
      - uses: cargo-bins/cargo-binstall@732870f031d2fb36309d0deaf36abcc704a7be65 # v1.20.1
      - name: setup-cargo
        run: |
          rustup default stable
          cargo binstall cargo-zigbuild
      - uses: snok/install-poetry@a783c322200f0519c7926aa6faa857c4e23e9263 # v1.4.2
      - if: matrix.os == 'windows-latest'
        run: 'echo "C:\Users\runneradmin\.local\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append'
      - uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
      - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
        with:
          cosign-release: "v3.0.3"
      - uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
      - run: task setup
      - run: task build
      - run: task test ${{ matrix.test-args }}
      - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
        if: matrix.os == 'ubuntu-latest'
        with:
          file: ./coverage.txt
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      - run: git diff
        if: ${{ always() }}
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          fetch-depth: 0
      - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
        with:
          distribution: goreleaser-pro
          version: "~> 2"
          args: check
        env:
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

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: build
concurrency:
  group: ${{ github.head_ref || github.ref_name }}
  cancel-in-progress: true
on:
  push:
    branches:
      - "main"
  pull_request:
    paths:
      - "go.*"
      - "**/*.go"
      - "**/*.golden"
      - "Taskfile.yml"
      - "Dockerfile"
      - ".github/workflows/*.yml"
      # XXX: these dirs might have yml, txt, and golden files that when changed
      # need to trigger CI as well
      - "cmd/**/*"
      - "pkg/**/*"
      - "internal/**/*"
permissions:
  contents: read
jobs:
  license-check:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
        with:
          go-version: stable
      - uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
        with:
          version: 3.x
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - run: task licenses:check
  semgrep:
    timeout-minutes: 30
    uses: caarlos0/meta/.github/workflows/semgrep.yml@c7f17af352dac91fa6c785d06ebac8547f1abdd3 # v0.1.0
  ruleguard:
    timeout-minutes: 30
    uses: caarlos0/meta/.github/workflows/ruleguard.yml@c7f17af352dac91fa6c785d06ebac8547f1abdd3 # v0.1.0
    with:
      args: "-disable largeloopcopy"
  test:
    timeout-minutes: 30
    strategy:
      fail-fast: true
      matrix:
        os: [ubuntu-latest, windows-latest]
        include:
          # the race detector is OS-independent and coverage is only uploaded
          # from ubuntu, so skip both on windows to speed up the slowest job.
          - os: windows-latest
            test-args: RACE=false COVER=false
    runs-on: ${{ matrix.os }}
    env:
      DOCKER_CLI_EXPERIMENTAL: "enabled"
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          fetch-depth: 0
      - uses: go-task/setup-task@01a4adf9db2d14c1de7a560f09170b6e0df736aa # v2.1.0
        with:
          version: 3.x
          repo-token: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
        if: matrix.os == 'ubuntu-latest'
      - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
        if: matrix.os == 'ubuntu-latest'
        with:
          driver-opts: network=host
      - name: setup-snapcraft
        if: matrix.os == 'ubuntu-latest'
        run: sudo snap install snapcraft --classic
      - uses: crazy-max/ghaction-upx@c83f378efc804f828e988debb88ed6116feb2368 # v4.0.0
        with:
          install-only: true
      - name: install-flatpak-makeself
        if: matrix.os == 'ubuntu-latest'
        run: |
          sudo apt update -q
          sudo apt install -yq makeself flatpak flatpak-builder
      - name: cache-flatpak
        id: cache-flatpak
        if: matrix.os == 'ubuntu-latest'
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
        with:
          path: ~/.local/share/flatpak
          key: flatpak-${{ runner.os }}-freedesktop-24.08
      - name: setup-flatpak
        # runtimes are installed --user so the cache (runner-owned) can restore
        # them without sudo; only download on a cache miss.
        if: matrix.os == 'ubuntu-latest' && steps.cache-flatpak.outputs.cache-hit != 'true'
        run: |
          flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
          flatpak install -y --user --noninteractive flathub org.freedesktop.Platform/x86_64/24.08 org.freedesktop.Sdk/x86_64/24.08 org.freedesktop.Platform/aarch64/24.08 org.freedesktop.Sdk/aarch64/24.08
      - uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7
        if: matrix.os == 'ubuntu-latest'
        with:
          github_access_token: ${{ secrets.GITHUB_TOKEN }}
      - run: nix profile add nixpkgs#pkgs.nixfmt nixpkgs#alejandra
        if: matrix.os == 'ubuntu-latest'
      - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
        with:
          go-version-file: go.mod
      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          cache: 'npm'
          node-version: "25"
      - uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
      - uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
      - uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
      - uses: cargo-bins/cargo-binstall@732870f031d2fb36309d0deaf36abcc704a7be65 # v1.20.1
      - name: setup-cargo
        run: |
          rustup default stable
          cargo binstall cargo-zigbuild
      - uses: snok/install-poetry@a783c322200f0519c7926aa6faa857c4e23e9263 # v1.4.2
      - if: matrix.os == 'windows-latest'
        run: 'echo "C:\Users\runneradmin\.local\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append'
      - uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
      - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
        with:
          cosign-release: "v3.0.3"
      - uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
      - run: task setup
      - run: task build
      - run: task test ${{ matrix.test-args }}
      - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
        if: matrix.os == 'ubuntu-latest'
        with:
          file: ./coverage.txt
        env:
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      - run: git diff
        if: ${{ always() }}
  check:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
        with:
          fetch-depth: 0
      - uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3
        with:
          distribution: goreleaser-pro
          version: "~> 2"
          args: check
        env:
          GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
 

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 5 jobs (6 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