Skip to content
Latchkey

Build workflow (Postcatlab/postcat)

The Build workflow from Postcatlab/postcat, explained and optimized by Latchkey.

D

CI health: D - needs work

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: Postcatlab/postcat.github/workflows/build.ymlLicense Apache-2.0View source

What it does

This is the Build workflow from the Postcatlab/postcat repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Build

on:
  push:
    # branches: [feat/xxx]
    tags:
      - 'v*.*.*'
jobs:
  release:
    name: build and release electron app
    runs-on: ${{ matrix.os }}

    strategy:
      fail-fast: false
      matrix:
        os: [macos-12, ubuntu-latest]

    steps:
      - name: Check out git repository
        uses: actions/checkout@v3.0.0

      - name: Install Node.js
        uses: actions/setup-node@v3.0.0
        with:
          node-version: '16'

      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT

      - uses: actions/cache@v3
        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install
        run: |
          yarn install --frozen-lockfile
          echo "${{ secrets.QINIU_ENV_JS }}" > scripts/qiniu_env.js

      - name: Release for MacOS
        if: matrix.os == 'macos-12'
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          # BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          # create variables
          CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
          # PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

          # import certificate and provisioning profile from secrets
          echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
          # echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH

          # create temporary keychain
          security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH

          # import certificate to keychain
          security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security list-keychain -d user -s $KEYCHAIN_PATH

          # apply provisioning profile
          # mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
          # cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
          echo "${{ secrets.NOTARIZE_JS }}" > scripts/notarize.js
          yarn release
          yarn upload

          # clean up keychain and provisioning profile
          security delete-keychain $RUNNER_TEMP/app-signing.keychain-db

      - name: Release for Linux
        if: matrix.os == 'ubuntu-latest'
        run: |
          yarn release
          yarn upload
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: Build
 
on:
  push:
    # branches: [feat/xxx]
    tags:
      - 'v*.*.*'
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  release:
    timeout-minutes: 30
    name: build and release electron app
    runs-on: ${{ matrix.os }}
 
    strategy:
      fail-fast: false
      matrix:
        os: [macos-12, ubuntu-latest]
 
    steps:
      - name: Check out git repository
        uses: actions/checkout@v3.0.0
 
      - name: Install Node.js
        uses: actions/setup-node@v3.0.0
        with:
          cache: 'npm'
          node-version: '16'
 
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
 
      - uses: actions/cache@v3
        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install
        run: |
          yarn install --frozen-lockfile
          echo "${{ secrets.QINIU_ENV_JS }}" > scripts/qiniu_env.js
 
      - name: Release for MacOS
        if: matrix.os == 'macos-12'
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
          BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          # BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          # create variables
          CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
          # PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
          KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
 
          # import certificate and provisioning profile from secrets
          echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
          # echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH
 
          # create temporary keychain
          security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
          security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
 
          # import certificate to keychain
          security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
          security list-keychain -d user -s $KEYCHAIN_PATH
 
          # apply provisioning profile
          # mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
          # cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
          echo "${{ secrets.NOTARIZE_JS }}" > scripts/notarize.js
          yarn release
          yarn upload
 
          # clean up keychain and provisioning profile
          security delete-keychain $RUNNER_TEMP/app-signing.keychain-db
 
      - name: Release for Linux
        if: matrix.os == 'ubuntu-latest'
        run: |
          yarn release
          yarn upload
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
 

What changed

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 (2 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow