From a5696806382856804315ba7d6460fc6d657afe49 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 11:09:03 -0800 Subject: [PATCH 01/12] Import signing certificate from secrets and use when building XCFramework --- .github/workflows/main.yml | 21 ++++++++++++++ Rakefile | 56 ++++++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a9335390f3..81ed9a8806 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,6 +86,27 @@ jobs: - '14.1' # Swift 5.7.1 steps: - uses: actions/checkout@v2 + - name: Install self-signing certificate + env: + LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64: ${{ secrets.LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64 }} + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} + run: | + # Adapted from https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development + # create variables + CERTIFICATE_PATH=$RUNNER_TEMP/Lottie_iOS.cer + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + # import certificate from secrets + echo -n "$LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64" | base64 --decode -o $CERTIFICATE_PATH + + # create temporary keychain + security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + security set-keychain-settings -lut 21600 $KEYCHAIN_PATH + security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH + + # import certificate to keychain + security import $CERTIFICATE_PATH -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + security list-keychain -d user -s $KEYCHAIN_PATH - uses: ./.github/actions/setup with: xcode: ${{ matrix.xcode }} diff --git a/Rakefile b/Rakefile index 666f2f226c..c8a63160f4 100644 --- a/Rakefile +++ b/Rakefile @@ -69,44 +69,60 @@ namespace :build do # Build the framework for each supported platform, including simulators xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination generic/platform=iOS -archivePath ".build/archives/Lottie_iOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - - ifVisionOSEnabled { - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - } + + # TODO: REVERT. Just making the job shorter to help debug more quickly. + #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + + #ifVisionOSEnabled { + # xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + # xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + #} # Combine all of the platforms into a single XCFramework xcframeworkInvocation = [ '-create-xcframework', '-framework .build/archives/Lottie_iOS.xcarchive/Products/Library/Frameworks/Lottie.framework', - '-framework .build/archives/Lottie_iOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', - '-framework .build/archives/Lottie_Mac_Catalyst.xcarchive/Products/Library/Frameworks/Lottie.framework', - '-framework .build/archives/Lottie_tvOS.xcarchive/Products/Library/Frameworks/Lottie.framework', - '-framework .build/archives/Lottie_tvOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', - '-framework .build/archives/Lottie_macOS.xcarchive/Products/Library/Frameworks/Lottie.framework', + # TODO: REVERT. Just making the job shorter to help debug more quickly. + #'-framework .build/archives/Lottie_iOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', + #'-framework .build/archives/Lottie_Mac_Catalyst.xcarchive/Products/Library/Frameworks/Lottie.framework', + #'-framework .build/archives/Lottie_tvOS.xcarchive/Products/Library/Frameworks/Lottie.framework', + #'-framework .build/archives/Lottie_tvOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', + #'-framework .build/archives/Lottie_macOS.xcarchive/Products/Library/Frameworks/Lottie.framework', ] - ifVisionOSEnabled { - xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS.xcarchive/Products/Library/Frameworks/Lottie.framework') - xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework') - } + #ifVisionOSEnabled { + # xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS.xcarchive/Products/Library/Frameworks/Lottie.framework') + # xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework') + #} xcframeworkInvocation.push('-output .build/archives/Lottie.xcframework') xcodebuild(xcframeworkInvocation.join(" ")) - # Archive the XCFramework into a zip file Dir.chdir('.build/archives') do + # Codesign the XCFramework using the "Lottie iOS" certificate installed as a secret in the lottie-ios repo. + # First we check to make sure the certificate is installed. In GitHub actions CI, only jobs run by contibutors have access + # to repo secrets, so PR jobs from external contributors won't have access to this certificate. + puts "Checking if signing certificate is installed..." + `security find-certificate -c 'Lottie iOS'` + if $?.success? + puts "Signing certificate is installed. Code signing Lottie.xcframework." + sh 'codesign --timestamp -v --sign "Lottie iOS" Lottie.xcframework' + else + puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." + end + + # Archive the XCFramework into a zip file # Use --symlinks to avoid "Multiple binaries share the same codesign path. This can happen if your build process copies frameworks by following symlinks." # error when validating macOS apps (#1948) sh "zip -r --symlinks #{args[:zip_archive_name]}.xcframework.zip Lottie.xcframework" sh 'rm -rf Lottie.xcframework' end + sh "swift package compute-checksum .build/archives/#{args[:zip_archive_name]}.xcframework.zip" end end From a876be270b4c6fef6a55ecf51cbe24c084ed2014 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 11:19:31 -0800 Subject: [PATCH 02/12] Tweak command for importing certificate --- .github/workflows/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 81ed9a8806..2fdd90a693 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -105,8 +105,10 @@ jobs: security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH # import certificate to keychain - security import $CERTIFICATE_PATH -A -t cert -f pkcs12 -k $KEYCHAIN_PATH + echo "Importing Lottie iOS self-signing certificate into keychain..." + security import $CERTIFICATE_PATH -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH + echo "Successfully imported certificate." - uses: ./.github/actions/setup with: xcode: ${{ matrix.xcode }} From 3608de13ecf82581fa5f6efc476eea5469b46358 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 13:15:22 -0800 Subject: [PATCH 03/12] Use password protected .p12 file, pass custom keychain path to rakefile --- .github/workflows/main.yml | 27 +++++++++++++++++---------- Rakefile | 20 +++++++++++++++----- 2 files changed, 32 insertions(+), 15 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2fdd90a693..4a3e92a972 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -88,16 +88,17 @@ jobs: - uses: actions/checkout@v2 - name: Install self-signing certificate env: - LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64: ${{ secrets.LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64 }} + LOTTIE_SIGNING_CERTIFICATE_BASE_64: ${{ secrets.LOTTIE_SIGNING_CERTIFICATE_BASE_64 }} + LOTTIE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.LOTTIE_SIGNING_CERTIFICATE_PASSWORD }} KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | - # Adapted from https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development + # From https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development # create variables - CERTIFICATE_PATH=$RUNNER_TEMP/Lottie_iOS.cer + CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - # import certificate from secrets - echo -n "$LOTTIE_IOS_SIGNING_CERTIFICATE_BASE_64" | base64 --decode -o $CERTIFICATE_PATH + # import certificate and provisioning profile from secrets + echo -n "$LOTTIE_SIGNING_CERTIFICATE_BASE_64" | base64 --decode -o $CERTIFICATE_PATH # create temporary keychain security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH @@ -105,17 +106,23 @@ jobs: security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH # import certificate to keychain - echo "Importing Lottie iOS self-signing certificate into keychain..." - security import $CERTIFICATE_PATH -k $KEYCHAIN_PATH + echo "Importing 'Lottie iOS Code Signing' self-signing certificate into keychain..." + security import $CERTIFICATE_PATH -P "$LOTTIE_SIGNING_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH echo "Successfully imported certificate." - uses: ./.github/actions/setup with: xcode: ${{ matrix.xcode }} - name: Build XCFramework - # Once there is a production Xcode version with the visionOS SDK, we will - # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true` - run: SKIP_VISION_OS=true bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] + run: | + # Once there is a production Xcode version with the visionOS SDK, we will + # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. + SKIP_VISION_OS=true + + # Codesign using the unlocked custom keychain created in the previous step. + KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db + + bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] - name: Upload XCFramework uses: actions/upload-artifact@v2 with: diff --git a/Rakefile b/Rakefile index c8a63160f4..66401984fd 100644 --- a/Rakefile +++ b/Rakefile @@ -104,14 +104,24 @@ namespace :build do xcodebuild(xcframeworkInvocation.join(" ")) Dir.chdir('.build/archives') do - # Codesign the XCFramework using the "Lottie iOS" certificate installed as a secret in the lottie-ios repo. - # First we check to make sure the certificate is installed. In GitHub actions CI, only jobs run by contibutors have access - # to repo secrets, so PR jobs from external contributors won't have access to this certificate. + # Codesign the XCFramework using the "Lottie iOS Code Signing" certificate, which should be installed in the keychain. + # - Check to make sure the certificate is installed before attemtping to codesign. + # - In GitHub actions CI, only jobs run by contibutors have access to repo secrets, + # so PR jobs from external contributors won't have access to this certificate. + # In that case we skip codesigning so the job doesn't fail. puts "Checking if signing certificate is installed..." - `security find-certificate -c 'Lottie iOS'` + `security find-certificate -c 'Lottie iOS Code Signing'` if $?.success? puts "Signing certificate is installed. Code signing Lottie.xcframework." - sh 'codesign --timestamp -v --sign "Lottie iOS" Lottie.xcframework' + + # In GitHub actions the certificate is in a custom keychain, which we have to pass when codesigning. + custom_keychain_path = ENV['KEYCHAIN_PATH'] + if !custom_keychain_path.nil? && !custom_keychain_path.empty? + sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" --keychain ' + custom_keychain_path + ' Lottie.xcframework' + else + sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' + end + else puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." end From 0cc19769fd0fe4b8f1293b08f35dafd8cf6d97b6 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 13:40:42 -0800 Subject: [PATCH 04/12] Unlock keychain in build script --- .github/workflows/main.yml | 4 +++- Rakefile | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4a3e92a972..d095f7f1e2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -114,12 +114,14 @@ jobs: with: xcode: ${{ matrix.xcode }} - name: Build XCFramework + env: + KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # Once there is a production Xcode version with the visionOS SDK, we will # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. SKIP_VISION_OS=true - # Codesign using the unlocked custom keychain created in the previous step. + # Codesign using the custom keychain created in the previous step. KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] diff --git a/Rakefile b/Rakefile index 66401984fd..1f12232ed8 100644 --- a/Rakefile +++ b/Rakefile @@ -114,16 +114,20 @@ namespace :build do if $?.success? puts "Signing certificate is installed. Code signing Lottie.xcframework." - # In GitHub actions the certificate is in a custom keychain, which we have to pass when codesigning. + # In GitHub actions the certificate is in a custom keychain, which we have to unlock and use when codesigning. custom_keychain_path = ENV['KEYCHAIN_PATH'] - if !custom_keychain_path.nil? && !custom_keychain_path.empty? + custom_keychain_password = ENV['KEYCHAIN_PASSWORD'] + if !custom_keychain_path.nil? && !custom_keychain_path.empty? && !custom_keychain_password.nil? && !custom_keychain_password.empty? + puts "Unlocking and using custom keychain..." + sh 'security unlock-keychain -p "' + custom_keychain_password + '" ' + custom_keychain_path sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" --keychain ' + custom_keychain_path + ' Lottie.xcframework' else sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' end + puts "Successfully codesigned Lottie.xcframework." else - puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." + puts "Signing certificate is not installed. Lottie.xcframework will not be codesigned." end # Archive the XCFramework into a zip file From 91cc0a6acf41ace51432123e0a5944570834021a Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 14:10:53 -0800 Subject: [PATCH 05/12] Revert "Unlock keychain in build script" This reverts commit e63369d39a27c0c40a52b1f7c623202e002eecb4. --- .github/workflows/main.yml | 4 +--- Rakefile | 10 +++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d095f7f1e2..4a3e92a972 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -114,14 +114,12 @@ jobs: with: xcode: ${{ matrix.xcode }} - name: Build XCFramework - env: - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} run: | # Once there is a production Xcode version with the visionOS SDK, we will # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. SKIP_VISION_OS=true - # Codesign using the custom keychain created in the previous step. + # Codesign using the unlocked custom keychain created in the previous step. KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] diff --git a/Rakefile b/Rakefile index 1f12232ed8..66401984fd 100644 --- a/Rakefile +++ b/Rakefile @@ -114,20 +114,16 @@ namespace :build do if $?.success? puts "Signing certificate is installed. Code signing Lottie.xcframework." - # In GitHub actions the certificate is in a custom keychain, which we have to unlock and use when codesigning. + # In GitHub actions the certificate is in a custom keychain, which we have to pass when codesigning. custom_keychain_path = ENV['KEYCHAIN_PATH'] - custom_keychain_password = ENV['KEYCHAIN_PASSWORD'] - if !custom_keychain_path.nil? && !custom_keychain_path.empty? && !custom_keychain_password.nil? && !custom_keychain_password.empty? - puts "Unlocking and using custom keychain..." - sh 'security unlock-keychain -p "' + custom_keychain_password + '" ' + custom_keychain_path + if !custom_keychain_path.nil? && !custom_keychain_path.empty? sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" --keychain ' + custom_keychain_path + ' Lottie.xcframework' else sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' end - puts "Successfully codesigned Lottie.xcframework." else - puts "Signing certificate is not installed. Lottie.xcframework will not be codesigned." + puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." end # Archive the XCFramework into a zip file From 10b73057dfc8936efd8be4ff18a08556496bde05 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 14:17:01 -0800 Subject: [PATCH 06/12] Simplify by using apple-actions/import-codesign-certs --- .github/workflows/main.yml | 39 +++++++------------------------------- Rakefile | 10 +--------- 2 files changed, 8 insertions(+), 41 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4a3e92a972..3b28cf1f9d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -86,43 +86,18 @@ jobs: - '14.1' # Swift 5.7.1 steps: - uses: actions/checkout@v2 - - name: Install self-signing certificate - env: - LOTTIE_SIGNING_CERTIFICATE_BASE_64: ${{ secrets.LOTTIE_SIGNING_CERTIFICATE_BASE_64 }} - LOTTIE_SIGNING_CERTIFICATE_PASSWORD: ${{ secrets.LOTTIE_SIGNING_CERTIFICATE_PASSWORD }} - KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }} - run: | - # From https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development - # create variables - CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - - # import certificate and provisioning profile from secrets - echo -n "$LOTTIE_SIGNING_CERTIFICATE_BASE_64" | base64 --decode -o $CERTIFICATE_PATH - - # create temporary keychain - security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - security set-keychain-settings -lut 21600 $KEYCHAIN_PATH - security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH - - # import certificate to keychain - echo "Importing 'Lottie iOS Code Signing' self-signing certificate into keychain..." - security import $CERTIFICATE_PATH -P "$LOTTIE_SIGNING_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH - security list-keychain -d user -s $KEYCHAIN_PATH - echo "Successfully imported certificate." + - uses: apple-actions/import-codesign-certs@v2 + with: + p12-file-base64: ${{ secrets.SIGNING_CERTIFICATE_BASE_64 }} + p12-password: ${{ secrets.SIGNING_CERTIFICATE_PASSWORD }} - uses: ./.github/actions/setup with: xcode: ${{ matrix.xcode }} - name: Build XCFramework + # Once there is a production Xcode version with the visionOS SDK, we will + # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. run: | - # Once there is a production Xcode version with the visionOS SDK, we will - # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. - SKIP_VISION_OS=true - - # Codesign using the unlocked custom keychain created in the previous step. - KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db - - bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] + SKIP_VISION_OS=true bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] - name: Upload XCFramework uses: actions/upload-artifact@v2 with: diff --git a/Rakefile b/Rakefile index 66401984fd..93da393d30 100644 --- a/Rakefile +++ b/Rakefile @@ -113,15 +113,7 @@ namespace :build do `security find-certificate -c 'Lottie iOS Code Signing'` if $?.success? puts "Signing certificate is installed. Code signing Lottie.xcframework." - - # In GitHub actions the certificate is in a custom keychain, which we have to pass when codesigning. - custom_keychain_path = ENV['KEYCHAIN_PATH'] - if !custom_keychain_path.nil? && !custom_keychain_path.empty? - sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" --keychain ' + custom_keychain_path + ' Lottie.xcframework' - else - sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' - end - + sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' else puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." end From ac9f320f0255761e1f446ca4297f0e976a7f41d7 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 14:32:18 -0800 Subject: [PATCH 07/12] Clean up --- .github/workflows/main.yml | 5 ++--- Rakefile | 41 ++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b28cf1f9d..ff74b13573 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,9 +95,8 @@ jobs: xcode: ${{ matrix.xcode }} - name: Build XCFramework # Once there is a production Xcode version with the visionOS SDK, we will - # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true`. - run: | - SKIP_VISION_OS=true bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] + # need to also build an XCFramework using that version but without `SKIP_VISION_OS=true` + run: SKIP_VISION_OS=true bundle exec rake build:xcframework[Lottie-Xcode-${{ matrix.xcode }}] - name: Upload XCFramework uses: actions/upload-artifact@v2 with: diff --git a/Rakefile b/Rakefile index 93da393d30..a42588e233 100644 --- a/Rakefile +++ b/Rakefile @@ -69,35 +69,32 @@ namespace :build do # Build the framework for each supported platform, including simulators xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination generic/platform=iOS -archivePath ".build/archives/Lottie_iOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - - # TODO: REVERT. Just making the job shorter to help debug more quickly. - #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - #xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - - #ifVisionOSEnabled { - # xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - # xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') - #} + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=iOS Simulator" -archivePath ".build/archives/Lottie_iOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (iOS)" -destination "generic/platform=macOS,variant=Mac Catalyst" -archivePath ".build/archives/Lottie_Mac_Catalyst" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (macOS)" -destination generic/platform=macOS -archivePath ".build/archives/Lottie_macOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination generic/platform=tvOS -archivePath ".build/archives/Lottie_tvOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (tvOS)" -destination "generic/platform=tvOS Simulator" -archivePath ".build/archives/Lottie_tvOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + + ifVisionOSEnabled { + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination generic/platform=visionOS -archivePath ".build/archives/Lottie_visionOS" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + xcodebuild('archive -workspace Lottie.xcworkspace -scheme "Lottie (visionOS)" -destination "generic/platform=visionOS Simulator" -archivePath ".build/archives/Lottie_visionOS_Simulator" SKIP_INSTALL=NO BUILD_LIBRARY_FOR_DISTRIBUTION=YES ENABLE_BITCODE=NO') + } # Combine all of the platforms into a single XCFramework xcframeworkInvocation = [ '-create-xcframework', '-framework .build/archives/Lottie_iOS.xcarchive/Products/Library/Frameworks/Lottie.framework', - # TODO: REVERT. Just making the job shorter to help debug more quickly. - #'-framework .build/archives/Lottie_iOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', - #'-framework .build/archives/Lottie_Mac_Catalyst.xcarchive/Products/Library/Frameworks/Lottie.framework', - #'-framework .build/archives/Lottie_tvOS.xcarchive/Products/Library/Frameworks/Lottie.framework', - #'-framework .build/archives/Lottie_tvOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', - #'-framework .build/archives/Lottie_macOS.xcarchive/Products/Library/Frameworks/Lottie.framework', + '-framework .build/archives/Lottie_iOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', + '-framework .build/archives/Lottie_Mac_Catalyst.xcarchive/Products/Library/Frameworks/Lottie.framework', + '-framework .build/archives/Lottie_tvOS.xcarchive/Products/Library/Frameworks/Lottie.framework', + '-framework .build/archives/Lottie_tvOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework', + '-framework .build/archives/Lottie_macOS.xcarchive/Products/Library/Frameworks/Lottie.framework', ] - #ifVisionOSEnabled { - # xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS.xcarchive/Products/Library/Frameworks/Lottie.framework') - # xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework') - #} + ifVisionOSEnabled { + xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS.xcarchive/Products/Library/Frameworks/Lottie.framework') + xcframeworkInvocation.push('-framework .build/archives/Lottie_visionOS_Simulator.xcarchive/Products/Library/Frameworks/Lottie.framework') + } xcframeworkInvocation.push('-output .build/archives/Lottie.xcframework') From 6b27a6713134d8366e9588b404ae1886b4a429f6 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 15:09:03 -0800 Subject: [PATCH 08/12] Update certificate name --- Rakefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Rakefile b/Rakefile index a42588e233..76e9037e6a 100644 --- a/Rakefile +++ b/Rakefile @@ -107,10 +107,10 @@ namespace :build do # so PR jobs from external contributors won't have access to this certificate. # In that case we skip codesigning so the job doesn't fail. puts "Checking if signing certificate is installed..." - `security find-certificate -c 'Lottie iOS Code Signing'` + `security find-certificate -c 'Lottie iOS'` if $?.success? puts "Signing certificate is installed. Code signing Lottie.xcframework." - sh 'codesign --timestamp -v --sign "Lottie iOS Code Signing" Lottie.xcframework ' + sh 'codesign --timestamp -v --sign "Lottie iOS" Lottie.xcframework' else puts "Signing certificate is not installed. Lottie.xcframework will not be code signed." end From 467a3dd4625882f89a9b0b01c4bcd12111e03a3d Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 20:25:00 -0800 Subject: [PATCH 09/12] Add content about self-signing fingerprint to README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 9438b33bc8..981e0a62b1 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,15 @@ Lottie supports Swift / Xcode versions back to the minimum version that is permi Lottie does not collect any data. We provide this notice to help you fill out [App Privacy Details](https://developer.apple.com/app-store/app-privacy-details/). We additionally provide a [privacy manifest](https://github.com/airbnb/lottie-ios/blob/master/PrivacyInfo.xcprivacy) which can be included in your app. +## Security + +We distribute XCFramework bundles for each release on [GitHub](https://github.com/airbnb/lottie-ios/releases/latest). In Lottie 4.4.0 and later, these XCFramework bundles include a [code signature](https://developer.apple.com/documentation/xcode/verifying-the-origin-of-your-xcframeworks). These bundles are self-signed under the name "Lottie iOS" and have the following fingerprint: + +``` +89 2F 1B 43 04 7B 50 53 8F 2F 46 EA D9 29 00 DD +3D 48 11 F358 21 78 C0 61 A5 FB 20 F1 11 CB 26 +``` + ## Contributing We always appreciate contributions from the community. To make changes to the project, you can clone the repo and open `Lottie.xcworkspace`. This workspace includes: From ca5f1eca9b5e0e0a85c559ad5842e83fd6d016c1 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Thu, 14 Dec 2023 20:34:12 -0800 Subject: [PATCH 10/12] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 981e0a62b1..6ccd01cf88 100644 --- a/README.md +++ b/README.md @@ -90,8 +90,7 @@ Lottie does not collect any data. We provide this notice to help you fill out [A We distribute XCFramework bundles for each release on [GitHub](https://github.com/airbnb/lottie-ios/releases/latest). In Lottie 4.4.0 and later, these XCFramework bundles include a [code signature](https://developer.apple.com/documentation/xcode/verifying-the-origin-of-your-xcframeworks). These bundles are self-signed under the name "Lottie iOS" and have the following fingerprint: ``` -89 2F 1B 43 04 7B 50 53 8F 2F 46 EA D9 29 00 DD -3D 48 11 F358 21 78 C0 61 A5 FB 20 F1 11 CB 26 +89 2F 1B 43 04 7B 50 53 8F 2F 46 EA D9 29 00 DD 3D 48 11 F358 21 78 C0 61 A5 FB 20 F1 11 CB 26 ``` ## Contributing From 4ac820daafa0cdc410d30570a0b94753684ba19a Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Fri, 15 Dec 2023 08:17:05 -0800 Subject: [PATCH 11/12] Clean up --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 76e9037e6a..2a5279b997 100644 --- a/Rakefile +++ b/Rakefile @@ -101,7 +101,7 @@ namespace :build do xcodebuild(xcframeworkInvocation.join(" ")) Dir.chdir('.build/archives') do - # Codesign the XCFramework using the "Lottie iOS Code Signing" certificate, which should be installed in the keychain. + # Codesign the XCFramework using the "Lottie iOS" certificate, which should be installed in the keychain. # - Check to make sure the certificate is installed before attemtping to codesign. # - In GitHub actions CI, only jobs run by contibutors have access to repo secrets, # so PR jobs from external contributors won't have access to this certificate. From c7944f61dfd7300ca9d735df9b00c4dda0e7c739 Mon Sep 17 00:00:00 2001 From: Cal Stephens Date: Fri, 15 Dec 2023 11:23:54 -0800 Subject: [PATCH 12/12] Add information about how to verify signature in Xcode --- README.md | 4 ++++ _Gifs/code_signature.png | Bin 0 -> 46181 bytes 2 files changed, 4 insertions(+) create mode 100644 _Gifs/code_signature.png diff --git a/README.md b/README.md index 6ccd01cf88..6c8a943fd1 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,10 @@ We distribute XCFramework bundles for each release on [GitHub](https://github.co 89 2F 1B 43 04 7B 50 53 8F 2F 46 EA D9 29 00 DD 3D 48 11 F358 21 78 C0 61 A5 FB 20 F1 11 CB 26 ``` +In Xcode you can verify this by selecting `Lottie.xcframework` and confirming that it shows the following information: + +![Code Signature in Xcode](_Gifs/code_signature.png) + ## Contributing We always appreciate contributions from the community. To make changes to the project, you can clone the repo and open `Lottie.xcworkspace`. This workspace includes: diff --git a/_Gifs/code_signature.png b/_Gifs/code_signature.png new file mode 100644 index 0000000000000000000000000000000000000000..098849ac028479db9648ab39b47cede943d9b49a GIT binary patch literal 46181 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 literal 0 HcmV?d00001