Skip to content
Latchkey

main workflow (doitintl/kube-no-trouble)

The main workflow from doitintl/kube-no-trouble, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, 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: doitintl/kube-no-trouble.github/workflows/main.yamlLicense MITView source

What it does

This is the main workflow from the doitintl/kube-no-trouble 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: main
on:
  push:
    branches:
    - master
    tags:
    - "*"
  pull_request:
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true
jobs:
  pre-commit:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4.2.2
    - uses: actions/setup-python@v5
      with:
        python-version: '3.x'
    - uses: pre-commit/action@v3.0.0
  test:
    name: test
    runs-on: ubuntu-latest
    container: golang:1.23-alpine3.20
    steps:
    - name: Install git
      run: apk add --update --no-cache git
    - name: Checkout code
      uses: actions/checkout@v4.2.2
      with:
        fetch-depth: 0
    - name: Test
      run: |
        scripts/alpine-setup.sh
        make test
  build:
    name: build
    runs-on: ubuntu-latest
    container: golang:1.23-alpine3.20
    strategy:
      matrix:
        os: [linux, darwin, windows]
        arch: [arm64, amd64]
        exclude:
          - os: windows
            arch: arm64
    steps:
      - name: Install git
        run: apk add --update --no-cache git
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Build
        run: |
          git config --global --add safe.directory /__w/kube-no-trouble/kube-no-trouble
          scripts/alpine-setup.sh
          GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} make all
        shell: sh
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Archive release artifacts
        uses: actions/upload-artifact@v4
        with:
          name: release-artifacts-${{ matrix.os }}-${{ matrix.arch }}
          path: release-artifacts
  build-docker:
    name: Build Docker Image
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: false
          platforms: |
            linux/arm64
            linux/amd64
          build-args: |
            GITHUB_REF
            GITHUB_SHA
          cache-from: type=gha
          cache-to: type=gha
  integration-test:
    name: integration test
    needs:
      [pre-commit, build, build-docker, test]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        k8s_version: [
          "kindest/node:v1.19.16",
          "kindest/node:v1.20.15",
          "kindest/node:v1.21.14",
          "kindest/node:v1.22.17",
          "kindest/node:v1.23.17",
          "kindest/node:v1.24.17",
          "kindest/node:v1.25.16",
          "kindest/node:v1.26.14",
          "kindest/node:v1.27.11",
          "kindest/node:v1.28.7",
          "kindest/node:v1.29.2"
        ]
    steps:
    - name: Checkout
      uses: actions/checkout@v4.2.2
      with:
        fetch-depth: 0
    - uses: actions/download-artifact@v4
      with:
        name: release-artifacts-linux-amd64
        path: release-artifacts
    - name: Create k8s Kind Cluster
      uses: helm/kind-action@v1.12.0
      with:
        node_image: ${{ matrix.k8s_version }}
        cluster_name: kubent-test-cluster
    - name: run integration test
      run: |
        tar xvzf release-artifacts/kubent-*-linux-amd64.tar.gz
        kubectl version
        kubectl cluster-info --context kind-kubent-test-cluster
        ./kubent
  create-release:
    name: Create Release
    needs:
      [integration-test]
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    outputs:
      upload_url: ${{ steps.create_release.outputs.upload_url }}
      tag_name: ${{ steps.get_tag.outputs.git_tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Generate a changelog
        uses: orhun/git-cliff-action@v4
        id: git-cliff
        with:
          config: cliff.toml
          args: --verbose --latest
        env:
          OUTPUT: changelog.md
      - uses: actions/download-artifact@v4
        with:
          name: release-artifacts-linux-amd64
          path: release-artifacts
      - name: Get the tag
        id: get_tag
        run: echo "git_tag=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ steps.get_tag.outputs.git_tag }}
          release_name: ${{ steps.get_tag.outputs.git_tag }}
          body_path: ${{ steps.git-cliff.outputs.changelog }}
          draft: ${{ startsWith(steps.get_tag.outputs.git_tag, 'nightly') != true }}
          prerelease: ${{ startsWith(steps.get_tag.outputs.git_tag, 'nightly') }}
  push-image:
    name: Push Image
    needs:
      [create-release]
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4.2.2
      - name: Log in to the Container registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          platforms: |
            linux/arm64
            linux/amd64
          tags: |
            ${{ format('{0}/{1}:{2}', env.REGISTRY, env.IMAGE_NAME, needs.create-release.outputs.tag_name) }}
            ${{ ( !startsWith(github.ref, 'refs/tags/nightly') && format('{0}/{1}:{2}', env.REGISTRY, env.IMAGE_NAME, 'latest') ) || '' }}
          build-args: |
            GITHUB_REF
            GITHUB_SHA
          cache-from: type=gha
          cache-to: type=gha
  release-artifacts:
    name: Release Artifacts
    needs:
      [create-release]
    runs-on: ubuntu-latest
    strategy:
      matrix:
        os: [linux, darwin, windows]
        arch: [arm64, amd64]
        exclude:
          - os: windows
            arch: arm64
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: release-artifacts-${{ matrix.os }}-${{ matrix.arch }}
          path: release-artifacts
      - name: Upload Release Asset - ${{ matrix.os }}-${{ matrix.arch }}
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./release-artifacts/kubent-${{ needs.create-release.outputs.tag_name }}-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
          asset_name: kubent-${{ needs.create-release.outputs.tag_name }}-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
          asset_content_type: application/tar+gzip

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: main
on:
  push:
    branches:
    - master
    tags:
    - "*"
  pull_request:
env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}
concurrency:
  group: ${{ github.ref }}-${{ github.workflow }}
  cancel-in-progress: true
jobs:
  pre-commit:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
    - uses: actions/checkout@v4.2.2
    - uses: actions/setup-python@v5
      with:
        cache: 'pip'
        python-version: '3.x'
    - uses: pre-commit/action@v3.0.0
  test:
    timeout-minutes: 30
    name: test
    runs-on: latchkey-small
    container: golang:1.23-alpine3.20
    steps:
    - name: Install git
      run: apk add --update --no-cache git
    - name: Checkout code
      uses: actions/checkout@v4.2.2
      with:
        fetch-depth: 0
    - name: Test
      run: |
        scripts/alpine-setup.sh
        make test
  build:
    timeout-minutes: 30
    name: build
    runs-on: latchkey-small
    container: golang:1.23-alpine3.20
    strategy:
      matrix:
        os: [linux, darwin, windows]
        arch: [arm64, amd64]
        exclude:
          - os: windows
            arch: arm64
    steps:
      - name: Install git
        run: apk add --update --no-cache git
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Build
        run: |
          git config --global --add safe.directory /__w/kube-no-trouble/kube-no-trouble
          scripts/alpine-setup.sh
          GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} make all
        shell: sh
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Archive release artifacts
        uses: actions/upload-artifact@v4
        with:
          name: release-artifacts-${{ matrix.os }}-${{ matrix.arch }}
          path: release-artifacts
  build-docker:
    timeout-minutes: 30
    name: Build Docker Image
    runs-on: latchkey-small
    steps:
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: false
          platforms: |
            linux/arm64
            linux/amd64
          build-args: |
            GITHUB_REF
            GITHUB_SHA
          cache-from: type=gha
          cache-to: type=gha
  integration-test:
    timeout-minutes: 30
    name: integration test
    needs:
      [pre-commit, build, build-docker, test]
    runs-on: latchkey-small
    strategy:
      matrix:
        k8s_version: [
          "kindest/node:v1.19.16",
          "kindest/node:v1.20.15",
          "kindest/node:v1.21.14",
          "kindest/node:v1.22.17",
          "kindest/node:v1.23.17",
          "kindest/node:v1.24.17",
          "kindest/node:v1.25.16",
          "kindest/node:v1.26.14",
          "kindest/node:v1.27.11",
          "kindest/node:v1.28.7",
          "kindest/node:v1.29.2"
        ]
    steps:
    - name: Checkout
      uses: actions/checkout@v4.2.2
      with:
        fetch-depth: 0
    - uses: actions/download-artifact@v4
      with:
        name: release-artifacts-linux-amd64
        path: release-artifacts
    - name: Create k8s Kind Cluster
      uses: helm/kind-action@v1.12.0
      with:
        node_image: ${{ matrix.k8s_version }}
        cluster_name: kubent-test-cluster
    - name: run integration test
      run: |
        tar xvzf release-artifacts/kubent-*-linux-amd64.tar.gz
        kubectl version
        kubectl cluster-info --context kind-kubent-test-cluster
        ./kubent
  create-release:
    timeout-minutes: 30
    name: Create Release
    needs:
      [integration-test]
    runs-on: latchkey-small
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    outputs:
      upload_url: ${{ steps.create_release.outputs.upload_url }}
      tag_name: ${{ steps.get_tag.outputs.git_tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4.2.2
        with:
          fetch-depth: 0
      - name: Generate a changelog
        uses: orhun/git-cliff-action@v4
        id: git-cliff
        with:
          config: cliff.toml
          args: --verbose --latest
        env:
          OUTPUT: changelog.md
      - uses: actions/download-artifact@v4
        with:
          name: release-artifacts-linux-amd64
          path: release-artifacts
      - name: Get the tag
        id: get_tag
        run: echo "git_tag=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_OUTPUT
      - name: Create Release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ steps.get_tag.outputs.git_tag }}
          release_name: ${{ steps.get_tag.outputs.git_tag }}
          body_path: ${{ steps.git-cliff.outputs.changelog }}
          draft: ${{ startsWith(steps.get_tag.outputs.git_tag, 'nightly') != true }}
          prerelease: ${{ startsWith(steps.get_tag.outputs.git_tag, 'nightly') }}
  push-image:
    timeout-minutes: 30
    name: Push Image
    needs:
      [create-release]
    runs-on: latchkey-small
    permissions:
      contents: read
      packages: write
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4.2.2
      - name: Log in to the Container registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          platforms: |
            linux/arm64
            linux/amd64
          tags: |
            ${{ format('{0}/{1}:{2}', env.REGISTRY, env.IMAGE_NAME, needs.create-release.outputs.tag_name) }}
            ${{ ( !startsWith(github.ref, 'refs/tags/nightly') && format('{0}/{1}:{2}', env.REGISTRY, env.IMAGE_NAME, 'latest') ) || '' }}
          build-args: |
            GITHUB_REF
            GITHUB_SHA
          cache-from: type=gha
          cache-to: type=gha
  release-artifacts:
    timeout-minutes: 30
    name: Release Artifacts
    needs:
      [create-release]
    runs-on: latchkey-small
    strategy:
      matrix:
        os: [linux, darwin, windows]
        arch: [arm64, amd64]
        exclude:
          - os: windows
            arch: arm64
    if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: release-artifacts-${{ matrix.os }}-${{ matrix.arch }}
          path: release-artifacts
      - name: Upload Release Asset - ${{ matrix.os }}-${{ matrix.arch }}
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ needs.create-release.outputs.upload_url }}
          asset_path: ./release-artifacts/kubent-${{ needs.create-release.outputs.tag_name }}-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
          asset_name: kubent-${{ needs.create-release.outputs.tag_name }}-${{ matrix.os }}-${{ matrix.arch }}.tar.gz
          asset_content_type: application/tar+gzip
 

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 8 jobs (28 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