Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fastlane/test_output

# macOS
.DS_Store
.claude

# Build output
build/

3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "2.1.0"
}
39 changes: 20 additions & 19 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand Down
10 changes: 10 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}
1 change: 1 addition & 0 deletions scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Loading