Skip to content

Commit 1e9816c

Browse files
committed
ci: pin brew-installed utilities to specific versions for supply-chain hardening
1 parent 00b3817 commit 1e9816c

8 files changed

Lines changed: 211 additions & 7 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
# RNFB CI vendored formula — do not install from third-party taps in workflows.
3+
# Upstream: wix/homebrew-brew @ 8f636f84541e — AppleSimulatorUtils 0.9.12
4+
# Update: see okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
5+
6+
class Applesimutils < Formula
7+
desc "Apple simulator utilities"
8+
homepage "https://github.com/wix/AppleSimulatorUtils"
9+
url "https://github.com/wix/AppleSimulatorUtils/releases/download/0.9.12/AppleSimulatorUtils-0.9.12.tar.gz"
10+
sha256 "4d6d02311959388ff5c28e2f4781848dbe1ca07f34b1d81d273940e099020b09"
11+
12+
bottle do
13+
root_url "https://github.com/wix/AppleSimulatorUtils/releases/download/0.9.12"
14+
15+
sha256 arm64_big_sur: "3373d85ea6051e77865b0a22960eb0b5d63f3126c7c99232d0b6b9c83ee2c133"
16+
sha256 catalina: "530e29950dba6d11ca6da6841d24b84d835f8215836664d6e6ce8b23acce4a51"
17+
sha256 mojave: "3373d85ea6051e77865b0a22960eb0b5d63f3126c7c99232d0b6b9c83ee2c133"
18+
sha256 high_sierra: "3373d85ea6051e77865b0a22960eb0b5d63f3126c7c99232d0b6b9c83ee2c133"
19+
sha256 sierra: "3373d85ea6051e77865b0a22960eb0b5d63f3126c7c99232d0b6b9c83ee2c133"
20+
sha256 big_sur: "3373d85ea6051e77865b0a22960eb0b5d63f3126c7c99232d0b6b9c83ee2c133"
21+
end
22+
23+
depends_on xcode: ["8.0", :build]
24+
25+
def install
26+
system "./buildForBrew.sh", prefix
27+
end
28+
29+
test do
30+
system "#{bin}/applesimutils", "--help"
31+
end
32+
end
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# frozen_string_literal: true
2+
# RNFB CI vendored formula — do not install from live homebrew-core in workflows.
3+
# Upstream: Homebrew/homebrew-core @ f2e343d17882 — xcbeautify 3.2.1
4+
# Update: see okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
5+
6+
class Xcbeautify < Formula
7+
desc "Little beautifier tool for xcodebuild"
8+
homepage "https://github.com/cpisciotta/xcbeautify"
9+
url "https://github.com/cpisciotta/xcbeautify/archive/refs/tags/3.2.1.tar.gz"
10+
sha256 "7575dcb90e4650f8d8f66b92ca2f3eaa5ad9feddda7bf3c63aeb0edca199aa80"
11+
license "MIT"
12+
13+
bottle do
14+
sha256 cellar: :any_skip_relocation, arm64_tahoe: "55d10b6b29942408802a3f7c141c8245b310054331c39be16f027f93867ad005"
15+
sha256 cellar: :any_skip_relocation, arm64_sequoia: "f1094ef28d3e6f734cc58b43201a7112218b2518ed5b47b0c4e3242071a90742"
16+
sha256 cellar: :any, arm64_sonoma: "f65b81e0e1d354fc026fda8e4006579b99e764a5bee9cdb20343a432c902f84a"
17+
sha256 cellar: :any, sonoma: "da329e9b36ffc742e9dcba04f9bc2d2dcb05e41ecb9d902b5ab016145a46ac2c"
18+
sha256 cellar: :any_skip_relocation, arm64_linux: "0699fc7ed411b8e6875d2273dd230b83947a10f38471e59ff953a57283cb4c26"
19+
sha256 cellar: :any_skip_relocation, x86_64_linux: "1121ea99822c46089101d09aa4d43ad5679c5883f6c2212e712ba016db5a3ffe"
20+
end
21+
22+
# needs Swift tools version 6.1.0
23+
uses_from_macos "swift" => :build, since: :sequoia
24+
uses_from_macos "libxml2"
25+
26+
on_sequoia do
27+
# Workaround for https://github.com/apple/swift-argument-parser/issues/827
28+
# Conditional should really be Swift >= 6.2 but not available so using
29+
# a check on the specific ld version included with Xcode >= 26
30+
depends_on xcode: :build if DevelopmentTools.ld64_version >= "1221.4"
31+
end
32+
33+
def install
34+
args = if OS.mac?
35+
%w[--disable-sandbox]
36+
else
37+
%w[--static-swift-stdlib -Xswiftc -use-ld=ld]
38+
end
39+
system "swift", "build", *args, "--configuration", "release"
40+
bin.install ".build/release/xcbeautify"
41+
generate_completions_from_executable(bin/"xcbeautify", "--generate-completion-script")
42+
end
43+
44+
test do
45+
log = "CompileStoryboard /Users/admin/MyApp/MyApp/Main.storyboard (in target: MyApp)"
46+
assert_match "[MyApp] Compiling Main.storyboard",
47+
pipe_output("#{bin}/xcbeautify --disable-colored-output", log).chomp
48+
assert_match version.to_s,
49+
shell_output("#{bin}/xcbeautify --version").chomp
50+
end
51+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/usr/bin/env bash
2+
# Install vendored RNFB Homebrew formulae (Brew 6+ requires a tap, not bare --formula paths).
3+
# Pin/update docs: okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
4+
set -euo pipefail
5+
6+
if [[ $# -lt 1 ]]; then
7+
echo "usage: $0 <formula> [<formula> ...]" >&2
8+
exit 1
9+
fi
10+
11+
TAP_ROOT="$(brew --repository)/Library/Taps/invertase/homebrew-rnfb"
12+
mkdir -p "$TAP_ROOT"
13+
cp -R .github/homebrew-rnfb/Formula "$TAP_ROOT/"
14+
15+
export HOMEBREW_NO_AUTO_UPDATE=1
16+
brew trust invertase/rnfb
17+
18+
# GHA images often ship homebrew-core formulae with the same names. Brew refuses to
19+
# install invertase/rnfb/<name> while core <name> is still in the Cellar.
20+
for formula in "$@"; do
21+
if brew list --formula "$formula" &>/dev/null; then
22+
echo "Uninstalling existing ${formula} before invertase/rnfb install..."
23+
brew uninstall --formula "$formula"
24+
fi
25+
done
26+
27+
install_args=()
28+
for formula in "$@"; do
29+
install_args+=("invertase/rnfb/${formula}")
30+
done
31+
brew install "${install_args[@]}"

.github/workflows/tests_e2e_ios.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,14 +264,15 @@ jobs:
264264
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
265265
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
266266
267+
# Vendored Homebrew formulae — pin/update: okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
267268
- name: Install brew utilities
268269
# https://github.com/nick-fields/retry/releases
269270
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
270271
with:
271272
timeout_minutes: 5
272273
retry_wait_seconds: 60
273274
max_attempts: 3
274-
command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils xcbeautify
275+
command: bash .github/workflows/scripts/install-homebrew-rnfb.sh applesimutils xcbeautify
275276

276277
- name: Build iOS App Debug
277278
if: contains(matrix.buildmode, 'debug')

.github/workflows/tests_e2e_other.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,14 +219,15 @@ jobs:
219219
- name: Start Firestore Emulator
220220
run: yarn tests:emulator:start-ci
221221

222+
# Vendored Homebrew formulae — pin/update: okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
222223
- name: Install brew utilities
223224
# https://github.com/nick-fields/retry/releases
224225
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
225226
with:
226227
timeout_minutes: 5
227228
retry_wait_seconds: 60
228229
max_attempts: 3
229-
command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install xcbeautify
230+
command: bash .github/workflows/scripts/install-homebrew-rnfb.sh xcbeautify
230231

231232
- name: Build macos App
232233
run: |

CONTRIBUTING.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ cd react-native-firebase
9999

100100
```bash
101101
yarn
102-
brew tap wix/brew
103-
brew install applesimutils xcbeautify
102+
bash .github/workflows/scripts/install-homebrew-rnfb.sh applesimutils xcbeautify
104103
```
105104

106105
> Note that this project is a mono-repo, so you only need to install NPM dependencies once at the root of the project with `yarn`.

okf-bundle/ci-workflows/ios.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,3 +221,93 @@ rg 'Coverage summary|jet-coverage' detox-step.log
221221
- **Release vs debug** — matrix runs both; each has separate artifacts (`debug` / `release` in the artifact name).
222222
- **Retry** — Pre-Boot retries up to 3 times with 60s between attempts (clean shutdown + boot each time).
223223
- **Do not boot the simulator only inside Detox** — historical races where the testee never sent “ready” to the Detox proxy; pre-boot remains mandatory.
224+
225+
### Pinned Homebrew utilities
226+
227+
CI installs macOS build helpers from **vendored formulae** in `.github/homebrew-rnfb/Formula/` instead of live taps (`wix/brew`, `homebrew-core`). Each formula file is frozen in git with pinned `url`, source `sha256`, and bottle hashes — similar in spirit to SHA-pinned GitHub Actions.
228+
229+
| Formula | Version | Upstream source | Used in |
230+
|---------|---------|-----------------|---------|
231+
| `applesimutils.rb` | 0.9.12 | [wix/homebrew-brew](https://github.com/wix/homebrew-brew) @ `8f636f84541e` | iOS e2e (`tests_e2e_ios.yml`) |
232+
| `xcbeautify.rb` | 3.2.1 | [homebrew-core](https://github.com/Homebrew/homebrew-core) @ `f2e343d17882` | iOS e2e + macOS e2e (`tests_e2e_other.yml`) |
233+
234+
**Workflow install** — both workflows call `.github/workflows/scripts/install-homebrew-rnfb.sh` (from repo root). Homebrew 6+ refuses bare `brew install --formula path/to.rb`; the script copies formulae into a local `invertase/rnfb` tap, trusts it once per job, then installs:
235+
236+
```bash
237+
# iOS e2e (tests_e2e_ios.yml)
238+
bash .github/workflows/scripts/install-homebrew-rnfb.sh applesimutils xcbeautify
239+
240+
# macOS e2e (tests_e2e_other.yml)
241+
bash .github/workflows/scripts/install-homebrew-rnfb.sh xcbeautify
242+
```
243+
244+
**Why** — Third-party taps can change formula definitions on every `brew update`. Vendoring avoids supply-chain drift and Brew 6 untrusted-tap warnings for live third-party taps. We still `brew trust invertase/rnfb` for the ephemeral local tap copy each job creates. The install script **uninstalls any existing `homebrew-core` (or other tap) install** of the same formula name first — GHA macOS images often preinstall `xcbeautify`, and Brew refuses same-name formulae from two taps.
245+
246+
#### When to update a pinned formula
247+
248+
- CI **Install brew utilities** fails after a macOS runner / Xcode image bump (common for `xcbeautify` Swift/`on_sequoia` conditionals).
249+
- You need a newer **applesimutils** or **xcbeautify** feature or bugfix.
250+
- A security advisory affects the pinned upstream release (bump `url` / version and checksums).
251+
252+
#### How to update a pinned formula
253+
254+
1. **Fetch the upstream formula** you want to vendor (usually `master`, or a specific commit if you need a known-good revision):
255+
256+
```bash
257+
# applesimutils (wix tap)
258+
curl -fsSL "https://raw.githubusercontent.com/wix/homebrew-brew/master/Formula/applesimutils.rb" \
259+
-o /tmp/applesimutils.rb
260+
261+
# xcbeautify (homebrew-core)
262+
curl -fsSL "https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/x/xcbeautify.rb" \
263+
-o /tmp/xcbeautify.rb
264+
```
265+
266+
2. **Record the upstream commit** (for the table above and the file header):
267+
268+
```bash
269+
# applesimutils
270+
gh api repos/wix/homebrew-brew/commits \
271+
-f path=Formula/applesimutils.rb -f per_page=1 \
272+
--jq '.[0].sha[:12]'
273+
274+
# xcbeautify
275+
gh api repos/Homebrew/homebrew-core/commits \
276+
-f path=Formula/x/xcbeautify.rb -f per_page=1 \
277+
--jq '.[0].sha[:12]'
278+
```
279+
280+
3. **Merge into `.github/homebrew-rnfb/Formula/<name>.rb`** — keep the RNFB header at the top (replace version + commit), then paste the upstream `class` body. Remove `head "..."` lines if present (frozen vendored formulae should not track moving branches). Example header:
281+
282+
```ruby
283+
# frozen_string_literal: true
284+
# RNFB CI vendored formula — do not install from third-party taps in workflows.
285+
# Upstream: wix/homebrew-brew @ <12-char-sha> — AppleSimulatorUtils <version>
286+
# Update: see okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities
287+
```
288+
289+
4. **Verify locally on macOS** (from repo root):
290+
291+
```bash
292+
bash .github/workflows/scripts/install-homebrew-rnfb.sh <name>
293+
<name> --version # xcbeautify
294+
applesimutils --help # applesimutils (no --version)
295+
```
296+
297+
If upgrading a formula already in your Cellar, uninstall first: `brew uninstall <name>`.
298+
299+
5. **Update this doc** — bump the version and upstream-commit columns in the table above.
300+
301+
6. **Open a PR** — CI will exercise the same install script as production workflows. Watch the **Install brew utilities** step timing (`applesimutils` often builds from source on `macos-26`).
302+
303+
#### Local dev (optional)
304+
305+
Match CI with the install script, or install a single formula file via the script:
306+
307+
```bash
308+
bash .github/workflows/scripts/install-homebrew-rnfb.sh applesimutils xcbeautify
309+
```
310+
311+
See also `CONTRIBUTING.md` and `tests/README.md`.
312+
313+
**`applesimutils` on modern runners** — upstream bottles target older macOS releases; GHA `macos-26` typically **builds from source** (needs Xcode). Expect a longer “Install brew utilities” step than `xcbeautify`, which usually installs from a matching bottle.

tests/README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ Our tests are powered by [Jet ✈️](https://github.com/invertase/jet).
1313
- [Apple Sim Utils](https://github.com/wix/AppleSimulatorUtils):
1414

1515
```bash
16-
brew tap wix/brew
17-
brew install wix/brew/applesimutils
16+
bash .github/workflows/scripts/install-homebrew-rnfb.sh applesimutils
1817
```
1918

20-
> **Note**: If Homebrew complains about a conflict in the `wix/brew` tap, run `brew untap wix/brew && brew tap wix/brew` and try installing again
19+
CI uses the same vendored formulae (see `okf-bundle/ci-workflows/ios.md#pinned-homebrew-utilities`).
2120

2221
---
2322

0 commit comments

Comments
 (0)