From dc84590d6931872a305137c0559a368d520b1d39 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 12 Aug 2026 01:06:26 +0800 Subject: [PATCH 1/3] =?UTF-8?q?probe:=20=E5=9C=A8=E7=9C=9F=E5=AE=9E=20macO?= =?UTF-8?q?S=20arm64=20=E4=B8=8A=E5=A4=8D=E7=8E=B0=20brew=20install=20?= =?UTF-8?q?=E6=8A=A5=E9=94=99(=E4=B8=B4=E6=97=B6,=E5=90=88=E5=85=A5?= =?UTF-8?q?=E5=89=8D=E5=88=A0=E9=99=A4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tmp-brew-macos-probe.yml | 112 +++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 .github/workflows/tmp-brew-macos-probe.yml diff --git a/.github/workflows/tmp-brew-macos-probe.yml b/.github/workflows/tmp-brew-macos-probe.yml new file mode 100644 index 00000000..c8d6d110 --- /dev/null +++ b/.github/workflows/tmp-brew-macos-probe.yml @@ -0,0 +1,112 @@ +name: tmp-brew-macos-probe + +# TEMPORARY. Delete before merging. +# +# Reproduces "brew install mcpp errors on macOS" on a real arm64 macOS runner +# and prints enough to identify WHICH step fails. Every brew invocation is +# allowed to fail and is followed by a diagnostic dump, because a job that dies +# on the first non-zero exit tells us the command failed and nothing else. + +on: + pull_request: + workflow_dispatch: + +jobs: + brew-probe: + name: brew install probe (macOS arm64) + runs-on: macos-14 + timeout-minutes: 40 + steps: + - uses: actions/checkout@v4 + + - name: Environment + run: | + echo "arch: $(uname -m)" + echo "macOS: $(sw_vers -productVersion)" + echo "brew: $(brew --version | head -1)" + echo "brew prefix: $(brew --prefix)" + echo "already installed mcpp? $(command -v mcpp || echo no)" + + - name: Tap + run: | + set -x + brew tap mcpp-community/mcpp + brew tap-info mcpp-community/mcpp + + # The formula as the tap publishes it. `brew info` first: it evaluates + # the ruby WITHOUT downloading, so a formula-level error (bad DSL, a + # requirement that cannot be satisfied on this runner) shows up here + # rather than being confused with a download/extract failure below. + - name: "brew info (evaluate formula only)" + run: | + set +e + brew info mcpp-community/mcpp/mcpp-m 2>&1 | tee info.log + echo "exit=$?" + echo "── ruby source as tapped ──" + cat "$(brew --repo mcpp-community/mcpp)/Formula/mcpp-m.rb" + + - name: "brew install mcpp-m (verbose, failure tolerated)" + id: install + run: | + set +e + brew install --verbose mcpp-community/mcpp/mcpp-m 2>&1 | tee install.log + rc=${PIPESTATUS[0]} + echo "install_rc=$rc" >> "$GITHUB_OUTPUT" + echo "=== install exit code: $rc ===" + exit 0 + + - name: "Diagnose a failed install" + if: ${{ steps.install.outputs.install_rc != '0' }} + run: | + echo "── last 60 lines ──" + tail -60 install.log + echo "── anything that looks like an error ──" + grep -nEi 'error|fail|cannot|no such|denied|unable|invalid' install.log | tail -40 || true + echo "── brew gist-logs (formula build logs) ──" + ls -la ~/Library/Logs/Homebrew/mcpp-m/ 2>/dev/null || echo "(no formula log dir)" + for f in ~/Library/Logs/Homebrew/mcpp-m/*; do + echo "===== $f ====="; cat "$f" + done 2>/dev/null || true + + - name: "Post-install: does the launcher work?" + if: ${{ steps.install.outputs.install_rc == '0' }} + run: | + set -x + brew list mcpp-community/mcpp/mcpp-m + which mcpp + mcpp --version + mcpp --help | head -5 + + # The alias path the formula's header comment promises. A user reading + # the README types `mcpp`, not `mcpp-m`, so this is a separate claim. + - name: "Alias: brew install …/mcpp resolves" + run: | + set +e + brew info mcpp-community/mcpp/mcpp 2>&1 | tail -20 + echo "alias info exit=$?" + + - name: "brew audit (formula hygiene)" + run: | + set +e + brew audit --strict --online mcpp-community/mcpp/mcpp-m 2>&1 | tail -40 + echo "audit exit=$?" + + - name: "brew test (the formula's own test block)" + if: ${{ steps.install.outputs.install_rc == '0' }} + run: | + set +e + brew test --verbose mcpp-community/mcpp/mcpp-m 2>&1 | tail -40 + echo "test exit=$?" + + # The real usability question, beyond "the files landed": a brew-installed + # mcpp must be able to bootstrap a toolchain and build something. + - name: "Real use: mcpp new → run" + if: ${{ steps.install.outputs.install_rc == '0' }} + run: | + set +e + cd "$(mktemp -d)" + mcpp new brewhello 2>&1 | tail -20 + echo "new exit=$?" + cd brewhello || exit 0 + mcpp run 2>&1 | tail -40 + echo "run exit=$?" From 658eb038e58f4d99118115bacd39039a7513f73f Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 12 Aug 2026 01:10:08 +0800 Subject: [PATCH 2/3] =?UTF-8?q?probe:=20=E6=89=A9=E6=88=90=20OS/arch/tap-p?= =?UTF-8?q?ath=20=E7=9F=A9=E9=98=B5(round=201=20=E5=9C=A8=20macos-14=20?= =?UTF-8?q?=E5=85=A8=E7=BB=BF,=E8=AF=B4=E6=98=8E=E4=B8=8D=E6=98=AF?= =?UTF-8?q?=E5=85=AC=E5=BC=8F=E5=9D=8F=E4=BA=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tmp-brew-macos-probe.yml | 131 +++++++++------------ 1 file changed, 57 insertions(+), 74 deletions(-) diff --git a/.github/workflows/tmp-brew-macos-probe.yml b/.github/workflows/tmp-brew-macos-probe.yml index c8d6d110..961539a3 100644 --- a/.github/workflows/tmp-brew-macos-probe.yml +++ b/.github/workflows/tmp-brew-macos-probe.yml @@ -2,10 +2,21 @@ name: tmp-brew-macos-probe # TEMPORARY. Delete before merging. # -# Reproduces "brew install mcpp errors on macOS" on a real arm64 macOS runner -# and prints enough to identify WHICH step fails. Every brew invocation is -# allowed to fail and is followed by a diagnostic dump, because a job that dies -# on the first non-zero exit tells us the command failed and nothing else. +# Round 1 (macos-14, pre-tapped) passed end to end: install → mcpp new → +# mcpp run → toolchain bootstrap → binary ran. So the reported breakage is not +# "the formula is broken"; it is environment- or path-specific. +# +# Round 2 widens along the three axes that can differ from that green run: +# OS version the runner was macOS 14; users are on 15 / 26 +# arch macos-13 is Intel — the formula REFUSES it by design, and +# this captures the exact message a user would see +# tap path round 1 tapped first; the documented one-liner relies on +# `brew install //` AUTO-tapping, which is +# a different code path +# +# Every brew invocation records its own exit code. Note the trap round 1 fell +# into: `cmd | tail -20` followed by `$?` reports TAIL's status, so a failing +# command reads as success. Exit codes here are captured before any pipe. on: pull_request: @@ -13,100 +24,72 @@ on: jobs: brew-probe: - name: brew install probe (macOS arm64) - runs-on: macos-14 + name: "brew ${{ matrix.os }}" + runs-on: ${{ matrix.os }} timeout-minutes: 40 + continue-on-error: true + strategy: + fail-fast: false + matrix: + os: [macos-14, macos-15, macos-26, macos-13] steps: - - uses: actions/checkout@v4 - - name: Environment run: | + echo "runner: ${{ matrix.os }}" echo "arch: $(uname -m)" echo "macOS: $(sw_vers -productVersion)" echo "brew: $(brew --version | head -1)" echo "brew prefix: $(brew --prefix)" - echo "already installed mcpp? $(command -v mcpp || echo no)" + echo "tapped? $(brew tap | grep -c mcpp || true)" - - name: Tap - run: | - set -x - brew tap mcpp-community/mcpp - brew tap-info mcpp-community/mcpp - - # The formula as the tap publishes it. `brew info` first: it evaluates - # the ruby WITHOUT downloading, so a formula-level error (bad DSL, a - # requirement that cannot be satisfied on this runner) shows up here - # rather than being confused with a download/extract failure below. - - name: "brew info (evaluate formula only)" - run: | - set +e - brew info mcpp-community/mcpp/mcpp-m 2>&1 | tee info.log - echo "exit=$?" - echo "── ruby source as tapped ──" - cat "$(brew --repo mcpp-community/mcpp)/Formula/mcpp-m.rb" - - - name: "brew install mcpp-m (verbose, failure tolerated)" + # EXACTLY the command README.md line 121 tells users to run — no prior + # `brew tap`. Auto-tapping is part of what is being tested. + - name: "brew install mcpp-community/mcpp/mcpp-m (documented one-liner)" id: install run: | set +e - brew install --verbose mcpp-community/mcpp/mcpp-m 2>&1 | tee install.log - rc=${PIPESTATUS[0]} + brew install mcpp-community/mcpp/mcpp-m > install.log 2>&1 + rc=$? echo "install_rc=$rc" >> "$GITHUB_OUTPUT" - echo "=== install exit code: $rc ===" + echo "=== documented one-liner exit: $rc ===" + tail -40 install.log exit 0 - - name: "Diagnose a failed install" + - name: "Diagnose" if: ${{ steps.install.outputs.install_rc != '0' }} run: | - echo "── last 60 lines ──" - tail -60 install.log - echo "── anything that looks like an error ──" - grep -nEi 'error|fail|cannot|no such|denied|unable|invalid' install.log | tail -40 || true - echo "── brew gist-logs (formula build logs) ──" - ls -la ~/Library/Logs/Homebrew/mcpp-m/ 2>/dev/null || echo "(no formula log dir)" + echo "── full log ──" + cat install.log + echo "── error-ish lines ──" + grep -nEi 'error|fail|cannot|no such|denied|unable|invalid|require' install.log | tail -40 || true for f in ~/Library/Logs/Homebrew/mcpp-m/*; do echo "===== $f ====="; cat "$f" done 2>/dev/null || true - - name: "Post-install: does the launcher work?" - if: ${{ steps.install.outputs.install_rc == '0' }} - run: | - set -x - brew list mcpp-community/mcpp/mcpp-m - which mcpp - mcpp --version - mcpp --help | head -5 - - # The alias path the formula's header comment promises. A user reading - # the README types `mcpp`, not `mcpp-m`, so this is a separate claim. - - name: "Alias: brew install …/mcpp resolves" - run: | - set +e - brew info mcpp-community/mcpp/mcpp 2>&1 | tail -20 - echo "alias info exit=$?" - - - name: "brew audit (formula hygiene)" - run: | - set +e - brew audit --strict --online mcpp-community/mcpp/mcpp-m 2>&1 | tail -40 - echo "audit exit=$?" - - - name: "brew test (the formula's own test block)" + - name: "Post-install: launcher + real build" if: ${{ steps.install.outputs.install_rc == '0' }} run: | set +e - brew test --verbose mcpp-community/mcpp/mcpp-m 2>&1 | tail -40 - echo "test exit=$?" + which mcpp; ver_rc=0 + mcpp --version > ver.log 2>&1 || ver_rc=$? + echo "--version exit=$ver_rc"; cat ver.log + cd "$(mktemp -d)" + mcpp new brewhello > new.log 2>&1; new_rc=$? + echo "new exit=$new_rc"; tail -10 new.log + [ $new_rc -eq 0 ] || exit 0 + cd brewhello + mcpp run > run.log 2>&1; run_rc=$? + echo "run exit=$run_rc"; tail -40 run.log + exit 0 - # The real usability question, beyond "the files landed": a brew-installed - # mcpp must be able to bootstrap a toolchain and build something. - - name: "Real use: mcpp new → run" - if: ${{ steps.install.outputs.install_rc == '0' }} + # The other spelling the tap README advertises (line 30). Installing + # through an alias is not the same code path as installing the formula. + - name: "Alias: brew install …/mcpp" + if: ${{ matrix.os != 'macos-13' }} run: | set +e - cd "$(mktemp -d)" - mcpp new brewhello 2>&1 | tail -20 - echo "new exit=$?" - cd brewhello || exit 0 - mcpp run 2>&1 | tail -40 - echo "run exit=$?" + brew uninstall --force mcpp-m > /dev/null 2>&1 + brew install mcpp-community/mcpp/mcpp > alias.log 2>&1 + echo "alias install exit=$?" + tail -25 alias.log + exit 0 From d0106deea31c24431e0b7b361b6aea032ad600c1 Mon Sep 17 00:00:00 2001 From: speak-agent <248744407+speak-agent@users.noreply.github.com> Date: Wed, 12 Aug 2026 01:26:11 +0800 Subject: [PATCH 3/3] =?UTF-8?q?probe=20round=203:=20=E5=AE=9A=E4=BD=8D=20H?= =?UTF-8?q?omebrew=206=20=E7=AC=AC=E4=B8=89=E6=96=B9=20tap=20=E4=BF=A1?= =?UTF-8?q?=E4=BB=BB=E9=97=A8,=E5=B9=B6=E9=AA=8C=E8=AF=81=20brew=20trust?= =?UTF-8?q?=20=E6=98=AF=E5=90=A6=E7=9C=9F=E8=83=BD=E4=BF=AE=E5=A5=BD?= =?UTF-8?q?=E6=AF=8F=E6=9D=A1=E7=94=A8=E6=88=B7=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/tmp-brew-macos-probe.yml | 149 ++++++++++++--------- 1 file changed, 86 insertions(+), 63 deletions(-) diff --git a/.github/workflows/tmp-brew-macos-probe.yml b/.github/workflows/tmp-brew-macos-probe.yml index 961539a3..417fdf18 100644 --- a/.github/workflows/tmp-brew-macos-probe.yml +++ b/.github/workflows/tmp-brew-macos-probe.yml @@ -2,94 +2,117 @@ name: tmp-brew-macos-probe # TEMPORARY. Delete before merging. # -# Round 1 (macos-14, pre-tapped) passed end to end: install → mcpp new → -# mcpp run → toolchain bootstrap → binary ran. So the reported breakage is not -# "the formula is broken"; it is environment- or path-specific. +# Round 2 found it. Homebrew 6.0.x gates third-party taps behind explicit +# trust: # -# Round 2 widens along the three axes that can differ from that green run: -# OS version the runner was macOS 14; users are on 15 / 26 -# arch macos-13 is Intel — the formula REFUSES it by design, and -# this captures the exact message a user would see -# tap path round 1 tapped first; the documented one-liner relies on -# `brew install //` AUTO-tapping, which is -# a different code path +# Refusing to load formula mcpp-community/mcpp/mcpp-m from untrusted tap +# mcpp-community/mcpp. +# Run `brew trust --formula …` or `brew trust mcpp-community/mcpp`. # -# Every brew invocation records its own exit code. Note the trap round 1 fell -# into: `cmd | tail -20` followed by `$?` reports TAIL's status, so a failing -# command reads as success. Exit codes here are captured before any pipe. +# macos-14 / 15 / 26 all hit it (Homebrew 6.0.5 / 6.0.12 / 6.0.13). The +# documented one-liner still passes because `brew install //` +# on an UNTAPPED repo taps and installs in one go, and Homebrew reads that as +# explicit intent. Everything after the tap exists is refused. +# +# Round 3 answers the two questions that decide the fix: +# 1. WHICH user-facing paths are actually broken (short form, re-running the +# documented command, `brew upgrade`, the alias) +# 2. Does `brew trust ` actually repair all of them — i.e. is the fix +# "document one command", or something more +# +# Exit codes are captured before any pipe. Round 1 reported `cmd | tail` and +# read tail's status, which turned a failure into a green line. on: pull_request: workflow_dispatch: jobs: - brew-probe: - name: "brew ${{ matrix.os }}" + brew-trust: + name: "trust gate ${{ matrix.os }}" runs-on: ${{ matrix.os }} - timeout-minutes: 40 + timeout-minutes: 30 continue-on-error: true strategy: fail-fast: false matrix: - os: [macos-14, macos-15, macos-26, macos-13] + os: [macos-14, macos-26] steps: - name: Environment run: | - echo "runner: ${{ matrix.os }}" - echo "arch: $(uname -m)" - echo "macOS: $(sw_vers -productVersion)" - echo "brew: $(brew --version | head -1)" - echo "brew prefix: $(brew --prefix)" - echo "tapped? $(brew tap | grep -c mcpp || true)" + echo "runner: ${{ matrix.os }} | macOS $(sw_vers -productVersion) | $(uname -m)" + brew --version | head -1 + echo "── does this brew even have \`trust\`? ──" + brew trust --help 2>&1 | head -25 || echo "(no brew trust subcommand)" - # EXACTLY the command README.md line 121 tells users to run — no prior - # `brew tap`. Auto-tapping is part of what is being tested. - - name: "brew install mcpp-community/mcpp/mcpp-m (documented one-liner)" - id: install + # ① the documented one-liner on a machine that has never tapped + - name: "1. documented one-liner (untapped machine)" run: | set +e - brew install mcpp-community/mcpp/mcpp-m > install.log 2>&1 - rc=$? - echo "install_rc=$rc" >> "$GITHUB_OUTPUT" - echo "=== documented one-liner exit: $rc ===" - tail -40 install.log - exit 0 + brew install mcpp-community/mcpp/mcpp-m > s1.log 2>&1 + echo "STEP1_rc=$?" + tail -5 s1.log - - name: "Diagnose" - if: ${{ steps.install.outputs.install_rc != '0' }} + # ② the SAME documented command again, now that the tap exists. This is + # what a user hits on their second machine-state, and what CI would + # hit on a warm image. + - name: "2. documented one-liner AGAIN (tap now present)" run: | - echo "── full log ──" - cat install.log - echo "── error-ish lines ──" - grep -nEi 'error|fail|cannot|no such|denied|unable|invalid|require' install.log | tail -40 || true - for f in ~/Library/Logs/Homebrew/mcpp-m/*; do - echo "===== $f ====="; cat "$f" - done 2>/dev/null || true + set +e + brew uninstall --force mcpp-m > /dev/null 2>&1 + brew install mcpp-community/mcpp/mcpp-m > s2.log 2>&1 + echo "STEP2_rc=$?" + tail -5 s2.log - - name: "Post-install: launcher + real build" - if: ${{ steps.install.outputs.install_rc == '0' }} + # ③ the short form the tap README advertises once tapped + - name: "3. short form: brew install mcpp-m" run: | set +e - which mcpp; ver_rc=0 - mcpp --version > ver.log 2>&1 || ver_rc=$? - echo "--version exit=$ver_rc"; cat ver.log - cd "$(mktemp -d)" - mcpp new brewhello > new.log 2>&1; new_rc=$? - echo "new exit=$new_rc"; tail -10 new.log - [ $new_rc -eq 0 ] || exit 0 - cd brewhello - mcpp run > run.log 2>&1; run_rc=$? - echo "run exit=$run_rc"; tail -40 run.log - exit 0 + brew uninstall --force mcpp-m > /dev/null 2>&1 + brew install mcpp-m > s3.log 2>&1 + echo "STEP3_rc=$?" + tail -5 s3.log - # The other spelling the tap README advertises (line 30). Installing - # through an alias is not the same code path as installing the formula. - - name: "Alias: brew install …/mcpp" - if: ${{ matrix.os != 'macos-13' }} + # ④ the alias spelling (tap README line 30) + - name: "4. alias: brew install …/mcpp" run: | set +e brew uninstall --force mcpp-m > /dev/null 2>&1 - brew install mcpp-community/mcpp/mcpp > alias.log 2>&1 - echo "alias install exit=$?" - tail -25 alias.log - exit 0 + brew install mcpp-community/mcpp/mcpp > s4.log 2>&1 + echo "STEP4_rc=$?" + tail -5 s4.log + + # ⑤ THE FIX, if it is one. Everything below must pass after this. + - name: "5. brew trust mcpp-community/mcpp" + run: | + set +e + brew trust mcpp-community/mcpp > s5.log 2>&1 + echo "STEP5_rc=$?" + cat s5.log + + - name: "6. after trust: short form" + run: | + set +e + brew uninstall --force mcpp-m > /dev/null 2>&1 + brew install mcpp-m > s6.log 2>&1 + echo "STEP6_rc=$?" + tail -5 s6.log + + - name: "7. after trust: alias" + run: | + set +e + brew uninstall --force mcpp-m > /dev/null 2>&1 + brew install mcpp-community/mcpp/mcpp > s7.log 2>&1 + echo "STEP7_rc=$?" + tail -5 s7.log + + - name: "8. after trust: upgrade path + the binary still works" + run: | + set +e + brew upgrade mcpp-m > s8.log 2>&1 + echo "STEP8_rc=$?" + tail -5 s8.log + mcpp --version; echo "VERSION_rc=$?" + cd "$(mktemp -d)" && mcpp new t > /dev/null 2>&1; echo "NEW_rc=$?" + cd t && mcpp run > s8run.log 2>&1; echo "RUN_rc=$?" + tail -6 s8run.log