release workflow (BurntSushi/ripgrep)
The release workflow from BurntSushi/ripgrep, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the release workflow from the BurntSushi/ripgrep repository, a real project running GitHub Actions. It is shown here with attribution under its Unlicense license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: release
# Only do the release on x.y.z tags.
on:
push:
tags:
- "[0-9]+.[0-9]+.[0-9]+"
# We need this to be able to create releases.
permissions:
contents: write
jobs:
# The create-release job runs purely to initialize the GitHub release itself,
# and names the release after the `x.y.z` tag that was pushed. It's separate
# from building the release so that we only create the release once.
create-release:
name: create-release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Get the release version from the tag
if: env.VERSION == ''
run: echo "VERSION=${{ github.ref_name }}" >> $GITHUB_ENV
- name: Show the version
run: |
echo "version is: $VERSION"
- name: Check that tag version and Cargo.toml version are the same
shell: bash
run: |
if ! grep -q "version = \"$VERSION\"" Cargo.toml; then
echo "version does not match Cargo.toml" >&2
exit 1
fi
- name: Create GitHub release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create $VERSION --draft --verify-tag --title $VERSION
outputs:
version: ${{ env.VERSION }}
build-release:
name: build-release
needs: ['create-release']
runs-on: ${{ matrix.os }}
env:
# For some builds, we use cross to test on 32-bit and big-endian
# systems.
CARGO: cargo
# When CARGO is set to CROSS, this is set to `--target matrix.target`.
TARGET_FLAGS:
# When CARGO is set to CROSS, TARGET_DIR includes matrix.target.
TARGET_DIR: ./target
# Bump this as appropriate. We pin to a version to make sure CI
# continues to work as cross releases in the past have broken things
# in subtle ways.
CROSS_VERSION: v0.2.5
# Emit backtraces on panics.
RUST_BACKTRACE: 1
# Build static releases with PCRE2.
PCRE2_SYS_STATIC: 1
strategy:
fail-fast: false
matrix:
include:
- build: linux
os: ubuntu-latest
rust: nightly
target: x86_64-unknown-linux-musl
strip: x86_64-linux-musl-strip
- build: stable-x86
os: ubuntu-latest
rust: stable
target: i686-unknown-linux-gnu
strip: x86_64-linux-gnu-strip
qemu: i386
- build: stable-aarch64
os: ubuntu-latest
rust: stable
target: aarch64-unknown-linux-gnu
strip: aarch64-linux-gnu-strip
qemu: qemu-aarch64
- build: stable-aarch64-musl
os: ubuntu-latest
rust: stable
target: aarch64-unknown-linux-musl
strip: aarch64-linux-musl-strip
qemu: qemu-aarch64
- build: stable-arm-gnueabihf
os: ubuntu-latest
rust: stable
target: armv7-unknown-linux-gnueabihf
strip: arm-linux-gnueabihf-strip
qemu: qemu-arm
- build: stable-arm-musleabihf
os: ubuntu-latest
rust: stable
target: armv7-unknown-linux-musleabihf
strip: arm-linux-musleabihf-strip
qemu: qemu-arm
- build: stable-arm-musleabi
os: ubuntu-latest
rust: stable
target: armv7-unknown-linux-musleabi
strip: arm-linux-musleabi-strip
qemu: qemu-arm
- build: stable-s390x
os: ubuntu-latest
rust: stable
target: s390x-unknown-linux-gnu
strip: s390x-linux-gnu-strip
qemu: qemu-s390x
- build: macos
os: macos-latest
rust: nightly
target: x86_64-apple-darwin
- build: macos
os: macos-latest
rust: nightly
target: aarch64-apple-darwin
- build: win-msvc
os: windows-latest
rust: nightly
target: x86_64-pc-windows-msvc
- build: win-gnu
os: windows-latest
rust: nightly-x86_64-gnu
target: x86_64-pc-windows-gnu
- build: winaarch64-msvc
os: windows-11-arm
rust: nightly
target: aarch64-pc-windows-msvc
- build: win32-msvc
os: windows-latest
rust: nightly
target: i686-pc-windows-msvc
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install packages (Ubuntu)
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
ci/ubuntu-install-packages
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
- name: Use Cross
if: matrix.os == 'ubuntu-latest' && matrix.target != ''
shell: bash
run: |
# In the past, new releases of 'cross' have broken CI. So for now, we
# pin it. We also use their pre-compiled binary releases because cross
# has over 100 dependencies and takes a bit to compile.
dir="$RUNNER_TEMP/cross-download"
mkdir "$dir"
echo "$dir" >> $GITHUB_PATH
cd "$dir"
curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz"
tar xf cross-x86_64-unknown-linux-musl.tar.gz
echo "CARGO=cross" >> $GITHUB_ENV
- name: Set target variables
shell: bash
run: |
echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
- name: Show command used for Cargo
shell: bash
run: |
echo "cargo command is: ${{ env.CARGO }}"
echo "target flag is: ${{ env.TARGET_FLAGS }}"
echo "target dir is: ${{ env.TARGET_DIR }}"
- name: Build release binary
shell: bash
run: |
${{ env.CARGO }} build --verbose --profile release-lto --features pcre2 ${{ env.TARGET_FLAGS }}
if [[ "${{ matrix.os }}" == windows-* ]]; then
bin="target/${{ matrix.target }}/release-lto/rg.exe"
else
bin="target/${{ matrix.target }}/release-lto/rg"
fi
echo "BIN=$bin" >> $GITHUB_ENV
- name: Strip release binary (macos)
if: matrix.os == 'macos-latest'
shell: bash
run: strip "$BIN"
- name: Strip release binary (cross)
if: env.CARGO == 'cross'
shell: bash
run: |
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.strip }}" \
"/$BIN"
- name: Determine archive name
shell: bash
run: |
version="${{ needs.create-release.outputs.version }}"
echo "ARCHIVE=ripgrep-$version-${{ matrix.target }}" >> $GITHUB_ENV
- name: Creating directory for archive
shell: bash
run: |
mkdir -p "$ARCHIVE"/{complete,doc}
cp "$BIN" "$ARCHIVE"/
cp {README.md,COPYING,UNLICENSE,LICENSE-MIT} "$ARCHIVE"/
cp {CHANGELOG.md,FAQ.md,GUIDE.md} "$ARCHIVE"/doc/
- name: Generate man page and completions (no emulation)
if: matrix.qemu == ''
shell: bash
run: |
"$BIN" --version
"$BIN" --generate complete-bash > "$ARCHIVE/complete/rg.bash"
"$BIN" --generate complete-fish > "$ARCHIVE/complete/rg.fish"
"$BIN" --generate complete-powershell > "$ARCHIVE/complete/_rg.ps1"
"$BIN" --generate complete-zsh > "$ARCHIVE/complete/_rg"
"$BIN" --generate man > "$ARCHIVE/doc/rg.1"
- name: Generate man page and completions (emulation)
if: matrix.qemu != ''
shell: bash
run: |
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" --version
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" \
--generate complete-bash > "$ARCHIVE/complete/rg.bash"
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" \
--generate complete-fish > "$ARCHIVE/complete/rg.fish"
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" \
--generate complete-powershell > "$ARCHIVE/complete/_rg.ps1"
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" \
--generate complete-zsh > "$ARCHIVE/complete/_rg"
docker run --rm -v \
"$PWD/target:/target:Z" \
"ghcr.io/cross-rs/${{ matrix.target }}:main" \
"${{ matrix.qemu }}" "/$BIN" \
--generate man > "$ARCHIVE/doc/rg.1"
- name: Build archive (Windows)
shell: bash
if: startsWith(matrix.os, 'windows')
run: |
7z a "$ARCHIVE.zip" "$ARCHIVE"
certutil -hashfile "$ARCHIVE.zip" SHA256 > "$ARCHIVE.zip.sha256"
echo "ASSET=$ARCHIVE.zip" >> $GITHUB_ENV
echo "ASSET_SUM=$ARCHIVE.zip.sha256" >> $GITHUB_ENV
- name: Build archive (Unix)
shell: bash
if: ${{ !startsWith(matrix.os, 'windows') }}
run: |
tar czf "$ARCHIVE.tar.gz" "$ARCHIVE"
shasum -a 256 "$ARCHIVE.tar.gz" > "$ARCHIVE.tar.gz.sha256"
echo "ASSET=$ARCHIVE.tar.gz" >> $GITHUB_ENV
echo "ASSET_SUM=$ARCHIVE.tar.gz.sha256" >> $GITHUB_ENV
- name: Upload release archive
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
version="${{ needs.create-release.outputs.version }}"
gh release upload "$version" ${{ env.ASSET }} ${{ env.ASSET_SUM }}
build-release-deb:
name: build-release-deb
needs: ['create-release']
runs-on: ubuntu-latest
env:
TARGET: x86_64-unknown-linux-musl
# Emit backtraces on panics.
RUST_BACKTRACE: 1
# Since we're distributing the dpkg, we don't know whether the user will
# have PCRE2 installed, so just do a static build.
PCRE2_SYS_STATIC: 1
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install packages (Ubuntu)
shell: bash
run: |
ci/ubuntu-install-packages
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: nightly
target: ${{ env.TARGET }}
- name: Install cargo-deb
shell: bash
run: |
cargo install cargo-deb
# 'cargo deb' does not seem to provide a way to specify an asset that is
# created at build time, such as ripgrep's man page. To work around this,
# we force a debug build, copy out the man page (and shell completions)
# produced from that build, put it into a predictable location and then
# build the deb, which knows where to look.
- name: Build debug binary to create release assets
shell: bash
run: |
cargo build --target ${{ env.TARGET }}
bin="target/${{ env.TARGET }}/debug/rg"
echo "BIN=$bin" >> $GITHUB_ENV
- name: Create deployment directory
shell: bash
run: |
dir=deployment/deb
mkdir -p "$dir"
echo "DEPLOY_DIR=$dir" >> $GITHUB_ENV
- name: Generate man page
shell: bash
run: |
"$BIN" --generate man > "$DEPLOY_DIR/rg.1"
- name: Generate shell completions
shell: bash
run: |
"$BIN" --generate complete-bash > "$DEPLOY_DIR/rg.bash"
"$BIN" --generate complete-fish > "$DEPLOY_DIR/rg.fish"
"$BIN" --generate complete-zsh > "$DEPLOY_DIR/_rg"
- name: Build release binary
shell: bash
run: |
cargo deb --profile deb --target ${{ env.TARGET }}
version="${{ needs.create-release.outputs.version }}"
echo "DEB_DIR=target/${{ env.TARGET }}/debian" >> $GITHUB_ENV
echo "DEB_NAME=ripgrep_$version-1_amd64.deb" >> $GITHUB_ENV
- name: Create sha256 sum of deb file
shell: bash
run: |
cd "$DEB_DIR"
sum="$DEB_NAME.sha256"
shasum -a 256 "$DEB_NAME" > "$sum"
echo "SUM=$sum" >> $GITHUB_ENV
- name: Upload release archive
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
shell: bash
run: |
cd "$DEB_DIR"
version="${{ needs.create-release.outputs.version }}"
gh release upload "$version" "$DEB_NAME" "$SUM"
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: release # Only do the release on x.y.z tags. on: push: tags: - "[0-9]+.[0-9]+.[0-9]+" # We need this to be able to create releases. permissions: contents: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # The create-release job runs purely to initialize the GitHub release itself, # and names the release after the `x.y.z` tag that was pushed. It's separate # from building the release so that we only create the release once. create-release: timeout-minutes: 30 name: create-release runs-on: latchkey-small steps: - uses: actions/checkout@v4 - name: Get the release version from the tag if: env.VERSION == '' run: echo "VERSION=${{ github.ref_name }}" >> $GITHUB_ENV - name: Show the version run: | echo "version is: $VERSION" - name: Check that tag version and Cargo.toml version are the same shell: bash run: | if ! grep -q "version = \"$VERSION\"" Cargo.toml; then echo "version does not match Cargo.toml" >&2 exit 1 fi - name: Create GitHub release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: gh release create $VERSION --draft --verify-tag --title $VERSION outputs: version: ${{ env.VERSION }} build-release: timeout-minutes: 30 name: build-release needs: ['create-release'] runs-on: ${{ matrix.os }} env: # For some builds, we use cross to test on 32-bit and big-endian # systems. CARGO: cargo # When CARGO is set to CROSS, this is set to `--target matrix.target`. TARGET_FLAGS: # When CARGO is set to CROSS, TARGET_DIR includes matrix.target. TARGET_DIR: ./target # Bump this as appropriate. We pin to a version to make sure CI # continues to work as cross releases in the past have broken things # in subtle ways. CROSS_VERSION: v0.2.5 # Emit backtraces on panics. RUST_BACKTRACE: 1 # Build static releases with PCRE2. PCRE2_SYS_STATIC: 1 strategy: fail-fast: false matrix: include: - build: linux os: ubuntu-latest rust: nightly target: x86_64-unknown-linux-musl strip: x86_64-linux-musl-strip - build: stable-x86 os: ubuntu-latest rust: stable target: i686-unknown-linux-gnu strip: x86_64-linux-gnu-strip qemu: i386 - build: stable-aarch64 os: ubuntu-latest rust: stable target: aarch64-unknown-linux-gnu strip: aarch64-linux-gnu-strip qemu: qemu-aarch64 - build: stable-aarch64-musl os: ubuntu-latest rust: stable target: aarch64-unknown-linux-musl strip: aarch64-linux-musl-strip qemu: qemu-aarch64 - build: stable-arm-gnueabihf os: ubuntu-latest rust: stable target: armv7-unknown-linux-gnueabihf strip: arm-linux-gnueabihf-strip qemu: qemu-arm - build: stable-arm-musleabihf os: ubuntu-latest rust: stable target: armv7-unknown-linux-musleabihf strip: arm-linux-musleabihf-strip qemu: qemu-arm - build: stable-arm-musleabi os: ubuntu-latest rust: stable target: armv7-unknown-linux-musleabi strip: arm-linux-musleabi-strip qemu: qemu-arm - build: stable-s390x os: ubuntu-latest rust: stable target: s390x-unknown-linux-gnu strip: s390x-linux-gnu-strip qemu: qemu-s390x - build: macos os: macos-latest rust: nightly target: x86_64-apple-darwin - build: macos os: macos-latest rust: nightly target: aarch64-apple-darwin - build: win-msvc os: windows-latest rust: nightly target: x86_64-pc-windows-msvc - build: win-gnu os: windows-latest rust: nightly-x86_64-gnu target: x86_64-pc-windows-gnu - build: winaarch64-msvc os: windows-11-arm rust: nightly target: aarch64-pc-windows-msvc - build: win32-msvc os: windows-latest rust: nightly target: i686-pc-windows-msvc steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install packages (Ubuntu) if: matrix.os == 'ubuntu-latest' shell: bash run: | ci/ubuntu-install-packages - name: Install Rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} - name: Use Cross if: matrix.os == 'ubuntu-latest' && matrix.target != '' shell: bash run: | # In the past, new releases of 'cross' have broken CI. So for now, we # pin it. We also use their pre-compiled binary releases because cross # has over 100 dependencies and takes a bit to compile. dir="$RUNNER_TEMP/cross-download" mkdir "$dir" echo "$dir" >> $GITHUB_PATH cd "$dir" curl -LO "https://github.com/cross-rs/cross/releases/download/$CROSS_VERSION/cross-x86_64-unknown-linux-musl.tar.gz" tar xf cross-x86_64-unknown-linux-musl.tar.gz echo "CARGO=cross" >> $GITHUB_ENV - name: Set target variables shell: bash run: | echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV - name: Show command used for Cargo shell: bash run: | echo "cargo command is: ${{ env.CARGO }}" echo "target flag is: ${{ env.TARGET_FLAGS }}" echo "target dir is: ${{ env.TARGET_DIR }}" - name: Build release binary shell: bash run: | ${{ env.CARGO }} build --verbose --profile release-lto --features pcre2 ${{ env.TARGET_FLAGS }} if [[ "${{ matrix.os }}" == windows-* ]]; then bin="target/${{ matrix.target }}/release-lto/rg.exe" else bin="target/${{ matrix.target }}/release-lto/rg" fi echo "BIN=$bin" >> $GITHUB_ENV - name: Strip release binary (macos) if: matrix.os == 'macos-latest' shell: bash run: strip "$BIN" - name: Strip release binary (cross) if: env.CARGO == 'cross' shell: bash run: | docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.strip }}" \ "/$BIN" - name: Determine archive name shell: bash run: | version="${{ needs.create-release.outputs.version }}" echo "ARCHIVE=ripgrep-$version-${{ matrix.target }}" >> $GITHUB_ENV - name: Creating directory for archive shell: bash run: | mkdir -p "$ARCHIVE"/{complete,doc} cp "$BIN" "$ARCHIVE"/ cp {README.md,COPYING,UNLICENSE,LICENSE-MIT} "$ARCHIVE"/ cp {CHANGELOG.md,FAQ.md,GUIDE.md} "$ARCHIVE"/doc/ - name: Generate man page and completions (no emulation) if: matrix.qemu == '' shell: bash run: | "$BIN" --version "$BIN" --generate complete-bash > "$ARCHIVE/complete/rg.bash" "$BIN" --generate complete-fish > "$ARCHIVE/complete/rg.fish" "$BIN" --generate complete-powershell > "$ARCHIVE/complete/_rg.ps1" "$BIN" --generate complete-zsh > "$ARCHIVE/complete/_rg" "$BIN" --generate man > "$ARCHIVE/doc/rg.1" - name: Generate man page and completions (emulation) if: matrix.qemu != '' shell: bash run: | docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" --version docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" \ --generate complete-bash > "$ARCHIVE/complete/rg.bash" docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" \ --generate complete-fish > "$ARCHIVE/complete/rg.fish" docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" \ --generate complete-powershell > "$ARCHIVE/complete/_rg.ps1" docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" \ --generate complete-zsh > "$ARCHIVE/complete/_rg" docker run --rm -v \ "$PWD/target:/target:Z" \ "ghcr.io/cross-rs/${{ matrix.target }}:main" \ "${{ matrix.qemu }}" "/$BIN" \ --generate man > "$ARCHIVE/doc/rg.1" - name: Build archive (Windows) shell: bash if: startsWith(matrix.os, 'windows') run: | 7z a "$ARCHIVE.zip" "$ARCHIVE" certutil -hashfile "$ARCHIVE.zip" SHA256 > "$ARCHIVE.zip.sha256" echo "ASSET=$ARCHIVE.zip" >> $GITHUB_ENV echo "ASSET_SUM=$ARCHIVE.zip.sha256" >> $GITHUB_ENV - name: Build archive (Unix) shell: bash if: ${{ !startsWith(matrix.os, 'windows') }} run: | tar czf "$ARCHIVE.tar.gz" "$ARCHIVE" shasum -a 256 "$ARCHIVE.tar.gz" > "$ARCHIVE.tar.gz.sha256" echo "ASSET=$ARCHIVE.tar.gz" >> $GITHUB_ENV echo "ASSET_SUM=$ARCHIVE.tar.gz.sha256" >> $GITHUB_ENV - name: Upload release archive env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | version="${{ needs.create-release.outputs.version }}" gh release upload "$version" ${{ env.ASSET }} ${{ env.ASSET_SUM }} build-release-deb: timeout-minutes: 30 name: build-release-deb needs: ['create-release'] runs-on: latchkey-small env: TARGET: x86_64-unknown-linux-musl # Emit backtraces on panics. RUST_BACKTRACE: 1 # Since we're distributing the dpkg, we don't know whether the user will # have PCRE2 installed, so just do a static build. PCRE2_SYS_STATIC: 1 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install packages (Ubuntu) shell: bash run: | ci/ubuntu-install-packages - name: Install Rust uses: dtolnay/rust-toolchain@master with: toolchain: nightly target: ${{ env.TARGET }} - name: Install cargo-deb shell: bash run: | cargo install cargo-deb # 'cargo deb' does not seem to provide a way to specify an asset that is # created at build time, such as ripgrep's man page. To work around this, # we force a debug build, copy out the man page (and shell completions) # produced from that build, put it into a predictable location and then # build the deb, which knows where to look. - name: Build debug binary to create release assets shell: bash run: | cargo build --target ${{ env.TARGET }} bin="target/${{ env.TARGET }}/debug/rg" echo "BIN=$bin" >> $GITHUB_ENV - name: Create deployment directory shell: bash run: | dir=deployment/deb mkdir -p "$dir" echo "DEPLOY_DIR=$dir" >> $GITHUB_ENV - name: Generate man page shell: bash run: | "$BIN" --generate man > "$DEPLOY_DIR/rg.1" - name: Generate shell completions shell: bash run: | "$BIN" --generate complete-bash > "$DEPLOY_DIR/rg.bash" "$BIN" --generate complete-fish > "$DEPLOY_DIR/rg.fish" "$BIN" --generate complete-zsh > "$DEPLOY_DIR/_rg" - name: Build release binary shell: bash run: | cargo deb --profile deb --target ${{ env.TARGET }} version="${{ needs.create-release.outputs.version }}" echo "DEB_DIR=target/${{ env.TARGET }}/debian" >> $GITHUB_ENV echo "DEB_NAME=ripgrep_$version-1_amd64.deb" >> $GITHUB_ENV - name: Create sha256 sum of deb file shell: bash run: | cd "$DEB_DIR" sum="$DEB_NAME.sha256" shasum -a 256 "$DEB_NAME" > "$sum" echo "SUM=$sum" >> $GITHUB_ENV - name: Upload release archive env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash run: | cd "$DEB_DIR" version="${{ needs.create-release.outputs.version }}" gh release upload "$version" "$DEB_NAME" "$SUM"
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cancel superseded runs when a branch or PR gets a newer push.
- 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 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.