release-automated workflow (parse-community/parse-server)
The release-automated workflow from parse-community/parse-server, 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-automated workflow from the parse-community/parse-server 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
name: release-automated
on:
push:
branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ]
jobs:
release:
runs-on: ubuntu-latest
outputs:
current_tag: ${{ steps.tag.outputs.current_tag }}
trigger_branch: ${{ steps.branch.outputs.trigger_branch }}
steps:
- name: Determine trigger branch name
id: branch
run: echo "::set-output name=trigger_branch::${GITHUB_REF#refs/*/}"
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22
registry-url: https://registry.npmjs.org/
- name: Cache Node.js modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- run: npx semantic-release
env:
GH_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Determine tag on current commit
id: tag
run: echo "::set-output name=current_tag::$(git describe --tags --abbrev=0 --exact-match || echo '')"
docker:
needs: release
if: needs.release.outputs.current_tag != ''
env:
REGISTRY: docker.io
IMAGE_NAME: parseplatform/parse-server
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Determine branch name
id: branch
run: echo "::set-output name=branch_name::${GITHUB_REF#refs/*/}"
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ needs.release.outputs.current_tag }}
- name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log into Docker Hub
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=${{ steps.branch.outputs.branch_name == 'release' }}
tags: |
type=semver,pattern={{version}},value=${{ needs.release.outputs.current_tag }}
- name: Build and push Docker image
uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64, linux/arm64/v8
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
docs:
needs: release
if: needs.release.outputs.current_tag != '' && github.ref == 'refs/heads/release'
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deploy.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 18.20.4
- name: Cache Node.js modules
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Generate Docs
run: |
echo $SOURCE_TAG
npm ci
./release_docs.sh
env:
SOURCE_TAG: ${{ needs.release.outputs.current_tag }}
- name: Configure Pages
uses: actions/configure-pages@v5
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v4
with:
path: ./docs
- name: Deploy to GitHub Pages
id: deploy
uses: actions/deploy-pages@v4
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-automated on: push: branches: [ release, alpha, beta, next-major, 'release-[0-9]+.x.x' ] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: release: timeout-minutes: 30 runs-on: latchkey-small outputs: current_tag: ${{ steps.tag.outputs.current_tag }} trigger_branch: ${{ steps.branch.outputs.trigger_branch }} steps: - name: Determine trigger branch name id: branch run: echo "::set-output name=trigger_branch::${GITHUB_REF#refs/*/}" - uses: actions/checkout@v4 with: persist-credentials: false - uses: actions/setup-node@v4 with: cache: 'npm' node-version: 22 registry-url: https://registry.npmjs.org/ - name: Cache Node.js modules uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - run: npm ci - run: npx semantic-release env: GH_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Determine tag on current commit id: tag run: echo "::set-output name=current_tag::$(git describe --tags --abbrev=0 --exact-match || echo '')" docker: timeout-minutes: 30 needs: release if: needs.release.outputs.current_tag != '' env: REGISTRY: docker.io IMAGE_NAME: parseplatform/parse-server runs-on: latchkey-small permissions: contents: read packages: write steps: - name: Determine branch name id: branch run: echo "::set-output name=branch_name::${GITHUB_REF#refs/*/}" - name: Checkout repository uses: actions/checkout@v4 with: ref: ${{ needs.release.outputs.current_tag }} - name: Set up QEMU id: qemu uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log into Docker Hub if: github.event_name != 'pull_request' uses: docker/login-action@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract Docker metadata id: meta uses: docker/metadata-action@v4 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} flavor: | latest=${{ steps.branch.outputs.branch_name == 'release' }} tags: | type=semver,pattern={{version}},value=${{ needs.release.outputs.current_tag }} - name: Build and push Docker image uses: docker/build-push-action@v3 with: context: . platforms: linux/amd64, linux/arm64/v8 push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} docs: needs: release if: needs.release.outputs.current_tag != '' && github.ref == 'refs/heads/release' runs-on: latchkey-small timeout-minutes: 15 permissions: contents: read pages: write id-token: write environment: name: github-pages url: ${{ steps.deploy.outputs.page_url }} steps: - uses: actions/checkout@v4 - name: Use Node.js uses: actions/setup-node@v4 with: cache: 'npm' node-version: 18.20.4 - name: Cache Node.js modules uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - name: Generate Docs run: | echo $SOURCE_TAG npm ci ./release_docs.sh env: SOURCE_TAG: ${{ needs.release.outputs.current_tag }} - name: Configure Pages uses: actions/configure-pages@v5 - name: Upload Pages artifact uses: actions/upload-pages-artifact@v4 with: path: ./docs - name: Deploy to GitHub Pages id: deploy uses: actions/deploy-pages@v4
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.
5 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.
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
- Container pulls and builds
This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.