Skip to content

Add Homebrew cask and document brew install - #284

Open
ChaoticQubit wants to merge 5 commits into
zachlatta:mainfrom
ChaoticQubit:add-homebrew-cask
Open

Add Homebrew cask and document brew install#284
ChaoticQubit wants to merge 5 commits into
zachlatta:mainfrom
ChaoticQubit:add-homebrew-cask

Conversation

@ChaoticQubit

@ChaoticQubit ChaoticQubit commented Jul 27, 2026

Copy link
Copy Markdown

Closes #185

Adds Homebrew as an install option:

brew tap zachlatta/freeflow https://github.com/zachlatta/freeflow
brew install --cask freeflow

The cask points at the notarized universal DMG this repo already publishes to GitHub Releases, so nothing about the build or signing setup changes.

Commits, each independently droppable:

  1. Casks/freeflow.rb - the cask itself.
  2. Auto-bump step in release.yml - the cask pins an exact version and sha256, so without this it goes stale on the next tag and Homebrew keeps serving the previous build. Uses the contents: write permission the workflow already has. No new secrets, no new actions.
  3. README - documents the install.

Why each stanza

Stanza Reason
depends_on macos: :ventura matches -target *-apple-macosx13.0 in the Makefile
auto_updates true UpdateManager downloads and self-installs. Without this, brew upgrade and the in-app updater fight over /Applications/FreeFlow.app
uninstall quit: / login_item: menu-bar app that registers itself for launch-at-login via SMAppService.mainApp
zap trash: the four paths a release build actually writes - Application Support/FreeFlow plus the Caches, HTTPStorages and Preferences entries for com.zachlatta.freeflow
livecheck + strategy :github_latest /releases/latest returns v1.2.0 and correctly skips the dev prerelease

Verification

Cask:

  • brew fetch --cask - checksum verified against the published v1.2.0 DMG
  • brew info --cask - resolves to 1.2.0 (auto_updates), Required: macOS >= 13, FreeFlow.app (App)
  • brew install --cask --dry-run - clean
  • Tapped the repo from a local clone to confirm Homebrew discovers Casks/freeflow.rb at the repo root
  • Published DMG independently confirmed accepted / source=Notarized Developer ID and stapled

Release step, exercised by extracting the step's shell body straight out of the YAML and running it against a scratch repo:

  • main moved since the tag, Info.plist left dirty by the version-stamp step - switches and bumps correctly
  • first push rejected to simulate a concurrent release - retries and succeeds, with main's intervening commit preserved
  • resulting cask carries the right version and a sha256 matching the DMG byte for byte
  • re-run against an already-bumped cask - no-op, exits 0
  • cask file missing from main - exits 1 with an ::error:: annotation

One gap worth flagging: I could not run brew style / brew audit locally, because the Homebrew install on my machine is read-only and can't bootstrap its developer gems. The cask loads and resolves correctly through Homebrew's own DSL, and its stanza order and content follow the Cask Cookbook and existing GitHub-hosted casks, but it has not been through the official linters.

Open question

This puts the cask in this repo, so the repo doubles as a tap. That works today, but it probably isn't the end state - brew tap has to clone 34.7 MB of app source to deliver a 29-line file.

I opened #283 to discuss in-repo tap vs a dedicated homebrew-freeflow tap vs submitting to Homebrew/homebrew-cask. FreeFlow clears the homebrew-cask notability bar comfortably. The cask file is identical in all three cases, so this PR isn't wasted work either way - happy to follow up with whichever you prefer.

ChaoticQubit added 3 commits July 27, 2026 10:48
Pins the notarized universal DMG from GitHub Releases. Declares
auto_updates because FreeFlow ships its own in-app updater, and a
minimum of macOS 13 to match the -target macosx13.0 build flag.

The zap paths are the four locations a release build actually writes:
Application Support/FreeFlow, plus the Caches, HTTPStorages, and
Preferences entries for com.zachlatta.freeflow.
The cask pins an exact version and sha256, so without this it goes
stale on the next tag and brew serves the previous build.
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Homebrew cask for FreeFlow, automates pinned version and checksum updates during releases, and documents Homebrew installation alongside direct downloads.

Changes

Homebrew distribution

Layer / File(s) Summary
FreeFlow cask definition and cleanup
Casks/freeflow.rb
Defines FreeFlow metadata, installation, livecheck, macOS requirements, uninstall behavior, and zap trash cleanup paths.
Release automation and Quick Start guidance
.github/workflows/release.yml, README.md
Computes and publishes updated cask version and DMG checksum values with retries, and documents Homebrew installation alongside direct downloads.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ReleaseWorkflow
  participant GitHubMain
  participant Homebrew
  participant FreeFlowApp
  ReleaseWorkflow->>GitHubMain: update and push cask version and checksum
  Homebrew->>GitHubMain: resolve cask metadata
  Homebrew->>FreeFlowApp: download and install FreeFlow.app
Loading

Possibly related issues

  • zachlatta/freeflow#283 — Covers the Homebrew tap and release-time cask auto-bumping implemented here.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a Homebrew cask and documenting Homebrew installation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

156-173: 🩺 Stability & Availability | 🔵 Trivial

Serialize release-time pushes to main.

Two releases running concurrently can both modify the same base revision; one push will then fail, leaving the newer published release without a matching cask update. Confirm this workflow already has a non-canceling concurrency group; otherwise add one or retry after rebasing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 156 - 173, The release workflow’s
cask update block must serialize pushes to main so concurrent releases cannot
race on the same revision. Inspect the workflow-level concurrency configuration
and ensure it uses a shared release group with cancellation disabled; if that is
already present, preserve it, otherwise add the non-canceling concurrency
settings rather than changing the checkout or commit logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 157-160: Update the missing-Casks/freeflow.rb guard in the release
workflow to fail the step instead of exiting successfully when the cask file is
absent. Preserve the diagnostic message, but use a nonzero exit status so
deleted or renamed casks cannot produce a successful release.

In `@Casks/freeflow.rb`:
- Line 5: Align the release workflow’s tag validation with the cask URL’s
v-prefixed convention: update the tag handling in release.yml to accept only
tags in the v#{version} form, while preserving the existing version extraction
and release behavior.

In `@README.md`:
- Line 32: Replace the “click here” link text in the FreeFlow installation
instructions with descriptive text such as “download FreeFlow.dmg,” while
preserving the existing release URL and surrounding installation guidance.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 156-173: The release workflow’s cask update block must serialize
pushes to main so concurrent releases cannot race on the same revision. Inspect
the workflow-level concurrency configuration and ensure it uses a shared release
group with cancellation disabled; if that is already present, preserve it,
otherwise add the non-canceling concurrency settings rather than changing the
checkout or commit logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fe9af1c6-712e-4ee3-9e3c-55a680081610

📥 Commits

Reviewing files that changed from the base of the PR and between 1de2c2f and 7c87efe.

📒 Files selected for processing (3)
  • .github/workflows/release.yml
  • Casks/freeflow.rb
  • README.md

Comment thread .github/workflows/release.yml Outdated
Comment thread Casks/freeflow.rb
Comment thread README.md Outdated
@TyceHerrman

Copy link
Copy Markdown

@ChaoticQubit This appears to address #185. Would you add Closes #185 to the PR description so GitHub automatically closes the issue if this merges?

ChaoticQubit added 2 commits July 28, 2026 07:16
The version-stamp step leaves Info.plist dirty, so a plain 'git checkout
main' aborts whenever main has moved since the tag. Notarization takes
long enough to make that a realistic race, so force the switch, re-read
main on each attempt, and retry a rejected push.

Also fail rather than pass when the cask file is missing: the release is
already published by that point, so a silent skip leaves Homebrew serving
the previous build behind a green workflow.
@ChaoticQubit

Copy link
Copy Markdown
Author

Thanks both. Round-up of the review:

@TyceHerrman - good catch, added Closes #185 to the description.

CodeRabbit, silently skipped cask update - valid, fixed in 3142ad0.

Digging into it surfaced a worse bug in the same block that the guard was masking. The earlier "Stamp app version" step plutil-edits Info.plist, so the tree is dirty by the time the bump runs, and a plain git checkout main aborts whenever main has moved since the tag:

error: Your local changes to the following files would be overwritten by checkout:
	Info.plist
Aborting

Notarization takes minutes, so main moving inside that window is realistic. The step now force-switches, re-reads main on every attempt, and retries a rejected push.

CodeRabbit, serialize release-time pushes - real risk, handled by that same retry rather than a concurrency: group. A concurrency group only covers two releases overlapping; the retry also covers the more likely case of an ordinary merge landing on main while the DMG is being notarized. It's local to this step, so it doesn't change the semantics of the rest of the workflow.

CodeRabbit, tag convention mismatch - I don't think this one holds; details in the thread. Short version: the trigger is tags: ["v*.*.*"], so a non-prefixed 1.2.3 tag never starts the workflow and the described mismatch can't arise.

CodeRabbit, "click here" link text - valid, applied in a519e03.

I tested the reworked release step rather than eyeballing it: extracted the step's shell body straight out of the YAML and ran it against a scratch repo covering moved-main-with-dirty-Info.plist, a rejected first push, an idempotent re-run, and a missing cask file. Results are in the updated description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

add homebrew release

2 participants