Release workflow (violentmonkey/violentmonkey)
The Release workflow from violentmonkey/violentmonkey, explained and optimized by Latchkey.
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.
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
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
- 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.
- Cache dependency installs on the setup step so they are served from cache.
- 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.
This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.