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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ jobs:
- uses: actions/checkout@v7
- run: zsh -n scripts/install.sh
- run: test -x scripts/install.sh
- run: zsh -n scripts/build-release.sh
- run: test -x scripts/build-release.sh
70 changes: 70 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
release:
runs-on: macos-14
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.14"

- name: Verify tag and version
shell: bash
run: |
set -euo pipefail
version="$(cat VERSION)"
test "$GITHUB_REF_NAME" = "v$version"
PYTHONPATH=src python -c 'import agent_switch; print(agent_switch.__version__)'

- name: Run release tests
run: |
PYTHONPATH=src python -m unittest discover -s tests -v
PYTHONPATH=src python -m unittest discover -s tests/integration -v

- name: Build release artifacts
run: |
python -m pip install --upgrade build
python -m build --sdist --outdir dist
./scripts/build-release.sh dist
cd dist
shasum -a 256 "agent_switch-$(cat ../VERSION).tar.gz" \
> "agent_switch-$(cat ../VERSION).tar.gz.sha256"

- name: Create GitHub prerelease
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
set -euo pipefail
version="$(cat VERSION)"
cat > "$RUNNER_TEMP/release-notes.md" <<EOF
Agent Switch $version is an alpha release for macOS 14 and newer.

## Install

\`\`\`bash
brew tap JNHFlow21/tap && brew trust --tap JNHFlow21/tap && HOMEBREW_CASK_OPTS=--no-quarantine brew install --cask JNHFlow21/tap/agent-switch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the unsupported brew trust step

When a tag creates this prerelease, the only advertised install command stops at brew trust --tap JNHFlow21/tap, so the subsequent cask installation never runs. Homebrew documents tap as brew tap [options] [user/repo] and does not provide a trust subcommand; remove this step (or replace it with a supported quarantine-handling instruction) so the release notes are executable. Homebrew manpage

Useful? React with 👍 / 👎.

\`\`\`

This build is ad-hoc signed and not notarized because the project does
not yet have an Apple Developer ID. The install command deliberately
disables Gatekeeper quarantine for this cask installation. Review the
public source and checksums before installing.
EOF
gh release create "$GITHUB_REF_NAME" \
dist/Agent-Switch-"$version"-macos-universal.zip \
dist/Agent-Switch-"$version"-macos-universal.zip.sha256 \
dist/agent_switch-"$version".tar.gz \
dist/agent_switch-"$version".tar.gz.sha256 \
--title "Agent Switch $version" \
--notes-file "$RUNNER_TEMP/release-notes.md" \
--prerelease
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

All notable changes to Agent Switch are documented here.

## 0.2.0 - Unreleased
## 0.2.0 - 2026-07-23

### Added

Expand All @@ -14,6 +14,8 @@ All notable changes to Agent Switch are documented here.
- Native import preview showing MCP IDs and secret names before adoption.
- Credential-to-MCP consumer mapping in status and the Secret UI.
- Detected-agent-only reconciliation for clean first-run behavior.
- Reproducible universal macOS release packaging for GitHub Releases.
- Homebrew Formula and Cask distribution through the project-owned Tap.

### Security

Expand All @@ -32,6 +34,7 @@ All notable changes to Agent Switch are documented here.
source checkout when that CLI is available.
- `doctor --strict` now fails for drift or missing required credentials as well
as blocked targets.
- The public alpha is ad-hoc signed and explicitly documented as not notarized.

## 0.1.3 - 2026-07-13

Expand Down
63 changes: 63 additions & 0 deletions scripts/build-release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/bin/zsh
set -euo pipefail

ROOT="${0:A:h:h}"
VERSION="$(<"$ROOT/VERSION")"
PROJECT="$ROOT/macos-app/AgentSwitch/AgentSwitch.xcodeproj"
SCHEME="AgentSwitch"
OUTPUT_DIR="${1:-$ROOT/dist}"
DERIVED_DATA="$(mktemp -d "${TMPDIR:-/tmp}/agent-switch-release.XXXXXX")"
APP="$DERIVED_DATA/Build/Products/Release/Agent Switch.app"
ARCHIVE="$OUTPUT_DIR/Agent-Switch-$VERSION-macos-universal.zip"

cleanup() {
rm -rf "$DERIVED_DATA"
}
trap cleanup EXIT

fail() {
print -u2 "Agent Switch release build failed: $*"
exit 1
}

[[ "$(uname -s)" == "Darwin" ]] || fail "macOS is required."
for command in xcodebuild codesign ditto lipo shasum; do
command -v "$command" >/dev/null 2>&1 || fail "$command is required."
done

mkdir -p "$OUTPUT_DIR"
rm -f "$ARCHIVE" "$ARCHIVE.sha256"

xcodebuild \
-project "$PROJECT" \
-scheme "$SCHEME" \
-configuration Release \
-destination "generic/platform=macOS" \
-derivedDataPath "$DERIVED_DATA" \
-quiet \
ARCHS="arm64 x86_64" \
ONLY_ACTIVE_ARCH=NO \
CODE_SIGNING_ALLOWED=NO \
build

[[ -d "$APP" ]] || fail "Xcode did not produce $APP"

APP_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$APP/Contents/Info.plist")"
[[ "$APP_VERSION" == "$VERSION" ]] || fail "App version $APP_VERSION does not match VERSION $VERSION."

ARCHS="$(lipo -archs "$APP/Contents/MacOS/Agent Switch")"
[[ " $ARCHS " == *" arm64 "* ]] || fail "Release is missing arm64."
[[ " $ARCHS " == *" x86_64 "* ]] || fail "Release is missing x86_64."

# The public alpha is intentionally ad-hoc signed until a Developer ID is
# available. Homebrew installation documents the resulting Gatekeeper tradeoff.
xattr -cr "$APP"
codesign --force --sign - --options runtime --timestamp=none "$APP"
codesign --verify --deep --strict --verbose=2 "$APP"

ditto -c -k --sequesterRsrc --keepParent "$APP" "$ARCHIVE"
(cd "$OUTPUT_DIR" && shasum -a 256 "${ARCHIVE:t}" > "${ARCHIVE:t}.sha256")

print "Built $ARCHIVE"
print "Architectures: $ARCHS"
print "Signing: ad-hoc (not notarized)"