Skip to content

Commit 2b2911b

Browse files
authored
Add a script to install Apple certificate for CI iOS jobs
Differential Revision: D61707676 Pull Request resolved: #4703
1 parent f560682 commit 2b2911b

File tree

4 files changed

+112
-3
lines changed

4 files changed

+112
-3
lines changed

.ci/scripts/setup-ios.sh

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
set -exu
9+
10+
# This script follows the instructions from GitHub to install an Apple certificate
11+
# https://docs.github.com/en/actions/use-cases-and-examples/deploying/installing-an-apple-certificate-on-macos-runners-for-xcode-development
12+
13+
CERTIFICATE_PATH="${RUNNER_TEMP}"/build_certificate.p12
14+
PP_PATH="${RUNNER_TEMP}"/build_pp.mobileprovision
15+
KEYCHAIN_PATH="${RUNNER_TEMP}"/app-signing.keychain-db
16+
17+
# Import certificate and provisioning profile from secrets
18+
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH
19+
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode -o $PP_PATH
20+
21+
# Create a temporary keychain
22+
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
23+
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
24+
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
25+
26+
# Import certificate to the keychain
27+
security import $CERTIFICATE_PATH -P "" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
28+
security set-key-partition-list -S apple-tool:,apple: -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
29+
security list-keychain -d user -s $KEYCHAIN_PATH
30+
31+
# Apply provisioning profile
32+
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
33+
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles

.github/workflows/apple.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
pull_request:
99
paths:
1010
- .ci/docker/**
11+
- .ci/scripts/setup-ios.sh
1112
- .github/workflows/apple.yml
1213
- install_requirements.sh
1314
- backends/apple/**
@@ -27,24 +28,35 @@ jobs:
2728
test-demo-ios:
2829
name: test-demo-ios
2930
uses: pytorch/test-infra/.github/workflows/macos_job.yml@main
31+
secrets: inherit
3032
with:
3133
runner: macos-latest-xlarge
3234
python-version: '3.11'
3335
submodules: 'true'
3436
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
3537
timeout: 90
38+
secrets-env: BUILD_CERTIFICATE_BASE64 EXECUTORCH_DEMO_BUILD_PROVISION_PROFILE_BASE64 KEYCHAIN_PASSWORD
39+
upload-artifact: ios-apps
3640
script: |
3741
BUILD_TOOL=cmake
3842
3943
.ci/scripts/setup-conda.sh
4044
45+
# Setup Apple certificate for iOS development
46+
BUILD_PROVISION_PROFILE_BASE64="${SECRET_EXECUTORCH_DEMO_BUILD_PROVISION_PROFILE_BASE64}" \
47+
BUILD_CERTIFICATE_BASE64="${SECRET_BUILD_CERTIFICATE_BASE64}" \
48+
KEYCHAIN_PASSWORD="${SECRET_KEYCHAIN_PASSWORD}" \
49+
.ci/scripts/setup-ios.sh
50+
4151
# Setup MacOS dependencies as there is no Docker support on MacOS atm
4252
GITHUB_RUNNER=1 PYTHON_EXECUTABLE=python ${CONDA_RUN} --no-capture-output \
4353
.ci/scripts/setup-macos.sh "${BUILD_TOOL}"
4454
55+
export ARTIFACTS_DIR_NAME=artifacts-to-be-uploaded
56+
4557
# Build and test iOS Demo App
4658
PYTHON_EXECUTABLE=python ${CONDA_RUN} --no-capture-output \
47-
build/test_ios_ci.sh
59+
build/test_ios_ci.sh ${ARTIFACTS_DIR_NAME}
4860
4961
build-frameworks-ios:
5062
name: build-frameworks-ios

build/test_ios_ci.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ APP_PATH="examples/demo-apps/apple_ios/ExecuTorchDemo/ExecuTorchDemo"
1111
MODEL_NAME="mv3"
1212
SIMULATOR_NAME="executorch"
1313

14+
# If this is set, copy the build artifacts to this directory
15+
ARTIFACTS_DIR_NAME="$1"
16+
1417
finish() {
1518
EXIT_STATUS=$?
1619
if xcrun simctl list | grep -q "$SIMULATOR_NAME"; then
@@ -64,3 +67,49 @@ xcodebuild test \
6467
-project "$APP_PATH.xcodeproj" \
6568
-scheme MobileNetClassifierTest \
6669
-destination name="$SIMULATOR_NAME"
70+
71+
# NB: https://docs.aws.amazon.com/devicefarm/latest/developerguide/test-types-ios-xctest-ui.html
72+
say "Package The Test Suite"
73+
74+
xcodebuild build-for-testing \
75+
-project "$APP_PATH.xcodeproj" \
76+
-scheme MobileNetClassifierTest \
77+
-destination platform="iOS" \
78+
-allowProvisioningUpdates \
79+
DEVELOPMENT_TEAM=78E7V7QP35 \
80+
CODE_SIGN_STYLE=Manual \
81+
PROVISIONING_PROFILE_SPECIFIER=ExecuTorchDemo \
82+
CODE_SIGN_IDENTITY="iPhone Distribution"
83+
84+
# The hack to figure out where the xctest package locates
85+
BUILD_DIR=$(xcodebuild -showBuildSettings -project "$APP_PATH.xcodeproj" -json | jq -r ".[0].buildSettings.BUILD_DIR")
86+
87+
# Prepare the demo app
88+
MODE="Debug"
89+
PLATFORM="iphoneos"
90+
pushd "${BUILD_DIR}/${MODE}-${PLATFORM}"
91+
92+
rm -rf Payload && mkdir Payload
93+
MOCK_APP_NAME=ExecuTorchDemo
94+
95+
ls -lah
96+
cp -r "${MOCK_APP_NAME}.app" Payload && zip -vr "${MOCK_APP_NAME}.ipa" Payload
97+
98+
popd
99+
100+
# Prepare the test suite
101+
pushd "${BUILD_DIR}"
102+
103+
ls -lah
104+
zip -vr "${MOCK_APP_NAME}.xctestrun.zip" *.xctestrun
105+
106+
popd
107+
108+
if [[ -n "${ARTIFACTS_DIR_NAME}" ]]; then
109+
mkdir -p "${ARTIFACTS_DIR_NAME}"
110+
# Prepare all the artifacts to upload
111+
cp "${BUILD_DIR}/${MODE}-${PLATFORM}/${MOCK_APP_NAME}.ipa" "${ARTIFACTS_DIR_NAME}/"
112+
cp "${BUILD_DIR}/${MOCK_APP_NAME}.xctestrun.zip" "${ARTIFACTS_DIR_NAME}/"
113+
114+
ls -lah "${ARTIFACTS_DIR_NAME}/"
115+
fi

examples/demo-apps/apple_ios/ExecuTorchDemo/ExecuTorchDemo.xcodeproj/project.pbxproj

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@
5959
remoteGlobalIDString = 03C818302AC79FCD0084CC29;
6060
remoteInfo = ImageClassification;
6161
};
62+
84EF1FE92C7850B6005922B4 /* PBXContainerItemProxy */ = {
63+
isa = PBXContainerItemProxy;
64+
containerPortal = 032C01672AC228E5002955E1 /* Project object */;
65+
proxyType = 1;
66+
remoteGlobalIDString = 032C016E2AC228E6002955E1;
67+
remoteInfo = App;
68+
};
6269
/* End PBXContainerItemProxy section */
6370

6471
/* Begin PBXCopyFilesBuildPhase section */
@@ -330,6 +337,7 @@
330337
buildRules = (
331338
);
332339
dependencies = (
340+
84EF1FEA2C7850B6005922B4 /* PBXTargetDependency */,
333341
);
334342
name = MobileNetClassifierTest;
335343
packageProductDependencies = (
@@ -489,6 +497,11 @@
489497
target = 03C818302AC79FCD0084CC29 /* ImageClassification */;
490498
targetProxy = 03C818452AC7A0DB0084CC29 /* PBXContainerItemProxy */;
491499
};
500+
84EF1FEA2C7850B6005922B4 /* PBXTargetDependency */ = {
501+
isa = PBXTargetDependency;
502+
target = 032C016E2AC228E6002955E1 /* App */;
503+
targetProxy = 84EF1FE92C7850B6005922B4 /* PBXContainerItemProxy */;
504+
};
492505
/* End PBXTargetDependency section */
493506

494507
/* Begin XCBuildConfiguration section */
@@ -633,7 +646,7 @@
633646
INFOPLIST_KEY_UIRequiresFullScreen = YES;
634647
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
635648
MARKETING_VERSION = 1.0;
636-
PRODUCT_BUNDLE_IDENTIFIER = org.pytorch.executorch.demo;
649+
PRODUCT_BUNDLE_IDENTIFIER = org.pytorch.executorch.demo.test;
637650
PRODUCT_NAME = "$(PROJECT_NAME)";
638651
PROVISIONING_PROFILE_SPECIFIER = "";
639652
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -661,7 +674,7 @@
661674
INFOPLIST_KEY_UIRequiresFullScreen = YES;
662675
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
663676
MARKETING_VERSION = 1.0;
664-
PRODUCT_BUNDLE_IDENTIFIER = org.pytorch.executorch.demo;
677+
PRODUCT_BUNDLE_IDENTIFIER = org.pytorch.executorch.demo.test;
665678
PRODUCT_NAME = "$(PROJECT_NAME)";
666679
PROVISIONING_PROFILE_SPECIFIER = "";
667680
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
@@ -703,6 +716,7 @@
703716
SUPPORTS_MACCATALYST = NO;
704717
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
705718
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
719+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ExecuTorchDemo.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/ExecuTorchDemo";
706720
};
707721
name = Debug;
708722
};
@@ -717,6 +731,7 @@
717731
PRODUCT_NAME = "$(TARGET_NAME)";
718732
SUPPORTS_MACCATALYST = NO;
719733
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
734+
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ExecuTorchDemo.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/ExecuTorchDemo";
720735
};
721736
name = Release;
722737
};

0 commit comments

Comments
 (0)