diff --git a/.github/scripts/build_release_nightly.py b/.github/scripts/build_release_nightly.py index b7cce37..0afd08c 100755 --- a/.github/scripts/build_release_nightly.py +++ b/.github/scripts/build_release_nightly.py @@ -21,6 +21,7 @@ from common import ( OS_NAME, PLATFORM_TARGET, DESKTOP, + notarize_macos_build, ) from upload_to_bintray import upload_from_json @@ -73,6 +74,7 @@ for target in TARGETS: else: if PLATFORM_TARGET == "native_mixed" and OS_NAME == "osx": fix_macos_rpath(target) + notarize_macos_build(target) archive = make_archive(target, make_release=RELEASE) if archive: upload_archive(archive, target, make_release=RELEASE) diff --git a/.github/scripts/common.py b/.github/scripts/common.py index f8307d7..9f90572 100644 --- a/.github/scripts/common.py +++ b/.github/scripts/common.py @@ -437,3 +437,49 @@ def trigger_docker_publish(target): except Exception as exc: print_message("Error triggering workflow: {exc}", exc=exc) raise exc + + +def notarize_macos_build(project): + """ sign and notarize files for macOS + + Expects the following environment: + - Imported Mac/Apple Distribution certificate (with private key) in Keychain + - `SIGNING_IDENTITY` environ with Certificate name/identity + - `ALTOOL_USERNAME` with Apple ID of an account with perms on the certificate + - Keychain entry `ALTOOL_PASSWORD` with an app-specific password for the account + - `ASC_PROVIDER` environ with Team ID + """ + if project != "libzim": + return + + # currently only supports libzim use case: sign every dylib + base_dir, export_files = EXPORT_FILES[project] + filepaths = [base_dir.joinpath(file) + for file in filter(lambda f: f.endswith(".dylib"), export_files) + if not base_dir.joinpath(file).is_symlink()] + + if not filepaths: + return + + for filepath in filepaths: + subprocess.check_call(["/usr/bin/codesign", "--force", "--sign", + os.getenv("SIGNING_IDENTITY", "no-signing-ident"), + str(filepath), "--deep", "--timestamp"], env=os.environ) + + # create a zip of the dylibs and upload for notarization + zip_name = "{}.zip".format(project) + subprocess.check_call( + ["/usr/bin/ditto", "-c", "-k", "--keepParent"] + + [str(f) for f in filepaths] + [zip_name], + env=os.environ) + + subprocess.check_call(["/usr/bin/xcrun", "altool", "--notarize-app", + "--file", str(zip_name), + "--primary-bundle-id", "org.kiwix.build.{}".format(project), + "--username", os.getenv("ALTOOL_USERNAME", "missing"), + "--password", "@keychain:ALTOOL_PASSWORD", + "--asc-provider", os.getenv("ASC_PROVIDER")], env=os.environ) + + # check notarization of a file (should be in-progress atm and this != 0) + subprocess.call(["/usr/sbin/spctl", "-a", "-v", "-t", "install", + filepaths[-1]], env=os.environ) diff --git a/.github/workflows/releaseNigthly.yml b/.github/workflows/releaseNigthly.yml index 59194f6..5de5c82 100644 --- a/.github/workflows/releaseNigthly.yml +++ b/.github/workflows/releaseNigthly.yml @@ -132,6 +132,10 @@ jobs: env: SSH_KEY: /tmp/id_rsa OS_NAME: osx + CERTIFICATE: /tmp/wmch-devid.p12 + SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} + ALTOOL_USERNAME: ${{ secrets.APPLE_SIGNING_ALTOOL_USERNAME }} + ASC_PROVIDER: ${{ secrets.APPLE_SIGNING_TEAM }} steps: - name: Checkout code uses: actions/checkout@v1 @@ -151,6 +155,19 @@ jobs: run: | echo "${{secrets.ssh_key}}" > $SSH_KEY chmod 600 $SSH_KEY + - name: install Apple certificate + shell: bash + run: | + echo "${{ secrets.APPLE_SIGNING_CERTIFICATE }}" | base64 --decode -o $CERTIFICATE + security create-keychain -p mysecretpassword build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p mysecretpassword build.keychain + security import $CERTIFICATE -k build.keychain -P "${{ secrets.APPLE_SIGNING_P12_PASSWORD }}" -A + rm $CERTIFICATE + "security set-key-partition-list -S apple-tool:,apple: -s -k mysecretpassword build.keychain" + security find-identity -v + sntp -sS time.apple.com + xcrun altool --store-password-in-keychain-item "ALTOOL_PASSWORD" -u "$ALTOOL_USERNAME" -p "${{ secrets.APPLE_SIGNING_ALTOOL_PASSWORD }}" - name: Ensure base deps shell: bash run: |