| 1 | #!/usr/bin/env bash |
| 2 | # Generate the GitHub Release body for a tag. |
| 3 | # |
| 4 | # Usage: generate-release-body.sh <vX.Y.Z> [path/to/CHANGELOG.md] |
| 5 | # |
| 6 | # The install/verify sections are static; the release notes and contributor |
| 7 | # credits come from the CHANGELOG section for the version, so they can never |
| 8 | # drift the way a hand-edited workflow body does. |
| 9 | set -euo pipefail |
| 10 | |
| 11 | tag="${1:?usage: $0 <vX.Y.Z> [CHANGELOG.md]}" |
| 12 | changelog="${2:-CHANGELOG.md}" |
| 13 | version="${tag#v}" |
| 14 | |
| 15 | section="$(awk -v version="${version}" ' |
| 16 | index($0, "## [" version "]") == 1 { in_section = 1; next } |
| 17 | in_section && /^## \[/ { exit } |
| 18 | in_section { print } |
| 19 | ' "${changelog}")" |
| 20 | |
| 21 | contributors="$(printf '%s\n' "${section}" | awk ' |
| 22 | /^### Contributors[[:space:]]*$/ { in_contributors = 1; next } |
| 23 | in_contributors && /^### / { exit } |
| 24 | in_contributors { print } |
| 25 | ')" |
| 26 | |
| 27 | notes="$(printf '%s\n' "${section}" | awk ' |
| 28 | /^### Contributors[[:space:]]*$/ { in_contributors = 1; next } |
| 29 | in_contributors && /^### / { in_contributors = 0 } |
| 30 | !in_contributors { print } |
| 31 | ')" |
| 32 | |
| 33 | cat <<EOF |
| 34 | > **Codewhale** is the public product from Shannon Labs. The \`codewhale\` |
| 35 | > command, npm package, and release-asset names remain lowercase technical |
| 36 | > identifiers. The legacy npm package \`deepseek-tui\` is deprecated and |
| 37 | > receives no further releases. Users coming from v0.8.x legacy \`deepseek\` / |
| 38 | > \`deepseek-tui\` names should migrate with \`docs/REBRAND.md\`. |
| 39 | |
| 40 | ## Install |
| 41 | |
| 42 | ### Recommended — npm (one command, all three entrypoints) |
| 43 | |
| 44 | \`\`\`bash |
| 45 | npm install -g codewhale |
| 46 | \`\`\` |
| 47 | |
| 48 | The wrapper downloads the matched \`codewhale\`, \`codew\`, and \`codewhale-tui\` |
| 49 | binaries from this Release and places them in the same directory. |
| 50 | |
| 51 | ### Docker / GHCR |
| 52 | |
| 53 | \`\`\`bash |
| 54 | docker run --rm -it \\ |
| 55 | -e DEEPSEEK_API_KEY="\$DEEPSEEK_API_KEY" \\ |
| 56 | -v codewhale-home:/home/codewhale/.codewhale \\ |
| 57 | ghcr.io/hmbown/codewhale:${tag} |
| 58 | \`\`\` |
| 59 | |
| 60 | The image ships the \`codewhale\` dispatcher, \`codew\` shim, and \`codewhale-tui\` runtime. The \`latest\` tag is also updated on release. |
| 61 | |
| 62 | ### Cargo (Linux / macOS) |
| 63 | |
| 64 | \`\`\`bash |
| 65 | cargo install codewhale-cli codewhale-tui --locked |
| 66 | \`\`\` |
| 67 | |
| 68 | Both crates are required — \`codewhale-cli\` produces the \`codewhale\` dispatcher and \`codew\` shim, while \`codewhale-tui\` produces the interactive runtime that the dispatcher delegates to. Installing only one crate will fail at runtime with a \`MISSING_COMPANION_BINARY\` error. |
| 69 | |
| 70 | ### Manual download — platform archives (recommended) |
| 71 | |
| 72 | Each archive below contains the \`codewhale\` dispatcher, \`codew\` shim, and \`codewhale-tui\` runtime, plus an install script: |
| 73 | |
| 74 | | Platform | Archive | Install script | |
| 75 | |---|---|---| |
| 76 | | Linux x64 | \`codewhale-linux-x64.tar.gz\` | \`install.sh\` | |
| 77 | | Linux ARM64 | \`codewhale-linux-arm64.tar.gz\` | \`install.sh\` | |
| 78 | | Android ARM64 (Termux) | \`codewhale-android-arm64.tar.gz\` | \`install.sh\` | |
| 79 | | macOS x64 | \`codewhale-macos-x64.tar.gz\` | \`install.sh\` | |
| 80 | | macOS ARM | \`codewhale-macos-arm64.tar.gz\` | \`install.sh\` | |
| 81 | | Windows x64 (installer) | \`CodeWhaleSetup.exe\` | NSIS setup | |
| 82 | | Windows x64 | \`codewhale-windows-x64.zip\` | \`install.bat\` | |
| 83 | | Windows x64 (portable) | \`codewhale-windows-x64-portable.zip\` | — | |
| 84 | | Windows ARM64 | \`codewhale-windows-arm64.zip\` | \`install.bat\` | |
| 85 | | Windows ARM64 (portable) | \`codewhale-windows-arm64-portable.zip\` | — | |
| 86 | |
| 87 | **Unix (Linux / macOS):** |
| 88 | \`\`\`bash |
| 89 | tar xzf codewhale-<platform>.tar.gz |
| 90 | cd codewhale-<platform> |
| 91 | ./install.sh |
| 92 | \`\`\` |
| 93 | |
| 94 | **Windows:** |
| 95 | - For the installer path, run \`CodeWhaleSetup.exe\`; it installs \`codewhale.exe\`, \`codew.exe\`, and \`codewhale-tui.exe\` under \`%LOCALAPPDATA%\\Programs\\CodeWhale\\bin\` and adds that directory to the current-user PATH. |
| 96 | - Extract the archive for your machine: \`codewhale-windows-x64.zip\` or |
| 97 | \`codewhale-windows-arm64.zip\` |
| 98 | - Run \`install.bat\` (copies to \`%USERPROFILE%\\bin\`) |
| 99 | - Add \`%USERPROFILE%\\bin\` to your PATH |
| 100 | |
| 101 | The **portable** Windows archive skips the install script — extract and run from any directory. The NSIS installer is currently unsigned and may trigger Windows SmartScreen until a signing certificate is wired into the release pipeline. |
| 102 | |
| 103 | Each platform also has **bare, unarchived** binaries attached below (\`codewhale-<platform>\`, \`codew-<platform>\`, and \`codewhale-tui-<platform>\`) — the npm wrapper and the in-app \`codewhale update\` download the matched runtime binaries, whereas the \`.tar.gz\` / \`.zip\` archives above are the recommended manual download and additionally bundle an install script. The legacy npm package \`deepseek-tui\` is deprecated and is not republished. For migration from v0.8.x legacy binary names, see \`docs/REBRAND.md\`. |
| 104 | |
| 105 | ### Verify (recommended) |
| 106 | |
| 107 | Download the checksum manifests from this Release and verify: |
| 108 | |
| 109 | \`\`\`bash |
| 110 | # Linux — archive bundles |
| 111 | sha256sum -c codewhale-bundles-sha256.txt --ignore-missing |
| 112 | |
| 113 | # Linux — individual binaries |
| 114 | sha256sum -c codewhale-artifacts-sha256.txt --ignore-missing |
| 115 | |
| 116 | # macOS |
| 117 | shasum -a 256 -c codewhale-bundles-sha256.txt --ignore-missing |
| 118 | shasum -a 256 -c codewhale-artifacts-sha256.txt --ignore-missing |
| 119 | \`\`\` |
| 120 | |
| 121 | ## What's in ${tag} |
| 122 | EOF |
| 123 | |
| 124 | if [[ -n "${notes}" ]]; then |
| 125 | printf '%s\n' "${notes}" |
| 126 | else |
| 127 | printf '%s\n' "See the changelog link below for this release's notes." |
| 128 | fi |
| 129 | |
| 130 | cat <<EOF |
| 131 | |
| 132 | ## Contributors |
| 133 | EOF |
| 134 | |
| 135 | if [[ -n "${contributors}" ]]; then |
| 136 | printf '%s\n' "${contributors}" |
| 137 | else |
| 138 | printf '%s\n' "Thank you to everyone whose reports, PRs, reviews, and reproductions shaped this release." |
| 139 | fi |
| 140 | |
| 141 | cat <<EOF |
| 142 | |
| 143 | See [CHANGELOG.md](https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md) for full notes and [docs/CHANGELOG_ARCHIVE.md](https://github.com/Hmbown/CodeWhale/blob/main/docs/CHANGELOG_ARCHIVE.md) for older releases. |
| 144 | EOF |
| 145 |