Skip to content
Latchkey

Build CLI workflow (gnmyt/Nexterm)

The Build CLI workflow from gnmyt/Nexterm, explained and optimized by Latchkey.

B

CI health: B - good

Run this on Latchkey for self-healing, caching, and up to 58% lower cost.

Grade your own workflow free or run it on Latchkey →
Source: gnmyt/Nexterm.github/workflows/build-cli.ymlLicense MITView source

What it does

This is the Build CLI workflow from the gnmyt/Nexterm 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 CLI

on:
  workflow_call:
    inputs:
      version:
        required: true
        type: string
      semver:
        required: true
        type: string
      upload_url:
        required: true
        type: string

jobs:
  build-cli:
    name: "CLI (${{ matrix.name }})"
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: linux-x64
            os: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact_name: nt-linux-x64
            is_linux: true
            deb_arch: amd64
            rpm_arch: x86_64
          - name: linux-arm64
            os: ubuntu-22.04-arm
            target: aarch64-unknown-linux-gnu
            artifact_name: nt-linux-arm64
            is_linux: true
            deb_arch: arm64
            rpm_arch: aarch64
          - name: macos-arm64
            os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: nt-macos-arm64
          - name: windows-x64
            os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: nt-windows-x64.exe

    steps:
      - name: Checkout project
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}

      - name: Install OpenSSL (Linux)
        if: startsWith(matrix.os, 'ubuntu-')
        run: |
          sudo apt-get update
          sudo apt-get install -y libssl-dev pkg-config

      - name: Update CLI version
        shell: bash
        run: |
          if [[ "${{ runner.os }}" == "macOS" ]]; then
            sed -i '' "s/^version = \".*\"/version = \"${{ inputs.semver }}\"/" cli/Cargo.toml
          else
            sed -i "s/^version = \".*\"/version = \"${{ inputs.semver }}\"/" cli/Cargo.toml
          fi

      - name: Build CLI
        working-directory: cli
        run: cargo build --release --target ${{ matrix.target }}

      - name: Upload to Release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: cli/target/${{ matrix.target }}/release/${{ runner.os == 'Windows' && 'nt.exe' || 'nt' }}
          asset_name: ${{ matrix.artifact_name }}
          asset_content_type: application/octet-stream

      - name: Install nfpm
        if: matrix.is_linux
        shell: bash
        run: |
          NFPM_VERSION=2.43.0
          case "$(uname -m)" in
            x86_64) HOST=x86_64 ;;
            aarch64|arm64) HOST=arm64 ;;
          esac
          TMP=$(mktemp -d)
          curl -fsSL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_${HOST}.tar.gz" -o "$TMP/nfpm.tar.gz"
          tar -xzf "$TMP/nfpm.tar.gz" -C "$TMP" nfpm
          sudo install -m 0755 "$TMP/nfpm" /usr/local/bin/nfpm
          rm -rf "$TMP"
          nfpm --version

      - name: Stage CLI binary + build .deb / .rpm
        if: matrix.is_linux
        shell: bash
        env:
          PKG_VERSION: ${{ inputs.semver }}
        run: |
          mkdir -p stage/cli dist
          cp cli/target/${{ matrix.target }}/release/nt stage/cli/nt
          chmod +x stage/cli/nt

          PKG_ARCH=${{ matrix.deb_arch }} nfpm pkg \
            --config packaging/nfpm-cli.yaml \
            --packager deb \
            --target "dist/nexterm-cli_${PKG_VERSION}_${{ matrix.deb_arch }}.deb"

          PKG_ARCH=${{ matrix.rpm_arch }} nfpm pkg \
            --config packaging/nfpm-cli.yaml \
            --packager rpm \
            --target "dist/nexterm-cli-${PKG_VERSION}-1.${{ matrix.rpm_arch }}.rpm"

          ls -la dist/

      - name: Upload .deb
        if: matrix.is_linux
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: dist/nexterm-cli_${{ inputs.semver }}_${{ matrix.deb_arch }}.deb
          asset_name: nexterm-cli_${{ inputs.semver }}_${{ matrix.deb_arch }}.deb
          asset_content_type: application/vnd.debian.binary-package

      - name: Upload .rpm
        if: matrix.is_linux
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: dist/nexterm-cli-${{ inputs.semver }}-1.${{ matrix.rpm_arch }}.rpm
          asset_name: nexterm-cli-${{ inputs.semver }}-1.${{ matrix.rpm_arch }}.rpm
          asset_content_type: application/x-rpm

The same workflow, on Latchkey

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

name: Build CLI
 
on:
  workflow_call:
    inputs:
      version:
        required: true
        type: string
      semver:
        required: true
        type: string
      upload_url:
        required: true
        type: string
 
jobs:
  build-cli:
    timeout-minutes: 30
    name: "CLI (${{ matrix.name }})"
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: linux-x64
            os: ubuntu-22.04
            target: x86_64-unknown-linux-gnu
            artifact_name: nt-linux-x64
            is_linux: true
            deb_arch: amd64
            rpm_arch: x86_64
          - name: linux-arm64
            os: ubuntu-22.04-arm
            target: aarch64-unknown-linux-gnu
            artifact_name: nt-linux-arm64
            is_linux: true
            deb_arch: arm64
            rpm_arch: aarch64
          - name: macos-arm64
            os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: nt-macos-arm64
          - name: windows-x64
            os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: nt-windows-x64.exe
 
    steps:
      - name: Checkout project
        uses: actions/checkout@v4
 
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
 
      - name: Install OpenSSL (Linux)
        if: startsWith(matrix.os, 'ubuntu-')
        run: |
          sudo apt-get update
          sudo apt-get install -y libssl-dev pkg-config
 
      - name: Update CLI version
        shell: bash
        run: |
          if [[ "${{ runner.os }}" == "macOS" ]]; then
            sed -i '' "s/^version = \".*\"/version = \"${{ inputs.semver }}\"/" cli/Cargo.toml
          else
            sed -i "s/^version = \".*\"/version = \"${{ inputs.semver }}\"/" cli/Cargo.toml
          fi
 
      - name: Build CLI
        working-directory: cli
        run: cargo build --release --target ${{ matrix.target }}
 
      - name: Upload to Release
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: cli/target/${{ matrix.target }}/release/${{ runner.os == 'Windows' && 'nt.exe' || 'nt' }}
          asset_name: ${{ matrix.artifact_name }}
          asset_content_type: application/octet-stream
 
      - name: Install nfpm
        if: matrix.is_linux
        shell: bash
        run: |
          NFPM_VERSION=2.43.0
          case "$(uname -m)" in
            x86_64) HOST=x86_64 ;;
            aarch64|arm64) HOST=arm64 ;;
          esac
          TMP=$(mktemp -d)
          curl -fsSL "https://github.com/goreleaser/nfpm/releases/download/v${NFPM_VERSION}/nfpm_${NFPM_VERSION}_Linux_${HOST}.tar.gz" -o "$TMP/nfpm.tar.gz"
          tar -xzf "$TMP/nfpm.tar.gz" -C "$TMP" nfpm
          sudo install -m 0755 "$TMP/nfpm" /usr/local/bin/nfpm
          rm -rf "$TMP"
          nfpm --version
 
      - name: Stage CLI binary + build .deb / .rpm
        if: matrix.is_linux
        shell: bash
        env:
          PKG_VERSION: ${{ inputs.semver }}
        run: |
          mkdir -p stage/cli dist
          cp cli/target/${{ matrix.target }}/release/nt stage/cli/nt
          chmod +x stage/cli/nt
 
          PKG_ARCH=${{ matrix.deb_arch }} nfpm pkg \
            --config packaging/nfpm-cli.yaml \
            --packager deb \
            --target "dist/nexterm-cli_${PKG_VERSION}_${{ matrix.deb_arch }}.deb"
 
          PKG_ARCH=${{ matrix.rpm_arch }} nfpm pkg \
            --config packaging/nfpm-cli.yaml \
            --packager rpm \
            --target "dist/nexterm-cli-${PKG_VERSION}-1.${{ matrix.rpm_arch }}.rpm"
 
          ls -la dist/
 
      - name: Upload .deb
        if: matrix.is_linux
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: dist/nexterm-cli_${{ inputs.semver }}_${{ matrix.deb_arch }}.deb
          asset_name: nexterm-cli_${{ inputs.semver }}_${{ matrix.deb_arch }}.deb
          asset_content_type: application/vnd.debian.binary-package
 
      - name: Upload .rpm
        if: matrix.is_linux
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ inputs.upload_url }}
          asset_path: dist/nexterm-cli-${{ inputs.semver }}-1.${{ matrix.rpm_arch }}.rpm
          asset_name: nexterm-cli-${{ inputs.semver }}-1.${{ matrix.rpm_arch }}.rpm
          asset_content_type: application/x-rpm
 

What changed

1 third-party action is referenced by a movable tag. Pin it 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 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow