diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5f5291e..0958105 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,12 +27,10 @@ jobs: - os: macos-latest target: macos build_flags: "" - package_flags: "--signing adhoc" artifact: "zig-out/package/*.dmg" - os: ubuntu-latest target: linux build_flags: "-Dplatform=linux" - package_flags: "" artifact: "zig-out/package/*.tar.gz" steps: - uses: actions/checkout@v5 @@ -55,8 +53,18 @@ jobs: run: native doctor - name: Build release binary run: native build ${{ matrix.build_flags }} - - name: Package - run: native package --target ${{ matrix.target }} ${{ matrix.package_flags }} --archive + - name: Package (Linux) + if: runner.os == 'Linux' + run: native package --target linux --archive + - name: Package (macOS) + # native package signs the space-free studio.app, then the script + # renames it to "OCPP DebugKit Studio.app" and builds the .dmg (the SDK + # can't sign a bundle path with spaces). TAG comes through the + # environment (injection-safe). + if: runner.os == 'macOS' + env: + TAG: ${{ github.ref_name }} + run: bash scripts/package-macos.sh "${TAG#v}" - name: Upload package artifact uses: actions/upload-artifact@v4 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 386f27f..36b513a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ reference are all pre-1.0, minor (0.x) releases may include breaking changes. ## [Unreleased] +### Changed + +- **macOS** — the packaged app bundle is now named `OCPP DebugKit Studio.app` + (previously `studio.app`), so its on-disk name matches its display name; the CLI + binary is unchanged (`studio`). The install docs now cover clearing the + Gatekeeper quarantine on the ad-hoc build. + ## [0.5.0] — 2026-07-12 Studio's first packaged, signed public release, assembled across milestones diff --git a/README.md b/README.md index 55656e0..a0c14bf 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,29 @@ The two share **no code**. They meet only at a *conformance contract*: the same ## Install -Download the latest release for your platform from the +Download the latest build for your platform from the [**Releases**](https://github.com/ocpp-debugkit/studio/releases) page. -- **macOS** — open the `.dmg` and drag *OCPP DebugKit Studio* to Applications. The - 0.5.0 build is **ad-hoc signed** (not yet notarized), so the first launch needs - **right-click → Open** (or *System Settings → Privacy & Security → Open Anyway*). -- **Linux** — extract the `.tar.gz` and run the `studio` binary. Requires GTK 4 - (`libgtk-4`, `libwebkitgtk-6.0`). +### macOS (Apple silicon) + +Open the `.dmg` and drag **OCPP DebugKit Studio** to Applications. The build is +**ad-hoc signed** (not notarized), so macOS quarantines the download and Gatekeeper +blocks the first launch. Clear it once with a single command: + +```sh +xattr -dr com.apple.quarantine "/Applications/OCPP DebugKit Studio.app" +``` + +Prefer not to use the Terminal? Double-click the app, and when macOS refuses, open +**System Settings → Privacy & Security** and click **Open Anyway**, then launch it +again. The ad-hoc signature is what lets the app run once unquarantined; +notarization — which would remove this step entirely — is a deliberate tradeoff +we've deferred. + +### Linux + +Extract the `.tar.gz` and run the `studio` binary. Requires GTK 4 (`libgtk-4`, +`libwebkitgtk-6.0`). Studio is pre-1.0 (0.x) while Zig, the Native SDK, and the toolkit conformance reference are all pre-1.0 — see the [roadmap](ROADMAP.md). diff --git a/RELEASING.md b/RELEASING.md index 5e31e90..8839203 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -14,10 +14,12 @@ which builds and publishes a GitHub release with two artifacts: | macOS | `studio-X.Y.Z-macos-ReleaseFast.dmg` | A `.app` bundle, **ad-hoc signed** | | Linux | `studio-X.Y.Z-linux-ReleaseFast.tar.gz` | The `studio` binary + resources | -**macOS Gatekeeper:** the ad-hoc build is not notarized, so first launch needs -**right-click → Open** (or *System Settings → Privacy & Security → Open Anyway*). -Notarization — which removes that prompt — is a post-0.5 follow-up; it needs an -Apple Developer identity and signing credentials wired into CI as secrets. +**macOS Gatekeeper:** the ad-hoc build is not notarized, so macOS quarantines the +download and blocks first launch. Users clear it once with +`xattr -dr com.apple.quarantine "/Applications/OCPP DebugKit Studio.app"` (or +*System Settings → Privacy & Security → Open Anyway*) — see the README. This is a +deliberate tradeoff; notarization, which removes the prompt, needs an Apple +Developer identity and is out of scope for now. ## Cutting a release @@ -45,9 +47,12 @@ Build a package without cutting a release (macOS): ```sh native build -native package --target macos --signing adhoc --archive -# → zig-out/package/studio.app and zig-out/package/studio--macos-ReleaseFast.dmg -open zig-out/package/studio.app # smoke-launch it +scripts/package-macos.sh 0.5.1 +# → zig-out/package/OCPP DebugKit Studio.app and zig-out/package/studio-0.5.1-macos-ReleaseFast.dmg +open "zig-out/package/OCPP DebugKit Studio.app" # smoke-launch it ``` -`native doctor --strict` gates the manifest; the release workflow runs it too. +[`scripts/package-macos.sh`](scripts/package-macos.sh) signs `studio.app`, renames +it to the display name, and builds the `.dmg` — see the script header for why the +rename can't go through `native package --output` directly. `native doctor +--strict` gates the manifest; the release workflow runs it too. diff --git a/scripts/package-macos.sh b/scripts/package-macos.sh new file mode 100755 index 0000000..d51bf95 --- /dev/null +++ b/scripts/package-macos.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# +# Package the macOS app as "OCPP DebugKit Studio.app" inside a .dmg. +# +# `native package` is run against the default bundle name `studio.app` and then +# renamed, rather than packaged straight to the display name via `--output`, +# because the SDK's codesign invocation does not quote the bundle path: a path +# with spaces splits into multiple arguments and ad-hoc signing silently fails, +# leaving an unsigned bundle (which will not launch on Apple silicon). Signing +# the space-free name and renaming afterwards keeps the seal intact — the ad-hoc +# signature covers bundle contents, not the directory name — and we build the +# .dmg ourselves so it wraps the renamed, signed bundle. +# +# Usage: scripts/package-macos.sh (run after `native build`) +set -euo pipefail + +version="${1:?usage: package-macos.sh }" +out="zig-out/package" +app="$out/OCPP DebugKit Studio.app" +dmg="$out/studio-${version}-macos-ReleaseFast.dmg" + +rm -rf "$out" +native package --target macos --signing adhoc +mv "$out/studio.app" "$app" + +# Fail loudly if the rename ever stops preserving the signature: an unsigned +# arm64 bundle would ship broken. +codesign --verify --deep --strict "$app" + +rm -f "$dmg" +hdiutil create -volname "OCPP DebugKit Studio" -srcfolder "$app" \ + -ov -format UDZO "$dmg" + +echo "packaged: $app" +echo "archive: $dmg"