9449485dcf
The generated cask used `pre_install` / `post_install`. Those are formula DSL methods; a cask has no such stanzas, so brew rejected the file at load time with Error: Cask 'gortex' definition is invalid: undefined method 'pre_install' Every brew command that touches the cask parses it, so `brew install` and `brew upgrade` both failed for every macOS user on both arches, starting with v0.63.7. Closes #639. Two further defects made a straight rename insufficient: * The cask DSL's `system_command` is `SystemCommand.run!`, which raises on a non-zero exit. `gortex daemon status` exits 1 exactly when no daemon is reachable, so `next unless status.success?` could never run — brew would have aborted the install outright on any machine without a live daemon. The probe now passes `must_succeed: false`. * `preflight` was the wrong hook for stopping the daemon. On upgrade brew unlinks the old cask's binary (`start_upgrade` -> `uninstall_artifacts`) before installing the new cask's artifacts, so by the time a preflight block runs there is no gortex on disk to ask. The stop half could never fire on the path it was written for. `postflight` handles both halves instead: after the new binary is linked, probe for a daemon and, only if one answers, `daemon restart` — which stops the old process (blocking until it exits, releasing the store lock) before starting the new one, so a store migration still runs alone. A fresh install and CI have no daemon answering and skip it. The cask body moves out of the release.yml heredoc into .github/homebrew/gortex.rb.tmpl, rendered by scripts/render-cask.sh. That makes it reviewable as Ruby, removes the shell-expansion hazards of an unquoted heredoc, and — the point — lets a real brew load it before publication. The renderer also refuses a malformed sha256, a version with a leading "v", or a placeholder that survived substitution. Rendered output is byte-identical to the published cask apart from the hook block. Nothing could have caught this: the file was valid Ruby, valid YAML, and the tap has no CI, so the first machine to evaluate the cask was a user's. scripts/validate-cask.sh renders the template with dummy values and loads it through a real brew. It runs on every PR that touches the cask (.github/workflows/homebrew-cask.yml) and again in build-darwin as the last gate before the release job pushes to the tap. Both are macOS-only — Homebrew on Linux cannot load casks. Verified by reintroducing `pre_install` in the template: the validator fails with the exact error users reported.