2121 - name : Checkout
2222 uses : actions/checkout@v4
2323
24+ - name : Install signing certificate
25+ env :
26+ BUILD_CERTIFICATE_BASE64 : ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
27+ P12_PASSWORD : ${{ secrets.P12_PASSWORD }}
28+ KEYCHAIN_PASSWORD : ${{ secrets.KEYCHAIN_PASSWORD }}
29+ run : |
30+ CERTIFICATE_PATH="$RUNNER_TEMP/build_certificate.p12"
31+ KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
32+ CERTIFICATE_BASE64_PATH="$RUNNER_TEMP/build_certificate.base64"
33+
34+ printf '%s' "$BUILD_CERTIFICATE_BASE64" > "$CERTIFICATE_BASE64_PATH"
35+ base64 -D -i "$CERTIFICATE_BASE64_PATH" -o "$CERTIFICATE_PATH"
36+
37+ security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
38+ security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
39+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
40+ security import "$CERTIFICATE_PATH" -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
41+ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
42+ security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
43+
2444 - name : Set version
2545 id : version
2646 run : |
@@ -36,44 +56,76 @@ jobs:
3656 echo "is_release=false" >> $GITHUB_OUTPUT
3757 fi
3858
39- - name : Build
59+ - name : Archive
4060 run : |
4161 xcodebuild \
4262 -project Wave.xcodeproj \
4363 -scheme Wave \
4464 -configuration Release \
65+ -archivePath build/Wave.xcarchive \
4566 -derivedDataPath build \
67+ archive \
4668 MARKETING_VERSION="${{ steps.version.outputs.marketing_version }}" \
4769 CURRENT_PROJECT_VERSION="${{ steps.version.outputs.marketing_version }}" \
48- CODE_SIGNING_ALLOWED=NO \
49- CODE_SIGNING_REQUIRED=NO \
70+ CODE_SIGN_IDENTITY="Developer ID Application" \
71+ OTHER_CODE_SIGN_FLAGS="--keychain $RUNNER_TEMP/app-signing.keychain-db" \
5072 STRIP_INSTALLED_PRODUCT=YES \
5173 DEAD_CODE_STRIPPING=YES \
5274 DEBUG_INFORMATION_FORMAT=dwarf-with-dsym \
5375 SWIFT_OPTIMIZATION_LEVEL=-Osize \
5476 SWIFT_COMPILATION_MODE=wholemodule \
5577 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES=NO
5678
79+ - name : Export signed app
80+ env :
81+ APPLE_TEAM_ID : ${{ secrets.APPLE_TEAM_ID }}
82+ run : |
83+ cat <<EOF > "$RUNNER_TEMP/ExportOptions.plist"
84+ <?xml version="1.0" encoding="UTF-8"?>
85+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
86+ <plist version="1.0">
87+ <dict>
88+ <key>method</key>
89+ <string>developer-id</string>
90+ <key>signingStyle</key>
91+ <string>automatic</string>
92+ <key>signingCertificate</key>
93+ <string>Developer ID Application</string>
94+ <key>teamID</key>
95+ <string>${APPLE_TEAM_ID}</string>
96+ </dict>
97+ </plist>
98+ EOF
99+
100+ xcodebuild \
101+ -exportArchive \
102+ -archivePath build/Wave.xcarchive \
103+ -exportPath build/export \
104+ -exportOptionsPlist "$RUNNER_TEMP/ExportOptions.plist" \
105+ OTHER_CODE_SIGN_FLAGS="--keychain $RUNNER_TEMP/app-signing.keychain-db"
106+
57107 - name : Debug app size
58108 run : |
59109 echo "=== App bundle total ==="
60- du -sh build/Build/Products/Release /Wave.app
110+ du -sh build/export /Wave.app
61111 echo "=== Contents breakdown ==="
62- du -sh build/Build/Products/Release /Wave.app/Contents/*
112+ du -sh build/export /Wave.app/Contents/*
63113 echo "=== Frameworks ==="
64- du -sh build/Build/Products/Release /Wave.app/Contents/Frameworks/* 2>/dev/null || echo "No frameworks"
114+ du -sh build/export /Wave.app/Contents/Frameworks/* 2>/dev/null || echo "No frameworks"
65115 echo "=== Binary ==="
66- du -sh build/Build/Products/Release /Wave.app/Contents/MacOS/*
116+ du -sh build/export /Wave.app/Contents/MacOS/*
67117 echo "=== Plugins/XPC ==="
68- du -sh build/Build/Products/Release /Wave.app/Contents/PlugIns/* 2>/dev/null || echo "No plugins"
118+ du -sh build/export /Wave.app/Contents/PlugIns/* 2>/dev/null || echo "No plugins"
69119 echo "=== Resources (top level) ==="
70- du -sh build/Build/Products/Release /Wave.app/Contents/Resources/* 2>/dev/null | sort -rh | head -20
120+ du -sh build/export /Wave.app/Contents/Resources/* 2>/dev/null | sort -rh | head -20
71121
72- - name : Ad-hoc sign
73- run : codesign --force --deep --sign - build/Build/Products/Release/Wave.app
122+ - name : Verify signed app
123+ run : |
124+ codesign --verify --deep --strict --verbose=2 build/export/Wave.app
125+ spctl -a -vvv -t execute build/export/Wave.app
74126
75127 - name : Upload app
76- run : ditto -c -k --sequesterRsrc --keepParent build/Build/Products/Release /Wave.app Wave.app.zip
128+ run : ditto -c -k --sequesterRsrc --keepParent build/export /Wave.app Wave.app.zip
77129
78130 - name : Upload app artifact
79131 uses : actions/upload-artifact@v4
@@ -97,6 +149,26 @@ jobs:
97149 - name : Extract app
98150 run : ditto -x -k Wave.app.zip .
99151
152+ - name : Install signing certificate
153+ env :
154+ BUILD_CERTIFICATE_BASE64 : ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
155+ P12_PASSWORD : ${{ secrets.P12_PASSWORD }}
156+ KEYCHAIN_PASSWORD : ${{ secrets.KEYCHAIN_PASSWORD }}
157+ run : |
158+ CERTIFICATE_PATH="$RUNNER_TEMP/build_certificate.p12"
159+ KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
160+ CERTIFICATE_BASE64_PATH="$RUNNER_TEMP/build_certificate.base64"
161+
162+ printf '%s' "$BUILD_CERTIFICATE_BASE64" > "$CERTIFICATE_BASE64_PATH"
163+ base64 -D -i "$CERTIFICATE_BASE64_PATH" -o "$CERTIFICATE_PATH"
164+
165+ security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
166+ security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
167+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
168+ security import "$CERTIFICATE_PATH" -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
169+ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
170+ security list-keychains -d user -s "$KEYCHAIN_PATH" $(security list-keychains -d user | tr -d '"')
171+
100172 - name : Install create-dmg
101173 run : brew install create-dmg
102174
@@ -118,6 +190,35 @@ jobs:
118190 "$DMG_NAME" \
119191 Wave.app/
120192
193+ - name : Sign DMG
194+ run : |
195+ DMG_NAME="${{ steps.dmg.outputs.dmg_name }}"
196+ codesign --force --sign "Developer ID Application" --keychain "$RUNNER_TEMP/app-signing.keychain-db" "$DMG_NAME"
197+ codesign --verify --verbose=2 "$DMG_NAME"
198+
199+ - name : Notarize and staple DMG
200+ env :
201+ APPLE_ID : ${{ secrets.APPLE_ID }}
202+ APPLE_APP_SPECIFIC_PASSWORD : ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
203+ APPLE_TEAM_ID : ${{ secrets.APPLE_TEAM_ID }}
204+ run : |
205+ DMG_NAME="${{ steps.dmg.outputs.dmg_name }}"
206+ KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db"
207+
208+ xcrun notarytool store-credentials wave-notary \
209+ --apple-id "$APPLE_ID" \
210+ --team-id "$APPLE_TEAM_ID" \
211+ --password "$APPLE_APP_SPECIFIC_PASSWORD" \
212+ --keychain "$KEYCHAIN_PATH"
213+
214+ xcrun notarytool submit "$DMG_NAME" \
215+ --keychain-profile wave-notary \
216+ --keychain "$KEYCHAIN_PATH" \
217+ --wait
218+
219+ xcrun stapler staple "$DMG_NAME"
220+ spctl -a -t open --context context:primary-signature -vv "$DMG_NAME"
221+
121222 - name : Upload DMG
122223 uses : actions/upload-artifact@v4
123224 with :
0 commit comments