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"

Reply via email to