GitHub Actions

Three workflows, from a one-liner to a sharded, cached pipeline. Pick the one that matches how much you want to optimize.

1. Simplest: checkout and run

Install Gooze and run the whole suite. No registry, no caching — a good starting point.

name: Mutation testing

on: [push, pull_request]

jobs:
  gooze:
    runs-on: ubuntu-latest
    container: golang:1.26       # official Go image: go is already installed
    steps:
      - uses: actions/checkout@v4
      - run: go install gooze.dev/pkg/gooze@latest
      - run: gooze run ./...

2. Sharded: run in parallel

Split the run across jobs with -s INDEX/TOTAL to cut wall-clock time. Each job tests its own slice and uploads its reports; a final merge job downloads them all and combines them with gooze report merge.

jobs:
  test:
    runs-on: ubuntu-latest
    container: golang:1.26
    strategy:
      matrix:
        shard: [0, 1, 2]
    steps:
      - uses: actions/checkout@v4
      - run: go install gooze.dev/pkg/gooze@latest

      # Each job tests one third of the mutations, in parallel.
      # Sharded runs write to .gooze-reports/shard_${{ matrix.shard }}/.
      - name: Run shard ${{ matrix.shard }}
        run: gooze run -s ${{ matrix.shard }}/3 ./...

      - name: Upload shard reports
        uses: actions/upload-artifact@v4
        with:
          name: gooze-shard-${{ matrix.shard }}
          path: .gooze-reports/

  merge:
    needs: test
    runs-on: ubuntu-latest
    container: golang:1.26
    steps:
      - run: go install gooze.dev/pkg/gooze@latest

      # Collect every shard's reports back into .gooze-reports/.
      - name: Download shard reports
        uses: actions/download-artifact@v4
        with:
          path: .gooze-reports
          pattern: gooze-shard-*
          merge-multiple: true

      # Merge shard_* subdirs into one combined report set.
      - name: Merge shard reports
        run: gooze report merge

3. Sharded + cached baseline

Add an OCI baseline so each run only re-tests changed files (incremental execution). Every shard pulls the :main baseline for the cache, then hands its reports to the merge job as an artifact — shards never push to the registry. The merge job combines them with gooze report merge and, only on main, publishes the single merged baseline back to :main.

permissions:
  contents: read
  packages: write          # push the merged baseline to GHCR

env:
  REPORTS_REF: ghcr.io/${{ github.repository }}/gooze-reports:main
  GOOZE_REGISTRY_USERNAME: ${{ github.actor }}
  GOOZE_REGISTRY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

jobs:
  test:
    runs-on: ubuntu-latest
    container: golang:1.26
    strategy:
      matrix:
        shard: [0, 1, 2]
    steps:
      - uses: actions/checkout@v4
      - run: go install gooze.dev/pkg/gooze@latest

      # Reuse the main baseline so unchanged files are skipped (the cache).
      - name: Restore baseline from main
        run: gooze report pull "$REPORTS_REF" || echo "no baseline yet"

      - name: Run shard ${{ matrix.shard }}
        run: gooze run -s ${{ matrix.shard }}/3 ./...

      # Hand reports to the merge job via an artifact — no registry push here.
      - name: Upload shard reports
        uses: actions/upload-artifact@v4
        with:
          name: gooze-shard-${{ matrix.shard }}
          path: .gooze-reports/

  merge:
    needs: test
    runs-on: ubuntu-latest
    container: golang:1.26
    steps:
      - run: go install gooze.dev/pkg/gooze@latest

      - name: Collect shard reports
        uses: actions/download-artifact@v4
        with:
          path: .gooze-reports
          pattern: gooze-shard-*
          merge-multiple: true

      - name: Merge shards
        run: gooze report merge

      # Only main publishes the merged baseline back to the registry.
      - name: Publish merged baseline (main only)
        if: ${{ github.ref == 'refs/heads/main' }}
        run: gooze report push "$REPORTS_REF"

Authentication

  • GOOZE_REGISTRY_USERNAME / GOOZE_REGISTRY_PASSWORD — the password may be a token/PAT (for GHCR use GITHUB_TOKEN).
  • If unset, Gooze falls back to the Docker credential store, so a prior docker/login-action step also works.
  • For a non-TLS or self-signed registry add --plain-http or --insecure to push/pull.