|
| 1 | +--- |
| 2 | +name: testing-homebrew-packaging |
| 3 | +description: How to verify the Systemica Homebrew formula end to end on Linux — rendering packaging/homebrew/Formula/systemica.rb with scripts/render-homebrew-formula.sh, installing/testing/auditing it through a throwaway local tap, and the adversarial paths worth checking. |
| 4 | +--- |
| 5 | + |
| 6 | +# Verifying the Systemica Homebrew formula (Linux) |
| 7 | + |
| 8 | +`packaging/homebrew/Formula/systemica.rb` is a **template** with `__TAG__` / `__SHA256_*__` |
| 9 | +placeholders. `scripts/render-homebrew-formula.sh <tag>` substitutes them from the release's |
| 10 | +`SHA256SUMS.txt` and strips the maintainer header. The tap repo `Open-MBEE/homebrew-tap` does |
| 11 | +not exist yet, so everything below uses a throwaway **local** tap. |
| 12 | + |
| 13 | +## Prerequisites |
| 14 | + |
| 15 | +- Homebrew is not preinstalled by the repo blueprint. On this box it lives at |
| 16 | + `/home/linuxbrew/.linuxbrew/bin/brew` — `export PATH=/home/linuxbrew/.linuxbrew/bin:$PATH`. |
| 17 | + If it is absent, install it (`/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"`). |
| 18 | +- Network access to `github.com` is required (release archives + `brew audit --online`). |
| 19 | +- No Go build is needed: the formula installs **prebuilt release binaries**, so this path is |
| 20 | + independent of `make build`. |
| 21 | + |
| 22 | +## Always start from a clean slate |
| 23 | + |
| 24 | +A previous run leaves state that makes a rerun a no-op and silently proves nothing: |
| 25 | + |
| 26 | +```bash |
| 27 | +brew uninstall systemica 2>/dev/null |
| 28 | +brew untap local/<previous-tap-name> 2>/dev/null |
| 29 | +which sysml # must print nothing before you begin |
| 30 | +brew tap # confirm no leftover local/* taps |
| 31 | +``` |
| 32 | + |
| 33 | +Use a **fresh** tap name each run (`local/pr73check`, not a reused one) so `tap-new` itself is |
| 34 | +exercised. First `brew install` pulls ~12 dependencies (gcc, glibc, binutils…) and takes |
| 35 | +2–4 minutes; budget for it and answer the `[y/n]` prompt (or `--yes`). |
| 36 | + |
| 37 | +## The verification recipe (mirrors packaging/homebrew/README.md) |
| 38 | + |
| 39 | +```bash |
| 40 | +./scripts/render-homebrew-formula.sh v0.0.4 > /tmp/systemica.rb |
| 41 | +brew tap-new local/<fresh> --no-git |
| 42 | +cp /tmp/systemica.rb "$(brew --repository local/<fresh>)/Formula/systemica.rb" |
| 43 | +brew install local/<fresh>/systemica && brew test local/<fresh>/systemica |
| 44 | +brew audit --strict --online local/<fresh>/systemica |
| 45 | +``` |
| 46 | + |
| 47 | +All four must exit 0. Benign noise to ignore: `fatal: ambiguous argument |
| 48 | +'refs/remotes/origin/main'` during auto-update, `Sandbox unavailable: building without |
| 49 | +sandboxing!`, and ``AllCops/UseProjectIndex` is enabled but the `rubydex` gem is not installed``. |
| 50 | + |
| 51 | +## Assertions that actually discriminate |
| 52 | + |
| 53 | +- **No `version` line.** Homebrew scans the version from the tag in the release URL; |
| 54 | + `brew audit --strict` fails with `` `version 0.0.4` is redundant with version scanned from |
| 55 | + URL``. Prove the removal matters with a **counterfactual**: re-insert the line into the tap |
| 56 | + copy and rerun the audit — it must fail with exactly that wording, then restore the file. |
| 57 | + Just seeing a green audit does not prove the fix. |
| 58 | +- **Checksums match the release**, not merely "look like hashes". Download |
| 59 | + `https://github.com/Open-MBEE/Systemica/releases/download/<tag>/SHA256SUMS.txt` and compare |
| 60 | + the four `systemica-<os>-<arch>.tar.gz` entries against the `url`/`sha256` pairs parsed out |
| 61 | + of the rendered file. Note the manifest also contains per-binary `sysml-*` / `sysml-lsp-*` |
| 62 | + entries — the formula only uses the `systemica-*` bundles. |
| 63 | +- **Zero placeholders**: `grep -c '__[A-Z0-9_]*__' /tmp/systemica.rb` → `0`. The script has its |
| 64 | + own guard for this (exit 1), so a rendering regression usually surfaces as a script failure. |
| 65 | +- **The installed binaries are the brew ones**: check `which sysml` resolves under |
| 66 | + `/home/linuxbrew/...`, not `./bin/sysml`, before smoke-testing. `sysml --version` must print |
| 67 | + the release tag (`sysml v0.0.4`), not a dev/commit string. |
| 68 | + |
| 69 | +## Adversarial paths (all cheap, all worth running) |
| 70 | + |
| 71 | +| Command | Expected | |
| 72 | +|---|---| |
| 73 | +| `render-homebrew-formula.sh v9.9.9` | exit 22, `curl: (22) ... error: 404`, no `class Systemica` in output | |
| 74 | +| `render-homebrew-formula.sh <tag> <sums-with-one-line>` | exit 1, `error: no checksum for systemica-darwin-amd64.tar.gz` | |
| 75 | +| `render-homebrew-formula.sh` (no args) | exit 2, `usage: ... <tag> [SHA256SUMS.txt]` | |
| 76 | +| `brew install` of the **unrendered** template | must FAIL — download URL contains literal `__TAG__` and 404s | |
| 77 | + |
| 78 | +Rehearse the 404 case sparingly: repeated unauthenticated GitHub hits can turn it into a |
| 79 | +misleading `HTTP Error 403: rate limit exceeded`. Report the 404 wording, not the 403. |
| 80 | + |
| 81 | +## Homebrew 6.x tap trust |
| 82 | + |
| 83 | +Homebrew 6 requires tap trust. Taps you create locally with `brew tap-new` are trusted |
| 84 | +automatically (`==> Trusted formula local/<tap>/systemica`), but installing from tap B will warn |
| 85 | +that tap A "is not trusted" if A is still tapped. That warning is cosmetic for this workflow; |
| 86 | +untap old taps to silence it, or `brew trust local/<tap>`. |
| 87 | + |
| 88 | +## Recording |
| 89 | + |
| 90 | +This is CLI work, so record a real terminal: see the "Recording setup" section of |
| 91 | +`.agents/skills/testing-sysml-repl/SKILL.md` (Konsole on `DISPLAY=:0`, `ctrl+plus` to enlarge |
| 92 | +the font, `wmctrl` to maximize). `clear` between steps keeps each assertion legible on camera. |
| 93 | + |
| 94 | +## Devin Secrets Needed |
| 95 | + |
| 96 | +None. All release assets are public; `brew audit --online` works unauthenticated. |
0 commit comments