Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/homebrew-tap.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ jobs:
TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
run: |
set -euxo pipefail
if [ -z "${TAP_TOKEN:-}" ]; then
echo "::error::HOMEBREW_TAP_TOKEN secret is empty or unset — cannot push to ${TAP_OWNER}/${TAP_REPO}. Add a fine-grained PAT (Contents: Read and write on the tap repo) as the HOMEBREW_TAP_TOKEN secret, then re-run this workflow." >&2
exit 1
fi
# We do NOT use actions/checkout for the tap repo because on the
# very first run the tap is empty and has no refs/heads/main yet.
# `git init` + `git fetch || true` + `git push -u origin main`
Expand Down
17 changes: 17 additions & 0 deletions packages/homebrew-tap/pythinker-code.rb.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ class PythinkerCode < Formula
bin.write_exec_script libexec/"pythinker"
end

def caveats
# Static settled frame of the curl/PowerShell installers' "Tetris" logo
# (install.sh / install.ps1). Homebrew renders caveats as plain text, so
# this is the uncoloured robot-head. The squiggly heredoc strips the common
# leading indent, so the art sits one column left of the curl banner.
<<~EOS

▛▀▀▀▀▀▀▀▜
◖█ ◉ ◉ █◗
▙▄▄▄≡▄▄▄▟

pythinker code · your next CLI agent
EOS
end

test do
assert_path_exists libexec/".pythinker-native"
assert_match version.to_s, shell_output("#{bin}/pythinker --version")
Expand Down
31 changes: 27 additions & 4 deletions tests/test_homebrew_formula.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,22 @@ def load_generator() -> ModuleType:
return module


def test_native_homebrew_formula_renders_release_tarballs() -> None:
generator = load_generator()
version = "1.2.3"
assets = {}
def _fake_assets(generator: ModuleType, version: str) -> dict[str, dict[str, str]]:
"""Build a fake GitHub release-asset map covering every native target."""
assets: dict[str, dict[str, str]] = {}
for target in generator.NATIVE_TARGETS:
name = target.asset_name(version)
assets[name] = {
"browser_download_url": f"https://example.invalid/{name}",
"digest": "sha256:" + ("a" * 64),
}
return assets


def test_native_homebrew_formula_renders_release_tarballs() -> None:
generator = load_generator()
version = "1.2.3"
assets = _fake_assets(generator, version)

formula = generator.render_formula(
TEMPLATE.read_text(encoding="utf-8"), generator.native_replacements(version, assets)
Expand Down Expand Up @@ -59,3 +65,20 @@ def test_native_homebrew_formula_fails_when_asset_missing() -> None:
assert "release asset missing" in str(exc)
else:
raise AssertionError("expected missing native asset to fail formula generation")


def test_native_homebrew_formula_caveats_show_logo() -> None:
generator = load_generator()
version = "1.2.3"
assets = _fake_assets(generator, version)

formula = generator.render_formula(
TEMPLATE.read_text(encoding="utf-8"), generator.native_replacements(version, assets)
)

# Homebrew prints `caveats` after install — this is where the static robot
# logo (parity with install.sh / install.ps1) must live.
assert "def caveats" in formula
assert "pythinker code · your next CLI agent" in formula
# The robot-head mouth row is the most distinctive line of the art.
assert "▙▄▄▄≡▄▄▄▟" in formula
Loading