@@ -2,17 +2,23 @@ name: Build Tauri App
22
33on :
44 push :
5+ # Tag pushes create the real release drafts. `main` pushes also run
6+ # the full build but skip release creation — they exist purely to
7+ # populate caches (Rust target/, libvips, x86_64 Homebrew) on the
8+ # default branch so subsequent tag pushes can restore from them.
9+ # Without this, every tag is a fully cold build.
10+ branches : [main]
511 tags :
612 - ' v*'
713 workflow_dispatch :
814
9- # Prevent concurrent release runs against the same ref (e.g. a re-tag or a
10- # manual dispatch colliding with a tag push) from racing to create the same
11- # draft release. Not cancelling in-progress runs: an aborted build can leave
12- # a half-uploaded release asset behind .
15+ # Tag builds must never be cancelled mid-flight: an aborted run can leave a
16+ # half-uploaded release asset behind. `main` and workflow_dispatch runs are
17+ # pure cache-warm / validation builds, so cancelling an older run when a
18+ # newer one arrives is safe and avoids queueing backlogs on rapid merges .
1319concurrency :
1420 group : release-${{ github.ref }}
15- cancel-in-progress : false
21+ cancel-in-progress : ${{ !startsWith(github.ref, 'refs/tags/') }}
1622
1723env :
1824 CARGO_INCREMENTAL : 0
8288 with :
8389 path : vendor/libvips-native
8490 key : libvips-win64-8.18.0
91+ restore-keys : |
92+ libvips-win64-
8593
8694 - name : Install libvips (Windows)
8795 if : runner.os == 'Windows' && steps.cache-vips.outputs.cache-hit != 'true'
@@ -113,19 +121,14 @@ jobs:
113121 Set-Content -Path platform-config.json -Value $json
114122 echo "config_args=--config platform-config.json" | Out-File -Append -FilePath $env:GITHUB_OUTPUT
115123
116- - name : Install libvips ARM64 (macOS)
117- if : runner.os == 'macOS'
118- env :
119- HOMEBREW_NO_AUTO_UPDATE : ' 1'
120- HOMEBREW_NO_INSTALL_CLEANUP : ' 1'
121- run : |
122- brew install vips
123- echo "VIPS_DIR=$(brew --prefix vips)" >> $GITHUB_ENV
124-
125124 # Cache the x86_64 Homebrew installation (Homebrew repo + Cellar) so we don't
126125 # re-run the install script and 'brew install vips' (+ ~40 transitive deps) on
127126 # every run. The cache key is pinned to "vips-v1"; bump to "vips-v2" when vips
128- # or a major dep updates and a fresh install is needed.
127+ # or a major dep updates and a fresh install is needed. `restore-keys`
128+ # lets a future bump (e.g. vips-v2) still fall back to an older entry
129+ # while the new cache populates, rather than going fully cold.
130+ # This step is placed BEFORE the install step so the cache-hit output is
131+ # available to the combined install script below.
129132 - name : Cache x86_64 Homebrew (macOS)
130133 if : runner.os == 'macOS'
131134 id : cache-x86-brew
@@ -135,13 +138,23 @@ jobs:
135138 /usr/local/Homebrew
136139 /usr/local/Cellar
137140 key : macos-x86-homebrew-vips-v1
138-
139- - name : Install libvips x86_64 (macOS, for universal build)
141+ restore-keys : |
142+ macos-x86-homebrew-vips-
143+
144+ # Install vips for both architectures in parallel. ARM64 install (~2m
145+ # fresh, seconds when cached at the runner level) runs in the background
146+ # while the x86_64 path runs in the foreground. Overlapping these two
147+ # saves ~2 minutes per cold build. We `wait` on the ARM64 PID at the
148+ # end so its exit code still fails the job.
149+ - name : Install libvips for both arches in parallel (macOS)
140150 if : runner.os == 'macOS'
141151 env :
142152 HOMEBREW_NO_AUTO_UPDATE : ' 1'
143153 HOMEBREW_NO_INSTALL_CLEANUP : ' 1'
144154 run : |
155+ brew install vips > arm64-brew.log 2>&1 &
156+ ARM64_PID=$!
157+
145158 if [ "${{ steps.cache-x86-brew.outputs.cache-hit }}" = "true" ]; then
146159 # Recreate /usr/local/bin/brew symlink and re-link all formulae whose
147160 # opt/lib/include symlinks are not preserved by the cache action.
@@ -156,13 +169,29 @@ jobs:
156169 # Hard-fail if the x86_64 vips prefix is missing — without this the
157170 # collect-universal-dylibs.sh script silently emits ::warning:: and
158171 # produces an ARM64-only DMG that breaks on Intel Macs.
172+ # Assert before waiting on ARM64 so failure messages stay
173+ # attributable to the right arch.
159174 X86_VIPS_PREFIX=$(arch -x86_64 /usr/local/bin/brew --prefix vips 2>/dev/null || true)
160175 if [ -z "$X86_VIPS_PREFIX" ] || [ ! -d "$X86_VIPS_PREFIX/lib" ]; then
161176 echo "::error::x86_64 Homebrew vips not available at expected prefix. Cache may be corrupt — bump the cache key (currently 'macos-x86-homebrew-vips-v1')."
162177 exit 1
163178 fi
164179 echo "x86_64 vips verified at $X86_VIPS_PREFIX"
165180
181+ # Wait for the backgrounded ARM64 install and surface its exit code.
182+ if ! wait "$ARM64_PID"; then
183+ echo "::error::ARM64 'brew install vips' failed — see log below"
184+ cat arm64-brew.log || true
185+ exit 1
186+ fi
187+ # Only print the ARM64 log on success if it contains warnings, to
188+ # avoid drowning out the x86_64 output above on normal runs.
189+ if grep -qiE 'warning|error' arm64-brew.log 2>/dev/null; then
190+ echo "--- ARM64 brew install log ---"
191+ cat arm64-brew.log
192+ fi
193+ echo "VIPS_DIR=$(brew --prefix vips)" >> $GITHUB_ENV
194+
166195 - name : Stage universal dylibs (macOS)
167196 if : runner.os == 'macOS'
168197 id : stage-macos
@@ -242,12 +271,17 @@ jobs:
242271 ${{ steps.stage-windows.outputs.config_args || '' }}
243272 ${{ steps.stage-macos.outputs.config_args || '' }}
244273 includeDebug : false
245- tagName : v__VERSION__
246- releaseName : ' Image Optimizer v__VERSION__'
247- releaseBody : ${{ steps.changelog.outputs.body }}
248- releaseDraft : true
274+ # On non-tag runs (main pushes, workflow_dispatch) we want to build
275+ # and verify the bundle — which warms all caches — but NOT publish a
276+ # draft release. tauri-action treats an empty tagName as "build
277+ # only": no release is created or updated. Release metadata inputs
278+ # are gated on the same condition to keep behaviour symmetric.
279+ tagName : ${{ startsWith(github.ref, 'refs/tags/') && 'v__VERSION__' || '' }}
280+ releaseName : ${{ startsWith(github.ref, 'refs/tags/') && 'Image Optimizer v__VERSION__' || '' }}
281+ releaseBody : ${{ startsWith(github.ref, 'refs/tags/') && steps.changelog.outputs.body || '' }}
282+ releaseDraft : ${{ startsWith(github.ref, 'refs/tags/') }}
249283 # Tags containing a hyphen (e.g. v0.7.0-beta.1) are treated as prereleases.
250- prerelease : ${{ contains(github.ref_name, '-') }}
284+ prerelease : ${{ startsWith(github.ref, 'refs/tags/') && contains(github.ref_name, '-') }}
251285
252286 - name : Verify bundled dylibs (macOS)
253287 if : runner.os == 'macOS'
0 commit comments