Skip to content

Phase 7: Review distribution strategy (Homebrew tap + cask)#7

Merged
rubenlr merged 159 commits into
masterfrom
feat/06-cli-parity
Jun 9, 2026
Merged

Phase 7: Review distribution strategy (Homebrew tap + cask)#7
rubenlr merged 159 commits into
masterfrom
feat/06-cli-parity

Conversation

@rubenlr

@rubenlr rubenlr commented Jun 4, 2026

Copy link
Copy Markdown
Owner

Summary

Phase 7: Review distribution strategy (Homebrew tap + cask)

Goal: Pivot v1 distribution away from signed DMG / split install paths to a Homebrew tap with cask that ships one package — CLI (workpot) and tray app together — so brew install and brew uninstall add or remove both surfaces atomically.

Status: Verified ✓ (YAML frontmatter status: passed; 17/21 automated must-haves; 4 external/human confirmations documented)

Workpot now distributes via brew tap rubenlr/workpot + brew install workpot. The workpot update subcommand and install.sh path are removed. CI builds Workpot-<version>-aarch64.tar.gz (app + CLI), drops DMG/Apple signing jobs, and auto-patches the Homebrew cask on each release via HOMEBREW_TAP_TOKEN. Decision record docs/distribution-strategy.md captures D-01–D-15; reference cask lives in-repo and the live tap is at github.com/rubenlr/homebrew-workpot.

Branch scope: feat/06-cli-parity is 132 commits ahead of master (last merged: phase 5, #4). This PR includes Phases 6 (CLI parity), 6.2 (tray UX polish), and 7 (distribution) — not phase 7 in isolation. Retitle or split if you intended a phase-7-only PR.

Changes

Plan 07-01: Remove update subcommand and DMG target

Deleted workpot update CLI subcommand and HTTP/checksum deps; Tauri bundle.targets is ["app"] only.

Key files:

  • Modified: crates/workpot-cli/src/main.rs, crates/workpot-cli/Cargo.toml, src-tauri/tauri.conf.json
  • Deleted: crates/workpot-cli/src/update.rs, crates/workpot-cli/tests/update_smoke.rs

Plan 07-02: CI bundle job, DMG removal, tap-update

Replaced binary+dmg jobs with combined bundle tarball + tap-update job; smoke workflow asserts new artifact contract.

Key files:

  • Modified: .github/workflows/release.yml, .github/workflows/release-smoke.yml, .github/workflows/release-artifacts.yml

Plan 07-03: Documentation cleanup and distribution strategy record

Deleted install scripts; INSTALL.md Homebrew-only; docs/distribution-strategy.md and updated docs/releasing.md.

Key files:

  • Created: docs/distribution-strategy.md
  • Modified: INSTALL.md, docs/releasing.md
  • Deleted: scripts/install.sh, scripts/tests/install_smoke.sh

Plan 07-04: Homebrew tap cask files

Cask with app+binary+postflight+zap; live tap verified (brew tap rubenlr/workpot).

Key files:

  • Created: docs/homebrew-tap-files/Casks/workpot.rb, docs/homebrew-tap-files/README.md

Requirements Addressed

Phase 7 uses distribution decisions D-01–D-15 from 07-CONTEXT.md (not REQUIREMENTS.md product IDs):

ID Topic
D-01 Tap repo rubenlr/homebrew-workpot
D-02 No signed/notarized DMG for v1
D-03 Cask auto-updated on CI release
D-04 Homebrew-only install docs
D-05 Cask (not formula) for app + CLI
D-06 binary stanza uses #{appdir}
D-07 Combined aarch64 tarball artifact
D-08 No Apple signing secrets in CI
D-09 SHA256 from published release asset
D-10 postflight quarantine xattr
D-11 No install.sh
D-12 No workpot update (use brew upgrade)
D-13 Smoke contract matches tarball
D-14 Tauri bundle app-only
D-15 Strategy doc in repo

Verification

  • Automated verification: passed (07-VERIFICATION.md — 17/21 truths verified in codebase)
  • UAT auto: 12/13 pass, 1 skip (brew install post-release) per 07-UAT.md
  • Human: brew tap rubenlr/workpot on fresh macOS
  • Human: HOMEBREW_TAP_TOKEN in repo Actions secrets
  • Human: github.com/rubenlr/homebrew-workpot public with expected Casks/workpot.rb
  • Human: cargo build -p workpot-cli clean (strong SUMMARY/test evidence; optional re-run)

Key Decisions

  • D-12: Users upgrade via brew upgrade, not workpot update
  • D-14: Tauri produces .app only; DMG path removed
  • D-08: No APPLE_* signing secrets in release workflow
  • D-09: Tap SHA256 patched from published GitHub Release download (not CI cache)
  • D-11: install.sh deleted with no deprecation period
  • Phase 7 UAT (2026-06-04): distribution contract tests 11/11; tap repo + token verified via gh

User Stories & Acceptance Criteria

  • Acceptance criteria are covered by the linked requirements and verification evidence.

rubenlr and others added 30 commits May 31, 2026 16:51
…_ordered_repos

- Port sectionSort + flatSectioned from src/lib/sort.ts into Rust
- Implement SectionedRepos { pinned, dirty, recent, rest } with four-tier ordering
- Honor D-20 (dirty beats recent), D-21 (null last_opened_at → rest), D-22 (min_recent_count padding)
- Export section_sort, flat_tray_ordered, flat_tray_ordered_repos from lib.rs public API
…r cases

- 11 tests covering pinned, dirty, recent window, min_recent_count padding, rest alphabetical, pin_order
- Explicit D-20 (dirty beats recent) and D-22 (padding floor) test cases
- D-21 (never-opened → rest, not padding candidate) tested twice
- No #[ignore] on any test; all 11 pass
…ector tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Implement fuzzy_score and fuzzy_match for RepoRecord
- Port subsequenceMatch, scoreField algorithm from src/lib/fuzzy.ts
- MAX_QUERY_LEN=256 DoS guard (T-06-02-01)
- Score fields: name (name bonus), path, branch, notes, each tag
- None branch/notes handled safely; empty/whitespace query → score 1
- Export from services/mod.rs; 11 unit tests green
- Port all 11 it() cases from src/lib/fuzzy.test.ts as named tests
- Add fuzzy_golden_vectors module with table-driven (query, repo, expected_match) rows
- Cover: name subsequence, branch, path, notes, tag, empty query, whitespace, overlong, no-match, case-insensitive, None fields
- Prove CLI-03 fuzzy parity: fuzzy_match matches TS expected booleans; score>0 iff match
- 13 tests in repo_fuzzy_test.rs, 0 ignored (SC#2 automated proof)
…rs green

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add priority_icon, shorten_parent_dir, format_list_row functions
- Add flat_tray_ordered_with_icons for Pinned>Dirty>Recent>Rest ordering
- Mirror TypeScript sectionSort algorithm from src/lib/sort.ts in Rust
- Unit tests: shorten_parent_dir, format_list_row snapshot, ordering
- Add Commands::List variant (top-level, not under repo subcommand)
- Implement run_list handler using flat_tray_ordered_with_icons
- Keep workpot repo list unchanged (legacy format preserved)
- Add cli_smoke tests: empty index exits 0, registered repo shows icon
- 2/2 tasks complete: list_display formatter + Commands::List handler
- 43 tests pass (19 unit + 24 integration)
- CLI-01 satisfied: workpot list shows priority-ordered repos with emoji icons
- Add shell-words dependency to workpot-core Cargo.toml
- Create crates/workpot-core/src/services/launch.rs with build_command,
  resolve_launch_program, launch_repo (+ inline unit tests)
- Export launch module in services/mod.rs
- Replace src-tauri/src/launch.rs body with pub use re-export from core
- All existing tray launch tests pass; core launch unit tests pass
- Add Open { repo } variant to top-level Commands enum (D-08)
- Implement run_open: resolve -> print "opening: <path>" -> launch_repo
  (D-10 success message, exit 0)
- Update resolve_repo_identifier: ambiguous prints numbered paths and
  "use the full path from 'workpot list'" (D-09), exit 1
- D-11: no match prints "repo not found: <identifier>", exit 1
- Launch spawn failure exits 2 (distinguishes from "not found" exit 1)
- Import workpot_core::services::launch::launch_repo (CLI-03 parity)
- Add 4 cli_smoke tests: exit 0 + opening prefix, name resolution,
  not-found exit 1, ambiguous exit 1 with numbered paths
…order

- Add Search { query } variant to Commands enum
- run_search: fuzzy_match filter -> flat_tray_ordered_with_icons -> format_list_row
- Empty/whitespace query retains all repos (matches workpot list output)
- No #tag parsing per D-07; documented in command doc comment
- Import workpot_core::services::repo_fuzzy::fuzzy_match
- search_filters_by_fuzzy_query: alpha+beta repos; search alpha → contains alpha, not beta
- search_empty_query_equals_list: workpot search '' output equals workpot list
- named_git_fixture helper for named repo directories (vs sample-repo default)
- SC#2 satisfied: fuzzy_golden vectors green + search smoke tests
- 30/30 workpot-cli tests pass
DoS guard used byte length; multi-byte queries were rejected early.

Co-authored-by: Cursor <cursoragent@cursor.com>
Removes duplicated section_sort so tray and CLI share one ordering path.

Co-authored-by: Cursor <cursoragent@cursor.com>
Bare cursor resolution no longer checks a dead branch; spawned IDE
processes are waited in a background thread to avoid zombies.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replaces inline exit() in run_open with LaunchFailed for testable flow.

Co-authored-by: Cursor <cursoragent@cursor.com>
rubenlr and others added 24 commits June 4, 2026 22:17
Co-authored-by: Cursor <cursoragent@cursor.com>
…ns and add test job

- Enhanced the `precommit` command in `CONTRIBUTING.md` to clarify build and formatting steps.
- Added a new `test` job in the `justfile` for running tests and coverage checks.
- Updated `DetailPane.svelte` to set `autocorrect` attribute on the textarea for better browser compatibility.
…leanup

- Added `eslint-plugin-unused-imports` to the project for detecting and removing unused imports.
- Updated `eslint.config.js` to include new rules for handling unused variables and imports.
- Enhanced the `justfile` to run `cargo fix` alongside existing formatting and linting commands.
- Improved the `CONTRIBUTING.md` to reflect changes in linting commands.
- Introduced new tests for the tray components and refactored existing tests to utilize a common git command function.
- Modified the GitHub Actions release workflow to use the workspace-root target directory for macOS builds.
- Added comprehensive tests for CLI command parsing in `workpot-cli`, ensuring correct handling of subcommands and repository operations.
- Improved assertions in existing tests to validate expected outcomes more effectively.
- Removed unused test file `trayLaunch.test.ts` to streamline the test suite.
…; enhance trayList tests with flatSectioned functionality
- Changed the SonarCloud GitHub Action from `SonarSource/sonarcloud-github-action@v5` to `SonarSource/sonarqube-scan-action@v8` for improved scanning capabilities.
- Added a new script `coverage-exclusions.mjs` to manage non-testable frontend files excluded from Vitest and Sonar coverage metrics.
- Updated `vite.config.ts` to include additional exclusions for test files.
- Modified `sonar-project.properties` to synchronize coverage exclusions with the new script and added more specific exclusions for Storybook and other non-testable files.
- Added tests for resolving repository aliases and handling ambiguous aliases in `workpot-cli`.
- Implemented tests to verify limits on adding watch roots and error handling for non-existent paths and files in `workpot-core`.
- Introduced new tests for Git operations, ensuring correct reporting of branch status and dirty worktree detection.
- Added unit tests for the `computeBackgroundOpenSelection` function in the tray module.
- Introduced a new test file `app_context_facade_test.rs` to validate various functionalities of the `AppContext` class, including version retrieval, database path access, and Git state refresh and persistence.
- Added tests to ensure correct handling of repository registration, tag management, and default path resolution under the home directory.
- Enhanced existing tests in `roots_test.rs` to verify rollback behavior when configuration save and pruning operations fail in read-only directories.
- Added an alias for the formatting command in the justfile to simplify usage.
- Updated the `discovery_test.rs` to initialize bare repositories with a main branch and added a function to seed bare repositories with an initial commit, preventing warnings during cloning.
- Introduced a new utility function in `common/mod.rs` to facilitate seeding of bare repositories with necessary configurations and an initial commit.
- Added multiple tests for keyboard navigation in the tray component, including handling of Escape, ArrowUp, ArrowDown, and ArrowRight keys.
- Verified that pressing Escape closes the detail panel and hides the tray, while Arrow keys correctly move the selection and open details for the selected repository.
- Enhanced the `onPanelKeydown` method tests in `trayPanelKeyboard.svelte.test.ts` to ensure proper behavior when interacting with the panel and input fields.
- Removed `package-lock.json` and added `pnpm-lock.yaml` to switch package management to pnpm.
- Introduced `pnpm-workspace.yaml` to configure workspace settings.
- Updated CI ruleset by removing the requirement for an approving review count on pull requests.
- Changed the CI action description to reflect the use of pnpm instead of npm.
- Updated the action steps to include pnpm setup and modified caching to use pnpm-lock.yaml.
- Replaced `npm ci` with `pnpm install --frozen-lockfile` for consistent package management.
@rubenlr rubenlr force-pushed the feat/06-cli-parity branch from 96930f0 to 2d7e516 Compare June 9, 2026 15:23
rubenlr added 3 commits June 9, 2026 19:50
- Updated all references from npm to pnpm in the contributing guidelines, justfile, and CI workflows for consistency.
- Replaced npm commands with their pnpm equivalents to ensure a unified development experience.
- Added a new GitHub action for pnpm installation to streamline dependency management in CI.
- Updated all references from npm to pnpm in the contributing guidelines, justfile, and CI workflows for consistency.
- Replaced npm commands with their pnpm equivalents to ensure a unified development experience.
- Added a new GitHub action for pnpm installation to streamline dependency management in CI.
@rubenlr rubenlr merged commit 25b2dc7 into master Jun 9, 2026
13 checks passed
@rubenlr rubenlr deleted the feat/06-cli-parity branch June 9, 2026 17:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant