build(macos): pin osrf/simulation tap under --ci

When homebrew-core bumps a shared dependency, OSRF's bot bumps each gz
formula's revision and deletes its bottle block within minutes of the upstream
merge. The matching rebuild is a separate, unautomated step: across 2026 the
gap ran 0.5 to 11 days, median 2.5, leaving gz unbottled roughly 18% of the
time. In that window macos.sh compiles gz-sim8, gz-msgs10 and five others from
source and the setup step goes from ~8min to 20-30min.

The removal only edits the formula. The bottle tarballs are never deleted from
OSRF's S3 bucket, so pinning to the last fully bottled revision keeps installs
binary while upstream catches up.

Gated behind a new --ci flag rather than applied unconditionally. Automation
wants a reproducible, fast install; development machines want the current
formulae and can absorb a source build, and should not have their tap left on
a detached HEAD as a side effect of running the setup script.

Only the gz tap is pinned. opencv@4, protobuf, gstreamer and the rest still
track homebrew-core, so CI keeps catching upstream formula breakage on every
PR, which is the reason --sim-tools runs there in the first place.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Ramon Roche <mrpollo@gmail.com>
This commit is contained in:
Ramon Roche
2026-08-19 13:10:10 -07:00
parent cda3c3603f
commit 6ed16e2748
3 changed files with 44 additions and 1 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ jobs:
- name: setup
run: |
./Tools/setup/macos.sh --sim-tools
./Tools/setup/macos.sh --sim-tools --ci
echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH
- uses: ./.github/actions/setup-ccache
+8
View File
@@ -0,0 +1,8 @@
# osrf/simulation revision used by macos.sh --sim-tools.
#
# OSRF strips the gz bottle blocks within minutes of a breaking homebrew-core
# dependency bump and rebuilds them days later. The tarballs stay on S3, so
# pinning keeps the install binary instead of compiling Gazebo from source.
# Move it to the newest commit where every gz formula macos.sh installs still
# carries a bottle block.
c90f81ac7ea8046e195c5e303cc4e1175642e587
+35
View File
@@ -8,6 +8,11 @@
## - Cross compilers for building hardware targets using NuttX
## - With --sim-tools: Gazebo Harmonic and jMAVSim simulation stack
##
## --ci trades freshness for reproducibility and is meant for automation,
## not development machines. Today it pins the osrf/simulation tap to
## gz-tap-pin.txt so Gazebo installs from bottles even while OSRF has
## them pulled.
##
## Homebrew 4.5+ no longer auto-resolves cross-tap dependencies, so
## every tap and package is listed explicitly here rather than hidden
## behind meta-formulae. See PX4/homebrew-px4#104 for background.
@@ -20,6 +25,8 @@ DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
REINSTALL_FORMULAS=""
# Install simulation tools?
INSTALL_SIM=""
# Favour reproducibility over freshness (automation, not dev machines)?
CI_MODE=""
# Parse arguments
for arg in "$@"
@@ -28,6 +35,8 @@ do
REINSTALL_FORMULAS=$arg
elif [[ $arg == "--sim-tools" ]]; then
INSTALL_SIM=$arg
elif [[ $arg == "--ci" ]]; then
CI_MODE=$arg
fi
done
@@ -121,6 +130,32 @@ if [[ $INSTALL_SIM == "--sim-tools" ]]; then
# osrf/simulation: gz-harmonic (Gazebo Harmonic meta-formula)
brew tap osrf/simulation
# Under --ci only: OSRF drops the gz bottle blocks within minutes of a
# breaking homebrew-core dependency bump and rebuilds them days later,
# so an unpinned tap compiles Gazebo from source for a large part of
# the year. Development machines keep tracking the tap normally, and
# get the newer formulae at the cost of that build. See gz-tap-pin.txt.
GZ_TAP_PIN=""
if [[ -n $CI_MODE ]]; then
GZ_TAP_PIN=$(grep -v '^#' "${DIR}/gz-tap-pin.txt" | tr -d '[:space:]')
fi
if [[ -n $GZ_TAP_PIN ]]; then
GZ_TAP_DIR=$(brew --repo osrf/simulation)
echo "[macos.sh] Pinning osrf/simulation to ${GZ_TAP_PIN}"
# brew taps are shallow clones, so the pinned commit has to be
# fetched by SHA before it can be checked out.
git -C "$GZ_TAP_DIR" fetch --quiet origin "$GZ_TAP_PIN" 2>/dev/null
if git -C "$GZ_TAP_DIR" checkout --quiet "$GZ_TAP_PIN"; then
# `brew update` walks local taps and would reset the pin.
# homebrew-core resolves through the JSON API, not this
# clone, so nothing else goes stale.
export HOMEBREW_NO_AUTO_UPDATE=1
else
echo "[macos.sh] WARNING: could not pin osrf/simulation to ${GZ_TAP_PIN}," \
"continuing on tap HEAD (gz may build from source)"
fi
fi
# Homebrew 6.0+ refuses to load formulae from untrusted third-party
# taps (see the toolchain trust block above). Without this, the
# gz-harmonic install aborts and the script still exits successfully,