Skip to content
Latchkey

release workflow (parcel-bundler/parcel)

The release workflow from parcel-bundler/parcel, explained and optimized by Latchkey.

B

CI health: B - good

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

What it does

This is the release workflow from the parcel-bundler/parcel 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_call:
    inputs:
      release-command:
        description: 'The command that will release packages as part of the final step'
        required: true
        type: string
      type:
        description: 'The type of release, usually corresponds to the dist-tag'
        required: true
        type: string
      profile:
        description: 'The profile to use when building the native binaries'
        required: false
        default: 'release'
        type: string
    secrets:
      GHCR_TOKEN:
        required: true
      NPM_TOKEN:
        required: true

permissions:
  contents: read # for actions/checkout

jobs:
  build-macos-windows:
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: aarch64-apple-darwin
            os: macos-latest
            target: aarch64-apple-darwin

          - name: x86_64-apple-darwin
            os: macos-latest
            target: x86_64-apple-darwin

          - name: windows-latest
            os: windows-latest
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          target: ${{ matrix.target }}
      - uses: bahmutov/npm-install@v1.8.35
      - uses: Swatinem/rust-cache@v2
        if: ${{ inputs.type != 'latest' }}
        with:
          shared-key: ${{ matrix.name }}
      - name: Remove CommandLineTools SDKs
        if: ${{ matrix.target == 'aarch64-apple-darwin' }}
        run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
      - name: Build native packages
        run: yarn build-native-${{ inputs.profile }}
        env:
          RUST_TARGET: ${{ matrix.target }}
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.name }}
          path: packages/*/*/*.node
      - name: Debug
        if: ${{ runner.os == 'macOS' }}
        run: ls -l packages/*/*/*.node
      - name: Smoke test
        if: ${{ !matrix.target }}
        run: node -e "require('@parcel/rust')"

  build-linux:
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            arch: x86_64
            cflags: -mevex512
            glibc: 2.26
            docker: node:20-slim
            args: ''
          - target: armv7-unknown-linux-gnueabihf
            arch: armhf
            cflags: -mfpu=neon
            glibc: 2.26
            docker: node:20-slim
            args: '--platform linux/arm/v7'
          - target: aarch64-unknown-linux-gnu
            arch: arm64
            cflags: ''
            glibc: 2.26
            docker: node:20-slim
            args: '--platform linux/arm64'
          - target: x86_64-unknown-linux-musl
            arch: x86_64
            cflags: -msse4.2 -mevex512
            glibc: ''
            docker: node:20-alpine
            args: ''
          - target: aarch64-unknown-linux-musl
            arch: aarch64
            cflags: ''
            glibc: ''
            docker: node:20-alpine
            args: '--platform linux/arm64'
    name: ${{ matrix.target }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          target: ${{ matrix.target }}
      - name: Install ziglang
        uses: goto-bus-stop/setup-zig@v1
        with:
          version: 0.14.0
      - name: Install cargo toolchains
        uses: taiki-e/install-action@v2
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          tool: cargo-zigbuild
      - uses: bahmutov/npm-install@v1.8.35
      - uses: Swatinem/rust-cache@v2
        if: ${{ inputs.type != 'latest' }}
        with:
          shared-key: ${{ matrix.target }}
      - name: Build native packages
        run: yarn build-native-${{ inputs.profile }}
        env:
          RUST_TARGET: ${{ matrix.target }}
          ZIG_GLIBC: ${{ matrix.glibc }}
          CFLAGS: ${{ matrix.cflags }}
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.target }}
          path: packages/*/*/*.node
      - name: debug
        run: ls -l packages/*/*/*.node
      - name: Set up QEMU
        if: ${{ matrix.arch != 'x86_64' }}
        uses: docker/setup-qemu-action@v3
        with:
          platforms: arm64,arm
      - name: Configure binfmt-support
        if: ${{ matrix.arch != 'x86_64' }}
        run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      - name: Smoke test
        uses: addnab/docker-run-action@v3
        with:
          image: ${{ matrix.docker }}
          options: ${{ matrix.args }} -v ${{ github.workspace }}:/build -w /build
          run: node -e "require('@parcel/rust')"

  build-and-release:
    runs-on: ubuntu-22.04
    name: Build and release
    needs:
      - build-linux
      - build-macos-windows
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: bahmutov/npm-install@v1.8.35
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts
      - name: Move bindings
        run: for d in artifacts/bindings-*/*/*; do cp $d/*.node packages/$(basename $(dirname $d))/$(basename $d); done
      - name: Debug
        run: |
          ls -l packages/*/*/*.node
      - run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: ${{ inputs.release-command }}

The same workflow, on Latchkey

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

name: release
 
on:
  workflow_call:
    inputs:
      release-command:
        description: 'The command that will release packages as part of the final step'
        required: true
        type: string
      type:
        description: 'The type of release, usually corresponds to the dist-tag'
        required: true
        type: string
      profile:
        description: 'The profile to use when building the native binaries'
        required: false
        default: 'release'
        type: string
    secrets:
      GHCR_TOKEN:
        required: true
      NPM_TOKEN:
        required: true
 
permissions:
  contents: read # for actions/checkout
 
jobs:
  build-macos-windows:
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: aarch64-apple-darwin
            os: macos-latest
            target: aarch64-apple-darwin
 
          - name: x86_64-apple-darwin
            os: macos-latest
            target: x86_64-apple-darwin
 
          - name: windows-latest
            os: windows-latest
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          target: ${{ matrix.target }}
      - uses: bahmutov/npm-install@v1.8.35
      - uses: Swatinem/rust-cache@v2
        if: ${{ inputs.type != 'latest' }}
        with:
          shared-key: ${{ matrix.name }}
      - name: Remove CommandLineTools SDKs
        if: ${{ matrix.target == 'aarch64-apple-darwin' }}
        run: sudo rm -Rf /Library/Developer/CommandLineTools/SDKs/*;
      - name: Build native packages
        run: yarn build-native-${{ inputs.profile }}
        env:
          RUST_TARGET: ${{ matrix.target }}
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.name }}
          path: packages/*/*/*.node
      - name: Debug
        if: ${{ runner.os == 'macOS' }}
        run: ls -l packages/*/*/*.node
      - name: Smoke test
        if: ${{ !matrix.target }}
        run: node -e "require('@parcel/rust')"
 
  build-linux:
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            arch: x86_64
            cflags: -mevex512
            glibc: 2.26
            docker: node:20-slim
            args: ''
          - target: armv7-unknown-linux-gnueabihf
            arch: armhf
            cflags: -mfpu=neon
            glibc: 2.26
            docker: node:20-slim
            args: '--platform linux/arm/v7'
          - target: aarch64-unknown-linux-gnu
            arch: arm64
            cflags: ''
            glibc: 2.26
            docker: node:20-slim
            args: '--platform linux/arm64'
          - target: x86_64-unknown-linux-musl
            arch: x86_64
            cflags: -msse4.2 -mevex512
            glibc: ''
            docker: node:20-alpine
            args: ''
          - target: aarch64-unknown-linux-musl
            arch: aarch64
            cflags: ''
            glibc: ''
            docker: node:20-alpine
            args: '--platform linux/arm64'
    name: ${{ matrix.target }}
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          target: ${{ matrix.target }}
      - name: Install ziglang
        uses: goto-bus-stop/setup-zig@v1
        with:
          version: 0.14.0
      - name: Install cargo toolchains
        uses: taiki-e/install-action@v2
        env:
          GITHUB_TOKEN: ${{ github.token }}
        with:
          tool: cargo-zigbuild
      - uses: bahmutov/npm-install@v1.8.35
      - uses: Swatinem/rust-cache@v2
        if: ${{ inputs.type != 'latest' }}
        with:
          shared-key: ${{ matrix.target }}
      - name: Build native packages
        run: yarn build-native-${{ inputs.profile }}
        env:
          RUST_TARGET: ${{ matrix.target }}
          ZIG_GLIBC: ${{ matrix.glibc }}
          CFLAGS: ${{ matrix.cflags }}
      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.target }}
          path: packages/*/*/*.node
      - name: debug
        run: ls -l packages/*/*/*.node
      - name: Set up QEMU
        if: ${{ matrix.arch != 'x86_64' }}
        uses: docker/setup-qemu-action@v3
        with:
          platforms: arm64,arm
      - name: Configure binfmt-support
        if: ${{ matrix.arch != 'x86_64' }}
        run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
      - name: Smoke test
        uses: addnab/docker-run-action@v3
        with:
          image: ${{ matrix.docker }}
          options: ${{ matrix.args }} -v ${{ github.workspace }}:/build -w /build
          run: node -e "require('@parcel/rust')"
 
  build-and-release:
    timeout-minutes: 30
    runs-on: latchkey-small
    name: Build and release
    needs:
      - build-linux
      - build-macos-windows
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: bahmutov/npm-install@v1.8.35
      - name: Download artifacts
        uses: actions/download-artifact@v4
        with:
          path: artifacts
      - name: Move bindings
        run: for d in artifacts/bindings-*/*/*; do cp $d/*.node packages/$(basename $(dirname $d))/$(basename $d); done
      - name: Debug
        run: |
          ls -l packages/*/*/*.node
      - run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      - run: ${{ inputs.release-command }}
 

What changed

7 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.

This workflow runs 3 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