From f6720349cf88e060d27054ea41efe6571aaa5168 Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:40:31 +0700 Subject: [PATCH 1/6] fix: create mount point before attaching DMG in installer hdiutil attach -mountpoint failed because the directory was never created, so the curl one-liner died at the mount step. mkdir -p it first. --- scripts/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/install.sh b/scripts/install.sh index ad20cc7..b70f025 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -26,6 +26,7 @@ echo "→ Downloading $URL" curl -fsSL "$URL" -o "$TMP/$DMG_NAME" echo "→ Mounting" +mkdir -p "$TMP/mnt" hdiutil attach "$TMP/$DMG_NAME" -nobrowse -quiet -mountpoint "$TMP/mnt" echo "→ Copying to /Applications" From 29049d29ac58e765c30c0a2de5789bceb23b3eab Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:40:57 +0700 Subject: [PATCH 2/6] ci: add release-please config and manifest Adopt release-please (simple release type) to own versioning: it maintains version.txt + CHANGELOG.md, tags as vX.Y.Z, and cuts GitHub releases from conventional commits. Baseline set to 2.1.0. --- .release-please-manifest.json | 3 +++ release-please-config.json | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 .release-please-manifest.json create mode 100644 release-please-config.json diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..969d3db --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "2.1.0" +} diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..ea2716e --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "include-component-in-tag": false, + "packages": { + ".": { + "release-type": "simple", + "package-name": "portbar" + } + } +} From 6eeb14b43e3ca0ec69d593b7b8351be317cdc880 Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:41:35 +0700 Subject: [PATCH 3/6] ci: build DMG and update Homebrew cask on release When release-please cuts a release, build the Release config with the release version injected, package a DMG, attach it to the GitHub release, and push the new version + sha256 to the mulhamna/homebrew-tap cask. Build runs in the same workflow (gated on releases_created) because a GITHUB_TOKEN-created release does not trigger a separate on:release workflow. Requires a TAP_TOKEN secret with repo scope on the tap. --- .github/workflows/release-please.yml | 84 ++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 .github/workflows/release-please.yml diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..f3cf718 --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,84 @@ +name: Release + +on: + push: + branches: [main] + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + name: Release PR / tag + runs-on: ubuntu-latest + outputs: + releases_created: ${{ steps.release.outputs.releases_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + config-file: release-please-config.json + manifest-file: .release-please-manifest.json + + release-build: + name: Build DMG + publish + needs: release-please + if: ${{ needs.release-please.outputs.releases_created == 'true' }} + runs-on: macos-15 + env: + TAG: ${{ needs.release-please.outputs.tag_name }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Select Xcode + run: sudo xcode-select -s /Applications/Xcode_16.app + + - name: Resolve version + id: v + run: echo "version=${TAG#v}" >> "$GITHUB_OUTPUT" + + - name: Build Release + run: | + xcodebuild \ + -project PortBar.xcodeproj \ + -scheme PortBar \ + -configuration Release \ + -destination "platform=macOS" \ + -derivedDataPath build \ + build \ + MARKETING_VERSION="${{ steps.v.outputs.version }}" \ + CURRENT_PROJECT_VERSION="${{ github.run_number }}" \ + CODE_SIGN_IDENTITY="" \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGNING_ALLOWED=NO + + - name: Package DMG + run: | + VERSION="${{ steps.v.outputs.version }}" + STAGE="$(mktemp -d)" + cp -R build/Build/Products/Release/PortBar.app "$STAGE/" + ln -s /Applications "$STAGE/Applications" + hdiutil create -volname "PortBar" -srcfolder "$STAGE" -ov -format UDZO "PortBar-$VERSION.dmg" + echo "SHA=$(shasum -a 256 "PortBar-$VERSION.dmg" | awk '{print $1}')" >> "$GITHUB_ENV" + + - name: Upload DMG to release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: gh release upload "$TAG" "PortBar-${{ steps.v.outputs.version }}.dmg" --clobber + + - name: Update Homebrew cask + env: + TAP_TOKEN: ${{ secrets.TAP_TOKEN }} + run: | + VERSION="${{ steps.v.outputs.version }}" + git clone "https://x-access-token:${TAP_TOKEN}@github.com/mulhamna/homebrew-tap" tap + cd tap + sed -i '' -E "s/version \"[^\"]+\"/version \"$VERSION\"/" Casks/portbar.rb + sed -i '' -E "s/sha256 \"[^\"]+\"/sha256 \"$SHA\"/" Casks/portbar.rb + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git commit -am "chore: portbar $VERSION" + git push From 33b648808270316e0d00f4b6a8fb4900994df44e Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:42:37 +0700 Subject: [PATCH 4/6] docs: document release-please workflow and versioning Replace the manual bump/DMG/cask instructions with the automated release-please flow (semver, injected MARKETING_VERSION, auto DMG + cask). --- CLAUDE.md | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0f23347..2f9f12d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -19,25 +19,26 @@ Steps: Only proceed to DMG/release if all steps pass. -## Versioning Rules - -Version format: `MAJOR.MINOR` (e.g. `2.1`, `3.0`) - -**When to bump MINOR** (e.g. 2.0 → 2.1): -- Bug fixes -- Small improvements to existing features (e.g. UI text, performance tweaks) -- Any source file change that goes into a release, even if trivial - -**When to bump MAJOR** (e.g. 2.x → 3.0): -- New user-facing features or capabilities -- Breaking changes to existing behavior -- Significant architectural changes - -**Rules:** -- Never ship a DMG without bumping the version — even a one-line fix must increment MINOR -- After bumping, rebuild DMG, recompute SHA256, and update `homebrew-tap/Casks/portbar.rb` -- Version is set in `PortBar.xcodeproj/project.pbxproj` → `MARKETING_VERSION` -- `CURRENT_PROJECT_VERSION` (build number) increments by 1 each release +## Versioning & Release (automated) + +Versioning is owned by **release-please** (semver `MAJOR.MINOR.PATCH`, e.g. `3.0.0`). +Do **not** hand-edit `MARKETING_VERSION` — the release build injects it from the +release tag. Version is tracked in `.release-please-manifest.json` / `version.txt`. + +**How a release happens:** +1. Land conventional commits on `main` (`feat:` → minor, `fix:` → patch, + `feat!`/`BREAKING CHANGE` → major). Use `Release-As: X.Y.Z` in a commit footer + to force a specific version. +2. `release-please` opens/updates a **release PR** (bumps version + CHANGELOG). +3. Merging that PR tags `vX.Y.Z` and cuts a GitHub Release. +4. `.github/workflows/release-please.yml` then builds the Release config + (`MARKETING_VERSION` = tag, `CURRENT_PROJECT_VERSION` = run number), packages + `PortBar-X.Y.Z.dmg`, attaches it to the release, and pushes the new version + + sha256 to the `mulhamna/homebrew-tap` cask. + +**Manual steps are gone** — no hand-built DMG, no manual sha256, no manual cask +edit. The only prerequisite is the repo secret `TAP_TOKEN` (PAT with `repo` scope +on the tap). The app is unsigned/unnotarized; users clear quarantine on install. ## What is PortBar? From de02a730084c17a59507d27e74bbebe6b004e53a Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:42:37 +0700 Subject: [PATCH 5/6] chore: release 3.0.0 Release-As: 3.0.0 From c398596faf29e69b74dd73c537a536e634a453be Mon Sep 17 00:00:00 2001 From: MULHAM Date: Wed, 8 Jul 2026 20:46:21 +0700 Subject: [PATCH 6/6] chore: ignore .claude local settings --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 66c0304..373ba35 100644 --- a/.gitignore +++ b/.gitignore @@ -63,7 +63,7 @@ fastlane/test_output # macOS .DS_Store +.claude # Build output build/ -