diff --git a/README.md b/README.md index ca0708ce..c28fa2aa 100644 --- a/README.md +++ b/README.md @@ -50,20 +50,11 @@ yay -S fizzy-cli **Homebrew (macOS):** -Latest stable Fizzy 3.x is available from the original tap: - ```bash -brew install robzolkos/fizzy-cli/fizzy-cli +brew install --cask basecamp/tap/fizzy ``` -Fizzy 4 release candidates are available from [Releases](https://github.com/basecamp/fizzy-cli/releases). - -> [!WARNING] -> The Basecamp Homebrew tap command is for Fizzy 4 stable once it is released. Release candidates are not published to Homebrew. -> -> ```bash -> brew install --cask basecamp/tap/fizzy -> ``` +Release candidates are not published to Homebrew; they are available from [Releases](https://github.com/basecamp/fizzy-cli/releases). **Scoop (Windows):** ```bash diff --git a/RELEASING.md b/RELEASING.md index b3221978..46efbe4e 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -51,23 +51,20 @@ Technical testers can install prereleases explicitly from the GitHub release ass ## CI Secrets -### Repository level (`Settings > Secrets and variables > Actions`) +All release credentials live in the `release` environment (`Settings > Environments > release`), so they are only exposed to jobs that pass the environment's required-reviewer gate. There are no repository-level release secrets. `HOMEBREW_TAP_TOKEN` does not exist as a stored secret — it is minted per-run from the `cli-release-bot` GitHub App credentials. | Name | Type | Purpose | |------|------|---------| | `RELEASE_CLIENT_ID` | variable | GitHub App client ID for `cli-release-bot` | | `RELEASE_APP_PRIVATE_KEY` | secret | GitHub App private key for tap push | | `AUR_KEY` | secret | ed25519 SSH private key for AUR (optional) | +| `MACOS_SIGN_P12` | secret | Base64-encoded Developer ID Application .p12 | +| `MACOS_SIGN_PASSWORD` | secret | Password for the .p12 certificate | +| `MACOS_NOTARY_KEY` | secret | Base64-encoded App Store Connect API key (.p8) | +| `MACOS_NOTARY_KEY_ID` | secret | App Store Connect API key ID (10 chars) | +| `MACOS_NOTARY_ISSUER_ID` | secret | App Store Connect issuer UUID | -### Environment level (`release` environment — `Settings > Environments`) - -| Secret | Purpose | -|--------|---------| -| `MACOS_SIGN_P12` | Base64-encoded Developer ID Application .p12 | -| `MACOS_SIGN_PASSWORD` | Password for the .p12 certificate | -| `MACOS_NOTARY_KEY` | Base64-encoded App Store Connect API key (.p8) | -| `MACOS_NOTARY_KEY_ID` | App Store Connect API key ID (10 chars) | -| `MACOS_NOTARY_ISSUER_ID` | App Store Connect issuer UUID | +Set a secret with `gh secret set --env release -R basecamp/fizzy-cli`; the `RELEASE_CLIENT_ID` variable uses `gh variable set` instead. For multi-line secrets like SSH keys, pipe the file directly (`gh secret set AUR_KEY --env release -R basecamp/fizzy-cli < keyfile`) so newlines are preserved — pasting a flattened key produces an "invalid format" SSH failure at publish time. ## Distribution Channels @@ -99,5 +96,18 @@ goreleaser release --snapshot --clean ## AUR Setup 1. Generate ed25519 SSH keypair: `ssh-keygen -t ed25519 -f aur_key` -2. Add public key to your AUR account profile -3. Add private key as `AUR_KEY` secret on the fizzy-cli repo +2. Add public key to the AUR account that maintains `fizzy-cli` +3. Validate the private key parses and authenticates: + `ssh-keygen -y -f aur_key > /dev/null && ssh -T -i aur_key aur@aur.archlinux.org` + (expect "Interactive shell is disabled") +4. Store it in the `release` environment, preserving newlines: + `gh secret set AUR_KEY --env release -R basecamp/fizzy-cli < aur_key` + +## Tap Migration Ordering + +When moving the Homebrew install path from another tap to `basecamp/tap` (learned during the v4.0.0 release, 2026-07-27): + +1. **First** ship a stable release so GoReleaser publishes `Casks/fizzy.rb` to `basecamp/homebrew-tap`. The cask must exist before anything points at it. +2. **Then** land `tap_migrations.json` (mapping the old formula to `basecamp/tap/fizzy`) in the old tap and remove its formula. `brew update` surfaces the migration to existing users. +3. Do **not** transfer the old tap repo into the basecamp org — a repo named `homebrew-*` or matching `basecamp/fizzy-cli` would become a stray implicit tap. Archive it once users have migrated. +4. Update README install instructions last, once `brew install --cask basecamp/tap/fizzy` actually works. diff --git a/scripts/install.sh b/scripts/install.sh index b12698a8..3c2c2f79 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -34,31 +34,32 @@ if [ -z "$VERSION" ]; then fi echo "Latest version: $VERSION" -# Download binary -BINARY_NAME="fizzy-${OS}-${ARCH}" +# Download release archive +EXT="tar.gz" if [ "$OS" = "windows" ]; then - BINARY_NAME="fizzy-${OS}-${ARCH}.exe" + EXT="zip" fi +ARCHIVE="fizzy_${VERSION#v}_${OS}_${ARCH}.${EXT}" -DOWNLOAD_URL="https://github.com/$REPO/releases/download/${VERSION}/${BINARY_NAME}" -CHECKSUMS_URL="https://github.com/$REPO/releases/download/${VERSION}/SHA256SUMS-${OS}-${ARCH}.txt" +DOWNLOAD_URL="https://github.com/$REPO/releases/download/${VERSION}/${ARCHIVE}" +CHECKSUMS_URL="https://github.com/$REPO/releases/download/${VERSION}/checksums.txt" TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' EXIT -echo "Downloading $BINARY_NAME..." -curl -fsSL "$DOWNLOAD_URL" -o "$TMPDIR/$BINARY_NAME" +echo "Downloading $ARCHIVE..." +curl -fsSL "$DOWNLOAD_URL" -o "$TMPDIR/$ARCHIVE" curl -fsSL "$CHECKSUMS_URL" -o "$TMPDIR/checksums.txt" # Verify SHA256 echo "Verifying checksum..." cd "$TMPDIR" -EXPECTED=$(awk '{print $1}' checksums.txt) +EXPECTED=$(awk -v f="$ARCHIVE" '$2 == f || $2 == "*" f {print $1}' checksums.txt) if [ -z "$EXPECTED" ]; then - echo "ERROR: Checksum not found" + echo "ERROR: Checksum for $ARCHIVE not found in checksums.txt" exit 1 fi -ACTUAL=$(sha256sum "$BINARY_NAME" 2>/dev/null || shasum -a 256 "$BINARY_NAME" | awk '{print $1}') +ACTUAL=$(sha256sum "$ARCHIVE" 2>/dev/null || shasum -a 256 "$ARCHIVE" | awk '{print $1}') ACTUAL=$(echo "$ACTUAL" | awk '{print $1}') if [ "$EXPECTED" != "$ACTUAL" ]; then echo "ERROR: Checksum mismatch!" @@ -68,13 +69,27 @@ if [ "$EXPECTED" != "$ACTUAL" ]; then fi echo "Checksum verified." -# Install -mkdir -p "$INSTALL_DIR" +# Extract BINARY="fizzy" if [ "$OS" = "windows" ]; then BINARY="fizzy.exe" fi -cp "$BINARY_NAME" "$INSTALL_DIR/${BINARY}" +if [ "$EXT" = "zip" ]; then + if command -v unzip > /dev/null; then + unzip -q "$ARCHIVE" "$BINARY" + elif tar -xf "$ARCHIVE" "$BINARY" 2>/dev/null && [ -f "$BINARY" ]; then + : # bsdtar (Windows 10+ tar.exe) reads zip archives + else + echo "ERROR: Could not extract $ARCHIVE — install unzip and re-run" + exit 1 + fi +else + tar -xzf "$ARCHIVE" "$BINARY" +fi + +# Install +mkdir -p "$INSTALL_DIR" +cp "$BINARY" "$INSTALL_DIR/${BINARY}" chmod +x "$INSTALL_DIR/${BINARY}" echo "" diff --git a/scripts/publish-aur.sh b/scripts/publish-aur.sh index 0fa726e5..b1fbb8f4 100755 --- a/scripts/publish-aur.sh +++ b/scripts/publish-aur.sh @@ -8,6 +8,11 @@ if [ -z "${GITHUB_REF_NAME:-}" ]; then echo "ERROR: GITHUB_REF_NAME is not set (must run from GitHub Actions release workflow)" exit 1 fi +if [ -z "${AUR_KEY:-}" ]; then + echo "ERROR: AUR_KEY is not set." \ + "Store it with: gh secret set AUR_KEY --env release -R basecamp/fizzy-cli < keyfile" + exit 1 +fi VERSION="${GITHUB_REF_NAME#v}" REPO="basecamp/fizzy-cli" @@ -86,8 +91,13 @@ EOF # Clone AUR repo and push mkdir -p ~/.ssh -echo "$AUR_KEY" > ~/.ssh/aur +printf '%s\n' "$AUR_KEY" | tr -d '\r' > ~/.ssh/aur chmod 600 ~/.ssh/aur +if ! ssh-keygen -y -f ~/.ssh/aur < /dev/null > /dev/null; then + echo "ERROR: AUR_KEY is not a valid unencrypted SSH private key." \ + "Re-store it with newlines intact: gh secret set AUR_KEY --env release -R basecamp/fizzy-cli < keyfile" + exit 1 +fi cat >> ~/.ssh/config << SSHEOF Host aur.archlinux.org IdentityFile ~/.ssh/aur