27 Commits
Author SHA1 Message Date
ZhaoYiFei b40995a232 Polish read-only services for review 2026-10-03 19:34:21 +08:00
ZhaoYiFei af6d8a8fcf Stabilise read-only services and UI tests 2026-09-23 15:04:07 +08:00
Graeme ArthurandClaude Opus 5 498fdd9f77 Add scripts/localize catalog sync
Xcode updates the String Catalogs after an IDE build, but xcodebuild
only emits the compiler's .stringsdata. scripts/localize sync builds
the app and runs `xcrun xcstringstool sync` over that data so the
catalogs can be kept current (and checked in CI) from the command line.
verify keeps catalogs in UI targets and rejects empty translations,
which render blank rather than falling back to English; status
summarises per-language progress.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 22:03:22 +10:00
Mike McQuaid 08afc260de Consolidate documentation and agent guidance
- Keep the project overview and development setup in `README.md`.
- Put system design in `ARCHITECTURE.md` and detailed contributor and
  agent guidance in `AGENTS.md`; symlink `CLAUDE.md` to that source.
- Remove duplicate rules, memory files and unused Jekyll tooling.
2026-09-17 08:51:47 +01:00
SurefireStudios 57f862f83c Fix the remaining stale Brew paths in lint, CI and docs
`.swiftlint.yml` had `included: Brew`, so `swiftlint lint --strict` skipped
the app targets entirely; it now lists `Homebrew` and `HomebrewUpgradeHelper`.

`pr_build_test.yml` filtered on `Brew/**` and `Brew.entitlements`, so an
app-only change could skip Build and Test. No entitlements file exists
anywhere in the tree, so that entry is dropped rather than repointed.

BrewUILint's glob reached `Homebrew` but not `HomebrewUpgradeHelper`, leaving
2 files unlinted; CI, `scripts/pre-commit` and AGENTS.md now agree on
`find Homebrew HomebrewUpgradeHelper Sources`.

CONVENTIONS.md and two Cursor rules pointed at `Brew/Models/HomebrewPackageReference.swift`
and `Brew/PreviewSupport/AppPreviewSupport.swift`, neither of which exists under
any prefix; they now point at `Sources/BrewCore/Models/HomebrewPackageID.swift`
and `Sources/BrewRepositoryInterfaces/PreviewSupport/PreviewSupport.swift`.
2026-09-16 08:51:20 -07:00
Graeme Arthur 363dd1c312 Run the live canaries on every pull request
Nightly cron only fires on the default branch, so the suite would have
gone unrun until after it merged, and the first real evidence it works
would have arrived on main. Moving it to pull_request means it is exercised
where it can still be fixed.

It stays a separate job rather than joining the deterministic suite's:
Brew-UI still skips these tests by name, so a live failure reads as a
live failure and never as a broken fixture-backed test. Concurrency now
keys on the pull request, since queueing every PR behind one run only made
sense while the group modelled a single shared machine.

The workflow file loses its `_nightly` name, and the docs that promised a
nightly schedule now say what actually happens.
2026-09-06 15:33:27 +10:00
Graeme Arthur 81bde36a2a Show what a flaky live canary looked like
Two gaps in a suite that retries. A failure's message says an element was
missing; it cannot say whether a dialog was covering the app, which is how
the last one actually failed. And a retry that turns red into green leaves
a run that reads as clean.

BrewUITestCase now attaches a screenshot of the whole screen to every
issue it records, so the picture lands in the result bundle CI uploads.
It goes in as PNG data rather than as the XCUIScreenshot, which cannot
cross out of the main actor into this nonisolated override. Both the
attachment and the plan keep screenshots always: the interesting one
belongs to a failed attempt of a test that ultimately passed, and
deleteOnSuccess prunes exactly that.

The plan now retries a failing test twice rather than once, and
annotate-flaky-tests reads the result bundle afterwards and names any test
that needed more than one run to pass — a ::warning:: annotation on GitHub,
plain text locally, never a failure by itself. It also tells the workflow
to keep the bundle for a green-but-retried run, so the evidence the
annotation points at still exists.
2026-09-06 15:33:27 +10:00
Graeme Arthur b74b540176 Trim comments to why-notes
The live suite's comments restated what the code says and argued its own
design at length. What survives is the part a reader cannot recover: that
a login shell keeps exported variables, that a real inventory virtualizes
so an installed row may never render, that cleanup runs after the app is
terminated to stay clear of Homebrew's lock, and why the runner must be
signed. The reasoning behind the rest is in the commits and in
E2E/README.md, which is where it belongs.
2026-09-06 15:33:27 +10:00
Graeme Arthur e5d53d2ab8 Let the live suite sign its test runner
The suite could not run at all: macOS put up "BrewUITests-Runner is
damaged and can't be opened", and xcodebuild sat there until it gave up
with "The test runner hung before establishing connection." The dialog is
the cause and the hang is only the consequence — a runner Gatekeeper
refuses to start never connects.

CODE_SIGNING_ALLOWED=NO, copied here from scripts/test-ui, does not
produce an unsigned runner. BrewUITests-Runner.app is a copy of Xcode's
XCTRunner.app template, which arrives signed by Apple; the build inserts
our .xctest into its PlugIns directory and then, with signing disallowed,
skips the CodeSign step. What launches is a bundle carrying Apple's
signature over contents that no longer match it, which codesign reports
as "code has no resources but signature indicates they must be present".

Allowing signing with identity "-" ad-hoc signs the runner as
sh.brew.BrewUITests.xctrunner with a valid seal. Ad-hoc needs no identity,
team or provisioning profile, so this is not a local-only accommodation —
it works on a bare CI runner too.

scripts/test-ui and the ui-test CI job still carry the flag and the same
latent defect; TROUBLESHOOTING.md now says so, so the next person to meet
this dialog reads it rather than re-derives it.
2026-09-06 15:33:27 +10:00
Graeme Arthur bf72375fa9 Run the live canaries nightly
A canary nobody runs is a canary that reports nothing, so the suite gets a
schedule rather than only a plan: nightly on an ephemeral GitHub runner,
which ships Homebrew and has egress to formulae.brew.sh and ghcr.io, and
by hand before cutting a release — the moment you most want to know brew
has not shifted under the app. The release workflow is deliberately not
wired to it; that stays a decision someone makes.

Concurrency is keyed on the workflow rather than the ref, because two runs
would fight over one machine's brew state.

scripts/test-e2e mirrors scripts/test-ui, including its refusal to pass
-derivedDataPath, and leads with what it does to the machine it runs on:
this one installs and uninstalls a formula, and the script is the last
place that fact can be read before it happens.
2026-09-06 15:31:51 +10:00
Graeme ArthurandClaude Opus 5 7a42a5a529 Run the UI suite locally and in CI
scripts/test-ui mirrors what CI runs, so green locally means green on CI.
It deliberately does not override -derivedDataPath: a project-relative
DerivedData location reproducibly makes the test runner hang for around
five minutes before failing to establish a connection, where the identical
run against the default location passes in seconds.

The ui-test CI job runs alongside the unit job with no needs: dependency,
so UI coverage costs wall-clock time on a separate runner rather than
sitting on the critical path.

It replaces ui_smoke.yml, which triggered on the same pull_request event
and ran the same Brew-UI scheme, so keeping both would run every test
twice. Its inline signing block is gone with it: the default path was the
ad-hoc signing scripts/test-ui already does, and keeping the logic in the
script is what keeps a local run honest about CI.

TROUBLESHOOTING.md covers the things that make a local run fail for
reasons unrelated to the code, since the suite drives real windows and
real input.

Also ignores the artefacts a UI run leaves behind: coverage drops .profraw
wherever an instrumented binary runs, and the script writes a result bundle
at the repository root.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 22:10:22 +10:00
Graeme Arthur 37dbfcdf80 Add the manual patch/minor/major release workflow 2026-07-15 22:57:36 +10:00
Graeme Arthur 003d9a9f43 Derive the app version and build number from git 2026-07-15 22:55:37 +10:00
Graeme ArthurandClaude Opus 4.8 301fbde6f4 Derive app version from git and stamp it at build time
Marketing version and build number are now derived from git rather than checked
in: derive-version maps the nearest v* tag + distance to a semver (distance 0 =>
the tag; past a tag on main => minor+1; on release/* => patch+1), and
derive-build-number is the commit count. A "Stamp app version" Xcode build phase
runs stamp-app-version on every build — local and CI — patching
CFBundleShortVersionString / CFBundleVersion into the built app's Info.plist
before signing, so a local debug build shows the real git version too.

Requires ENABLE_USER_SCRIPT_SANDBOXING = NO (the phase shells out to git).
Version.xcconfig keeps only inert placeholders to seed GENERATE_INFOPLIST_FILE
before the phase overwrites them. Validated with a real Debug build: the app
came out stamped 0.2.0 (build 706).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 17:09:00 +10:00
Graeme ArthurandClaude Opus 4.8 a30cf555ec Bundle Homebrew.pkg as a sub-package instead of a postinstall script
The postinstall script installed Homebrew by curling install.sh at
install time: it needs network access during installation, runs as the
console user via su, and fails silently on headless/MDM installs.

Instead, download the official Homebrew.pkg and ship it as a nested
sub-package in the distribution: productbuild --synthesize builds a
distribution that installs Homebrew first, then Brew.app. This drops the
--scripts postinstall from pkgbuild and deletes scripts/postinstall.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 22:53:00 +10:00
Graeme ArthurandClaude Opus 4.8 e0891c96e2 Fix pre-commit hook path after Brew -> Homebrew folder rename
The BrewUILint step scanned 'Brew/', which no longer exists after the
source folder was renamed to 'Homebrew/', so the hook errored on every
commit. Point the whole-tree scan at 'Homebrew/'.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 20:49:14 +10:00
Graeme ArthurandClaude Opus 4.8 2fcdcb2ea4 Rename app to Homebrew
Rename the Xcode app target, product, and project from Brew to Homebrew:
- Brew.xcodeproj -> Homebrew.xcodeproj, and fix the file-system-
  synchronized group path (Brew -> Homebrew) so the app target picks
  up its sources again
- Source folder Brew/ -> Homebrew/
- Update schemes, test plans, CI workflows, README, and bootstrap script
- PRODUCT_BUNDLE_IDENTIFIER and pkgbuild identifier -> sh.brew.app

The package and repository names are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 20:49:14 +10:00
Graeme Arthur da03b3ad0a Add test script 2026-06-18 22:52:43 +10:00
Graeme ArthurandClaude Opus 4.7 dbe65cfb90 Restore whole-tree BrewUILint coverage after modularisation
BrewUILint only scanned Brew/ (now the thin app shell), so its rules — notably
NonisolatedExtensionRule, which guards the cross-package MainActor-default
extension trap the split made possible — no longer reached Sources/. Point CI
(and the AGENTS.md parity command) at `find Brew Sources`, and add a pre-commit
step that builds + runs BrewUILint over the whole tree on every commit (it must
see all files in one pass so the rule knows every `nonisolated` type). Tests/
stay excluded. Also annotate two fixture extensions on BrewCore types
`nonisolated` per that rule.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 16:27:55 +10:00
Graeme ArthurandCursor e4916c128f Integrate BrewUILint into Swift quality CI.
Run the custom linter on Brew sources in swift_quality, document local parity in AGENTS.md, align package identity cursor guidance, and fix pre-commit when no files are partially staged.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-23 16:24:40 +10:00
Graeme Arthur d4ae1dc706 Update git hooks to allow selective staging 2026-05-21 20:21:44 +10:00
Graeme Arthur c80803b4d9 Migrate linter package management to Mint 2026-04-12 22:27:28 +10:00
Graeme Arthur 0dc8b394a6 Rename BrewUI targets to Brew for naming clarity 2026-03-26 18:50:53 +11:00
Graeme Arthur c277061c7e Xcode to use xcconfig for local development 2026-03-26 18:50:53 +11:00
Graeme Arthur 877e465ec2 Add pre-commit hook + linter/formatter config 2026-03-26 18:50:53 +11:00
Graeme Arthur 8e1a665d8d Create bootstrap script 2026-03-26 18:50:53 +11:00
Graeme Arthur 5bb849316a Create release workflow 2026-03-26 18:50:53 +11:00