Files
probo/contrib/claude/release/probo-agent.md
Ludovic Vielle d73fd02e91 Fix white frame around Probo Agent app icon
The master PNG was fully opaque, so its white corners showed as a
square frame once macOS composited the icon onto its rounded plate.
Swap in the auditor-mode artwork, which has transparent corners.

Signed-off-by: Ludovic Vielle <ludovic@probo.com>
2026-07-27 10:38:25 +02:00

234 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Release `probo-agent`
After confirming commits below, follow the
[common steps](./README.md#3-common-steps-every-track).
## Track facts
- **Tag pattern**: `probo-agent/v*`
- **Version source**: `cmd/probo-agent/VERSION` (single `X.Y.Z` line)
- **Version bump**: Edit `cmd/probo-agent/VERSION` directly
- **Changelog**: `cmd/probo-agent/CHANGELOG.md`
- **Files to stage**: `cmd/probo-agent/VERSION`, `cmd/probo-agent/CHANGELOG.md`
- **Workflow**: `.github/workflows/release-probo-agent.yaml`
- **Path filter**: `cmd/probo-agent pkg/deviceagent`
## Detect commits
```shell
git log $(git describe --tags --abbrev=0 --match='probo-agent/v*')..HEAD --oneline \
-- cmd/probo-agent pkg/deviceagent
```
If empty or non-user-facing only, do not release this track.
## Build
```shell
make bin/probo-agent
```
On macOS hosts, `make` enables CGO so the menu bar enrollment helper
is included. Windows tray support is pure Go (`CGO_ENABLED=0`). Linux
and FreeBSD builds stay pure Go (no tray).
## Notes
CI builds binaries for linux, windows, and freebsd (amd64/arm64) on
Linux runners, and builds **CGO-enabled** darwin archives plus a
signed/notarized fat `.pkg` on a macOS runner. The GitHub
Release includes those archives, `probo-agent_*_darwin.pkg`,
`install.sh`, signed checksums, SBOM, and build attestations. The agent
auto-update path downloads the matching archive plus `checksums.txt` and
verifies the cosign bundle before installing.
The menu bar / tray enrollment flow is **macOS and Windows only**.
Linux and FreeBSD use `probo-agent install --server …
--enrollment-token …` from the shell, or the curl-to-sh installer
documented below. Windows release binaries are cross-compiled from
Linux with `CGO_ENABLED=0` (tray is pure Go). macOS release binaries
and the `.pkg` are built on macOS with `CGO_ENABLED=1`.
### macOS `.pkg` (MDM / GUI install)
Release and local builds use
`cmd/probo-agent/installer/macos/build.sh` (requires macOS, a
pre-built fat binary via `lipo`, and the Swift toolchain).
**Signing is mandatory:** `CODESIGN_IDENTITY` and `APPLE_TEAM_ID`
must be set. The script compiles `Probo Agent.app` (the headless
`probo://` URL handler + privileged helper) from
`cmd/probo-agent/installer/macos/enroll-ui/`, signs nested Mach-Os
then the app bundle, optionally signs the product with
`INSTALLER_IDENTITY`, and notarizes/staples when `APPLE_ID` and
`APPLE_ID_PASSWORD` are set (password is stored into a keychain
profile; submits use `--keychain-profile` so the secret is not on
`notarytool submit` argv).
The Finder/Dock icon for `Probo Agent.app` comes from a single master
PNG, `cmd/probo-agent/installer/macos/enroll-ui/Resources/icon-original.png`
(Probo square mark). At PKG build time `build.sh` pads/resizes it with
`sips`, compiles `AppIcon.icns` with `iconutil` under the build stage
directory, and installs it into `Contents/Resources/`. `Info.plist`
sets `CFBundleIconFile` to `AppIcon`. Do not commit generated
`.icns` / iconset PNGs.
The master PNG must have the rounded-square mark pre-baked with fully
transparent corners. macOS composites legacy `.icns` icons onto a light
rounded plate, so any opaque pixel outside the rounded square renders as
a visible square frame around the mark.
There is no unsigned PKG path and no osascript elevation fallback.
Local testing of browser enrollment requires a Developer ID–signed
build. CLI enrollment without the app uses `sudo probo-agent install`.
```shell
# Local signed pkg (example)
export CODESIGN_IDENTITY="Developer ID Application: Probo Inc (TEAMID)"
export INSTALLER_IDENTITY="Developer ID Installer: Probo Inc (TEAMID)"
export APPLE_TEAM_ID="TEAMID"
GOOS=darwin GOARCH=arm64 CGO_ENABLED=1 go build -o dist/probo-agent_arm64 ./cmd/probo-agent
GOOS=darwin GOARCH=amd64 CGO_ENABLED=1 go build -o dist/probo-agent_amd64 ./cmd/probo-agent
lipo -create dist/probo-agent_arm64 dist/probo-agent_amd64 -output dist/probo-agent_universal
cmd/probo-agent/installer/macos/build.sh \
--binary dist/probo-agent_universal \
--version "$(cat cmd/probo-agent/VERSION)"
```
PKG postinstall always installs the global tray LaunchAgent, registers
`probo://`, and installs the privileged helper
(`com.probo.agent.helper`) under `/Library/PrivilegedHelperTools` as
root. The only admin authentication is the normal macOS Installer
prompt for the PKG itself. The LaunchDaemon for `probo-agent run` is
created only after enrollment (`probo-agent install`, deep link, or MDM
`/tmp/probo-agent.conf`).
Browser enrollment uses `Probo Agent.app` over XPC to the
PKG-installed helper — no SMJobBless and no admin prompt on the enroll
path. A missing or dead helper surfaces an error asking to reinstall
the package.
Manual QA checklist (macOS PKG):
1. Fresh signed PKG: Installer may ask for admin once; deep link enrolls with no further prompt.
2. Repeat deep link on an enrolled device: no prompt, immediate success.
3. After `sudo make -C cmd/probo-agent uninstall`, deep link fails with a clear “reinstall package” error (no osascript).
4. `sudo make -C cmd/probo-agent uninstall` removes daemon, tray, helper, app, and state.
5. MDM `/tmp/probo-agent.conf` postinstall still enrolls without a browser prompt.
6. Notarized PKG passes Gatekeeper; `codesign --verify --deep` succeeds on the app bundle.
7. Unsigned `build.sh` exits with an error requiring `CODESIGN_IDENTITY`.
### Apple signing secrets (GitHub)
The `build-macos` job in `release-probo-agent.yaml` expects the same
secret names as the auditor-mode release workflow. Configure these on
the probo GitHub repository (or org) before tagging a release:
| Secret | Purpose |
|--------|---------|
| `APPLE_CERTIFICATE` | Base64-encoded `.p12` (Developer ID) |
| `APPLE_CERTIFICATE_PASSWORD` | `.p12` password |
| `KEYCHAIN_PASSWORD` | Ephemeral CI keychain password |
| `CODESIGN_IDENTITY` | e.g. `Developer ID Application: Probo Inc (TEAMID)` |
| `INSTALLER_IDENTITY` | e.g. `Developer ID Installer: Probo Inc (TEAMID)` |
| `APPLE_ID` | Apple ID email for `notarytool store-credentials` |
| `APPLE_ID_PASSWORD` | App-specific password (stored into a keychain profile; not passed to `submit`) |
| `APPLE_TEAM_ID` | 10-character Team ID |
Local notarization uses the same env vars as CI:
```shell
export APPLE_ID="you@example.com"
export APPLE_ID_PASSWORD="app-specific-password"
# optional: NOTARYTOOL_KEYCHAIN_PROFILE=probo-agent-notary (default)
```
Windows enrollment is browser-driven: the console issues a
`probo://enroll?server=...&token=...` deep link handled by
`Probo Agent.app` on macOS (PKG-installed helper + XPC) or
`probo-agent enroll-url` on Windows. After install, register the protocol for the
current user with
`cmd/probo-agent/installer/windows/register-protocol.ps1` (per-user
`HKCU` handler pointing at `probo-agent.exe`). The system tray helper
(`probo-agent tray`) shows enrollment status; enrollment itself happens
in the browser.
Region labels and console URLs for the macOS installer HTML live in
`cmd/probo-agent/installer/regions.json`. A Go test keeps US/EU URLs in
sync with `pkg/deviceagent/server_url.go`.
## Install script
`cmd/probo-agent/installer/install.sh` is published as `install.sh` on each
`probo-agent/v*` GitHub Release. It supports Darwin, Linux, and FreeBSD.
Each published `install.sh` pins one release: the release workflow injects
the tag and archive SHA-256 checksums into the script before upload.
```shell
# Interactive — curl install.sh from the target release
curl -fsSL "https://github.com/getprobo/probo/releases/download/probo-agent/vX.Y.Z/install.sh" | sudo sh
# Unattended / MDM
curl -fsSL "…/install.sh" | sudo \
PROBO_SERVER_URL=https://us.probo.com \
PROBO_ENROLLMENT_TOKEN='…' sh
# Mirror release assets (PROBO_AGENT_RELEASE_BASE must end with the embedded tag)
PROBO_AGENT_RELEASE_BASE="https://mirror.example/probo-agent/vX.Y.Z" \
curl -fsSL "…/install.sh" | sudo sh
```
The script downloads only the matching platform archive and verifies its
SHA-256 against checksums embedded in `install.sh` at release time. This
anchors trust to the script the user already obtained, rather than a
co-downloaded `checksums.txt`. Post-install upgrades still use cosign
bundle verification via the agent auto-update path.
The script installs the binary to `/usr/local/bin/probo-agent`, then runs
`probo-agent install` to enroll and start the OS service. Agent state defaults
to `/var/lib/probo-agent` (override with `--dir` or `PROBO_AGENT_STATE_DIR`).
Environment variables:
| Variable | Purpose |
|----------|---------|
| `PROBO_AGENT_RELEASE_BASE` | Override release download base URL (must match embedded tag) |
| `PROBO_AGENT_RELEASE_TAG` | Override embedded release tag (local dev) |
| `PROBO_AGENT_SKIP_CHECKSUM_VERIFY` | Skip SHA-256 verification (local dev only) |
| `PROBO_AGENT_STATE_DIR` | Agent state directory (`--dir`; default `/var/lib/probo-agent`) |
| `PROBO_SERVER_URL` | Probo server base URL (skip interactive prompt) |
| `PROBO_ENROLLMENT_TOKEN` | One-shot enrollment token (skip interactive prompt) |
| `PROBO_NO_AUTO_UPDATE` | Set to `true` to pass `--no-auto-update` |
Never pass the enrollment token in the curl URL.
## Local install (macOS PKG)
Primary loop for testing browser enrollment (app + privileged helper):
```shell
export CODESIGN_IDENTITY="Developer ID Application: … (TEAMID)"
export INSTALLER_IDENTITY="Developer ID Installer: … (TEAMID)" # optional
export APPLE_TEAM_ID="TEAMID"
make -C cmd/probo-agent install # uninstall leftovers → build PKG → installer
make -C cmd/probo-agent uninstall # full system teardown (idempotent)
make -C cmd/probo-agent clean # uninstall + wipe dist/ caches / enroll-ui/.build
```
`install` always runs `uninstall` first so previous helpers, apps, and
Launch Services registrations cannot shadow the new build. Signing env
vars are required for `pkg` / `install` on Darwin.
### CLI-only install (no app / helper)
Binary-only path via `installer/install.sh` (any Unix). State under
`~/.local/share/probo-agent-dev`; staging under `~/.cache/probo-agent-dev`.
```shell
make -C cmd/probo-agent install-cli \
PROBO_SERVER_URL=https://us.probo.com \
PROBO_ENROLLMENT_TOKEN='…'
make -C cmd/probo-agent run
```