Add read-only Homebrew services - #241
ZhaoYifei9 wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Copilot review overview
馃煛 Changes recommended
Login-setting operations can leave a loaded-but-stopped service running after the toggle.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (3)
What changed in this PR
Adds current-user Homebrew service discovery and management to BrewUI, integrated with existing repositories, command centre and console.
Changes:
- Adds service models, JSON parsing, state-preserving commands and repository handling.
- Adds searchable Services UI with status, ownership, actions, login controls and copyable paths.
- Updates navigation, accessibility IDs, deterministic fixtures, tests and documentation.
| File | Description |
|---|---|
Tests/鈥婤rewRepositoriesTests/鈥婼ervicesRepositoryTests.swift |
Repository behaviour tests |
Tests/鈥婤rewRepositoriesTests/鈥婼ervicesJSONTests.swift |
JSON mapping tests |
Tests/鈥婤rewFeatureServicesTests/鈥婼ervicesViewModelTests.swift |
View-model tests |
Tests/鈥婤rewCoreTests/鈥婼ervicesCommandTests.swift |
Command construction tests |
Tests/鈥婤rewAccessibilityIDTests/鈥婣XIDTests.swift |
Accessibility ID tests |
Sources/鈥婤rewUIComponents/鈥媀iews/鈥婣syncContentView.swift |
Independent Retry accessibility |
Sources/鈥婤rewRepositoryInterfaces/鈥婸rotocols/鈥婼ervicesRepository.swift |
Services repository contract |
Sources/鈥婤rewRepositoryInterfaces/鈥婸reviewSupport/鈥婸reviewSupport+Services.swift |
Preview service data |
Sources/鈥婤rewRepositoryInterfaces/鈥婩akes/鈥婼ervicesStub.swift |
Service test/preview stub |
Sources/鈥婤rewRepositoryInterfaces/鈥婥ommandJob.swift |
Service command presentation support |
Sources/鈥婤rewRepositories/鈥婤rewServicesRepository.swift |
Service reads and mutations |
Sources/鈥婤rewRepositories/鈥婤rewServiceJSON.swift |
Service JSON decoding |
Sources/鈥婤rewFeatureServices/鈥媀iews/鈥婼ervicesView.swift |
Service list and search UI |
Sources/鈥婤rewFeatureServices/鈥媀iews/鈥婼ervicesColumns.swift |
Services composition and layout |
Sources/鈥婤rewFeatureServices/鈥媀iews/鈥婼erviceDetailView.swift |
Service details and actions |
Sources/鈥婤rewFeatureServices/鈥媀iewModels/鈥婼ervicesViewModel.swift |
Service presentation state |
Sources/鈥婤rewFeatureServices/鈥媀iewModels/鈥婼erviceItem.swift |
Service presentation mapping |
Sources/鈥婤rewCore/鈥婳perations/鈥婤rewOperationModels.swift |
Service operation kinds |
Sources/鈥婤rewCore/鈥婳perations/鈥婤rewCommands.swift |
Service command builders |
Sources/鈥婤rewCore/鈥婱odels/鈥婤rewServiceAction.swift |
Service actions |
Sources/鈥婤rewCore/鈥婱odels/鈥婤rewService.swift |
Service domain model |
Sources/鈥婤rewAppEnvironment/鈥婾nimplementedRepositories.swift |
Default repository implementation |
Sources/鈥婤rewAppEnvironment/鈥婻epositoryEnvironment.swift |
Environment injection |
Sources/鈥婤rewAccessibilityID/鈥婣XID.swift |
Service accessibility identifiers |
README.md |
Services user documentation |
Package.swift |
Feature target and tests |
Homebrew/鈥媀iews/鈥婼idebarItem.swift |
Sidebar order and shortcuts |
Homebrew/鈥媀iews/鈥婱ainSidebarView.swift |
Services sidebar row |
Homebrew/鈥婩eatures/鈥婱ainWindow/鈥媀iews/鈥婱ainWindowView.swift |
Services navigation and refresh |
Homebrew/鈥婤rewApp.swift |
Production repository wiring |
Homebrew.xcodeproj/鈥媝roject.pbxproj |
App package dependency |
BrewUITests/鈥婽ests/鈥婼ervicesUITests.swift |
Service UI coverage |
BrewUITests/鈥婽ests/鈥婲avigationUITests.swift |
Navigation shortcut coverage |
BrewUITests/鈥婼creens/鈥婼idebar.swift |
Services navigation page object |
BrewUITests/鈥婼creens/鈥婼ervicesScreen.swift |
Services page object |
BrewUITests/鈥婬arness/鈥婩akeBrew.swift |
Stateful service fixture execution |
BrewUITests/鈥婬arness/鈥婤rewUITestScenario.swift |
Service test scenarios |
BrewUITests/鈥婩ixtures/鈥婼erviceFixtures.swift |
Service fixtures and transitions |
BrewUITests/鈥婩ixtures/鈥婼cenarioFixtures.swift |
Scenario registration |
ARCHITECTURE.md |
Services architecture documentation |
馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
7a8679c to
35b0c1f
Compare
|
This is a huge change and a feature which just really isn't a typical basic user case. Definitely not a pre 1.0 feature. Please at least make a feature request for something this large so maintainers can discuss before opening a >4000 line PR. Edit: Correction, opening a PR is fine, but please break feature like this large into more manageable chunks so it's easier to review. |
|
Had a private chat with @graeme so reopening. Thanks for the PR @ZhaoYifei9! Main issue here is just the diff is huge. Need to get this well under <1000 lines changed. Perhaps start with just making this read-only for a first version? |
|
Thanks @MikeMcQuaid for discussing this with @graeme and reopening the PR! I agree that a smaller, read-only first version is a more sensible and cautious approach. I鈥檓 happy to focus on displaying service information, leave management actions for later and bring the diff well below 1,000 lines changed. Sorry @graeme for making the initial PR so large and difficult to review. I hadn鈥檛 fully appreciated the review and maintenance burden, especially before 1.0. Thanks to both of you for the guidance! |
35b0c1f to
1d66994
Compare
There was a problem hiding this comment.
Copilot review overview
馃煛 Changes recommended
Unresolved review findings include a compilation issue, missing retry and live-canary coverage, and dropped decode diagnostics.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
1d66994 to
da00d5e
Compare
da00d5e to
c919092
Compare
c919092 to
309bd20
Compare
309bd20 to
4cdb1e8
Compare
There was a problem hiding this comment.
Copilot review overview
馃煛 Changes recommended
Three moderate review issues remain: empty paths render blank, the copied command omits --json, and the repository protocol lacks Observable.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
4cdb1e8 to
906b1d6
Compare
There was a problem hiding this comment.
Copilot review overview
馃煛 Changes recommended
Shared 鈱楻 refresh behavior must be corrected for Services and other cached surfaces.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Resolved since last review (1)
906b1d6 to
ad77414
Compare
There was a problem hiding this comment.
Copilot review overview
馃煛 Changes recommended
The ServicesRepository contract must guarantee observable state and refresh-error updates before approval.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Resolved since last review (1)
| import BrewCore | ||
|
|
||
| /// App-scoped cached source of the services known to Homebrew. | ||
| @MainActor | ||
| public protocol ServicesRepository: Sendable { |


What and why
Add a read-only Services tab as the first increment toward #240. It lists the current user's Homebrew services with All, Running and Stopped filters. The resizable detail pane shows Homebrew's status text unchanged, including
none, plus the owner, PID, exit code, login registration, schedulability and copyable configuration and log paths.The first visit reads
brew services info --all --json. The inventory remains cached when switching tabs or returning to the app. The Services Refresh button rereads services only; Command-R refreshes the window's cached surfaces, including Services. A failed refresh keeps the existing list and displays the error. Services is the second sidebar destination and the Command-1 through Command-6 shortcuts follow sidebar order. The code PR diff is 924 additions and 9 deletions.Validation
Environment: macOS 27.0 (26A428), Apple silicon, Xcode 27.0 (27A266a), Swift 6.4. Toolchain and dependency pins are unchanged.
scripts/test: passed for both Swift packages. The full deterministicscripts/test-uisuite passed 50/50 on the current code commit on the MacBook built-in display, including cross-tab Command-R refresh, cached navigation, status text, service details and window-frame restoration.SwiftFormat lint, strict SwiftLint, release BrewUILint over the production tree, string-catalog sync/check and verification: passed. Xcode 27 emitted
*-t.buildstrings data, so local Debug strings data was mirrored into the layout expected by the unchanged localisation script.Homebrew service output and its serializer were checked for the service fields.
schedulableis the service's cron or interval definition, not evidence that it is running or enabled. The UI displays an absent value as Unknown.Local UI inspection confirmed light appearance, unchanged Homebrew status text, schedulability, copy-labelled paths and the Upgrades-style Refresh control. Keyboard navigation and divider stability passed in UI tests. @ZhaoYifei9 manually checked dark appearance and listened through the Services UI with VoiceOver; no issues were found. Local
scripts/test-e2ewas not run because it installs and uninstalls a real Homebrew package; the CI live canaries passed.CI passed on code commit
af6d8a8, including Build and Test, UI tests, Swift Quality and Live E2E Canaries. Copilot review was not requested again for this documentation update.I followed the conventions and workflow, checked for duplicate PRs and kept this change focused.
I added regression coverage for bug fixes or explained why automated coverage is impractical, and reported the relevant validation above.
Screenshots
Actual captures on the same MacBook built-in display in light appearance, with matching maximised windows and no search filters. Before shows Installed from PR base
06ee742; after shows Services with All selected and Redis details from implementationaf6d8a8.AI assistance
OpenAI Codex with GPT-6 Sol implemented the read-only Services feature, drafted its tests and documentation, ran the local checks listed above and drafted this description. @ZhaoYifei9 manually verified the Services UI and reviewed the PR text.