omnigent: pin google-re2 to its upstream wheel, and stop ignoring build failures - #17
omnigent: pin google-re2 to its upstream wheel, and stop ignoring build failures#17fanzeyi wants to merge 4 commits into
Conversation
…ld failures
The formula has not built since 0.7.0. omnigent moved CEL policy evaluation
from cel-expr-python to cel-python, and cel-python hard-depends on google-re2
(imported at celpy module scope, no fallback). google-re2's sdist runs
`bazel build` whenever GITHUB_ACTIONS is set -- always true here -- and its
non-bazel path needs re2, abseil and pybind11 headers plus C++17, none of which
it requests:
bazel build --extra_toolchains=//python/toolchains:all ... -- :all
error: command 'bazel' failed: No such file or directory
::error::omnigent-ai/tap/omnigent 0.8.1 did not build
Pin google-re2 to the upstream cp314 macOS wheels instead. They statically link
re2 and abseil (`otool -L` shows only system libraries), so this needs no build
toolchain and, unlike `depends_on "abseil"`, does not tie the bottle to abseil's
ABI and its frequent revision bumps. Homebrew only auto-installs `py3-none-any`
wheels, so platform wheels are copied from their cached download to the real
filename and pip-installed directly -- the same approach this formula used for
google-antigravity.
The reason this shipped three times unnoticed: test-bot sets ignore_failures for
any formula that is neither newly added nor already bottled at its current
version, which is every version bump here, since `brew pr-pull` only adds the
bottle block afterwards. `brew install --build-bottle` then fails, test-bot
prints "Warning: 1 failed step ignored!", and the job still exits 0. 0.7.0,
0.8.0 and 0.8.1 all merged with three green checks and no bottle. Gate the job
on test-bot's own steps_output.txt so an ignored failure fails the run.
Also assert `import re2, celpy` in the formula test: omnigent imports celpy
behind a try/except, so a missing google-re2 disables inline policies silently
rather than failing the build.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
The google-re2 wheel pin got the build past bazel, but it then failed 26 minutes
in on pendulum:
Undefined symbols for architecture arm64: "__Py_Dealloc", "__Py_NoneStruct",
"__Py_TrueStruct", "__Py_FalseStruct"
ld: symbol(s) not found for architecture arm64
error: could not compile `_pendulum` (lib)
Those are libpython symbols an extension module resolves lazily at load time via
`-undefined dynamic_lookup`, which maturin injects as cargo-config rustflags.
The formula's `ENV.append_to_rustflags "-C link-args=-Wl,-headerpad_max_install
_names"` sets RUSTFLAGS in the environment, and env RUSTFLAGS *replaces*
config-file rustflags rather than adding to them -- so the headerpad workaround
added for jiter silently removed pendulum's dynamic_lookup flags.
Rather than juggle link flags per resource, pin all 14 compiled extensions to
the wheels upstream already publishes for cp314 macOS: argon2-cffi-bindings,
google-re2, grpcio, httptools, jiter, markupsafe, pendulum, protobuf, pyyaml,
regex, tiktoken, uvloop, watchfiles, zstandard. Resource versions are unchanged
-- only sdist urls become wheel urls. grpcio, httptools, regex, uvloop,
argon2-cffi-bindings and protobuf ship universal2/abi3 wheels, so those need no
arch conditional at all.
Native wheels are chosen over pure-Python ones on purpose: protobuf and pendulum
also publish `py3-none-any` fallbacks that are markedly slower implementations.
With no source build left, three things go away: the `rust` build dependency,
the RUSTFLAGS headerpad workaround (which caused this failure), and the
argon2-cffi-bindings SETUPTOOLS_SCM pin -- the latter also read
`resource(...).version`, which is unreliable against a wheel filename.
86 pure-Python sdists remain, so the bottle build is now dominated by unpacking
rather than by cc and rustc on a 3-core runner.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
Wheel-pinning everything traded pendulum's link error for a relocation error:
Failed changing dylib ID of .../site-packages/jiter/jiter.cpython-314-darwin.so
Failed to fix install linkage
That is omnigent issue #866. maturin builds its wheels without
-headerpad_max_install_names, so there is no room in the Mach-O header for
Homebrew to rewrite the install name to the Cellar path during keg relocation.
It is exactly what the RUSTFLAGS workaround in this formula was for, and taking
the prebuilt wheel threw that away.
Audited every wheel by replaying Homebrew's own operation
(`install_name_tool -id <Cellar path>`) against the extracted .so:
google-re2, protobuf have padding, relink OK
grpcio, httptools, uvloop, regex, MH_BUNDLE, no dylib ID, brew skips them
argon2-cffi-bindings, markupsafe,
pyyaml, zstandard
jiter, tiktoken, watchfiles, pendulum maturin, cannot relink
So jiter, tiktoken and watchfiles go back to source builds with the headerpad
RUSTFLAGS -- the configuration every bottled release through 0.6.0 used -- and
`depends_on "rust" => :build` comes back for them.
pendulum cannot go either way: its wheel cannot be relocated and its sdist does
not link on python 3.14 (pyo3 leaves _Py_NoneStruct, _Py_Dealloc and
_Py_TrueStruct undefined; arm64 link fails). It now takes the pure-Python
`py3-none-any` wheel, which ships no extension module at all, so there is nothing
to relocate and nothing to compile. Verified it imports and does timezone
arithmetic correctly under brewed python@3.14. Only cel-python depends on it, for
CEL timestamp handling, so the slower implementation is off the hot path.
Net: grpcio -- by far the most expensive build -- and 9 others come from wheels,
3 small Rust crates still compile, and 89 pure-Python sdists just unpack.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
## Related issue Closes #866 ## Summary The `omnigent` Homebrew formula has not built since 0.7.0, and the tap reported green anyway, so 0.7.0, 0.8.0 and 0.8.1 all merged with no bottle — every user compiled from source, and CEL policies silently did not work. - **Root cause was the CEL migration.** #2970 swapped `cel-expr-python` for `cel-python` on the premise that it is pure Python. It is not: `cel-python` hard-depends on `google-re2`, whose sdist runs `bazel build` whenever `GITHUB_ACTIONS` is set. The bazel dependency moved rather than disappeared. - **Pin compiled extensions to upstream wheels.** `generate_formula.py` gains `WHEEL_REQUIRED` / `PREFER_WHEEL` / `PURE_WHEEL` with abi3 and universal2 handling, so grpcio (by far the most expensive build), protobuf, regex, uvloop, httptools, argon2-cffi-bindings, markupsafe, pyyaml, zstandard and google-re2 stop being compiled. Native wheels rank above pure-Python ones, so protobuf keeps its upb build instead of the slow fallback. - **jiter, tiktoken and watchfiles keep building from source.** Their maturin wheels carry no Mach-O install-name padding, so Homebrew relocation fails with "Failed changing dylib ID" (#866). `pendulum` can go neither way — its wheel cannot be relocated and its sdist does not link on 3.14 (pyo3 leaves `_Py_NoneStruct` undefined) — so it takes the pure-Python wheel, which ships no extension module at all. - **A dropped dependency is now an error, not a warning.** A missing sdist used to be skipped silently, yielding a formula whose venv lacked an import; `--allow-no-sdist` is the explicit waiver. The formula test also asserts `import re2, celpy`, since omnigent imports celpy behind `try/except ImportError` and would otherwise disable policies silently. - **Delete `update-homebrew.yml`.** It raced `homebrew-tap-pr.yml` on the same `release: published` event and asserted on hand-maintained stanzas the template no longer emits, so it failed on every run. Its one worthwhile part moves into `homebrew-tap-pr.yml`: an admin/maintain gate on manual dispatch (it writes to another repo with an App token), plus `persist-credentials: false`. Its nightly `schedule` is deliberately NOT carried over -- that cron only existed because `brew update-python-resources` resolves through pip's `--uploaded-prior-to=P1D` window and so could never see a same-day release. The generator runs `uv pip compile --no-config` straight against PyPI, so the blindness it worked around no longer exists, and a nightly regeneration would just burn a runner to print "nothing to do". ## Test Plan Verified by building the generated formula in the tap, not by inspection. - `omnigent-ai/homebrew-tap#18` contains **verbatim output of this `generate_formula.py`** and bottled successfully on macos-15 and macos-26 (run 30944428771, `bottles_macos-15` / `bottles_macos-26` ≈ 37 MB each). This is the check that matters: it proves the generator — not a hand-edit — produces a buildable formula, so the next release regenerates something that works. - `omnigent-ai/homebrew-tap#17` carries the same fix for the shipped 0.8.1 formula and is green on all three runners, with `brew test` running `import re2, celpy`. Inspected the bottle: `celpy/__init__.py`, `re2/_re2.cpython-314-darwin.so`, and a relocated `jiter/jiter.cpython-314-darwin.so`. - Audited every pinned wheel by replaying Homebrew's own operation, `install_name_tool -id <Cellar path>` against each extracted `.so`, so the wheel/source split is evidence-based rather than guessed. - `python3.12 -m py_compile`, `ruff check`, `ruff format --check`, `brew style` (no offenses), `ruby -c`, plus stubbed-PyPI unit checks of the new failure paths (missing sdist is fatal, `--allow-no-sdist` waives it, abi3 accepted, free-threaded `cp314t` rejected). - Confirmed generator output matches the green formula: same 100 resources, identical sdist/wheel split, no non-comment differences. ## Demo N/A — release tooling, no user-visible UI. ## Type of change - [x] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change ## Test coverage - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [ ] Existing tests cover this change - [ ] Not applicable ## Coverage notes The generator has no test suite in this repo, and its real contract — "the emitted formula builds under Homebrew on macOS" — cannot be asserted here. It is covered instead by building the generated formula on the tap's `brew test-bot` matrix (homebrew-tap#18, bottles produced on macos-15 and macos-26). The two new generator failure paths were exercised locally against stubbed PyPI metadata, and every wheel pin was verified relocatable with `install_name_tool`. ## Changelog `brew install omnigent` works again, and installs prebuilt wheels instead of compiling grpcio and friends from source. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
Closes #866 The `omnigent` Homebrew formula has not built since 0.7.0, and the tap reported green anyway, so 0.7.0, 0.8.0 and 0.8.1 all merged with no bottle — every user compiled from source, and CEL policies silently did not work. - **Root cause was the CEL migration.** #2970 swapped `cel-expr-python` for `cel-python` on the premise that it is pure Python. It is not: `cel-python` hard-depends on `google-re2`, whose sdist runs `bazel build` whenever `GITHUB_ACTIONS` is set. The bazel dependency moved rather than disappeared. - **Pin compiled extensions to upstream wheels.** `generate_formula.py` gains `WHEEL_REQUIRED` / `PREFER_WHEEL` / `PURE_WHEEL` with abi3 and universal2 handling, so grpcio (by far the most expensive build), protobuf, regex, uvloop, httptools, argon2-cffi-bindings, markupsafe, pyyaml, zstandard and google-re2 stop being compiled. Native wheels rank above pure-Python ones, so protobuf keeps its upb build instead of the slow fallback. - **jiter, tiktoken and watchfiles keep building from source.** Their maturin wheels carry no Mach-O install-name padding, so Homebrew relocation fails with "Failed changing dylib ID" (#866). `pendulum` can go neither way — its wheel cannot be relocated and its sdist does not link on 3.14 (pyo3 leaves `_Py_NoneStruct` undefined) — so it takes the pure-Python wheel, which ships no extension module at all. - **A dropped dependency is now an error, not a warning.** A missing sdist used to be skipped silently, yielding a formula whose venv lacked an import; `--allow-no-sdist` is the explicit waiver. The formula test also asserts `import re2, celpy`, since omnigent imports celpy behind `try/except ImportError` and would otherwise disable policies silently. - **Delete `update-homebrew.yml`.** It raced `homebrew-tap-pr.yml` on the same `release: published` event and asserted on hand-maintained stanzas the template no longer emits, so it failed on every run. Its one worthwhile part moves into `homebrew-tap-pr.yml`: an admin/maintain gate on manual dispatch (it writes to another repo with an App token), plus `persist-credentials: false`. Its nightly `schedule` is deliberately NOT carried over -- that cron only existed because `brew update-python-resources` resolves through pip's `--uploaded-prior-to=P1D` window and so could never see a same-day release. The generator runs `uv pip compile --no-config` straight against PyPI, so the blindness it worked around no longer exists, and a nightly regeneration would just burn a runner to print "nothing to do". Verified by building the generated formula in the tap, not by inspection. - `omnigent-ai/homebrew-tap#18` contains **verbatim output of this `generate_formula.py`** and bottled successfully on macos-15 and macos-26 (run 30944428771, `bottles_macos-15` / `bottles_macos-26` ≈ 37 MB each). This is the check that matters: it proves the generator — not a hand-edit — produces a buildable formula, so the next release regenerates something that works. - `omnigent-ai/homebrew-tap#17` carries the same fix for the shipped 0.8.1 formula and is green on all three runners, with `brew test` running `import re2, celpy`. Inspected the bottle: `celpy/__init__.py`, `re2/_re2.cpython-314-darwin.so`, and a relocated `jiter/jiter.cpython-314-darwin.so`. - Audited every pinned wheel by replaying Homebrew's own operation, `install_name_tool -id <Cellar path>` against each extracted `.so`, so the wheel/source split is evidence-based rather than guessed. - `python3.12 -m py_compile`, `ruff check`, `ruff format --check`, `brew style` (no offenses), `ruby -c`, plus stubbed-PyPI unit checks of the new failure paths (missing sdist is fatal, `--allow-no-sdist` waives it, abi3 accepted, free-threaded `cp314t` rejected). - Confirmed generator output matches the green formula: same 100 resources, identical sdist/wheel split, no non-comment differences. N/A — release tooling, no user-visible UI. - [x] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [ ] Existing tests cover this change - [ ] Not applicable The generator has no test suite in this repo, and its real contract — "the emitted formula builds under Homebrew on macOS" — cannot be asserted here. It is covered instead by building the generated formula on the tap's `brew test-bot` matrix (homebrew-tap#18, bottles produced on macos-15 and macos-26). The two new generator failure paths were exercised locally against stubbed PyPI metadata, and every wheel pin was verified relocatable with `install_name_tool`. `brew install omnigent` works again, and installs prebuilt wheels instead of compiling grpcio and friends from source. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
|
Closing unmerged — the tap will be updated by the generator instead. The formula fix lands in omnigent-ai/omnigent#4080 ( This branch did its job as verification: it proved the corrected formula builds and bottles on macos-15 and macos-26 (run 30941636439), and #18 proved the generator reproduces that result byte-for-byte in substance. Note for whoever reviews the generated PR: the |
Closes #866 The `omnigent` Homebrew formula has not built since 0.7.0, and the tap reported green anyway, so 0.7.0, 0.8.0 and 0.8.1 all merged with no bottle — every user compiled from source, and CEL policies silently did not work. - **Root cause was the CEL migration.** #2970 swapped `cel-expr-python` for `cel-python` on the premise that it is pure Python. It is not: `cel-python` hard-depends on `google-re2`, whose sdist runs `bazel build` whenever `GITHUB_ACTIONS` is set. The bazel dependency moved rather than disappeared. - **Pin compiled extensions to upstream wheels.** `generate_formula.py` gains `WHEEL_REQUIRED` / `PREFER_WHEEL` / `PURE_WHEEL` with abi3 and universal2 handling, so grpcio (by far the most expensive build), protobuf, regex, uvloop, httptools, argon2-cffi-bindings, markupsafe, pyyaml, zstandard and google-re2 stop being compiled. Native wheels rank above pure-Python ones, so protobuf keeps its upb build instead of the slow fallback. - **jiter, tiktoken and watchfiles keep building from source.** Their maturin wheels carry no Mach-O install-name padding, so Homebrew relocation fails with "Failed changing dylib ID" (#866). `pendulum` can go neither way — its wheel cannot be relocated and its sdist does not link on 3.14 (pyo3 leaves `_Py_NoneStruct` undefined) — so it takes the pure-Python wheel, which ships no extension module at all. - **A dropped dependency is now an error, not a warning.** A missing sdist used to be skipped silently, yielding a formula whose venv lacked an import; `--allow-no-sdist` is the explicit waiver. The formula test also asserts `import re2, celpy`, since omnigent imports celpy behind `try/except ImportError` and would otherwise disable policies silently. - **Delete `update-homebrew.yml`.** It raced `homebrew-tap-pr.yml` on the same `release: published` event and asserted on hand-maintained stanzas the template no longer emits, so it failed on every run. Its one worthwhile part moves into `homebrew-tap-pr.yml`: an admin/maintain gate on manual dispatch (it writes to another repo with an App token), plus `persist-credentials: false`. Its nightly `schedule` is deliberately NOT carried over -- that cron only existed because `brew update-python-resources` resolves through pip's `--uploaded-prior-to=P1D` window and so could never see a same-day release. The generator runs `uv pip compile --no-config` straight against PyPI, so the blindness it worked around no longer exists, and a nightly regeneration would just burn a runner to print "nothing to do". Verified by building the generated formula in the tap, not by inspection. - `omnigent-ai/homebrew-tap#18` contains **verbatim output of this `generate_formula.py`** and bottled successfully on macos-15 and macos-26 (run 30944428771, `bottles_macos-15` / `bottles_macos-26` ≈ 37 MB each). This is the check that matters: it proves the generator — not a hand-edit — produces a buildable formula, so the next release regenerates something that works. - `omnigent-ai/homebrew-tap#17` carries the same fix for the shipped 0.8.1 formula and is green on all three runners, with `brew test` running `import re2, celpy`. Inspected the bottle: `celpy/__init__.py`, `re2/_re2.cpython-314-darwin.so`, and a relocated `jiter/jiter.cpython-314-darwin.so`. - Audited every pinned wheel by replaying Homebrew's own operation, `install_name_tool -id <Cellar path>` against each extracted `.so`, so the wheel/source split is evidence-based rather than guessed. - `python3.12 -m py_compile`, `ruff check`, `ruff format --check`, `brew style` (no offenses), `ruby -c`, plus stubbed-PyPI unit checks of the new failure paths (missing sdist is fatal, `--allow-no-sdist` waives it, abi3 accepted, free-threaded `cp314t` rejected). - Confirmed generator output matches the green formula: same 100 resources, identical sdist/wheel split, no non-comment differences. N/A — release tooling, no user-visible UI. - [x] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [ ] Existing tests cover this change - [ ] Not applicable The generator has no test suite in this repo, and its real contract — "the emitted formula builds under Homebrew on macOS" — cannot be asserted here. It is covered instead by building the generated formula on the tap's `brew test-bot` matrix (homebrew-tap#18, bottles produced on macos-15 and macos-26). The two new generator failure paths were exercised locally against stubbed PyPI metadata, and every wheel pin was verified relocatable with `install_name_tool`. `brew install omnigent` works again, and installs prebuilt wheels instead of compiling grpcio and friends from source. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
The first version of this workflow was exploitable. It is a `workflow_run` job,
so it runs in the BASE repo context holding `contents: write` even when the
test-bot run it reacts to came from a fork PR -- and this repo is public with
tests.yml on `pull_request`, so anyone can trigger that run.
`head_branch` on a fork PR is the contributor's own branch name, so the
`auto/formula/*` prefix was not a security control: a stranger could fork, push
`auto/formula/v9.9.9` containing only a modified Formula/omnigent.rb, and pass
every gate. The formula-only diff check does not help, because a hostile formula
IS a formula-only diff -- a formula is executable Ruby plus arbitrary download
URLs -- and the bottle-artifact check does not help either, because building a
hostile formula still produces bottles. The result would have been published as
the bottle every `brew install omnigent` user receives.
Now trust is established before anything runs:
* `head_repository.full_name == github.repository` in the job `if`, so fork
runs never start the job at all, plus an `isCrossRepository` assert in-step;
* the PR author must be the omnigent-ci App (tolerating gh's `app/` prefix,
which is what it actually reports -- comparing against the bare slug would
have made this a permanent silent skip);
* `workflow_run.head_sha` must still equal the PR head, because `brew pr-pull`
resolves the PR's CURRENT head rather than the SHA that was tested, so a
green run followed by a force-push would otherwise publish untested code.
Also SHA-pin the three Homebrew/actions references instead of `@main`: this job
has `contents: write` and decides what users install, so a moving tag is a
supply-chain vector. Pinned to 18fcb8e3, the same commit omnigent-ai/omnigent
pins.
Anything that fails a gate falls through to the existing manual `pr-pull` label,
where a human reviews the diff first. Replayed against real PRs: #19
(app/omnigent-ci) is admitted; #17 and #18 (human-authored) skip to the manual
path.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: auto-publish generated formula bumps when bottles exist
omnigent's release automation opens `auto/formula/<tag>` here on every release,
but landing it still needs a human to notice the PR and apply `pr-pull`. That is
why the tap froze at 0.2.0 while PyPI moved to 0.5.1, and why 0.8.1 sat unbottled
for two days. Auto-publish those PRs once the build has demonstrably produced
bottles.
Runs `brew pr-pull` directly rather than adding the `pr-pull` label, because a
label applied with the default GITHUB_TOKEN does not start a new workflow run, so
publish.yml would never fire. The label path is untouched and still works for
humans.
Gated on evidence, not on a green tick, because a green tick here does not mean
the formula built. `brew test-bot` sets ignore_failures for any formula that is
neither newly added nor already bottled at its current version
(lib/tests/formulae.rb) -- every version bump in this tap, since the bottle block
is only added afterwards -- so a failed `brew install --build-bottle` still exits
0 and merely prints "Warning: N failed step ignored!". 0.7.0, 0.8.0 and 0.8.1 all
reported green that way with no bottle.
Three guards, each checked against real runs of this repo:
1. bottle artifacts must exist and be non-trivial. upload-artifact uses
if-no-files-found: warn, so a build that produced no bottle uploads nothing.
2. no job log may contain "failed step ignored!".
3. the diff must be exactly Formula/omnigent.rb, so anything touching
workflows or other files keeps the manual review gate.
Verified against run 30964311208 (the generated 0.8.1, bottles on macos-15 and
macos-26) -> both gates pass; and run 30856043824 (the original 0.8.1, which
reported three green checks and never built) -> both gates reject. The scope
guard admits #19 (Formula/omnigent.rb only) and excludes #17, which also touched
.github/workflows/tests.yml.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: harden auto pr-pull against fork PRs and force-pushes
The first version of this workflow was exploitable. It is a `workflow_run` job,
so it runs in the BASE repo context holding `contents: write` even when the
test-bot run it reacts to came from a fork PR -- and this repo is public with
tests.yml on `pull_request`, so anyone can trigger that run.
`head_branch` on a fork PR is the contributor's own branch name, so the
`auto/formula/*` prefix was not a security control: a stranger could fork, push
`auto/formula/v9.9.9` containing only a modified Formula/omnigent.rb, and pass
every gate. The formula-only diff check does not help, because a hostile formula
IS a formula-only diff -- a formula is executable Ruby plus arbitrary download
URLs -- and the bottle-artifact check does not help either, because building a
hostile formula still produces bottles. The result would have been published as
the bottle every `brew install omnigent` user receives.
Now trust is established before anything runs:
* `head_repository.full_name == github.repository` in the job `if`, so fork
runs never start the job at all, plus an `isCrossRepository` assert in-step;
* the PR author must be the omnigent-ci App (tolerating gh's `app/` prefix,
which is what it actually reports -- comparing against the bare slug would
have made this a permanent silent skip);
* `workflow_run.head_sha` must still equal the PR head, because `brew pr-pull`
resolves the PR's CURRENT head rather than the SHA that was tested, so a
green run followed by a force-push would otherwise publish untested code.
Also SHA-pin the three Homebrew/actions references instead of `@main`: this job
has `contents: write` and decides what users install, so a moving tag is a
supply-chain vector. Pinned to 18fcb8e3, the same commit omnigent-ai/omnigent
pins.
Anything that fails a gate falls through to the existing manual `pr-pull` label,
where a human reviews the diff first. Replayed against real PRs: #19
(app/omnigent-ci) is admitted; #17 and #18 (human-authored) skip to the manual
path.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: request review on formula bumps instead of auto-publishing
Replace the auto pr-pull job with one that asks a maintainer to look, and tells
them whether the formula actually built. Publishing stays manual: a human reviews
the resource diff and applies `pr-pull`, exactly as today.
The problem worth solving was never that applying the label is hard, it was that
nobody notices the PR -- the tap froze at 0.2.0 while PyPI moved to 0.5.1, and
0.8.1 sat unbottled after its formula was fixed. A review request fixes that
without handing a robot the ability to publish what users install.
It also removes the risk the auto-publishing version carried. That was a
`workflow_run` job holding `contents: write`, which on a public repo whose
tests.yml runs on `pull_request` meant anyone could reach it: `head_branch` on a
fork PR is the contributor's own branch name, so an `auto/formula/*` prefix
authenticates nothing, a hostile formula is still a formula-only diff, and
building one still produces bottles. This job holds no `contents` write and uses
no third-party actions, so the worst a hostile PR gets from it is a review
request on itself.
The verdict is the useful part, because a green check here does not mean the
formula built. `brew test-bot` sets ignore_failures for any formula that is
neither newly added nor already bottled at its current version
(lib/tests/formulae.rb) -- every version bump in this tap -- so a failed
`brew install --build-bottle` still exits 0 and merely prints
"Warning: N failed step ignored!". The comment therefore reports bottle artifacts
(the only trustworthy proof of a build), any swallowed failures, and whether the
tested SHA is still the head.
Dry-run against real runs of this repo:
30964311208 (generated 0.8.1) -> "bottles produced for bottles_macos-15,
bottles_macos-26, no swallowed failures", review requested;
30856043824 (original 0.8.1, three green checks, never built) -> "not safe to
publish: no bottle artifacts; test-bot (macos-15) and (macos-26) ignored a
failed step", with an explicit do-not-label warning.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: use an unguessable delimiter for the verdict step output
`problems` embeds job and artifact names. With a fixed heredoc delimiter, a
crafted name containing that delimiter could close the block early and inject
further step outputs — including ok=true, which is what decides whether the
comment says the bump is safe to publish. Only same-repo App-authored PRs reach
this step today, so this is defence in depth rather than a live hole.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: fix brew style shellcheck findings in the review workflow
`brew style` on a tap does not only lint Ruby: it runs shellcheck and actionlint
over the `run:` blocks of .github/workflows too, so this workflow failed the
`brew test-bot --only-tap-syntax` step. Two findings, both mine:
SC2129 -- consecutive `echo ... >> "$GITHUB_OUTPUT"` lines should be one
grouped redirect.
SC2016 -- the comment bodies were built with single-quoted printf formats
containing markdown code spans, and shellcheck reads those backticks as
command substitution.
Replaced the printf calls with unquoted heredocs, which need no single quotes and
read better, using \` for literal backticks so they stay markdown rather than
becoming command substitution. Bodies now go to a file under $RUNNER_TEMP and are
passed via --body-file.
Reproduced locally with `brew style omnigent-ai/tap` against the real linter
(3 files inspected, no offenses detected) and rendered both comment variants to
confirm the code spans survive.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
* ci: indent the heredoc bodies so the workflow is valid YAML
The heredoc bodies and their EOF terminators sat at column 0, which ends the
`run: |` block scalar. YAML then tried to parse the body as YAML and hit `@`, a
reserved indicator:
formula-bump-review.yml:156:0: could not parse as YAML: found character that
cannot start any token [syntax-check]
Indent them to the block-scalar level instead. YAML strips that common
indentation, so bash still receives the terminator at column 0 and the heredoc
works.
I had claimed `brew style` was clean before pushing the previous commit. It was
not: I grepped its output for shellcheck/actionlint/offenses, and the failing line
is tagged [syntax-check], so my own filter hid it. Verified properly this time --
full `brew style` output (3 files inspected, no offenses detected, exit 0), the
YAML parsed and the comment step extracted and executed with a stubbed `gh` to
confirm the rendered markdown has no stray indentation.
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
---------
Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
…ent-ai#4080) Closes omnigent-ai#866 The `omnigent` Homebrew formula has not built since 0.7.0, and the tap reported green anyway, so 0.7.0, 0.8.0 and 0.8.1 all merged with no bottle — every user compiled from source, and CEL policies silently did not work. - **Root cause was the CEL migration.** omnigent-ai#2970 swapped `cel-expr-python` for `cel-python` on the premise that it is pure Python. It is not: `cel-python` hard-depends on `google-re2`, whose sdist runs `bazel build` whenever `GITHUB_ACTIONS` is set. The bazel dependency moved rather than disappeared. - **Pin compiled extensions to upstream wheels.** `generate_formula.py` gains `WHEEL_REQUIRED` / `PREFER_WHEEL` / `PURE_WHEEL` with abi3 and universal2 handling, so grpcio (by far the most expensive build), protobuf, regex, uvloop, httptools, argon2-cffi-bindings, markupsafe, pyyaml, zstandard and google-re2 stop being compiled. Native wheels rank above pure-Python ones, so protobuf keeps its upb build instead of the slow fallback. - **jiter, tiktoken and watchfiles keep building from source.** Their maturin wheels carry no Mach-O install-name padding, so Homebrew relocation fails with "Failed changing dylib ID" (omnigent-ai#866). `pendulum` can go neither way — its wheel cannot be relocated and its sdist does not link on 3.14 (pyo3 leaves `_Py_NoneStruct` undefined) — so it takes the pure-Python wheel, which ships no extension module at all. - **A dropped dependency is now an error, not a warning.** A missing sdist used to be skipped silently, yielding a formula whose venv lacked an import; `--allow-no-sdist` is the explicit waiver. The formula test also asserts `import re2, celpy`, since omnigent imports celpy behind `try/except ImportError` and would otherwise disable policies silently. - **Delete `update-homebrew.yml`.** It raced `homebrew-tap-pr.yml` on the same `release: published` event and asserted on hand-maintained stanzas the template no longer emits, so it failed on every run. Its one worthwhile part moves into `homebrew-tap-pr.yml`: an admin/maintain gate on manual dispatch (it writes to another repo with an App token), plus `persist-credentials: false`. Its nightly `schedule` is deliberately NOT carried over -- that cron only existed because `brew update-python-resources` resolves through pip's `--uploaded-prior-to=P1D` window and so could never see a same-day release. The generator runs `uv pip compile --no-config` straight against PyPI, so the blindness it worked around no longer exists, and a nightly regeneration would just burn a runner to print "nothing to do". Verified by building the generated formula in the tap, not by inspection. - `omnigent-ai/homebrew-tap#18` contains **verbatim output of this `generate_formula.py`** and bottled successfully on macos-15 and macos-26 (run 30944428771, `bottles_macos-15` / `bottles_macos-26` ≈ 37 MB each). This is the check that matters: it proves the generator — not a hand-edit — produces a buildable formula, so the next release regenerates something that works. - `omnigent-ai/homebrew-tap#17` carries the same fix for the shipped 0.8.1 formula and is green on all three runners, with `brew test` running `import re2, celpy`. Inspected the bottle: `celpy/__init__.py`, `re2/_re2.cpython-314-darwin.so`, and a relocated `jiter/jiter.cpython-314-darwin.so`. - Audited every pinned wheel by replaying Homebrew's own operation, `install_name_tool -id <Cellar path>` against each extracted `.so`, so the wheel/source split is evidence-based rather than guessed. - `python3.12 -m py_compile`, `ruff check`, `ruff format --check`, `brew style` (no offenses), `ruby -c`, plus stubbed-PyPI unit checks of the new failure paths (missing sdist is fatal, `--allow-no-sdist` waives it, abi3 accepted, free-threaded `cp314t` rejected). - Confirmed generator output matches the green formula: same 100 resources, identical sdist/wheel split, no non-comment differences. N/A — release tooling, no user-visible UI. - [x] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [ ] Existing tests cover this change - [ ] Not applicable The generator has no test suite in this repo, and its real contract — "the emitted formula builds under Homebrew on macOS" — cannot be asserted here. It is covered instead by building the generated formula on the tap's `brew test-bot` matrix (homebrew-tap#18, bottles produced on macos-15 and macos-26). The two new generator failure paths were exercised locally against stubbed PyPI metadata, and every wheel pin was verified relocatable with `install_name_tool`. `brew install omnigent` works again, and installs prebuilt wheels instead of compiling grpcio and friends from source. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com> Co-authored-by: Zeyi (Rice) Fan <zeyi.f@databricks.com>
…ent-ai#4080) Closes omnigent-ai#866 The `omnigent` Homebrew formula has not built since 0.7.0, and the tap reported green anyway, so 0.7.0, 0.8.0 and 0.8.1 all merged with no bottle — every user compiled from source, and CEL policies silently did not work. - **Root cause was the CEL migration.** omnigent-ai#2970 swapped `cel-expr-python` for `cel-python` on the premise that it is pure Python. It is not: `cel-python` hard-depends on `google-re2`, whose sdist runs `bazel build` whenever `GITHUB_ACTIONS` is set. The bazel dependency moved rather than disappeared. - **Pin compiled extensions to upstream wheels.** `generate_formula.py` gains `WHEEL_REQUIRED` / `PREFER_WHEEL` / `PURE_WHEEL` with abi3 and universal2 handling, so grpcio (by far the most expensive build), protobuf, regex, uvloop, httptools, argon2-cffi-bindings, markupsafe, pyyaml, zstandard and google-re2 stop being compiled. Native wheels rank above pure-Python ones, so protobuf keeps its upb build instead of the slow fallback. - **jiter, tiktoken and watchfiles keep building from source.** Their maturin wheels carry no Mach-O install-name padding, so Homebrew relocation fails with "Failed changing dylib ID" (omnigent-ai#866). `pendulum` can go neither way — its wheel cannot be relocated and its sdist does not link on 3.14 (pyo3 leaves `_Py_NoneStruct` undefined) — so it takes the pure-Python wheel, which ships no extension module at all. - **A dropped dependency is now an error, not a warning.** A missing sdist used to be skipped silently, yielding a formula whose venv lacked an import; `--allow-no-sdist` is the explicit waiver. The formula test also asserts `import re2, celpy`, since omnigent imports celpy behind `try/except ImportError` and would otherwise disable policies silently. - **Delete `update-homebrew.yml`.** It raced `homebrew-tap-pr.yml` on the same `release: published` event and asserted on hand-maintained stanzas the template no longer emits, so it failed on every run. Its one worthwhile part moves into `homebrew-tap-pr.yml`: an admin/maintain gate on manual dispatch (it writes to another repo with an App token), plus `persist-credentials: false`. Its nightly `schedule` is deliberately NOT carried over -- that cron only existed because `brew update-python-resources` resolves through pip's `--uploaded-prior-to=P1D` window and so could never see a same-day release. The generator runs `uv pip compile --no-config` straight against PyPI, so the blindness it worked around no longer exists, and a nightly regeneration would just burn a runner to print "nothing to do". Verified by building the generated formula in the tap, not by inspection. - `omnigent-ai/homebrew-tap#18` contains **verbatim output of this `generate_formula.py`** and bottled successfully on macos-15 and macos-26 (run 30944428771, `bottles_macos-15` / `bottles_macos-26` ≈ 37 MB each). This is the check that matters: it proves the generator — not a hand-edit — produces a buildable formula, so the next release regenerates something that works. - `omnigent-ai/homebrew-tap#17` carries the same fix for the shipped 0.8.1 formula and is green on all three runners, with `brew test` running `import re2, celpy`. Inspected the bottle: `celpy/__init__.py`, `re2/_re2.cpython-314-darwin.so`, and a relocated `jiter/jiter.cpython-314-darwin.so`. - Audited every pinned wheel by replaying Homebrew's own operation, `install_name_tool -id <Cellar path>` against each extracted `.so`, so the wheel/source split is evidence-based rather than guessed. - `python3.12 -m py_compile`, `ruff check`, `ruff format --check`, `brew style` (no offenses), `ruby -c`, plus stubbed-PyPI unit checks of the new failure paths (missing sdist is fatal, `--allow-no-sdist` waives it, abi3 accepted, free-threaded `cp314t` rejected). - Confirmed generator output matches the green formula: same 100 resources, identical sdist/wheel split, no non-comment differences. N/A — release tooling, no user-visible UI. - [x] Bug fix - [ ] Feature - [ ] UI / frontend change - [ ] Refactor / chore - [ ] Docs - [ ] Test / CI - [ ] Breaking change - [ ] Unit tests added / updated - [ ] Integration tests added / updated - [ ] E2E tests added / updated - [x] Manual verification completed - [ ] Existing tests cover this change - [ ] Not applicable The generator has no test suite in this repo, and its real contract — "the emitted formula builds under Homebrew on macOS" — cannot be asserted here. It is covered instead by building the generated formula on the tap's `brew test-bot` matrix (homebrew-tap#18, bottles produced on macos-15 and macos-26). The two new generator failure paths were exercised locally against stubbed PyPI metadata, and every wheel pin was verified relocatable with `install_name_tool`. `brew install omnigent` works again, and installs prebuilt wheels instead of compiling grpcio and friends from source. Signed-off-by: Zeyi (Rice) Fan <zeyi.f@databricks.com> Co-authored-by: Zeyi (Rice) Fan <zeyi.f@databricks.com> Co-authored-by: Nick Isaacs <nick.isaacs@datadoghq.com>
Summary
Formula/omnigent.rbhas not built since 0.7.0, and CI reported green anyway.omnigent moved CEL policy evaluation from
cel-expr-pythontocel-python, andcel-pythonhard-depends ongoogle-re2(celpy/evaluation.py:83importsre2at module scope, no fallback).google-re2's sdist runsbazel buildwheneverGITHUB_ACTIONSis set — always true here — and its non-bazel path needs re2, abseil and pybind11 headers plus C++17, none of which it requests:(that is from run 30856043824, the
omnigent 0.8.1PR that merged with three green checks)Two changes:
Pin
google-re2to the upstream cp314 macOS wheels. They statically link re2 and abseil —otool -Lon the installed extension shows only system libraries — so this needs no build toolchain, and unlikedepends_on "abseil"it does not tie the bottle to abseil's ABI and its frequent revision bumps. Homebrew only auto-installspy3-none-anywheels, so platform wheels are copied from their cached download back to the real filename and pip-installed directly — the same approach this formula already used forgoogle-antigravity.Stop ignoring build failures. test-bot sets
ignore_failuresfor any formula that is neither newly added nor already bottled at its current version (lib/tests/formulae.rb:!test_default_formula? && !bottled_on_current_version && !new_formula). That is every version bump in this tap, becausebrew pr-pullonly adds the bottle block afterwards. Sobrew install --build-bottlefails, test-bot printsWarning: 1 failed step ignored!, and the job still exits 0 (failed_steps.empty?). 0.7.0, 0.8.0 and 0.8.1 all merged that way, with no bottle. The new step gates the job on test-bot's ownsteps_output.txt.The formula test now also asserts
import re2, celpy: omnigent importscelpybehind atry/except ImportError, so a missinggoogle-re2disables inline CEL policies silently instead of failing the build.Test Plan
Verified locally on macOS 26 / arm64 before opening:
brew style omnigent-ai/tap/omnigent— no offenses (confirmson_arm/on_intelinside aresourceis valid;ResourceincludesOnSystem::MacOSAndLinux)ruby -c Formula/omnigent.rb— Syntax OKre2.search(r'a(b+)c', 'xxabbbcyy').group(1)→bbbotool -L .../re2/_re2.cpython-314-darwin.so→ onlylibc++,CoreFoundation,Foundation,libobjc,libSystem; no brewedlibre2/libabslstd_pip_args, i.e.--no-binary=:all: --no-deps --ignore-installed --no-compile --uploaded-prior-to=P1D) installs the platform wheel:Successfully installed google-re2-1.1.20251105—--no-binarydoes not block a direct wheel pathmatches():env.program(env.compile('event.type == "tool_call" && event.name.matches("^sys_.*shell$")'))→Truebrew install --build-from-source, the arm64 wheel downloaded and checksum-verifiedA full from-source build could not be completed on my machine (no egress to
pypi.orgfor pip build isolation, none toindex.crates.iofor the Rust resources — Homebrew overridesCARGO_HOME). test-bot on this PR is the real gate, and it is now honest — if the formula still does not build, this PR goes red instead of green.Notes
omnigent-ai/omnigent,.github/scripts/homebrew/) are being fixed in the same change, so the next release regenerates this formula with the wheel stanza rather than reverting it.pr-pullto bottle and merge — 0.8.1 currently has no bottle at all.