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: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ jobs:
cp target/aarch64-apple-darwin/release/kit stage/kit
if [[ $SIGN_RELEASE == true ]]; then
codesign --force --options runtime --timestamp \
--identifier com.danielkov.kit \
--identifier com.speakeasy.kit \
--sign "$MACOS_SIGNING_IDENTITY" stage/kit
codesign --verify --strict --verbose=2 stage/kit
ditto -c -k --keepParent stage/kit "$RUNNER_TEMP/kit-notarization.zip"
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "kit"
version = "0.1.97"
version = "0.1.98"
edition = "2024"
rust-version = "1.94.0"
publish = false
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ target/release/kit tui --mcp-config mcp.json \
On macOS, `.cargo/config.toml` routes `cargo run` through a runner that signs the
fresh debug binary before executing it. Set `KIT_CODESIGN_IDENTITY`, or put the
certificate name in the gitignored `.kit-codesign-identity` file. Both paths use
the stable identifier `com.danielkov.kit`, overridable with
the stable identifier `com.speakeasy.kit`, overridable with
`KIT_CODESIGN_IDENTIFIER`. A changed identity, a missing certificate, or a
locked Keychain may prompt again. `cargo install`
does not run the runner; sign its installed binary separately. Apple Development
Expand Down
58 changes: 44 additions & 14 deletions docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,55 @@ Clippy, and tests, builds Linux x86-64 and macOS arm64 archives, generates
checksums, and publishes them to the tagged GitHub release. Prerelease tags are
marked as prereleases on GitHub.

## Optional macOS signing and notarization
## macOS signing and notarization

The macOS build does not require Apple credentials. When none are configured,
the workflow publishes an unsigned, unnotarized archive and identifies it as
such in the release notes. This is the expected setup until signing credentials
are added to the repository.
The release workflow signs the standalone Mach-O executable with the code-signing
identifier `com.speakeasy.kit`, enables the hardened runtime, and submits it to
Apple's notary service. This Developer ID distribution does not require an Apple
App ID or provisioning profile.

To enable signing and notarization, configure all of these repository secrets:
Create the credentials as follows:

- `MACOS_CERTIFICATE_P12_BASE64`
- `MACOS_CERTIFICATE_PASSWORD`
- `MACOS_SIGNING_IDENTITY`
- `APPLE_API_KEY_P8_BASE64`
- `APPLE_API_KEY_ID`
- `APPLE_API_ISSUER_ID`
1. In Keychain Access, use **Certificate Assistant > Request a Certificate From
a Certificate Authority** to save a certificate signing request (CSR).
2. In Apple Developer **Certificates, Identifiers & Profiles**, create a
**Developer ID Application** certificate from that CSR. If that option is not
available for your role, ask the team's Account Holder to create it. Import
the downloaded certificate on the Mac that created the CSR.
3. In Keychain Access, export the Developer ID certificate together with its
private key as a password-protected PKCS#12 (`.p12`) file. Record the exact
identity shown by `security find-identity -v -p codesigning`. It normally has
the form `Developer ID Application: <Organization> (<TEAM_ID>)`.
4. In App Store Connect **Users and Access > Integrations**, create a team API
key that can access the notary service. Record its key ID and issuer ID, and
retain the downloaded `.p8`; Apple does not allow it to be downloaded again.
5. Store the `.p12`, its password, and the `.p8` in the company's secret manager.
Configure these repository Actions secrets:

- `MACOS_CERTIFICATE_P12_BASE64`: base64-encoded `.p12`
- `MACOS_CERTIFICATE_PASSWORD`: `.p12` export password
- `MACOS_SIGNING_IDENTITY`: exact Keychain identity from step 3
- `APPLE_API_KEY_P8_BASE64`: base64-encoded `.p8`
- `APPLE_API_KEY_ID`: App Store Connect API key ID
- `APPLE_API_ISSUER_ID`: App Store Connect issuer ID

For example, from a trusted Mac authenticated to GitHub CLI:

```sh
repo=speakeasy-api/kit
base64 < DeveloperIDApplication.p12 | gh secret set MACOS_CERTIFICATE_P12_BASE64 -R "$repo"
read -r -s 'p12_password?P12 password: '; echo
printf %s "$p12_password" | gh secret set MACOS_CERTIFICATE_PASSWORD -R "$repo"
unset p12_password
printf %s 'Developer ID Application: Example Corp (TEAMID)' | gh secret set MACOS_SIGNING_IDENTITY -R "$repo"
base64 < AuthKey_KEYID.p8 | gh secret set APPLE_API_KEY_P8_BASE64 -R "$repo"
printf %s 'KEYID' | gh secret set APPLE_API_KEY_ID -R "$repo"
printf %s 'issuer-uuid' | gh secret set APPLE_API_ISSUER_ID -R "$repo"
```

The workflow fails on a partial configuration rather than silently publishing
an unsigned build. Downloaded `.p8` keys cannot be downloaded again, so retain
the original in the company's secret manager.
an unsigned build. With none of these secrets configured, it still publishes an
unsigned, unnotarized archive and identifies it as such in the release notes.

## Verify a release

Expand Down
2 changes: 1 addition & 1 deletion scripts/codesign-runner.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ if [ "$(basename "$binary")" = kit ]; then
if [ -z "$identity" ] && [ -r "$root/.kit-codesign-identity" ]; then
IFS= read -r identity < "$root/.kit-codesign-identity"
fi
identifier="${KIT_CODESIGN_IDENTIFIER:-com.danielkov.kit}"
identifier="${KIT_CODESIGN_IDENTIFIER:-com.speakeasy.kit}"
if [ -n "$identity" ] && security find-identity -v -p codesigning 2>/dev/null | grep -Fq "\"$identity\""; then
codesign --force --options runtime --identifier "$identifier" --sign "$identity" "$binary"
else
Expand Down
8 changes: 4 additions & 4 deletions scripts/notarize-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ Builds, Developer ID signs, and notarizes the macOS ARM64 release binary on
this Mac. The exact signed binary is preserved under dist/notarize/vVERSION/.

Required configuration (`.env` or environment variables):
KIT_CODESIGN_IDENTITY
KIT_NOTARY_API_KEY_DOCUMENT
KIT_NOTARY_API_KEY_VAULT
KIT_NOTARY_API_KEY_ID
KIT_NOTARY_API_ISSUER_ID

Optional overrides:
KIT_CODESIGN_IDENTITY
KIT_CODESIGN_IDENTIFIER
EOF
}
Expand Down Expand Up @@ -57,8 +57,8 @@ if [[ -n $(git status --porcelain) ]]; then
exit 1
fi

identity=${KIT_CODESIGN_IDENTITY:-Developer ID Application: Inlucent Limited (TAMRUK8SL6)}
identifier=${KIT_CODESIGN_IDENTIFIER:-com.danielkov.kit}
identity=${KIT_CODESIGN_IDENTITY:?KIT_CODESIGN_IDENTITY must be set}
identifier=${KIT_CODESIGN_IDENTIFIER:-com.speakeasy.kit}
api_key_document=${KIT_NOTARY_API_KEY_DOCUMENT:?KIT_NOTARY_API_KEY_DOCUMENT must be set}
api_key_vault=${KIT_NOTARY_API_KEY_VAULT:?KIT_NOTARY_API_KEY_VAULT must be set}
api_key_id=${KIT_NOTARY_API_KEY_ID:?KIT_NOTARY_API_KEY_ID must be set}
Expand Down Expand Up @@ -88,7 +88,7 @@ umask 077
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/kit-notary.XXXXXX")
trap 'rm -rf "$tmp_dir"' EXIT
api_key="$tmp_dir/AuthKey_${api_key_id}.p8"
op document get "$api_key_document" --vault "$api_key_vault" --output "$api_key" >/dev/null
op document get "$api_key_document" --vault "$api_key_vault" --out-file "$api_key" >/dev/null
chmod 600 "$api_key"
source_dir="$tmp_dir/source"
mkdir -p "$source_dir"
Expand Down
2 changes: 1 addition & 1 deletion scripts/sign-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if [ -z "$KIT_CODESIGN_IDENTITY" ] && [ -r "$root/.kit-codesign-identity" ]; the
IFS= read -r KIT_CODESIGN_IDENTITY < "$root/.kit-codesign-identity"
fi
: "${KIT_CODESIGN_IDENTITY:?set KIT_CODESIGN_IDENTITY or create .kit-codesign-identity}"
KIT_CODESIGN_IDENTIFIER="${KIT_CODESIGN_IDENTIFIER:-com.danielkov.kit}"
KIT_CODESIGN_IDENTIFIER="${KIT_CODESIGN_IDENTIFIER:-com.speakeasy.kit}"

if [ "$(uname -s)" != Darwin ]; then
echo "codesigning is only supported on macOS" >&2
Expand Down