Skip to content
Latchkey

Release workflow (violentmonkey/violentmonkey)

The Release workflow from violentmonkey/violentmonkey, explained and optimized by Latchkey.

F

CI health: F - at risk

Point runs-on at Latchkey and get caching, run de-duplication, 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: violentmonkey/violentmonkey.github/workflows/release.ymlLicense MITView source

What it does

This is the Release workflow from the violentmonkey/violentmonkey 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_dispatch:
  push:
    tags:
      - v*

jobs:
  build:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v1 # v1 keeps tags
        with:
          fetch-depth: 250 # for `action-helper`
          # persist-credentials: false # not implemented in v1

      - uses: pnpm/action-setup@v6

      - uses: actions/setup-node@v6
        with:
          node-version-file: 'package.json'

      - name: Prepare
        run: pnpm i && node scripts/action-helper.js
        env:
          ACTION_BUILD_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
          DISCORD_WEBHOOK_RELEASE: ${{ secrets.DISCORD_WEBHOOK_RELEASE }}

      - name: Test
        run: pnpm run ci

      - name: Build
        env:
          SYNC_DROPBOX_CLIENT_ID: ${{ secrets.SYNC_DROPBOX_CLIENT_ID }}
          SYNC_GOOGLE_DESKTOP_ID: ${{ secrets.SYNC_GOOGLE_DESKTOP_ID }}
          SYNC_GOOGLE_DESKTOP_SECRET: ${{ secrets.SYNC_GOOGLE_DESKTOP_SECRET }}
          SYNC_ONEDRIVE_CLIENT_ID: ${{ secrets.SYNC_ONEDRIVE_CLIENT_ID }}
        run: |
          mkdir -p $ASSETS_DIR $TEMP_DIR

          # Create source zip
          git archive @ --format=zip > $TEMP_DIR/$SOURCE_ZIP
          # Include .env to ensure the output is reproducible
          export | grep SYNC_ | sed -e 's/^declare -x //' > .env \
            && zip -u $TEMP_DIR/$SOURCE_ZIP .env && rm .env

          # Build for release, also upload to GitHub assets
          pnpm build
          # Build one more time to make sure the output is the same
          # mv dist $TEMP_DIR/dist && pnpm build && diff -qr dist $TEMP_DIR/dist

      - name: Zip
        run: |
          cd dist && zip -r ../$ASSETS_DIR/$ASSET_ZIP . && cd ..

          # Build for AMO unlisted, append `BETA` to version name and set update_url for FF
          # Same as `pnpm build:selfHosted` but only manifest is changed by now
          TARGET=selfHosted BETA=1 npx gulp manifest
          cd dist && zip -r ../$TEMP_DIR/$ASSET_SELF_HOSTED_ZIP . && cd ..

      - run: pnpm build:mv3
        env:
          SYNC_DROPBOX_CLIENT_ID: ${{ secrets.SYNC_DROPBOX_CLIENT_ID }}
          SYNC_GOOGLE_DESKTOP_ID: ${{ secrets.SYNC_GOOGLE_DESKTOP_ID }}
          SYNC_GOOGLE_DESKTOP_SECRET: ${{ secrets.SYNC_GOOGLE_DESKTOP_SECRET }}
          SYNC_ONEDRIVE_CLIENT_ID: ${{ secrets.SYNC_ONEDRIVE_CLIENT_ID }}

      - name: Zip MV3
        run: |
          cd dist-mv3 && zip -r ../$ASSETS_DIR/$ASSET_CWS_ZIP . && cd ..

          # Build for CWS beta, append `BETA` to version name
          # Same as `BETA=1 pnpm build` but only manifest is changed by now
          BETA=1 MV3=1 npx gulp manifest
          cd dist-mv3 && zip -r ../$TEMP_DIR/$ASSET_CWS_BETA_ZIP . && cd ..

      - name: Publish to AMO
        continue-on-error: true
        run: |
          mkdir -p $TEMP_DIR/updates
          if [ "$PRERELEASE" = "true" ]; then
            echo Publish unlisted version
            export BETA=1
          else
            echo Publish listed version
          fi
          if ! node scripts/amo-upload.mjs 2>"$TEMP_DIR/stderr.log"; then
            export ERROR=$(cat "$TEMP_DIR/stderr.log" 2>/dev/null || true)
            ERROR="${ERROR:-AMO publish failed}"
          fi
          export TARGET=AMO
          node scripts/notify-release.mjs
        env:
          AMO_KEY: ${{ secrets.AMO_KEY }}
          AMO_SECRET: ${{ secrets.AMO_SECRET }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # Try to publish if not exist
          AMO_PUBLISH: true

      - name: Publish to CWS
        continue-on-error: true
        run: |
          set -x
          if [ "$PRERELEASE" != "true" ]; then
            echo Publish release
            CWS_EXT_ID=$EXTENSION_ID_RELEASE
            CWS_SOURCE=$ASSETS_DIR/$ASSET_CWS_ZIP
          else
            echo Publish prerelease
            CWS_EXT_ID=$EXTENSION_ID_BETA
            CWS_SOURCE=$TEMP_DIR/$ASSET_CWS_BETA_ZIP
          fi
          if ! npx chrome-webstore-upload-cli@4 --extension-id $CWS_EXT_ID --source $CWS_SOURCE 2>"$TEMP_DIR/stderr.log"; then
            export ERROR=$(cat "$TEMP_DIR/stderr.log" 2>/dev/null || true)
            ERROR="${ERROR:-CWS publish failed}"

            # Ignore pending review error: "❌ You may not edit or publish an item that is in review."
            if [[ "$ERROR" == *"is in review"* ]]; then
              echo "::warning::PENDING_REVIEW: skipping CWS publish notification"
              exit 0
            fi
          fi
          export TARGET=CWS
          node scripts/notify-release.mjs
        env:
          EXTENSION_ID_BETA: opokoaglpekkimldnlggpoagmjegichg
          EXTENSION_ID_RELEASE: jinjaccalgkegednnccohejagnlnfdag
          PUBLISHER_ID: ${{ secrets.CWS_PUBLISHER_ID }}
          CLIENT_ID: ${{ secrets.CWS_CLIENT_ID }}
          CLIENT_SECRET: ${{ secrets.CWS_CLIENT_SECRET }}
          REFRESH_TOKEN: ${{ secrets.CWS_REFRESH_TOKEN }}

      - name: Create/Update Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          node -e 'import("./scripts/release-helper.mjs").then(({ uploadAssets }) => uploadAssets())';

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: Release
 
on:
  workflow_dispatch:
  push:
    tags:
      - v*
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
 
      - uses: actions/checkout@v1 # v1 keeps tags
        with:
          fetch-depth: 250 # for `action-helper`
          # persist-credentials: false # not implemented in v1
 
      - uses: pnpm/action-setup@v6
 
      - uses: actions/setup-node@v6
        with:
          cache: 'npm'
          node-version-file: 'package.json'
 
      - name: Prepare
        run: pnpm i && node scripts/action-helper.js
        env:
          ACTION_BUILD_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
          DISCORD_WEBHOOK_RELEASE: ${{ secrets.DISCORD_WEBHOOK_RELEASE }}
 
      - name: Test
        run: pnpm run ci
 
      - name: Build
        env:
          SYNC_DROPBOX_CLIENT_ID: ${{ secrets.SYNC_DROPBOX_CLIENT_ID }}
          SYNC_GOOGLE_DESKTOP_ID: ${{ secrets.SYNC_GOOGLE_DESKTOP_ID }}
          SYNC_GOOGLE_DESKTOP_SECRET: ${{ secrets.SYNC_GOOGLE_DESKTOP_SECRET }}
          SYNC_ONEDRIVE_CLIENT_ID: ${{ secrets.SYNC_ONEDRIVE_CLIENT_ID }}
        run: |
          mkdir -p $ASSETS_DIR $TEMP_DIR
 
          # Create source zip
          git archive @ --format=zip > $TEMP_DIR/$SOURCE_ZIP
          # Include .env to ensure the output is reproducible
          export | grep SYNC_ | sed -e 's/^declare -x //' > .env \
            && zip -u $TEMP_DIR/$SOURCE_ZIP .env && rm .env
 
          # Build for release, also upload to GitHub assets
          pnpm build
          # Build one more time to make sure the output is the same
          # mv dist $TEMP_DIR/dist && pnpm build && diff -qr dist $TEMP_DIR/dist
 
      - name: Zip
        run: |
          cd dist && zip -r ../$ASSETS_DIR/$ASSET_ZIP . && cd ..
 
          # Build for AMO unlisted, append `BETA` to version name and set update_url for FF
          # Same as `pnpm build:selfHosted` but only manifest is changed by now
          TARGET=selfHosted BETA=1 npx gulp manifest
          cd dist && zip -r ../$TEMP_DIR/$ASSET_SELF_HOSTED_ZIP . && cd ..
 
      - run: pnpm build:mv3
        env:
          SYNC_DROPBOX_CLIENT_ID: ${{ secrets.SYNC_DROPBOX_CLIENT_ID }}
          SYNC_GOOGLE_DESKTOP_ID: ${{ secrets.SYNC_GOOGLE_DESKTOP_ID }}
          SYNC_GOOGLE_DESKTOP_SECRET: ${{ secrets.SYNC_GOOGLE_DESKTOP_SECRET }}
          SYNC_ONEDRIVE_CLIENT_ID: ${{ secrets.SYNC_ONEDRIVE_CLIENT_ID }}
 
      - name: Zip MV3
        run: |
          cd dist-mv3 && zip -r ../$ASSETS_DIR/$ASSET_CWS_ZIP . && cd ..
 
          # Build for CWS beta, append `BETA` to version name
          # Same as `BETA=1 pnpm build` but only manifest is changed by now
          BETA=1 MV3=1 npx gulp manifest
          cd dist-mv3 && zip -r ../$TEMP_DIR/$ASSET_CWS_BETA_ZIP . && cd ..
 
      - name: Publish to AMO
        continue-on-error: true
        run: |
          mkdir -p $TEMP_DIR/updates
          if [ "$PRERELEASE" = "true" ]; then
            echo Publish unlisted version
            export BETA=1
          else
            echo Publish listed version
          fi
          if ! node scripts/amo-upload.mjs 2>"$TEMP_DIR/stderr.log"; then
            export ERROR=$(cat "$TEMP_DIR/stderr.log" 2>/dev/null || true)
            ERROR="${ERROR:-AMO publish failed}"
          fi
          export TARGET=AMO
          node scripts/notify-release.mjs
        env:
          AMO_KEY: ${{ secrets.AMO_KEY }}
          AMO_SECRET: ${{ secrets.AMO_SECRET }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          # Try to publish if not exist
          AMO_PUBLISH: true
 
      - name: Publish to CWS
        continue-on-error: true
        run: |
          set -x
          if [ "$PRERELEASE" != "true" ]; then
            echo Publish release
            CWS_EXT_ID=$EXTENSION_ID_RELEASE
            CWS_SOURCE=$ASSETS_DIR/$ASSET_CWS_ZIP
          else
            echo Publish prerelease
            CWS_EXT_ID=$EXTENSION_ID_BETA
            CWS_SOURCE=$TEMP_DIR/$ASSET_CWS_BETA_ZIP
          fi
          if ! npx chrome-webstore-upload-cli@4 --extension-id $CWS_EXT_ID --source $CWS_SOURCE 2>"$TEMP_DIR/stderr.log"; then
            export ERROR=$(cat "$TEMP_DIR/stderr.log" 2>/dev/null || true)
            ERROR="${ERROR:-CWS publish failed}"
 
            # Ignore pending review error: "❌ You may not edit or publish an item that is in review."
            if [[ "$ERROR" == *"is in review"* ]]; then
              echo "::warning::PENDING_REVIEW: skipping CWS publish notification"
              exit 0
            fi
          fi
          export TARGET=CWS
          node scripts/notify-release.mjs
        env:
          EXTENSION_ID_BETA: opokoaglpekkimldnlggpoagmjegichg
          EXTENSION_ID_RELEASE: jinjaccalgkegednnccohejagnlnfdag
          PUBLISHER_ID: ${{ secrets.CWS_PUBLISHER_ID }}
          CLIENT_ID: ${{ secrets.CWS_CLIENT_ID }}
          CLIENT_SECRET: ${{ secrets.CWS_CLIENT_SECRET }}
          REFRESH_TOKEN: ${{ secrets.CWS_REFRESH_TOKEN }}
 
      - name: Create/Update Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          node -e 'import("./scripts/release-helper.mjs").then(({ uploadAssets }) => uploadAssets())';
 

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.

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