diff --git a/.github/autobuild/ios.sh b/.github/autobuild/ios.sh
index 3d96df84d3..1c01e1c94d 100755
--- a/.github/autobuild/ios.sh
+++ b/.github/autobuild/ios.sh
@@ -39,17 +39,75 @@ setup() {
fi
}
+
+prepare_signing() {
+ [[ "${SIGN_IF_POSSIBLE:-0}" == "1" ]] || return 1
+
+ # Signing was requested, now check all prerequisites:
+ [[ -n "${IOSDIST_CERTIFICATE:-}" ]] || return 1
+ [[ -n "${IOSDIST_CERTIFICATE_ID:-}" ]] || return 1
+ [[ -n "${IOSDIST_CERTIFICATE_PWD:-}" ]] || return 1
+ [[ -n "${NOTARIZATION_PASSWORD:-}" ]] || return 1
+ [[ -n "${IOS_PROV_PROFILE_B64:-}" ]] || return 1
+ [[ -n "${KEYCHAIN_PASSWORD:-}" ]] || return 1
+
+ echo "Signing was requested and all dependencies are satisfied"
+
+ # use this as filename for Provisioning Profile
+ IOS_PP_PATH="embedded.mobileprovision"
+
+ ## Put the cert to a file
+ # IOSDIST_CERTIFICATE - iOS Distribution
+ echo "${IOSDIST_CERTIFICATE}" | base64 --decode > iosdist_certificate.p12
+
+ ## Echo Provisioning Profile to file
+ echo -n "${IOS_PROV_PROFILE_B64}" | base64 --decode > $IOS_PP_PATH
+
+ # Set up a keychain for the build:
+ security create-keychain -p "${KEYCHAIN_PASSWORD}" build.keychain
+ security default-keychain -s build.keychain
+ security unlock-keychain -p "${KEYCHAIN_PASSWORD}" build.keychain
+ security import iosdist_certificate.p12 -k build.keychain -P "${IOSDIST_CERTIFICATE_PWD}" -A -T /usr/bin/codesign
+ security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" build.keychain
+ # add notarization/validation/upload password to keychain
+ xcrun altool --store-password-in-keychain-item --keychain build.keychain APPCONNAUTH -u $NOTARIZATION_USER -p $NOTARIZATION_PASSWORD
+ # set lock timeout on keychain to 6 hours
+ security set-keychain-settings -lut 21600
+
+ # apply provisioning profile
+ #FIXME - maybe redundant?
+ mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
+ cp $IOS_PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
+
+ # Tell Github Workflow that we need notarization & stapling:
+ echo "::set-output name=ios_signed::true"
+ return 0
+}
+
build_app_as_ipa() {
# Add the Qt binaries to the PATH:
export PATH="${QT_DIR}/${QT_VERSION}/ios/bin:${PATH}"
- ./ios/deploy_ios.sh
+
+ # Mac's bash version considers BUILD_ARGS unset without at least one entry:
+ BUILD_ARGS=("")
+ if prepare_signing; then
+ BUILD_ARGS=("-s" "${IOSDIST_CERTIFICATE_ID}" "-k" "${KEYCHAIN_PASSWORD}")
+ fi
+ ./ios/deploy_ios.sh "${BUILD_ARGS[@]}"
}
pass_artifact_to_job() {
- local artifact="jamulus_${JAMULUS_BUILD_VERSION}_iOSUnsigned${ARTIFACT_SUFFIX:-}.ipa"
+ local artifact="jamulus_${JAMULUS_BUILD_VERSION}_iOS_unsigned${ARTIFACT_SUFFIX:-}.ipa"
echo "Moving build artifact to deploy/${artifact}"
- mv ./deploy/Jamulus.ipa "./deploy/${artifact}"
- echo "artifact_1=${artifact}" >> "$GITHUB_OUTPUT"
+ mv ./deploy/Jamulus_unsigned.ipa "./deploy/${artifact}"
+ echo "::set-output name=artifact_1::${artifact}"
+
+ local artifact2="jamulus_${JAMULUS_BUILD_VERSION}_iOS_signed${ARTIFACT_SUFFIX:-}.ipa"
+ if [ -f ./deploy/Jamulus_signed.ipa ]; then
+ echo "Moving build artifact to deploy/${artifact2}"
+ mv ./deploy/Jamulus_signed.ipa "./deploy/${artifact2}"
+ echo "::set-output name=artifact_2::${artifact2}"
+ fi
}
case "${1:-}" in
diff --git a/.github/workflows/autobuild.yml b/.github/workflows/autobuild.yml
index c88bd22812..66e863dfb4 100644
--- a/.github/workflows/autobuild.yml
+++ b/.github/workflows/autobuild.yml
@@ -252,12 +252,12 @@ jobs:
- config_name: iOS (artifacts)
target_os: ios
building_on_os: macos-11
- base_command: QT_VERSION=5.15.2 ./.github/autobuild/ios.sh
+ base_command: QT_VERSION=5.15.2 SIGN_IF_POSSIBLE=1 ./.github/autobuild/ios.sh
# Build failed with CodeQL enabled when last tested 03/2022 (#2490).
# There are no hints that iOS is supposed to be supported by CodeQL.
# Therefore, disable it:
run_codeql: false
- xcode_version: 12.5.1
+ xcode_version: 13.2.1
- config_name: Windows (artifact+codeQL)
target_os: windows
@@ -363,6 +363,10 @@ jobs:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERT}}
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERT_PWD }}
MACOS_CERTIFICATE_ID: ${{ secrets.MACOS_CERT_ID }}
+ IOSDIST_CERTIFICATE: ${{ secrets.IOSDIST_CERT}}
+ IOSDIST_CERTIFICATE_PWD: ${{ secrets.IOSDIST_CERT_PWD }}
+ IOSDIST_CERTIFICATE_ID: ${{ secrets.IOSDIST_CERT_ID }}
+ IOS_PROV_PROFILE_B64: ${{ secrets.IOS_PROVISIONING_PROFILE }}
NOTARIZATION_PASSWORD: ${{ secrets.NOTARIZATION_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
MACOS_CA_PUBLICKEY: ${{ secrets.MACOS_CA_PUBKEY }}
diff --git a/ios/Info-make.plist b/ios/Info-make.plist
new file mode 100644
index 0000000000..3b6a6c6f13
--- /dev/null
+++ b/ios/Info-make.plist
@@ -0,0 +1,57 @@
+
+
+
+
+ CFBundleExecutable
+ @EXECUTABLE@
+ CFBundleIdentifier
+ @BUNDLEIDENTIFIER@
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ @EXECUTABLE@
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSMicrophoneUsageDescription
+ We need access to your microphone to let others hear you.
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ audio
+
+ UILaunchScreen
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
+
diff --git a/ios/Info-xcode.plist b/ios/Info-xcode.plist
new file mode 100644
index 0000000000..fc10eac30e
--- /dev/null
+++ b/ios/Info-xcode.plist
@@ -0,0 +1,59 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSMicrophoneUsageDescription
+ We need access to your microphone to let others hear you.
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ audio
+
+ UILaunchScreen
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
+
diff --git a/ios/deploy_ios.sh b/ios/deploy_ios.sh
index c5c150b17d..3e0afa489c 100755
--- a/ios/deploy_ios.sh
+++ b/ios/deploy_ios.sh
@@ -1,18 +1,119 @@
#!/bin/bash
set -eu -o pipefail
-## Builds an ipa file for iOS. Should be run from the repo-root
+root_path="$(pwd)"
+project_path="${root_path}/Jamulus.pro"
+iosdeploy_path="${root_path}/ios"
+resources_path="${root_path}/src/res"
+build_path="${root_path}/build"
+deploy_path="${root_path}/deploy"
+iosdist_cert_name=""
+keychain_pass=""
-# Create Xcode file and build
-qmake -spec macx-xcode Jamulus.pro
-/usr/bin/xcodebuild -project Jamulus.xcodeproj -scheme Jamulus -configuration Release clean archive -archivePath "build/Jamulus.xcarchive" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CODE_SIGN_ENTITLEMENTS=""
+while getopts 'hs:k:' flag; do
+ case "${flag}" in
+ s)
+ iosdist_cert_name=$OPTARG
+ if [[ -z "$iosdist_cert_name" ]]; then
+ echo "Please add the name of the certificate to use: -s \"\""
+ fi
+ ;;
+ k)
+ keychain_pass=$OPTARG
+ if [[ -z "$keychain_pass" ]]; then
+ echo "Please add keychain password to use: -k \"\""
+ fi
+ ;;
+ h)
+ echo "Usage: -s for signing ios build"
+ exit 0
+ ;;
+ *)
+ exit 1
+ ;;
+ esac
+done
-# Generate ipa by copying the .app file from the xcarchive directory
-mkdir build/Payload
-cp -r build/Jamulus.xcarchive/Products/Applications/Jamulus.app build/Payload/
-cd build
-zip -0 -y -r Jamulus.ipa Payload/
+cleanup()
+{
+ # Clean up previous deployments
+ rm -rf "${build_path}"
+ rm -rf "${deploy_path}"
+ mkdir -p "${build_path}"
+ mkdir -p "${build_path}/Exports"
+ mkdir -p "${deploy_path}"
+}
-# Make a deploy folder and copy file
-mkdir ../deploy
-mv Jamulus.ipa ../deploy
+build_ipa()
+{
+ ## Builds an ipa file for iOS. Should be run from the repo-root
+
+ # Create Xcode project file
+ qmake -spec macx-xcode Jamulus.pro
+
+ # disable deprecation warnings re legacy build system - XCode 13 errors on this
+ /usr/libexec/PlistBuddy -c "Add :DisableBuildSystemDeprecationDiagnostic bool" Jamulus.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+ /usr/libexec/PlistBuddy -c "Set :DisableBuildSystemDeprecationDiagnostic true" Jamulus.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+
+ # Build
+ if [[ -z "$iosdist_cert_name" ]]; then
+ # Build unsigned
+ /usr/bin/xcodebuild -project Jamulus.xcodeproj -scheme Jamulus -configuration Release clean archive \
+ -archivePath "build/Jamulus.xcarchive" \
+ CODE_SIGN_IDENTITY="" \
+ CODE_SIGNING_REQUIRED=NO \
+ CODE_SIGNING_ALLOWED=NO \
+ CODE_SIGN_ENTITLEMENTS=""
+ else
+ # Build signed ipa file
+ # Ref: https://developer.apple.com/forums/thread/70326
+ # // Builds the app into an archive
+ /usr/bin/xcodebuild -project Jamulus.xcodeproj -scheme Jamulus -configuration Release clean archive \
+ -archivePath "build/Jamulus.xcarchive" \
+ DEVELOPMENT_TEAM="XXXXXXXXXX" \
+ CODE_SIGN_IDENTITY="" \
+ CODE_SIGNING_REQUIRED=NO \
+ CODE_SIGNING_ALLOWED=NO
+
+ #FIXME this may be redundant - since provisioning profile is specified in exportOptionsRelease.plist
+ cp ~/Library/MobileDevice/Provisioning\ Profiles/embedded.mobileprovision build/Jamulus.xcarchive/Products/Applications/Jamulus.app/
+
+ # // Exports the archive according to the export options specified by the plist
+ # export signed installer to build/Exports/Jamulus.ipa
+ /usr/bin/xcodebuild -exportArchive \
+ -archivePath "build/Jamulus.xcarchive" \
+ -exportPath "build/Exports/" \
+ -exportOptionsPlist "ios/exportOptionsRelease.plist" \
+ DEVELOPMENT_TEAM="XXXXXXXXXX" \
+ CODE_SIGN_IDENTITY="${iosdist_cert_name}" \
+ CODE_SIGNING_REQUIRED=YES \
+ CODE_SIGNING_ALLOWED=YES \
+ CODE_SIGN_STYLE="Manual"
+
+ # if validate/upload
+ xcrun altool --validate-app -f "${build_path}/Exports/Jamulus.ipa" -t ios -p @keychain:APPCONNAUTH
+ xcrun altool --upload-app -f "${build_path}/Exports/Jamulus.ipa" -t ios -p @keychain:APPCONNAUTH
+ fi
+
+ # Generate unsigned ipa by copying the .app structure from the xcarchive directory
+ cd ${root_path}
+ mkdir -p build/unsigned/Payload
+ cp -r build/Jamulus.xcarchive/Products/Applications/Jamulus.app build/unsigned/Payload/
+ cd build/unsigned
+ zip -0 -y -r Jamulus.ipa Payload/
+
+ # copy files
+ cd ${root_path}
+ # unsigned IPA
+ mv build/unsigned/Jamulus.ipa deploy/Jamulus_unsigned.ipa
+ # signed IPA
+ if [[ ! -z "$iosdist_cert_name" ]]; then
+ mv build/Exports/Jamulus.ipa deploy/Jamulus_signed.ipa
+ fi
+}
+
+# Cleanup previous deployments
+cleanup
+
+# Build ipa file for App Store submission (eg via Transporter etc)
+build_ipa
\ No newline at end of file
diff --git a/ios/exportOptionsRelease.plist b/ios/exportOptionsRelease.plist
new file mode 100644
index 0000000000..0cafc0a921
--- /dev/null
+++ b/ios/exportOptionsRelease.plist
@@ -0,0 +1,15 @@
+
+
+
+
+ method
+ app-store
+ teamID
+ XXXXXXXXXX
+ provisioningProfiles
+
+ io.jamulus.Jamulus
+ UUID_GOES_HERE
+
+
+
\ No newline at end of file