This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch ci-homebrew-trust-validator-tap in repository https://gitbox.apache.org/repos/asf/camel.git
commit fa792185de3c99799443573a565300ad5931616e Author: Claus Ibsen <[email protected]> AuthorDate: Thu Oct 29 17:03:22 2026 +0100 chore: camel-launcher - the Homebrew validator trusts its local tap, as recent Homebrew refuses to load a formula from an untrusted tap Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../src/jreleaser/bin/camel-validate.sh | 10 +++++-- .../launcher/PackageNativeValidationTest.java | 33 ++++++++++++++++++++-- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/dsl/camel-jbang/camel-launcher/src/jreleaser/bin/camel-validate.sh b/dsl/camel-jbang/camel-launcher/src/jreleaser/bin/camel-validate.sh index 508868cae534..d95b867f7c0a 100755 --- a/dsl/camel-jbang/camel-launcher/src/jreleaser/bin/camel-validate.sh +++ b/dsl/camel-jbang/camel-launcher/src/jreleaser/bin/camel-validate.sh @@ -125,12 +125,13 @@ fi TMPDIR_BASE=$(mktemp -d) # Name of the throwaway local Homebrew tap created by validate_homebrew() (empty until it -# creates one). Kept at script scope so the EXIT trap can always untap it, even if +# creates one). Kept at script scope so the EXIT trap can always untrust and untap it, even if # validate_homebrew() returns early (SKIP/FAIL) partway through. BREW_TAP_NAME="" brew_untap_validator_tap() { if [ -n "$BREW_TAP_NAME" ] && command -v brew >/dev/null 2>&1; then + HOMEBREW_NO_AUTO_UPDATE=1 brew untrust --tap "$BREW_TAP_NAME" >/dev/null 2>&1 || true HOMEBREW_NO_AUTO_UPDATE=1 brew untap "$BREW_TAP_NAME" >/dev/null 2>&1 || true fi } @@ -210,8 +211,10 @@ validate_homebrew() { # ("Homebrew requires formulae to be in a tap" / "brew audit [path ...] is disabled"); # empirically confirmed on this machine. A throwaway local tap (removed via `brew untap` # in the script's EXIT trap) satisfies that requirement without any network access or - # real publication. `brew install` auto-trusts formulae from a tap created this way (no - # separate trust command exists or is needed - empirically confirmed). + # real publication. Recent Homebrew refuses to load a formula from a tap that is not trusted + # ("Refusing to load formula ... from untrusted tap"), so the tap is trusted right after it + # is created, and untrusted again in the EXIT trap. A Homebrew without `brew trust` + # loads any tap, so a failure of that call is ignored. local tap_name="camel-cli-validators/formulae" local tap_dir tap_output @@ -222,6 +225,7 @@ validate_homebrew() { return 1 fi BREW_TAP_NAME="$tap_name" + HOMEBREW_NO_AUTO_UPDATE=1 brew trust --tap "$tap_name" >/dev/null 2>&1 || true tap_dir=$(brew --repository "$tap_name") if ! cp -p "$formula_file" "$tap_dir/Formula/${fmla}.rb"; then diff --git a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/PackageNativeValidationTest.java b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/PackageNativeValidationTest.java index 202cb73d5e8f..104b44c75ef3 100644 --- a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/PackageNativeValidationTest.java +++ b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/PackageNativeValidationTest.java @@ -333,6 +333,29 @@ class PackageNativeValidationTest { assertThat(r.out()).contains("FAIL: homebrew audit --strict reported issues (exit 1)"); } + @Test + void homebrewValidatorTrustsItsTapForTheAuditAndUntrustsItOnExit(@TempDir Path tmp) throws Exception { + // Recent Homebrew refuses to load a formula from an untrusted tap, so the validator must + // trust its throwaway tap before `brew audit`, and must not leave that trust behind. + Path fakeBinDir = Files.createDirectory(tmp.resolve("fake-bin")); + writeFakeBrew(fakeBinDir.resolve("brew")); + Path target = Files.createDirectory(tmp.resolve("target")); + Path tapDir = Files.createDirectory(tmp.resolve("tap")); + stageHomebrewFormula(target, "camel-launcher-9.9.9-bin.tar.gz"); + + Result r = sh(null, List.of( + "PATH=" + fakeBinDir.toAbsolutePath() + File.pathSeparator + System.getenv("PATH"), + "CAMEL_PACKAGE_TEST_MODE=true", + "CAMEL_PACKAGE_TEST_VERSION=" + VERSION, + "CAMEL_VALIDATE_TARGET_DIR=" + target.toAbsolutePath(), + "FAKE_BREW_TAP_DIR=" + tapDir.toAbsolutePath(), + "FAKE_BREW_REQUIRE_TRUST=true"), + "/bin/bash " + VALIDATE.toAbsolutePath() + " homebrew"); + + assertThat(r.out()).doesNotContain("untrusted tap").contains("PASS: homebrew style/audit passed"); + assertThat(tapDir.resolve(".trusted")).doesNotExist(); + } + @Test void homebrewValidatorSkipsWhenJavaDependencyMissing(@TempDir Path tmp) throws Exception { // A `brew install` failure caused by a missing/incompatible Java on the host is an environment @@ -424,8 +447,9 @@ class PackageNativeValidationTest { * heuristics can be pinned without needing a real Homebrew install. Behavior for the {@code audit} and * {@code install} subcommands is driven by {@code FAKE_BREW_AUDIT_RC}/{@code * FAKE_BREW_AUDIT_OUTPUT} and {@code FAKE_BREW_INSTALL_RC}/{@code FAKE_BREW_INSTALL_OUTPUT}; the tap directory it - * reports is {@code FAKE_BREW_TAP_DIR}. Every other subcommand it needs (tap-new, untap, style, uninstall) just - * succeeds. + * reports is {@code FAKE_BREW_TAP_DIR}. With {@code FAKE_BREW_REQUIRE_TRUST=true}, {@code audit} refuses the tap + * unless {@code trust --tap} was called, as recent Homebrew does. Every other subcommand it needs (tap-new, untap, + * untrust, style, uninstall) just succeeds. */ private static Path writeFakeBrew(Path file) throws IOException { return writeExecutable(file, "#!/bin/sh\n" @@ -433,8 +457,13 @@ class PackageNativeValidationTest { + " tap-new) mkdir -p \"$FAKE_BREW_TAP_DIR/Formula\"; exit 0 ;;\n" + " --repository) echo \"$FAKE_BREW_TAP_DIR\"; exit 0 ;;\n" + " untap) exit 0 ;;\n" + + " trust) touch \"$FAKE_BREW_TAP_DIR/.trusted\"; exit 0 ;;\n" + + " untrust) rm -f \"$FAKE_BREW_TAP_DIR/.trusted\"; exit 0 ;;\n" + " style) exit 0 ;;\n" + " audit)\n" + + " if [ \"$FAKE_BREW_REQUIRE_TRUST\" = true ] && [ ! -f \"$FAKE_BREW_TAP_DIR/.trusted\" ]; then\n" + + " echo \"Error: Refusing to load formula $3 from untrusted tap.\"; exit 1\n" + + " fi\n" + " [ -n \"$FAKE_BREW_AUDIT_OUTPUT\" ] && echo \"$FAKE_BREW_AUDIT_OUTPUT\"\n" + " exit \"${FAKE_BREW_AUDIT_RC:-0}\" ;;\n" + " install)\n"
