Core Build and Release workflow (SurgeDM/Surge)
The Core Build and Release workflow from SurgeDM/Surge, explained and optimized by Latchkey.
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.
What it does
This is the Core Build and Release workflow from the SurgeDM/Surge 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: Core Build and Release
on:
push:
branches:
- main
tags:
- "v*"
- "!ext-v*"
pull_request:
branches:
- main
paths-ignore:
- "extension/**"
permissions:
contents: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test and Check (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.0"
check-latest: false
- name: Install gotestsum
run: go install gotest.tools/gotestsum@latest
- name: Build
shell: bash
run: go build -v ./...
- name: Test
shell: bash
run: |
cover_arg=""
if [ "$RUNNER_OS" = "Linux" ]; then
cover_arg="-coverprofile=coverage.out"
fi
gotestsum --junitfile test-results.xml --format testdox -- -race $cover_arg ./...
- name: Comment Test Failures
if: always() && github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const signature = '<!-- core-build-test-failures-${{ matrix.os }} -->';
// 1. Delete previous comments
try {
const comments = await github.paginate(github.rest.issues.listComments, {
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
});
for (const comment of comments) {
if (comment.user?.type === 'Bot' && comment.body.includes(signature)) {
await github.rest.issues.deleteComment({
comment_id: comment.id,
owner: context.repo.owner,
repo: context.repo.repo,
});
}
}
} catch (err) {
core.warning(`Could not delete old comments: ${err.message}`);
}
// 2. Post new comment if there are failures
if (!fs.existsSync('test-results.xml')) return;
const content = fs.readFileSync('test-results.xml', 'utf8');
const regex = /<testcase classname="([^"]+)" name="([^"]+)"[^>]*>\s*<(?:failure|error)/g;
let match;
const failures = [];
while ((match = regex.exec(content)) !== null) {
failures.push(`- **${match[1]}**: \`${match[2]}\``);
}
if (failures.length > 0) {
const body = `${signature}\n### ❌ Test Failures on \`${{ matrix.os }}\`\n` + failures.join('\n');
try {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: body
});
} catch (err) {
// Fork PRs have a read-only token; log but don't fail the step.
core.warning(`Could not post comment (fork PR?): ${err.message}`);
}
}
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
if: matrix.os == 'ubuntu-latest' && success() && hashFiles('coverage.out') != ''
with:
token: ${{ secrets.CODECOV_TOKEN }}
release:
name: Release
runs-on: ubuntu-latest
needs: test
# Extra guard: only core tags (v*), never extension tags (ext-v*)
if: startsWith(github.ref, 'refs/tags/v') && !startsWith(github.ref, 'refs/tags/ext-v')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.25.0"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser-pro
version: latest
args: release --clean
env:
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Core Build and Release on: push: branches: - main tags: - "v*" - "!ext-v*" pull_request: branches: - main paths-ignore: - "extension/**" permissions: contents: write pull-requests: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: test: timeout-minutes: 30 name: Test and Check (${{ matrix.os }}) strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: "1.25.0" check-latest: false - name: Install gotestsum run: go install gotest.tools/gotestsum@latest - name: Build shell: bash run: go build -v ./... - name: Test shell: bash run: | cover_arg="" if [ "$RUNNER_OS" = "Linux" ]; then cover_arg="-coverprofile=coverage.out" fi gotestsum --junitfile test-results.xml --format testdox -- -race $cover_arg ./... - name: Comment Test Failures if: always() && github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const fs = require('fs'); const signature = '<!-- core-build-test-failures-${{ matrix.os }} -->'; // 1. Delete previous comments try { const comments = await github.paginate(github.rest.issues.listComments, { issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); for (const comment of comments) { if (comment.user?.type === 'Bot' && comment.body.includes(signature)) { await github.rest.issues.deleteComment({ comment_id: comment.id, owner: context.repo.owner, repo: context.repo.repo, }); } } } catch (err) { core.warning(`Could not delete old comments: ${err.message}`); } // 2. Post new comment if there are failures if (!fs.existsSync('test-results.xml')) return; const content = fs.readFileSync('test-results.xml', 'utf8'); const regex = /<testcase classname="([^"]+)" name="([^"]+)"[^>]*>\s*<(?:failure|error)/g; let match; const failures = []; while ((match = regex.exec(content)) !== null) { failures.push(`- **${match[1]}**: \`${match[2]}\``); } if (failures.length > 0) { const body = `${signature}\n### ❌ Test Failures on \`${{ matrix.os }}\`\n` + failures.join('\n'); try { await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: body }); } catch (err) { // Fork PRs have a read-only token; log but don't fail the step. core.warning(`Could not post comment (fork PR?): ${err.message}`); } } - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 if: matrix.os == 'ubuntu-latest' && success() && hashFiles('coverage.out') != '' with: token: ${{ secrets.CODECOV_TOKEN }} release: timeout-minutes: 30 name: Release runs-on: latchkey-small needs: test # Extra guard: only core tags (v*), never extension tags (ext-v*) if: startsWith(github.ref, 'refs/tags/v') && !startsWith(github.ref, 'refs/tags/ext-v') steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v5 with: go-version: "1.25.0" - name: Run GoReleaser uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser-pro version: latest args: release --clean env: GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
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. - Add a job timeout so a hung step cannot burn hours of runner time.
2 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 2 jobs (4 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.