Skip to content
Latchkey

Release workflow (avajs/ava)

The Release workflow from avajs/ava, explained and optimized by Latchkey.

A

CI health: A - excellent

Point runs-on at Latchkey and get 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: avajs/ava.github/workflows/release.ymlLicense MITView source

What it does

This is the Release workflow from the avajs/ava 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: Release
on:
  workflow_dispatch:
    inputs:
      ref:
        description: 'Commit ref or existing version tag (e.g., abc1234 or v1.2.3)'
        required: true
        type: string
      new_version:
        description: 'New version for npm version (e.g., patch, minor, major, 1.2.3). Must be empty when providing an existing tag.'
        required: false
        type: string
      skip_ci_check:
        description: 'Skip CI status check'
        required: false
        type: boolean
        default: false

jobs:
  preflight:
    name: Validate
    runs-on: ubuntu-slim
    permissions:
      actions: read
      contents: read
    outputs:
      ref_is_tag: ${{steps.validation.outputs.ref_is_tag}}
    steps:
      - name: Validate inputs
        id: validation
        env:
          REF: ${{inputs.ref}}
          NEW_VERSION: ${{inputs.new_version}}
        run: |
          if [[ "$REF" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
            echo "ref_is_tag=true" >> "$GITHUB_OUTPUT"
            if [[ -n "$NEW_VERSION" ]]; then
              echo "::error::new_version must be empty when an existing tag is provided"
              exit 1
            fi
          else
            echo "ref_is_tag=false" >> "$GITHUB_OUTPUT"
            if [[ -z "$NEW_VERSION" ]]; then
              echo "::error::new_version is required when a commit ref is provided"
              exit 1
            fi
          fi

      - name: Checkout
        uses: actions/checkout@v6
        with:
          ref: ${{inputs.ref}}
          fetch-depth: 0

      - name: Verify ref is HEAD of main
        if: steps.validation.outputs.ref_is_tag == 'false'
        env:
          REF: ${{inputs.ref}}
        run: |
          MAIN_SHA=$(git rev-parse origin/main)
          CURRENT_SHA=$(git rev-parse HEAD)
          if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
            echo "::error::ref ${REF} (${CURRENT_SHA}) is not the HEAD of main (${MAIN_SHA})"
            exit 1
          fi

      - name: Verify tag matches package.json version
        if: steps.validation.outputs.ref_is_tag == 'true'
        env:
          REF: ${{inputs.ref}}
        run: |
          jq --raw-output --exit-status --arg tag "$REF" '
            if (.version == ($tag | ltrimstr("v"))) then
              "Package version (\(.version)) matches tag version (\($tag | ltrimstr(\"v\")))"
            else
              "Package version (\(.version)) does not match tag version (\($tag | ltrimstr(\"v\")))" | halt_error(1)
            end' package.json

      - name: Check CI status
        if: '!inputs.skip_ci_check'
        run: |
          gh run list --commit "$(git rev-parse HEAD)" --workflow ci.yml --status success --json databaseId \
            | jq --raw-output --exit-status '
                if (length > 0) then
                  "CI checks have passed"
                else
                  "CI has not completed successfully for this commit" | halt_error(1)
                end'
        env:
          GH_TOKEN: ${{secrets.GITHUB_TOKEN}}

  release:
    name: Release
    runs-on: ubuntu-latest
    needs: preflight
    environment: npm
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          ref: ${{inputs.ref}}
          fetch-depth: 0

      - name: Verify ref is still HEAD of main
        if: needs.preflight.outputs.ref_is_tag == 'false'
        env:
          REF: ${{inputs.ref}}
        run: |
          MAIN_SHA=$(git rev-parse origin/main)
          CURRENT_SHA=$(git rev-parse HEAD)
          if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
            echo "::error::ref ${REF} (${CURRENT_SHA}) is no longer the HEAD of main (${MAIN_SHA})"
            exit 1
          fi

      - name: Generate app token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{vars.LAUNCHBOT_ID}}
          private-key: ${{secrets.LAUNCHBOT_PRIVATE_KEY}}

      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: package.json
          cache: npm
          registry-url: https://registry.npmjs.org

      - name: Bump version
        if: needs.preflight.outputs.ref_is_tag == 'false'
        env:
          NEW_VERSION: ${{inputs.new_version}}
        run: npm version "$NEW_VERSION" --no-git-tag-version

      - name: Push version commit
        if: needs.preflight.outputs.ref_is_tag == 'false'
        id: push-commit
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}
        run: |
          RELEASE_TAG="v$(jq --raw-output .version package.json)"
          PARENT_SHA=$(git rev-parse HEAD)

          jq --null-input \
            --arg repo "$GITHUB_REPOSITORY" \
            --arg parentSha "$PARENT_SHA" \
            --arg headline "$RELEASE_TAG" \
            --rawfile pkgContent package.json \
            --rawfile lockContent package-lock.json \
            '{
              query: "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid } } }",
              variables: {
                input: {
                  branch: { repositoryNameWithOwner: $repo, branchName: "main" },
                  message: { headline: $headline },
                  expectedHeadOid: $parentSha,
                  fileChanges: {
                    additions: [
                      { path: "package.json", contents: ($pkgContent | @base64) },
                      { path: "package-lock.json", contents: ($lockContent | @base64) }
                    ]
                  }
                }
              }
            }' > /tmp/request.json

          COMMIT_SHA=$(gh api graphql --input /tmp/request.json \
            --jq '.data.createCommitOnBranch.commit.oid')

          echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
          echo "version_commit_sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"

      - name: Create version tag
        if: needs.preflight.outputs.ref_is_tag == 'false'
        run: |
          gh api "repos/$GITHUB_REPOSITORY/git/refs" \
            -f ref="refs/tags/${{steps.push-commit.outputs.release_tag}}" \
            -f sha="${{steps.push-commit.outputs.version_commit_sha}}"
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}

      - name: Publish to npm with provenance
        run: npm publish --provenance

      - name: Create GitHub Release
        run: |
          RELEASE_TAG="v$(jq --raw-output .version package.json)"
          gh release create "$RELEASE_TAG" \
            --title "$RELEASE_TAG" \
            --draft \
            --generate-notes
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}

The same workflow, on Latchkey

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

name: Release
on:
  workflow_dispatch:
    inputs:
      ref:
        description: 'Commit ref or existing version tag (e.g., abc1234 or v1.2.3)'
        required: true
        type: string
      new_version:
        description: 'New version for npm version (e.g., patch, minor, major, 1.2.3). Must be empty when providing an existing tag.'
        required: false
        type: string
      skip_ci_check:
        description: 'Skip CI status check'
        required: false
        type: boolean
        default: false
 
jobs:
  preflight:
    timeout-minutes: 30
    name: Validate
    runs-on: ubuntu-slim
    permissions:
      actions: read
      contents: read
    outputs:
      ref_is_tag: ${{steps.validation.outputs.ref_is_tag}}
    steps:
      - name: Validate inputs
        id: validation
        env:
          REF: ${{inputs.ref}}
          NEW_VERSION: ${{inputs.new_version}}
        run: |
          if [[ "$REF" =~ ^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$ ]]; then
            echo "ref_is_tag=true" >> "$GITHUB_OUTPUT"
            if [[ -n "$NEW_VERSION" ]]; then
              echo "::error::new_version must be empty when an existing tag is provided"
              exit 1
            fi
          else
            echo "ref_is_tag=false" >> "$GITHUB_OUTPUT"
            if [[ -z "$NEW_VERSION" ]]; then
              echo "::error::new_version is required when a commit ref is provided"
              exit 1
            fi
          fi
 
      - name: Checkout
        uses: actions/checkout@v6
        with:
          ref: ${{inputs.ref}}
          fetch-depth: 0
 
      - name: Verify ref is HEAD of main
        if: steps.validation.outputs.ref_is_tag == 'false'
        env:
          REF: ${{inputs.ref}}
        run: |
          MAIN_SHA=$(git rev-parse origin/main)
          CURRENT_SHA=$(git rev-parse HEAD)
          if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
            echo "::error::ref ${REF} (${CURRENT_SHA}) is not the HEAD of main (${MAIN_SHA})"
            exit 1
          fi
 
      - name: Verify tag matches package.json version
        if: steps.validation.outputs.ref_is_tag == 'true'
        env:
          REF: ${{inputs.ref}}
        run: |
          jq --raw-output --exit-status --arg tag "$REF" '
            if (.version == ($tag | ltrimstr("v"))) then
              "Package version (\(.version)) matches tag version (\($tag | ltrimstr(\"v\")))"
            else
              "Package version (\(.version)) does not match tag version (\($tag | ltrimstr(\"v\")))" | halt_error(1)
            end' package.json
 
      - name: Check CI status
        if: '!inputs.skip_ci_check'
        run: |
          gh run list --commit "$(git rev-parse HEAD)" --workflow ci.yml --status success --json databaseId \
            | jq --raw-output --exit-status '
                if (length > 0) then
                  "CI checks have passed"
                else
                  "CI has not completed successfully for this commit" | halt_error(1)
                end'
        env:
          GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
 
  release:
    timeout-minutes: 30
    name: Release
    runs-on: latchkey-small
    needs: preflight
    environment: npm
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          ref: ${{inputs.ref}}
          fetch-depth: 0
 
      - name: Verify ref is still HEAD of main
        if: needs.preflight.outputs.ref_is_tag == 'false'
        env:
          REF: ${{inputs.ref}}
        run: |
          MAIN_SHA=$(git rev-parse origin/main)
          CURRENT_SHA=$(git rev-parse HEAD)
          if [[ "$CURRENT_SHA" != "$MAIN_SHA" ]]; then
            echo "::error::ref ${REF} (${CURRENT_SHA}) is no longer the HEAD of main (${MAIN_SHA})"
            exit 1
          fi
 
      - name: Generate app token
        id: app-token
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{vars.LAUNCHBOT_ID}}
          private-key: ${{secrets.LAUNCHBOT_PRIVATE_KEY}}
 
      - name: Setup Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: package.json
          cache: npm
          registry-url: https://registry.npmjs.org
 
      - name: Bump version
        if: needs.preflight.outputs.ref_is_tag == 'false'
        env:
          NEW_VERSION: ${{inputs.new_version}}
        run: npm version "$NEW_VERSION" --no-git-tag-version
 
      - name: Push version commit
        if: needs.preflight.outputs.ref_is_tag == 'false'
        id: push-commit
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}
        run: |
          RELEASE_TAG="v$(jq --raw-output .version package.json)"
          PARENT_SHA=$(git rev-parse HEAD)
 
          jq --null-input \
            --arg repo "$GITHUB_REPOSITORY" \
            --arg parentSha "$PARENT_SHA" \
            --arg headline "$RELEASE_TAG" \
            --rawfile pkgContent package.json \
            --rawfile lockContent package-lock.json \
            '{
              query: "mutation($input: CreateCommitOnBranchInput!) { createCommitOnBranch(input: $input) { commit { oid } } }",
              variables: {
                input: {
                  branch: { repositoryNameWithOwner: $repo, branchName: "main" },
                  message: { headline: $headline },
                  expectedHeadOid: $parentSha,
                  fileChanges: {
                    additions: [
                      { path: "package.json", contents: ($pkgContent | @base64) },
                      { path: "package-lock.json", contents: ($lockContent | @base64) }
                    ]
                  }
                }
              }
            }' > /tmp/request.json
 
          COMMIT_SHA=$(gh api graphql --input /tmp/request.json \
            --jq '.data.createCommitOnBranch.commit.oid')
 
          echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
          echo "version_commit_sha=$COMMIT_SHA" >> "$GITHUB_OUTPUT"
 
      - name: Create version tag
        if: needs.preflight.outputs.ref_is_tag == 'false'
        run: |
          gh api "repos/$GITHUB_REPOSITORY/git/refs" \
            -f ref="refs/tags/${{steps.push-commit.outputs.release_tag}}" \
            -f sha="${{steps.push-commit.outputs.version_commit_sha}}"
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}
 
      - name: Publish to npm with provenance
        run: npm publish --provenance
 
      - name: Create GitHub Release
        run: |
          RELEASE_TAG="v$(jq --raw-output .version package.json)"
          gh release create "$RELEASE_TAG" \
            --title "$RELEASE_TAG" \
            --draft \
            --generate-notes
        env:
          GH_TOKEN: ${{steps.app-token.outputs.token}}
 

What changed

This workflow runs 2 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow