diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7d5c1934..5d37c2ac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -144,6 +144,49 @@ jobs: files: | FreeFlow.dmg + # --- Homebrew cask --- + # The cask in Casks/ pins an exact version and checksum, so it has to be + # bumped on every release or `brew upgrade` keeps serving the old build. + # Done here rather than by hand because a manual step gets forgotten. + - name: Bump Homebrew cask + run: | + VERSION="${{ steps.version.outputs.version }}" + DMG_SHA="$(shasum -a 256 FreeFlow.dmg | cut -d ' ' -f 1)" + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + + # Retry because main can move while the DMG is being notarized, which + # takes long enough for that to be a realistic race. Each attempt + # re-reads main so the bump always lands on its current tip. --force + # is needed because the earlier version-stamp step leaves Info.plist + # dirty, which otherwise blocks the branch switch. + for attempt in 1 2 3; do + git fetch --force origin main:refs/remotes/origin/main + git checkout --force -B main origin/main + + if [ ! -f Casks/freeflow.rb ]; then + echo "::error::Casks/freeflow.rb is missing on main. Release $VERSION is published but Homebrew still serves the previous build." + exit 1 + fi + + sed -i '' -E "s|^ version \".*\"$| version \"$VERSION\"|" Casks/freeflow.rb + sed -i '' -E "s|^ sha256 \".*\"$| sha256 \"$DMG_SHA\"|" Casks/freeflow.rb + + if git diff --quiet -- Casks/freeflow.rb; then + echo "Cask already at $VERSION." + exit 0 + fi + + git commit -m "Bump Homebrew cask to $VERSION" -- Casks/freeflow.rb + git push origin main && exit 0 + + echo "Push rejected, main moved. Retrying ($attempt/3)." + done + + echo "::error::Could not push the cask bump for $VERSION after 3 attempts." + exit 1 + # --- Cleanup --- - name: Cleanup signing artifacts if: always() diff --git a/Casks/freeflow.rb b/Casks/freeflow.rb new file mode 100644 index 00000000..c5765881 --- /dev/null +++ b/Casks/freeflow.rb @@ -0,0 +1,29 @@ +cask "freeflow" do + version "1.2.0" + sha256 "f55e384d6da375e5c85d6cff40de5655dff8c1e8e14dd903a6c09703c7556da6" + + url "https://github.com/zachlatta/freeflow/releases/download/v#{version}/FreeFlow.dmg" + name "FreeFlow" + desc "Dictation app with AI transcription and context-aware cleanup" + homepage "https://github.com/zachlatta/freeflow" + + livecheck do + url :url + strategy :github_latest + end + + auto_updates true + depends_on macos: :ventura + + app "FreeFlow.app" + + uninstall quit: "com.zachlatta.freeflow", + login_item: "FreeFlow" + + zap trash: [ + "~/Library/Application Support/FreeFlow", + "~/Library/Caches/com.zachlatta.freeflow", + "~/Library/HTTPStorages/com.zachlatta.freeflow", + "~/Library/Preferences/com.zachlatta.freeflow.plist", + ] +end diff --git a/README.md b/README.md index f7d389d9..e68afa66 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,15 @@ FreeFlow is a free Mac dictation app inspired by [Wispr Flow](https://wisprflow. ## Quick Start -1. Download the app from above or [click here](https://github.com/zachlatta/freeflow/releases/latest/download/FreeFlow.dmg) +1. Install FreeFlow - [download FreeFlow.dmg](https://github.com/zachlatta/freeflow/releases/latest/download/FreeFlow.dmg), or use Homebrew: + + ```sh + brew tap zachlatta/freeflow https://github.com/zachlatta/freeflow + brew install --cask freeflow + ``` + + FreeFlow updates itself, so Homebrew leaves it alone after install. To let Homebrew handle upgrades too, run `brew upgrade --cask --greedy freeflow`. + 2. Get a free Groq API key from [groq.com](https://groq.com/) 3. Hold `Fn` to talk, or tap `Command-Fn` to start and stop dictation, and have whatever you say pasted into the current text field