Skip to content
Latchkey

CI workflow (itchyny/gojq)

The CI workflow from itchyny/gojq, explained and optimized by Latchkey.

C

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.

Grade your own workflow free or run it on Latchkey →
Source: itchyny/gojq.github/workflows/ci.yamlLicense MITView source

What it does

This is the CI workflow from the itchyny/gojq 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: CI

on:
  push:
    branches:
      - main
    tags:
      - v*
  pull_request:

permissions:
  contents: read

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Setup Go
        uses: actions/setup-go@v6
        with:
          go-version: 1.26.x
      - name: Build
        run: make build
      - name: Check command examples
        run: |
          # shellcheck disable=SC2016
          ./gojq -Rsr 'scan("```sh\n( \\$ .*?)```"; "m")[] |
            gsub(" +#.*"; "") | splits(" \\$ ") |
            capture("(?<command>.+?)\n(?<output>.+)"; "m") |
            "if diff <(printf %s \(.output | @sh)) \\
              <(\(.command | gsub("gojq"; "./gojq")) 2>&1); then
              echo ok: \(.command | @sh)
            else
              echo ng: \(.command | @sh); exit 1
            fi"
          ' README.md | bash
        shell: bash
      - name: Cross build
        run: make cross
      - name: Upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: goxz
          path: goxz
      - name: Clean
        run: make clean

  test:
    name: Test
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        go: [1.26.x, 1.25.x, 1.24.x]
      fail-fast: false
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Setup Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ matrix.go }}
      - name: Test
        run: make test
      - name: Test with GOARCH=386
        run: env GOARCH=386 go test -v ./...
        if: matrix.os != 'macos-latest'
      - name: Lint
        run: make lint
      - name: Check tools
        run: make check-tools
      - name: Check go generate
        run: go generate && ! git diff | grep ^
        shell: bash

  docker:
    name: Docker
    permissions:
      packages: write
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Docker metadata
        uses: docker/metadata-action@v6
        id: metadata
        with:
          images: |
            ${{ github.repository }}
            ghcr.io/${{ github.repository }}
          tags: |
            type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=semver,pattern={{major}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=sha,format=long,enable=${{ !startsWith(github.ref, 'refs/tags/v') }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Login to Docker Hub
        if: startsWith(github.ref, 'refs/tags/v')
        uses: docker/login-action@v4
        with:
          username: ${{ vars.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Login to GitHub Container Registry
        if: startsWith(github.ref, 'refs/tags/v')
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and release Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          push: ${{ startsWith(github.ref, 'refs/tags/v') }}
          provenance: false
          platforms: linux/amd64, linux/arm64
          tags: ${{ steps.metadata.outputs.tags }}
          labels: ${{ steps.metadata.outputs.labels }}

  release:
    name: Release
    needs: [build, test, docker]
    if: startsWith(github.ref, 'refs/tags/v')
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Download artifacts
        uses: actions/download-artifact@v8
        with:
          name: goxz
          path: goxz
      - name: Setup release body
        run: sed -n '/\[${{ github.ref_name }}\]/,/^$/{//!p}' CHANGELOG.md >release-body.txt
      - name: Create release
        uses: ncipollo/release-action@v1
        with:
          name: Release ${{ github.ref_name }}
          bodyFile: release-body.txt
          artifacts: goxz/*

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: CI
 
on:
  push:
    branches:
      - main
    tags:
      - v*
  pull_request:
 
permissions:
  contents: read
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build:
    timeout-minutes: 30
    name: Build
    runs-on: latchkey-small
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Setup Go
        uses: actions/setup-go@v6
        with:
          go-version: 1.26.x
      - name: Build
        run: make build
      - name: Check command examples
        run: |
          # shellcheck disable=SC2016
          ./gojq -Rsr 'scan("```sh\n( \\$ .*?)```"; "m")[] |
            gsub(" +#.*"; "") | splits(" \\$ ") |
            capture("(?<command>.+?)\n(?<output>.+)"; "m") |
            "if diff <(printf %s \(.output | @sh)) \\
              <(\(.command | gsub("gojq"; "./gojq")) 2>&1); then
              echo ok: \(.command | @sh)
            else
              echo ng: \(.command | @sh); exit 1
            fi"
          ' README.md | bash
        shell: bash
      - name: Cross build
        run: make cross
      - name: Upload artifact
        uses: actions/upload-artifact@v7
        with:
          name: goxz
          path: goxz
      - name: Clean
        run: make clean
 
  test:
    timeout-minutes: 30
    name: Test
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        go: [1.26.x, 1.25.x, 1.24.x]
      fail-fast: false
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Setup Go
        uses: actions/setup-go@v6
        with:
          go-version: ${{ matrix.go }}
      - name: Test
        run: make test
      - name: Test with GOARCH=386
        run: env GOARCH=386 go test -v ./...
        if: matrix.os != 'macos-latest'
      - name: Lint
        run: make lint
      - name: Check tools
        run: make check-tools
      - name: Check go generate
        run: go generate && ! git diff | grep ^
        shell: bash
 
  docker:
    timeout-minutes: 30
    name: Docker
    permissions:
      packages: write
    runs-on: latchkey-small
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Docker metadata
        uses: docker/metadata-action@v6
        id: metadata
        with:
          images: |
            ${{ github.repository }}
            ghcr.io/${{ github.repository }}
          tags: |
            type=semver,pattern={{version}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=semver,pattern={{major}}.{{minor}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=semver,pattern={{major}},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
            type=sha,format=long,enable=${{ !startsWith(github.ref, 'refs/tags/v') }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4
      - name: Login to Docker Hub
        if: startsWith(github.ref, 'refs/tags/v')
        uses: docker/login-action@v4
        with:
          username: ${{ vars.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Login to GitHub Container Registry
        if: startsWith(github.ref, 'refs/tags/v')
        uses: docker/login-action@v4
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and release Docker image
        uses: docker/build-push-action@v7
        with:
          context: .
          push: ${{ startsWith(github.ref, 'refs/tags/v') }}
          provenance: false
          platforms: linux/amd64, linux/arm64
          tags: ${{ steps.metadata.outputs.tags }}
          labels: ${{ steps.metadata.outputs.labels }}
 
  release:
    timeout-minutes: 30
    name: Release
    needs: [build, test, docker]
    if: startsWith(github.ref, 'refs/tags/v')
    permissions:
      contents: write
    runs-on: latchkey-small
    steps:
      - name: Checkout code
        uses: actions/checkout@v7
      - name: Download artifacts
        uses: actions/download-artifact@v8
        with:
          name: goxz
          path: goxz
      - name: Setup release body
        run: sed -n '/\[${{ github.ref_name }}\]/,/^$/{//!p}' CHANGELOG.md >release-body.txt
      - name: Create release
        uses: ncipollo/release-action@v1
        with:
          name: Release ${{ github.ref_name }}
          bodyFile: release-body.txt
          artifacts: goxz/*
 

What changed

6 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

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 4 jobs (12 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