diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 074a6feb48..68737fdb3f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1119,11 +1119,16 @@ jobs: id: mac_lib_build if: ${{ !cancelled() && needs.maybe-release.outputs.libs_tag && steps.mac_cli_build.outcome == 'success' }} shell: bash + env: + APPLE_SIMPLEX_SIGNING_KEYCHAIN: ${{ secrets.APPLE_SIMPLEX_SIGNING_KEYCHAIN }} + APPLE_SIMPLEX_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_APPLE_ID }} + APPLE_SIMPLEX_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_PASSWORD }} run: | SKIP_VLC=1 scripts/desktop/build-lib-mac.sh name=simplex-chat-libs-macos-${{ matrix.arch }} mkdir -p release-libs/$name/libs find apps/multiplatform/common/src/commonMain/cpp/desktop/libs/mac-${{ matrix.arch }} -maxdepth 1 -type f -exec cp {} release-libs/$name/libs/ \; + scripts/ci/sign-libs-mac.sh release-libs/$name/libs (cd release-libs/$name && zip -r ../$name.zip libs) - name: Upload library diff --git a/docs/contributing/RELEASES.md b/docs/contributing/RELEASES.md index ea6123e4c8..e0b80fda5b 100644 --- a/docs/contributing/RELEASES.md +++ b/docs/contributing/RELEASES.md @@ -54,7 +54,7 @@ pypi.. commit of the publication 3. Run of `build.yml`: - `maybe-release`: version claimed for the commit in `releases.toml`, draft `core-` created - - build jobs: 6 library zips uploaded + - build jobs: 6 library zips uploaded; macOS libraries signed with the Developer ID and notarized - `releases`: release published - `publish`: `@simplex-chat/types` published, when its version is unpublished - `record`: types version recorded @@ -141,6 +141,7 @@ Versions unpublished after a failure: published by the next push to the branch. - simplex-chat-libs: release immutability enabled - secret `NODEJS_REPO_TOKEN`: contents of simplex-chat-libs, read and write +- secrets `APPLE_SIMPLEX_SIGNING_KEYCHAIN`, `APPLE_SIMPLEX_NOTARIZATION_APPLE_ID` and `APPLE_SIMPLEX_NOTARIZATION_PASSWORD`: signing and notarization of the macOS libraries, shared with the desktop app build - trusted publisher of `simplex-chat` and `@simplex-chat/types` on npm and of `simplex-chat` on PyPI: workflow `build.yml` - secrets `NPM_TOKEN` and `PYPI_API_TOKEN`: used instead of trusted publishing when set - variables `NPM_SCOPE`, `PYPI_PROJECT`, `PYPI_URL` and `PYPI_UPLOAD_URL`: publication under other names, for test repositories diff --git a/scripts/ci/sign-libs-mac.sh b/scripts/ci/sign-libs-mac.sh new file mode 100755 index 0000000000..e455404503 --- /dev/null +++ b/scripts/ci/sign-libs-mac.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -euo pipefail + +libs=$1 +team=5NN7GUYB6T +keychain=/tmp/simplex.keychain +temp=$(mktemp -d) +trap 'rm -rf "$keychain" "$temp"' EXIT + +notarytool() { + xcrun notarytool "$@" --apple-id "$APPLE_SIMPLEX_NOTARIZATION_APPLE_ID" --password "$APPLE_SIMPLEX_NOTARIZATION_PASSWORD" --team-id "$team" +} + +echo "$APPLE_SIMPLEX_SIGNING_KEYCHAIN" | base64 --decode -o "$keychain" +security unlock-keychain -p "" "$keychain" +security list-keychains -s $(security list-keychains | xargs) "$keychain" + +for lib in "$libs"/*.dylib; do + codesign --remove-signature "$lib" + codesign --timestamp --options runtime --force --sign "Developer ID Application: SimpleX Chat Ltd ($team)" --keychain "$keychain" "$lib" +done + +ditto -c -k --keepParent "$libs" "$temp/libs.zip" +notarytool submit "$temp/libs.zip" --wait --timeout 1h --output-format json > "$temp/submission.json" || true +cat "$temp/submission.json" +read -r id status < <(python3 -c 'import json, sys; r = json.load(open(sys.argv[1])); print(r["id"], r["status"])' "$temp/submission.json") +notarytool log "$id" +if [ "$status" != Accepted ]; then + exit 1 +fi