One build per push: previews carry the PR check
Build App (Preview) / compute-version (pull_request) Successful in 3s
Build App (Preview) / create-release (pull_request) Successful in 1s
Build App (Preview) / build-macos (pull_request) Successful in 2m44s
Build App (Preview) / build-windows (pull_request) Successful in 5m27s
Build App (Preview) / build-linux (pull_request) Successful in 5m36s

Every push to the PR started two workflows on the same commit.
build-app.yml ran on pull_request and compiled all three platforms —
then published nothing, because every publishing step in it is gated on
`gitea.event_name == 'push'`. build-app-preview.yml compiled the same
three and published them. Six OS builds per push, half of them
unreachable.

So the PR trigger moves to the preview workflow, which was already doing
the identical compilation and has something to show for it.
build-app.yml is now push-to-main and manual dispatch only: releases.

Two things a pull_request event changes, handled rather than inherited:
`gitea.sha` can be the merge ref — not the commit anyone is testing, and
not something to hang a tag on — so the release's target comes from
`git rev-parse HEAD` in the checkout; and `gitea.ref_name` is the PR
number, so the release body uses `gitea.head_ref` when there is one.

The cost is one prerelease per PR commit touching app/**, which the
existing Cleanup Old Releases sweep already prunes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-11 10:41:35 -07:00
co-authored by Claude Opus 5
parent f239fa1c82
commit 5bd80a05bc
2 changed files with 32 additions and 8 deletions
+26 -2
View File
@@ -2,7 +2,15 @@ name: Build App (Preview)
# Builds the Tauri app for branches other than main and publishes the bundles as # Builds the Tauri app for branches other than main and publishes the bundles as
# a **prerelease**, so they are downloadable from the Releases page. No GitHub # a **prerelease**, so they are downloadable from the Releases page. No GitHub
# sync — intended for smoke-testing a feature branch before it merges. # sync.
#
# This is also the **PR build check**: it compiles Linux, macOS and Windows, so
# a push that breaks any of them fails here. build-app.yml used to do that job
# in parallel and publish nothing, which meant six OS builds per push and one
# unreachable set of bundles; it is now releases-only.
#
# The cost of the swap, stated plainly: one prerelease per PR commit that
# touches `app/**`. They are pruned by Cleanup Old Releases (see Lifecycle).
# #
# ## Why not workflow artifacts # ## Why not workflow artifacts
# #
@@ -36,6 +44,15 @@ env:
REPO: ${{ gitea.repository }} REPO: ${{ gitea.repository }}
on: on:
# Every push to an open PR: this *is* the branch's build check — it compiles
# Linux, macOS and Windows — and publishing the result costs nothing extra
# once they are built. build-app.yml deliberately no longer runs on PRs.
pull_request:
branches: [main]
paths:
- "app/**"
- "VERSION"
- ".gitea/workflows/build-app-preview.yml"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -43,6 +60,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
version: ${{ steps.version.outputs.VERSION }} version: ${{ steps.version.outputs.VERSION }}
sha: ${{ steps.version.outputs.SHA }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -54,6 +72,10 @@ jobs:
run: | run: |
MAJOR_MINOR=$(cat VERSION | tr -d '[:space:]') MAJOR_MINOR=$(cat VERSION | tr -d '[:space:]')
SHORT_SHA=$(git rev-parse --short HEAD) SHORT_SHA=$(git rev-parse --short HEAD)
# From the checkout, not from `gitea.sha`: on a pull_request event
# that variable can be the merge ref, which is not the commit anyone
# is testing and not something to hang a tag on.
echo "SHA=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT
# The patch number is computed exactly as build-app.yml does it, so a # The patch number is computed exactly as build-app.yml does it, so a
# preview is labelled with the version the release it previews would # preview is labelled with the version the release it previews would
@@ -89,6 +111,8 @@ jobs:
env: env:
TOKEN: ${{ secrets.REGISTRY_TOKEN }} TOKEN: ${{ secrets.REGISTRY_TOKEN }}
VERSION: ${{ needs.compute-version.outputs.version }} VERSION: ${{ needs.compute-version.outputs.version }}
SHA: ${{ needs.compute-version.outputs.sha }}
BRANCH: ${{ gitea.head_ref || gitea.ref_name }}
run: | run: |
set -euo pipefail set -euo pipefail
TAG="preview-${VERSION##*.}" TAG="preview-${VERSION##*.}"
@@ -108,7 +132,7 @@ jobs:
curl -fsS -X POST \ curl -fsS -X POST \
-H "Authorization: token ${TOKEN}" \ -H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d "{\"tag_name\": \"${TAG}\", \"target_commitish\": \"${{ gitea.sha }}\", \"name\": \"Preview ${VERSION}\", \"prerelease\": true, \"body\": \"Unreleased build of \`${{ gitea.ref_name }}\` at ${{ gitea.sha }}. Not a release — pruned by Cleanup Old Releases.\"}" \ -d "{\"tag_name\": \"${TAG}\", \"target_commitish\": \"${SHA}\", \"name\": \"Preview ${VERSION}\", \"prerelease\": true, \"body\": \"Unreleased build of \`${BRANCH}\` at ${SHA}. Not a release — pruned by Cleanup Old Releases.\"}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases" > release.json "${GITEA_URL}/api/v1/repos/${REPO}/releases" > release.json
;; ;;
*) *)
+6 -6
View File
@@ -7,14 +7,14 @@ on:
- "app/**" - "app/**"
- "VERSION" - "VERSION"
- ".gitea/workflows/build-app.yml" - ".gitea/workflows/build-app.yml"
pull_request:
branches: [main]
paths:
- "app/**"
- "VERSION"
- ".gitea/workflows/build-app.yml"
workflow_dispatch: workflow_dispatch:
# Deliberately **not** on pull_request. Every publishing step here is gated on
# `gitea.event_name == 'push'`, so a PR run compiled all three platforms and
# produced nothing — and it ran alongside build-app-preview.yml, which compiles
# the same three and publishes them. Six OS builds per push, one set of which
# was unreachable. Previews now carry the PR check; this workflow is releases.
env: env:
GITEA_URL: ${{ gitea.server_url }} GITEA_URL: ${{ gitea.server_url }}
REPO: ${{ gitea.repository }} REPO: ${{ gitea.repository }}