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
12 changes: 6 additions & 6 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1665,9 +1665,9 @@ jobs:

- name: Start Computer Use helper notarization
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
state="$RUNNER_TEMP/cmux-computer-use-notarization.state"
Expand Down Expand Up @@ -1789,9 +1789,9 @@ jobs:

- name: Notarize app ticket through final DMG
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
CMUX_COMPUTER_USE_NOTARY_SUBMISSION_FILE: ${{ runner.temp }}/cmux-computer-use-notarization.state
CMUX_CHANNEL: ${{ needs.decide.outputs.channel }}
Expand Down
30 changes: 16 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,9 +326,9 @@ jobs:
- name: Start Computer Use helper notarization
if: steps.guard_release_assets.outputs.skip_all != 'true'
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
state="$RUNNER_TEMP/cmux-computer-use-notarization.state"
Expand Down Expand Up @@ -543,15 +543,17 @@ jobs:
- name: Notarize app
if: steps.guard_release_assets.outputs.skip_all != 'true'
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
if [ -z "$APPLE_ID" ] || [ -z "$APPLE_APP_SPECIFIC_PASSWORD" ] || [ -z "$APPLE_TEAM_ID" ]; then
echo "Missing notarization secrets (APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID)" >&2
exit 1
fi
# notarytool authenticates with the team App Store Connect API key.
# The decoded key stays in a private temp dir removed on exit.
NOTARY_TMP="$(mktemp -d "$RUNNER_TEMP/cmux-notary.XXXXXX")"
trap 'rm -rf "$NOTARY_TMP"' EXIT
source ./scripts/ci/lib/notary-auth.sh
notary_auth_init "$NOTARY_TMP"
APP_PATH="build-universal/Build/Products/Release/cmux.app"
ZIP_SUBMIT="cmux-notary.zip"
DMG_RELEASE="cmux-macos.dmg"
Expand All @@ -561,12 +563,12 @@ jobs:
cmux.release.entitlements \
"$APPLE_SIGNING_IDENTITY"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ZIP_SUBMIT"
APP_SUBMIT_JSON="$(xcrun notarytool submit "$ZIP_SUBMIT" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --wait --output-format json)"
APP_SUBMIT_JSON="$(xcrun notarytool submit "$ZIP_SUBMIT" "${NOTARY_AUTH_ARGS[@]}" --wait --output-format json)"
APP_SUBMIT_ID="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$APP_SUBMIT_JSON")"
APP_STATUS="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])' <<<"$APP_SUBMIT_JSON")"
if [ "$APP_STATUS" != "Accepted" ]; then
echo "App notarization failed with status: $APP_STATUS" >&2
xcrun notarytool log "$APP_SUBMIT_ID" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" || true
xcrun notarytool log "$APP_SUBMIT_ID" "${NOTARY_AUTH_ARGS[@]}" || true
exit 1
fi
xcrun stapler staple "$APP_PATH"
Expand All @@ -587,12 +589,12 @@ jobs:
--sign "$APPLE_SIGNING_IDENTITY" \
"$DMG_RELEASE"
/usr/bin/codesign --verify --verbose=2 "$DMG_RELEASE"
DMG_SUBMIT_JSON="$(xcrun notarytool submit "$DMG_RELEASE" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --wait --output-format json)"
DMG_SUBMIT_JSON="$(xcrun notarytool submit "$DMG_RELEASE" "${NOTARY_AUTH_ARGS[@]}" --wait --output-format json)"
DMG_SUBMIT_ID="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$DMG_SUBMIT_JSON")"
DMG_STATUS="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])' <<<"$DMG_SUBMIT_JSON")"
if [ "$DMG_STATUS" != "Accepted" ]; then
echo "DMG notarization failed with status: $DMG_STATUS" >&2
xcrun notarytool log "$DMG_SUBMIT_ID" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" || true
xcrun notarytool log "$DMG_SUBMIT_ID" "${NOTARY_AUTH_ARGS[@]}" || true
exit 1
fi
xcrun stapler staple "$DMG_RELEASE"
Expand Down
40 changes: 22 additions & 18 deletions .github/workflows/repair-v0-64-25-helper-rpaths.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,9 @@ jobs:

- name: Start helper notarization
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
set -euo pipefail
Expand All @@ -153,9 +153,9 @@ jobs:

- name: Finish helper notarization
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
set -euo pipefail
Expand All @@ -167,17 +167,19 @@ jobs:

- name: Notarize and staple repaired app
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
run: |
set -euo pipefail
notary_tmp="$(mktemp -d "$RUNNER_TEMP/cmux-notary.XXXXXX")"
trap 'rm -rf "$notary_tmp"' EXIT
source ./scripts/ci/lib/notary-auth.sh
notary_auth_init "$notary_tmp"
zip_path="$REPAIR_ROOT/cmux-notary.zip"
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$zip_path"
submit_json="$(xcrun notarytool submit "$zip_path" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
"${NOTARY_AUTH_ARGS[@]}" \
--wait --output-format json)"
status="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])' <<<"$submit_json")"
if [ "$status" != Accepted ]; then
Expand All @@ -191,12 +193,16 @@ jobs:

- name: Create and notarize repaired DMG
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
ASC_API_KEY_ID: ${{ secrets.ASC_API_KEY_ID }}
ASC_API_ISSUER_ID: ${{ secrets.ASC_API_ISSUER_ID }}
ASC_API_KEY_P8_BASE64: ${{ secrets.ASC_API_KEY_P8_BASE64 }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
set -euo pipefail
notary_tmp="$(mktemp -d "$RUNNER_TEMP/cmux-notary.XXXXXX")"
trap 'rm -rf "$notary_tmp"' EXIT
source ./scripts/ci/lib/notary-auth.sh
notary_auth_init "$notary_tmp"
dmg_dir="$REPAIR_ROOT/dmg-output"
mkdir -p "$dmg_dir"
create-dmg --no-code-sign "$APP_PATH" "$dmg_dir"
Expand All @@ -207,9 +213,7 @@ jobs:
--sign "$APPLE_SIGNING_IDENTITY" "$DMG_PATH"
codesign --verify --verbose=2 "$DMG_PATH"
submit_json="$(xcrun notarytool submit "$DMG_PATH" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
"${NOTARY_AUTH_ARGS[@]}" \
--wait --output-format json)"
status="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])' <<<"$submit_json")"
if [ "$status" != Accepted ]; then
Expand Down
40 changes: 40 additions & 0 deletions scripts/ci/lib/notary-auth.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# notarytool authentication with the team App Store Connect API key.
#
# Source this file, then call `notary_auth_init <private-dir>` once. It decodes
# ASC_API_KEY_P8_BASE64 into <private-dir> with mode 600 and sets the
# NOTARY_AUTH_ARGS array for `xcrun notarytool submit|wait|log|history`.
# The caller owns <private-dir> and must delete it on exit (an EXIT trap), so
# the decoded key never outlives the script that used it.
#
# Required environment: ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64.

NOTARY_AUTH_ARGS=()

notary_auth_init() {
local key_dir="${1:-}" key_path
if [ -z "$key_dir" ] || [ ! -d "$key_dir" ]; then
echo "notary_auth_init needs an existing private directory" >&2
return 1
fi
if [ -z "${ASC_API_KEY_ID:-}" ] \
|| [ -z "${ASC_API_ISSUER_ID:-}" ] \
|| [ -z "${ASC_API_KEY_P8_BASE64:-}" ]; then
echo "Missing notarization secrets (ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64)" >&2
return 1
fi

key_path="$key_dir/notary-key/AuthKey_${ASC_API_KEY_ID}.p8"
(
umask 077
mkdir -p "$(dirname "$key_path")"
printf '%s' "$ASC_API_KEY_P8_BASE64" | base64 --decode > "$key_path"
)
chmod 600 "$key_path"
if [ ! -s "$key_path" ]; then
echo "ASC_API_KEY_P8_BASE64 did not decode to a key" >&2
return 1
fi

NOTARY_AUTH_ARGS=(--key "$key_path" --key-id "$ASC_API_KEY_ID" --issuer "$ASC_API_ISSUER_ID")
}
28 changes: 12 additions & 16 deletions scripts/ci/notarize-computer-use-helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ CODESIGN_TOOL="${CMUX_CODESIGN_TOOL:-/usr/bin/codesign}"
SPCTL_TOOL="${CMUX_SPCTL_TOOL:-spctl}"
# shellcheck source=lib/notarization-ticket.sh
source "$ROOT_DIR/scripts/ci/lib/notarization-ticket.sh"
# shellcheck source=lib/notary-auth.sh
source "$ROOT_DIR/scripts/ci/lib/notary-auth.sh"
# Gatekeeper learns about a fresh notarization ticket from Apple's CDN, which
# lags the notarytool "Accepted" status: usually by a minute or two, but
# nightly run 34208928547 (2026-09-08) was still rejected 4m50s after
Expand Down Expand Up @@ -100,10 +102,10 @@ if [ ! -f "$HELPER_ENTITLEMENTS" ]; then
echo "Computer Use helper entitlements not found: $HELPER_ENTITLEMENTS" >&2
exit 1
fi
if [ -z "${APPLE_ID:-}" ] \
|| [ -z "${APPLE_APP_SPECIFIC_PASSWORD:-}" ] \
|| [ -z "${APPLE_TEAM_ID:-}" ]; then
echo "Missing notarization secrets (APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID)" >&2
if [ -z "${ASC_API_KEY_ID:-}" ] \
|| [ -z "${ASC_API_ISSUER_ID:-}" ] \
|| [ -z "${ASC_API_KEY_P8_BASE64:-}" ]; then
echo "Missing notarization secrets (ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64)" >&2
exit 1
fi

Expand All @@ -112,6 +114,8 @@ cleanup() {
rm -rf "$TMP_DIR"
}
trap cleanup EXIT
# The decoded API key lives in TMP_DIR, which the EXIT trap removes.
notary_auth_init "$TMP_DIR"

HELPER_ZIP="$TMP_DIR/cmux-cua-notary.zip"
STANDALONE_DIR="$TMP_DIR/standalone"
Expand Down Expand Up @@ -162,9 +166,7 @@ start_submission() {
"$DITTO_TOOL" -c -k --sequesterRsrc --keepParent "$HELPER_PATH" "$HELPER_ZIP"

submit_json="$("$XCRUN_TOOL" notarytool submit "$HELPER_ZIP" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
"${NOTARY_AUTH_ARGS[@]}" \
--output-format json)"
submit_id="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$submit_json")"
submit_status="$(python3 -c 'import json,sys; print(json.load(sys.stdin).get("status", "unknown"))' <<<"$submit_json")"
Expand Down Expand Up @@ -207,9 +209,7 @@ finish_submission() {

set +e
wait_json="$("$XCRUN_TOOL" notarytool wait "$submit_id" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" \
"${NOTARY_AUTH_ARGS[@]}" \
--output-format json)"
wait_status=$?
set -e
Expand All @@ -221,16 +221,12 @@ finish_submission() {
if [ "$wait_status" -ne 0 ] || [ "$submit_status" != "Accepted" ]; then
echo "Computer Use helper notarization failed with status: $submit_status (wait exit $wait_status)" >&2
"$XCRUN_TOOL" notarytool log "$submit_id" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" || true
"${NOTARY_AUTH_ARGS[@]}" || true
exit 1
fi

"$XCRUN_TOOL" notarytool log "$submit_id" \
--apple-id "$APPLE_ID" \
--team-id "$APPLE_TEAM_ID" \
--password "$APPLE_APP_SPECIFIC_PASSWORD" > "$TMP_DIR/notary-log.json"
"${NOTARY_AUTH_ARGS[@]}" > "$TMP_DIR/notary-log.json"
cat "$TMP_DIR/notary-log.json"
verify_ticket_contents_cover_slices "$TMP_DIR/notary-log.json" "$HELPER_PATH"
"$XCRUN_TOOL" stapler staple "$HELPER_PATH"
Expand Down
13 changes: 9 additions & 4 deletions scripts/ci/notarize-nightly-dmg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ case "$CHANNEL" in
;;
esac
APP_ENTITLEMENTS="${CMUX_APP_ENTITLEMENTS:-$ROOT_DIR/cmux.${CHANNEL}.entitlements}"
# shellcheck source=lib/notary-auth.sh
source "$ROOT_DIR/scripts/ci/lib/notary-auth.sh"

if [ ! -d "$APP_PATH/Contents" ]; then
echo "Signed app not found: $APP_PATH" >&2
exit 1
fi
if [ -z "${APPLE_ID:-}" ] || [ -z "${APPLE_APP_SPECIFIC_PASSWORD:-}" ] || [ -z "${APPLE_TEAM_ID:-}" ]; then
echo "Missing notarization secrets (APPLE_ID, APPLE_APP_SPECIFIC_PASSWORD, APPLE_TEAM_ID)" >&2
if [ -z "${ASC_API_KEY_ID:-}" ] || [ -z "${ASC_API_ISSUER_ID:-}" ] || [ -z "${ASC_API_KEY_P8_BASE64:-}" ]; then
echo "Missing notarization secrets (ASC_API_KEY_ID, ASC_API_ISSUER_ID, ASC_API_KEY_P8_BASE64)" >&2
exit 1
fi
if [ -z "${APPLE_SIGNING_IDENTITY:-}" ]; then
Expand All @@ -61,6 +63,9 @@ cleanup() {
rm -rf "$DMG_TMP_DIR"
}
trap cleanup EXIT
NOTARY_DIR="$DMG_TMP_DIR/notary"
mkdir -m 700 "$NOTARY_DIR"
notary_auth_init "$NOTARY_DIR"

if [ -n "$COMPUTER_USE_NOTARY_SUBMISSION_FILE" ]; then
"$NOTARIZE_COMPUTER_USE_HELPER_TOOL" \
Expand Down Expand Up @@ -96,12 +101,12 @@ fi
"$DMG_RELEASE"
"$CODESIGN_TOOL" --verify --verbose=2 "$DMG_RELEASE"

DMG_SUBMIT_JSON="$("$XCRUN_TOOL" notarytool submit "$DMG_RELEASE" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --wait --output-format json)"
DMG_SUBMIT_JSON="$("$XCRUN_TOOL" notarytool submit "$DMG_RELEASE" "${NOTARY_AUTH_ARGS[@]}" --wait --output-format json)"
DMG_SUBMIT_ID="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' <<<"$DMG_SUBMIT_JSON")"
DMG_STATUS="$(python3 -c 'import json,sys; print(json.load(sys.stdin)["status"])' <<<"$DMG_SUBMIT_JSON")"
if [ "$DMG_STATUS" != "Accepted" ]; then
echo "DMG notarization failed for $DMG_RELEASE with status: $DMG_STATUS" >&2
"$XCRUN_TOOL" notarytool log "$DMG_SUBMIT_ID" --apple-id "$APPLE_ID" --team-id "$APPLE_TEAM_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" || true
"$XCRUN_TOOL" notarytool log "$DMG_SUBMIT_ID" "${NOTARY_AUTH_ARGS[@]}" || true
exit 1
fi

Expand Down
2 changes: 1 addition & 1 deletion skills/cmux-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ If the pretag guard fails, run `./scripts/bump-version.sh`, commit the build-num
## Release artifacts and secrets

- The release asset is `cmux-macos.dmg`, attached to the tag. The README download button points to `releases/latest/download/cmux-macos.dmg`.
- Signing and notarization require the GitHub secrets `APPLE_CERTIFICATE_BASE64`, `APPLE_CERTIFICATE_PASSWORD`, `APPLE_SIGNING_IDENTITY`, `APPLE_ID`, `APPLE_APP_SPECIFIC_PASSWORD`, `APPLE_TEAM_ID`.
- Signing requires the GitHub secrets `APPLE_CERTIFICATE_BASE64`, `APPLE_CERTIFICATE_PASSWORD` and `APPLE_SIGNING_IDENTITY`. CI notarization authenticates with the team App Store Connect API key (`ASC_API_KEY_ID`, `ASC_API_ISSUER_ID`, `ASC_API_KEY_P8_BASE64`) through `scripts/ci/lib/notary-auth.sh`, which decodes the key to a mode-600 temp file that the caller deletes. The local `scripts/build-sign-upload.sh` still uses an Apple ID and app-specific password.

## Detailed reference

Expand Down
Loading
Loading