From fde480d506377a0bdbdc50e2397b0893350801b9 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Sat, 2 May 2026 10:49:05 +1000 Subject: [PATCH] Document inputs, outputs, and usage Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1203506..453d50a 100644 --- a/README.md +++ b/README.md @@ -1 +1,130 @@ -Wails Release Action +# Wails Release Action + +Build, sign, notarize, and (optionally) upload a [Wails](https://wails.io/) macOS app from a Forgejo Actions workflow on a self-hosted macOS runner. + +The action produces a notarized, stapled `-.app.zip` and exposes its local path and (if uploaded) its `s3://` URL as outputs. + +## Requirements + +- A self-hosted **macOS** runner. +- `go` on `PATH` (Wails requires it). +- Network access to Apple's notary service and (if uploading) your S3 endpoint. + +## Quick start + +```yaml +name: Release + +on: + push: + tags: ['v*'] + +jobs: + release: + runs-on: macos + steps: + - uses: actions/checkout@v4 + + - uses: leonmika/wails-release@v1 + with: + developer-id-cert-base64: ${{ secrets.MAC_DEVELOPER_ID_CERT_BASE64 }} + developer-id-cert-password: ${{ secrets.MAC_DEVELOPER_ID_CERT_PASSWORD }} + notarization-api-key-base64: ${{ secrets.AC_API_KEY_BASE64 }} + notarization-api-key-id: ${{ secrets.AC_API_KEY_ID }} + notarization-api-issuer-id: ${{ secrets.AC_API_ISSUER_ID }} + s3-bucket: my-releases + s3-key: myapp/{version}/{filename} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} +``` + +## Inputs + +| Name | Required | Default | Description | +|---|---|---|---| +| `working-directory` | no | `.` | Directory containing `wails.json` | +| `app-name` | no | `wails.json` `name` | Override for the app name in artifact filenames | +| `version` | no | derived | Override; otherwise: matching semver tag → strip `v`, else 7-char short SHA | +| `wails-version` | no | from `go.mod` | Override the Wails CLI version | +| `extra-build-flags` | no | `""` | Additional flags appended to `wails build` (shell-quoted) | +| `developer-id-cert-base64` | **yes** | — | Base64-encoded Developer ID `.p12` | +| `developer-id-cert-password` | **yes** | — | `.p12` password | +| `notarization-method` | no | `auto` | `api-key`, `apple-id`, or `auto` (auto picks whichever group is fully populated) | +| `notarization-api-key-base64` | conditional | — | Base64-encoded App Store Connect `.p8` | +| `notarization-api-key-id` | conditional | — | API key ID | +| `notarization-api-issuer-id` | conditional | — | Issuer ID | +| `notarization-apple-id` | conditional | — | Apple ID (email) | +| `notarization-apple-password` | conditional | — | App-specific password | +| `notarization-team-id` | conditional | — | Developer Team ID | +| `s3-bucket` | no | — | Bucket name. If unset, upload is skipped. | +| `s3-key` | conditional | — | Object key. Required if `s3-bucket` is set. Supports `{version}` and `{filename}` placeholders. | +| `s3-endpoint-url` | no | — | Custom endpoint for S3-compatible storage (MinIO, R2, etc.) | +| `s3-region` | no | `us-east-1` | AWS region | + +AWS credentials (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, optionally `AWS_SESSION_TOKEN`) are read from the standard environment, **not** from action inputs. + +## Outputs + +| Name | Description | +|---|---| +| `version` | Resolved version string | +| `app-name` | Resolved app name | +| `artifact-path` | Local absolute path to the `.app.zip` | +| `artifact-filename` | Just the filename (e.g. `MyApp-1.2.3.app.zip`) | +| `s3-url` | `s3://bucket/key/...` if uploaded, else empty | + +## Versioning rule + +- A git ref of the form `refs/tags/vX.Y.Z` (no pre-release suffix) → version becomes `X.Y.Z`. +- Anything else → 7-character short SHA from `HEAD`. +- Override via the `version` input. + +## Notarization credentials + +You can use **either**: + +- **App Store Connect API key** (recommended). Generate one in App Store Connect → Users and Access → Keys. You need the `.p8` file, the Key ID, and the Issuer ID. +- **Apple ID + app-specific password + team ID**. Generate the app-specific password at [appleid.apple.com](https://appleid.apple.com) → Sign-In and Security → App-Specific Passwords. + +If both groups are populated and `notarization-method` is `auto`, the action errors with an ambiguity message — set `notarization-method` explicitly to disambiguate. + +## S3-compatible storage + +Set `s3-endpoint-url` to point at your storage: + +```yaml +- uses: leonmika/wails-release@v1 + with: + # … + s3-bucket: releases + s3-key: myapp/{version}/{filename} + s3-endpoint-url: https://my-minio.example.com + s3-region: auto + env: + AWS_ACCESS_KEY_ID: ${{ secrets.MINIO_KEY }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.MINIO_SECRET }} +``` + +For Cloudflare R2, set the endpoint to `https://.r2.cloudflarestorage.com` and `s3-region` to `auto`. + +## How it works + +1. Resolve config from `INPUT_*` env, validate, and mask secrets in logs. +2. Resolve version (tag → strip `v`, else short SHA) and app name (from `wails.json`). +3. Ensure the Wails CLI matches the version pinned in your project's `go.mod` (or the `wails-version` override). +4. Run `wails build -platform darwin/universal -clean -trimpath` plus your `extra-build-flags`. +5. Create a temporary keychain, import the `.p12`, and codesign the `.app` with the hardened runtime and a secure timestamp. Verify the signature. +6. `ditto` the `.app` into a zip for notary submission. +7. `xcrun notarytool submit --wait` (API key or Apple ID, whichever was supplied). On rejection, fetch the per-submission log and embed it in the error. +8. `xcrun stapler staple` the bundle and re-zip so the on-disk artifact is offline-verifiable. +9. Optionally upload via the AWS SDK (custom endpoint supported). +10. Always run cleanup: delete the temp keychain and remove decoded `.p12` / `.p8` files. + +## Local development + +```bash +go test ./... +``` + +Smoke-testing real signing requires real credentials and is documented inline in `cmd/wails-release/integration_test.go`. The integration test itself uses fake external binaries on `PATH` and runs hermetically.