| 1 | #!/usr/bin/env bash |
| 2 | # Update the Homebrew tap at Hmbown/homebrew-deepseek-tui after a release. |
| 3 | # |
| 4 | # Expected environment: |
| 5 | # TAG – git tag, e.g. "v0.8.31" |
| 6 | # MANIFEST – path to codewhale-artifacts-sha256.txt |
| 7 | # TAP_REPO – owner/repo of the Homebrew tap |
| 8 | # TOKEN – PAT with contents:write on TAP_REPO (optional; skips if unset) |
| 9 | # FORMULA_OUTPUT – optional local render path used by contract tests |
| 10 | |
| 11 | set -euo pipefail |
| 12 | |
| 13 | : "${TAG:?}" |
| 14 | : "${MANIFEST:?}" |
| 15 | : "${TAP_REPO:?}" |
| 16 | |
| 17 | if [ -z "${TOKEN:-}" ] && [ -z "${FORMULA_OUTPUT:-}" ]; then |
| 18 | echo "No Homebrew tap token configured; skipping." |
| 19 | exit 0 |
| 20 | fi |
| 21 | |
| 22 | VERSION="${TAG#v}" |
| 23 | |
| 24 | die() { echo "::error::${1}" >&2; exit 1; } |
| 25 | |
| 26 | sha() { |
| 27 | local file="${1:?}" |
| 28 | local val |
| 29 | val="$(awk -v f="${file}" '$2 == f {print $1; exit}' "${MANIFEST}")" |
| 30 | if [ -z "${val}" ]; then |
| 31 | die "Missing binary in checksum manifest: ${file}" |
| 32 | fi |
| 33 | echo "${val}" |
| 34 | } |
| 35 | |
| 36 | # --- read checksums --------------------------------------------------- |
| 37 | |
| 38 | # Canonical dispatcher and TUI |
| 39 | SHA_COD_MACOS_ARM="$(sha codewhale-macos-arm64)" |
| 40 | SHA_CODEW_MACOS_ARM="$(sha codew-macos-arm64)" |
| 41 | SHA_TUI_MACOS_ARM="$(sha codewhale-tui-macos-arm64)" |
| 42 | SHA_COD_MACOS_X64="$(sha codewhale-macos-x64)" |
| 43 | SHA_CODEW_MACOS_X64="$(sha codew-macos-x64)" |
| 44 | SHA_TUI_MACOS_X64="$(sha codewhale-tui-macos-x64)" |
| 45 | SHA_COD_LINUX_ARM="$(sha codewhale-linux-arm64)" |
| 46 | SHA_CODEW_LINUX_ARM="$(sha codew-linux-arm64)" |
| 47 | SHA_TUI_LINUX_ARM="$(sha codewhale-tui-linux-arm64)" |
| 48 | SHA_COD_LINUX_X64="$(sha codewhale-linux-x64)" |
| 49 | SHA_CODEW_LINUX_X64="$(sha codew-linux-x64)" |
| 50 | SHA_TUI_LINUX_X64="$(sha codewhale-tui-linux-x64)" |
| 51 | readonly SHA_COD_MACOS_ARM SHA_CODEW_MACOS_ARM SHA_TUI_MACOS_ARM |
| 52 | readonly SHA_COD_MACOS_X64 SHA_CODEW_MACOS_X64 SHA_TUI_MACOS_X64 |
| 53 | readonly SHA_COD_LINUX_ARM SHA_CODEW_LINUX_ARM SHA_TUI_LINUX_ARM |
| 54 | readonly SHA_COD_LINUX_X64 SHA_CODEW_LINUX_X64 SHA_TUI_LINUX_X64 |
| 55 | |
| 56 | # --- temp dirs -------------------------------------------------------- |
| 57 | |
| 58 | FORMULA_FILE="$(mktemp)" |
| 59 | TAP_DIR="$(mktemp -d)" |
| 60 | trap 'rm -rf "${TAP_DIR}" "${FORMULA_FILE}"' EXIT |
| 61 | |
| 62 | # --- generate formula -------------------------------------------------- |
| 63 | |
| 64 | readonly BASE_URL="https://github.com/Hmbown/CodeWhale/releases/download/${TAG}" |
| 65 | |
| 66 | cat > "${FORMULA_FILE}" << EOF |
| 67 | class DeepseekTui < Formula |
| 68 | desc "Agentic terminal for open-source and open-weight coding models" |
| 69 | homepage "https://github.com/Hmbown/CodeWhale" |
| 70 | version "${VERSION}" |
| 71 | license "MIT" |
| 72 | |
| 73 | on_macos do |
| 74 | if Hardware::CPU.arm? |
| 75 | url "${BASE_URL}/codewhale-macos-arm64", using: :nounzip |
| 76 | sha256 "${SHA_COD_MACOS_ARM}" |
| 77 | resource "codew" do |
| 78 | url "${BASE_URL}/codew-macos-arm64", using: :nounzip |
| 79 | sha256 "${SHA_CODEW_MACOS_ARM}" |
| 80 | end |
| 81 | resource "tui" do |
| 82 | url "${BASE_URL}/codewhale-tui-macos-arm64", using: :nounzip |
| 83 | sha256 "${SHA_TUI_MACOS_ARM}" |
| 84 | end |
| 85 | else |
| 86 | url "${BASE_URL}/codewhale-macos-x64", using: :nounzip |
| 87 | sha256 "${SHA_COD_MACOS_X64}" |
| 88 | resource "codew" do |
| 89 | url "${BASE_URL}/codew-macos-x64", using: :nounzip |
| 90 | sha256 "${SHA_CODEW_MACOS_X64}" |
| 91 | end |
| 92 | resource "tui" do |
| 93 | url "${BASE_URL}/codewhale-tui-macos-x64", using: :nounzip |
| 94 | sha256 "${SHA_TUI_MACOS_X64}" |
| 95 | end |
| 96 | end |
| 97 | end |
| 98 | |
| 99 | on_linux do |
| 100 | if Hardware::CPU.arm? |
| 101 | url "${BASE_URL}/codewhale-linux-arm64", using: :nounzip |
| 102 | sha256 "${SHA_COD_LINUX_ARM}" |
| 103 | resource "codew" do |
| 104 | url "${BASE_URL}/codew-linux-arm64", using: :nounzip |
| 105 | sha256 "${SHA_CODEW_LINUX_ARM}" |
| 106 | end |
| 107 | resource "tui" do |
| 108 | url "${BASE_URL}/codewhale-tui-linux-arm64", using: :nounzip |
| 109 | sha256 "${SHA_TUI_LINUX_ARM}" |
| 110 | end |
| 111 | else |
| 112 | url "${BASE_URL}/codewhale-linux-x64", using: :nounzip |
| 113 | sha256 "${SHA_COD_LINUX_X64}" |
| 114 | resource "codew" do |
| 115 | url "${BASE_URL}/codew-linux-x64", using: :nounzip |
| 116 | sha256 "${SHA_CODEW_LINUX_X64}" |
| 117 | end |
| 118 | resource "tui" do |
| 119 | url "${BASE_URL}/codewhale-tui-linux-x64", using: :nounzip |
| 120 | sha256 "${SHA_TUI_LINUX_X64}" |
| 121 | end |
| 122 | end |
| 123 | end |
| 124 | |
| 125 | def install |
| 126 | bin.install Dir["*"].first => "codewhale" |
| 127 | resource("codew").stage { bin.install Dir["*"].first => "codew" } |
| 128 | resource("tui").stage { bin.install Dir["*"].first => "codewhale-tui" } |
| 129 | end |
| 130 | |
| 131 | test do |
| 132 | system "#{bin}/codewhale", "--version" |
| 133 | system "#{bin}/codew", "--version" |
| 134 | system "#{bin}/codewhale-tui", "--version" |
| 135 | end |
| 136 | end |
| 137 | EOF |
| 138 | |
| 139 | if [ -n "${FORMULA_OUTPUT:-}" ]; then |
| 140 | cp "${FORMULA_FILE}" "${FORMULA_OUTPUT}" |
| 141 | echo "Rendered Homebrew formula to ${FORMULA_OUTPUT}" |
| 142 | exit 0 |
| 143 | fi |
| 144 | |
| 145 | # --- push to tap repo -------------------------------------------------- |
| 146 | |
| 147 | ENCODED_TOKEN="$(printf '%s' "${TOKEN}" | python3 -c 'import sys,urllib.parse;print(urllib.parse.quote(sys.stdin.read(),safe=""))')" |
| 148 | TAP_URL="https://x-access-token:${ENCODED_TOKEN}@github.com/${TAP_REPO}.git" |
| 149 | |
| 150 | git clone --depth 1 "${TAP_URL}" "${TAP_DIR}" |
| 151 | |
| 152 | mkdir -p "${TAP_DIR}/Formula" |
| 153 | cp "${FORMULA_FILE}" "${TAP_DIR}/Formula/deepseek-tui.rb" |
| 154 | |
| 155 | cd "${TAP_DIR}" |
| 156 | git config user.name "github-actions[bot]" |
| 157 | git config user.email "github-actions[bot]@users.noreply.github.com" |
| 158 | |
| 159 | git add Formula/deepseek-tui.rb |
| 160 | |
| 161 | if git diff --cached --quiet; then |
| 162 | echo "Formula unchanged (already at ${VERSION}); nothing to push." |
| 163 | exit 0 |
| 164 | fi |
| 165 | |
| 166 | git commit -m "chore: bump formula to ${VERSION} |
| 167 | |
| 168 | Automated update from the release workflow." |
| 169 | |
| 170 | git push origin HEAD:main |
| 171 | echo "Pushed formula update to ${TAP_REPO} (v${VERSION})" |
| 172 |