Skip to content

Commit 4152729

Browse files
danryusoftins
authored andcommitted
Add signed package build and App Store submission
This commit combines all the changes made by Dan G into one.
1 parent cbbdb1a commit 4152729

File tree

3 files changed

+113
-11
lines changed

3 files changed

+113
-11
lines changed

.github/autobuild/mac.sh

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,24 @@ setup() {
7171
}
7272

7373
prepare_signing() {
74+
## Certificate types in use:
75+
# - MACOS_CERTIFICATE - Developer ID Application - for codesigning for adhoc release
76+
# - MAC_STORE_APP_CERT - Mac App Distribution - codesigning for App Store submission
77+
# - MAC_STORE_INST_CERT - Mac Installer Distribution - for signing installer pkg file for App Store submission
78+
7479
[[ "${SIGN_IF_POSSIBLE:-0}" == "1" ]] || return 1
7580

7681
# Signing was requested, now check all prerequisites:
7782
[[ -n "${MACOS_CERTIFICATE:-}" ]] || return 1
7883
[[ -n "${MACOS_CERTIFICATE_ID:-}" ]] || return 1
7984
[[ -n "${MACOS_CERTIFICATE_PWD:-}" ]] || return 1
85+
[[ -n "${MAC_STORE_APP_CERT:-}" ]] || return 1
86+
[[ -n "${MAC_STORE_APP_CERT_ID:-}" ]] || return 1
87+
[[ -n "${MAC_STORE_APP_CERT_PWD:-}" ]] || return 1
88+
[[ -n "${MAC_STORE_INST_CERT:-}" ]] || return 1
89+
[[ -n "${MAC_STORE_INST_CERT_ID:-}" ]] || return 1
90+
[[ -n "${MAC_STORE_INST_CERT_PWD:-}" ]] || return 1
91+
[[ -n "${NOTARIZATION_PASSWORD:-}" ]] || return 1
8092
[[ -n "${KEYCHAIN_PASSWORD:-}" ]] || return 1
8193

8294
# Check for notarization (not wanted on self signed build)
@@ -90,8 +102,16 @@ prepare_signing() {
90102

91103
echo "Signing was requested and all dependencies are satisfied"
92104

93-
# Put the cert to a file
94-
echo "${MACOS_CERTIFICATE}" | base64 --decode > certificate.p12
105+
## Put the certs to files
106+
echo "${MACOS_CERTIFICATE}" | base64 --decode > macos_certificate.p12
107+
108+
# If distribution cert is present, set for store signing + submission
109+
if [[ -n "${MAC_STORE_APP_CERT}" ]]; then
110+
echo "${MAC_STORE_APP_CERT}" | base64 --decode > macapp_certificate.p12
111+
echo "${MAC_STORE_INST_CERT}" | base64 --decode > macinst_certificate.p12
112+
# Tell Github Workflow that we are building for store submission
113+
echo "macos_store=true" >> "$GITHUB_OUTPUT"
114+
fi
95115

96116
# If set, put the CA public key into a file
97117
if [[ -n "${MACOS_CA_PUBLICKEY}" ]]; then
@@ -104,8 +124,10 @@ prepare_signing() {
104124
# Remove default re-lock timeout to avoid codesign hangs:
105125
security set-keychain-settings build.keychain
106126
security unlock-keychain -p "${KEYCHAIN_PASSWORD}" build.keychain
107-
security import certificate.p12 -k build.keychain -P "${MACOS_CERTIFICATE_PWD}" -T /usr/bin/codesign
108-
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "${KEYCHAIN_PASSWORD}" build.keychain
127+
security import macos_certificate.p12 -k build.keychain -P "${MACOS_CERTIFICATE_PWD}" -A -T /usr/bin/codesign
128+
security import macapp_certificate.p12 -k build.keychain -P "${MAC_STORE_APP_CERT_PWD}" -A -T /usr/bin/codesign
129+
security import macinst_certificate.p12 -k build.keychain -P "${MAC_STORE_INST_CERT_PWD}" -A -T /usr/bin/productbuild
130+
security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" build.keychain
109131

110132
# Tell Github Workflow that we want signing
111133
echo "macos_signed=true" >> "$GITHUB_OUTPUT"
@@ -136,7 +158,7 @@ build_app_as_dmg_installer() {
136158
# Mac's bash version considers BUILD_ARGS unset without at least one entry:
137159
BUILD_ARGS=("")
138160
if prepare_signing; then
139-
BUILD_ARGS=("-s" "${MACOS_CERTIFICATE_ID}")
161+
BUILD_ARGS=("-s" "${MACOS_CERTIFICATE_ID}" "-a" "${MAC_STORE_APP_CERT_ID}" "-i" "${MAC_STORE_INST_CERT_ID}" "-k" "${KEYCHAIN_PASSWORD}")
140162
fi
141163
TARGET_ARCHS="${TARGET_ARCHS}" ./mac/deploy_mac.sh "${BUILD_ARGS[@]}"
142164
}
@@ -146,6 +168,27 @@ pass_artifact_to_job() {
146168
echo "Moving build artifact to deploy/${artifact}"
147169
mv ./deploy/Jamulus-*installer-mac.dmg "./deploy/${artifact}"
148170
echo "artifact_1=${artifact}" >> "$GITHUB_OUTPUT"
171+
172+
artifact2="jamulus_${JAMULUS_BUILD_VERSION}_mac${ARTIFACT_SUFFIX:-}.pkg"
173+
for file in ./deploy/Jamulus_*.pkg; do
174+
if [ -f "${file}" ]; then
175+
echo "Moving build artifact2 to deploy/${artifact2}"
176+
mv "${file}" "./deploy/${artifact2}"
177+
echo "artifact_2=${artifact2}" >> "$GITHUB_OUTPUT"
178+
fi
179+
done
180+
}
181+
182+
appstore_submit() {
183+
echo "Submitting package to AppStore Connect..."
184+
# test the signature of package
185+
pkgutil --check-signature "${ARTIFACT_PATH}"
186+
187+
xcrun notarytool submit "${ARTIFACT_PATH}" \
188+
--apple-id "${NOTARIZATION_USERNAME}" \
189+
--team-id "${APPLE_TEAM_ID}" \
190+
--password "${NOTARIZATION_PASSWORD}" \
191+
--wait
149192
}
150193

151194
case "${1:-}" in
@@ -158,6 +201,9 @@ case "${1:-}" in
158201
get-artifacts)
159202
pass_artifact_to_job
160203
;;
204+
appstore-submit)
205+
appstore_submit
206+
;;
161207
*)
162208
echo "Unknown stage '${1:-}'"
163209
exit 1

.github/workflows/autobuild.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,12 @@ jobs:
368368
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERT}}
369369
MACOS_CERTIFICATE_PWD: ${{ secrets.MACOS_CERT_PWD }}
370370
MACOS_CERTIFICATE_ID: ${{ secrets.MACOS_CERT_ID }}
371+
MAC_STORE_APP_CERT: ${{ secrets.MACAPP_CERT}}
372+
MAC_STORE_APP_CERT_PWD: ${{ secrets.MACAPP_CERT_PWD }}
373+
MAC_STORE_APP_CERT_ID: ${{ secrets.MACAPP_CERT_ID }}
374+
MAC_STORE_INST_CERT: ${{ secrets.MACAPP_INST_CERT}}
375+
MAC_STORE_INST_CERT_PWD: ${{ secrets.MACAPP_INST_CERT_PWD }}
376+
MAC_STORE_INST_CERT_ID: ${{ secrets.MACAPP_INST_CERT_ID }}
371377
NOTARIZATION_PASSWORD: ${{ secrets.NOTARIZATION_PASSWORD }}
372378
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
373379
MACOS_CA_PUBLICKEY: ${{ secrets.MACOS_CA_PUBKEY }}
@@ -430,6 +436,20 @@ jobs:
430436
env:
431437
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
432438

439+
## RELEASE PROCEDURE FOR: macOS App Store - storesigned pkg
440+
- name: Validate and Upload macOS Storesign Pkg
441+
if: >-
442+
steps.build.outputs.macos_store == 'true' &&
443+
needs.create_release.outputs.publish_to_release == 'true'
444+
id: macos_validate_upload
445+
run: ${{ matrix.config.base_command }} appstore-submit
446+
env:
447+
ARTIFACT_PATH: deploy/${{ steps.get-artifacts.outputs.artifact_2 }}
448+
NOTARIZATION_USERNAME: ${{ secrets.NOTARIZATION_USERNAME }}
449+
NOTARIZATION_PASSWORD: ${{ secrets.NOTARIZATION_PASSWORD }}
450+
JAMULUS_BUILD_VERSION: ${{ needs.create_release.outputs.build_version }}
451+
APPLE_TEAM_ID: XXXXXXXXXXX
452+
433453
- name: Perform CodeQL Analysis
434454
if: matrix.config.run_codeql
435455
uses: github/codeql-action/analyze@v3

mac/deploy_mac.sh

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,36 @@ resources_path="${root_path}/src/res"
77
build_path="${root_path}/build"
88
deploy_path="${root_path}/deploy"
99
cert_name=""
10+
macapp_cert_name=""
11+
macinst_cert_name=""
12+
keychain_pass=""
1013

11-
while getopts 'hs:' flag; do
14+
while getopts 'hs:k:a:i:' flag; do
1215
case "${flag}" in
1316
s)
1417
cert_name=$OPTARG
1518
if [[ -z "$cert_name" ]]; then
1619
echo "Please add the name of the certificate to use: -s \"<name>\""
1720
fi
1821
;;
22+
a)
23+
macapp_cert_name=$OPTARG
24+
if [[ -z "$macapp_cert_name" ]]; then
25+
echo "Please add the name of the codesigning certificate to use: -a \"<name>\""
26+
fi
27+
;;
28+
i)
29+
macinst_cert_name=$OPTARG
30+
if [[ -z "$macinst_cert_name" ]]; then
31+
echo "Please add the name of the installer signing certificate to use: -i \"<name>\""
32+
fi
33+
;;
34+
k)
35+
keychain_pass=$OPTARG
36+
if [[ -z "$keychain_pass" ]]; then
37+
echo "Please add keychain password to use: -k \"<name>\""
38+
fi
39+
;;
1940
h)
2041
echo "Usage: -s <cert name> for signing mac build"
2142
exit 0
@@ -83,6 +104,25 @@ build_app() {
83104
else
84105
macdeployqt "${build_path}/${target_name}.app" -verbose=2 -always-overwrite -hardened-runtime -timestamp -appstore-compliant -sign-for-notarization="${cert_name}"
85106
fi
107+
108+
## Build installer pkg file - for submission to App Store
109+
if [[ -z "$macapp_cert_name" ]]; then
110+
echo "No cert to sign for App Store, bypassing..."
111+
else
112+
# Clone the build directory to leave the adhoc signed app untouched
113+
cp -a "${build_path}" "${build_path}_storesign"
114+
115+
# Add Qt deployment deps and codesign the app for App Store submission
116+
macdeployqt "${build_path}_storesign/${target_name}.app" -verbose=2 -always-overwrite -hardened-runtime -timestamp -appstore-compliant -sign-for-notarization="${macapp_cert_name}"
117+
118+
# Create pkg installer and sign for App Store submission
119+
productbuild --sign "${macinst_cert_name}" --keychain build.keychain --component "${build_path}_storesign/${target_name}.app" /Applications "${build_path}/Jamulus_${JAMULUS_BUILD_VERSION}.pkg"
120+
121+
# move created pkg file to prep for download
122+
mv "${build_path}/Jamulus_${JAMULUS_BUILD_VERSION}.pkg" "${deploy_path}"
123+
fi
124+
125+
# move app bundle to prep for dmg creation
86126
mv "${build_path}/${target_name}.app" "${deploy_path}"
87127

88128
# Cleanup
@@ -114,10 +154,6 @@ build_installer_image() {
114154
# FIXME: Currently caching is disabled due to an error in the extract step
115155
brew install create-dmg
116156

117-
# Get Jamulus version
118-
local app_version
119-
app_version=$(sed -nE 's/^VERSION *= *(.*)$/\1/p' "${project_path}")
120-
121157
# Build installer image
122158

123159
# When this script is run on Github's CI with CodeQL enabled, CodeQL adds dynamic library
@@ -141,7 +177,7 @@ build_installer_image() {
141177
--icon "${client_target_name}.app" 630 210 \
142178
--icon "${server_target_name}.app" 530 210 \
143179
--eula "${root_path}/COPYING" \
144-
"${deploy_path}/${client_target_name}-${app_version}-installer-mac.dmg" \
180+
"${deploy_path}/${client_target_name}-${JAMULUS_BUILD_VERSION}-installer-mac.dmg" \
145181
"${deploy_path}/"
146182
}
147183

0 commit comments

Comments
 (0)