Build CLI workflow (gnmyt/Nexterm)
The Build CLI workflow from gnmyt/Nexterm, explained and optimized by Latchkey.
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 →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
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
- Add a job timeout so a hung step cannot burn hours of runner time.
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:
- Dependency installs
- Network fetches
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.