Skip to content

Ensure universal build support for package installation #5

Ensure universal build support for package installation

Ensure universal build support for package installation #5

Workflow file for this run

name: Build, sign, and notarize pull requests
on:
pull_request_target:
types:
- labeled
jobs:
build:
name: Xcode build, sign, and notarize
runs-on: macos-26
if: contains(github.event.pull_request.labels.*.name, 'buildable')
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Install app signing certificates
uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0
with:
keychain-password: ${{ github.run_id }}
p12-file-base64: ${{ secrets.APP_CERTIFICATES_P12_MAOS }}
p12-password: ${{ secrets.APP_CERTIFICATES_P12_PASSWORD_MAOS }}
- name: Install package signing certificates
uses: apple-actions/import-codesign-certs@8f3fb608891dd2244cdab3d69cd68c0d37a7fe93 # v2.0.0
with:
create-keychain: false
keychain-password: ${{ github.run_id }}
p12-file-base64: ${{ secrets.PKG_CERTIFICATES_P12_MAOS }}
p12-password: ${{ secrets.PKG_CERTIFICATES_P12_PASSWORD_MAOS }}
- name: Build release app
run: |
xcodebuild \
-project "AutoPkg Wizard/AutoPkg Wizard.xcodeproj" \
-scheme "AutoPkg Wizard" \
-configuration Release ARCHS="arm64 x86_64" ONLY_ACTIVE_ARCH=NO \
-destination "platform=macOS" \
SYMROOT="$(pwd)/.build" \
build
- name: Set environment variables
run: |
VERSION=$(grep 'MARKETING_VERSION = ' "AutoPkg Wizard/AutoPkg Wizard.xcodeproj/project.pbxproj" | head -1 | sed 's/.*= //;s/;//;s/ //g')
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "APP_PATH=$(pwd)/.build/Release/AutoPkg Wizard.app" >> $GITHUB_ENV
- name: Sign app bundle
run: |
# Sign embedded frameworks and libraries
find "$APP_PATH/Contents/Frameworks" -maxdepth 1 \
\( -name "*.framework" -o -name "*.dylib" \) 2>/dev/null | \
while IFS= read -r item; do
echo "Signing: $item"
/usr/bin/codesign --force --options runtime --timestamp \
--sign "${{ vars.SIGN_ID_APP }}" "$item"
done
# Sign the app bundle
/usr/bin/codesign --force --options runtime --timestamp \
--sign "${{ vars.SIGN_ID_APP }}" "$APP_PATH"
# Verify
/usr/bin/codesign --verify --deep --strict --verbose=2 "$APP_PATH"
- name: Notarize app
run: |
# Zip app for notarization
/usr/bin/ditto -c -k --keepParent "$APP_PATH" "/tmp/AutoPkgWizard.zip"
# Store credentials and submit
xcrun notarytool store-credentials \
--apple-id "${{ vars.NOTARY_APPLE_ID }}" \
--team-id "${{ vars.TEAM_ID }}" \
--password "${{ secrets.NOTARY_APP_PASSWORD_MAOS }}" \
default
xcrun notarytool submit "/tmp/AutoPkgWizard.zip" \
--keychain-profile "default" \
--wait
# Staple
xcrun stapler staple "$APP_PATH"
rm -f /tmp/AutoPkgWizard.zip
- name: Build installer package
run: |
mkdir -p artifacts
COMPONENT="artifacts/AutoPkgWizard-component.pkg"
DIST_XML="artifacts/distribution.xml"
# Verify universal binary
ARCHS=$(lipo -archs "$APP_PATH/Contents/MacOS/AutoPkg Wizard" 2>/dev/null || echo "error")
if [ "$ARCHS" = "error" ]; then
echo "ERROR: Could not read architectures from $APP_PATH" >&2
echo " Binary may be missing or invalid." >&2
exit 1
fi
echo "App architectures: $ARCHS"
if ! echo "$ARCHS" | grep -q "arm64"; then
echo "ERROR: App does not contain arm64 architecture. Found: $ARCHS" >&2
exit 1
fi
if ! echo "$ARCHS" | grep -q "x86_64"; then
echo "ERROR: App does not contain x86_64 architecture. Found: $ARCHS" >&2
exit 1
fi
# Create component package
pkgbuild \
--component "$APP_PATH" \
--install-location /Applications \
--identifier "com.grahamrpugh.AutoPkg-Wizard" \
--version "$VERSION" \
--sign "${{ vars.SIGN_ID_PKG }}" \
"$COMPONENT"
# Write distribution XML
cat > "$DIST_XML" <<EOF
<?xml version="1.0" encoding="utf-8"?>
<installer-gui-script minSpecVersion="2">
<title>AutoPkg Wizard</title>
<pkg-ref id="com.grahamrpugh.AutoPkg-Wizard"/>
<options customize="never" require-scripts="false" rootVolumeOnly="true" hostArchitectures="arm64,x86_64"/>
<choices-outline>
<line choice="default">
<line choice="com.grahamrpugh.AutoPkg-Wizard"/>
</line>
</choices-outline>
<choice id="default"/>
<choice id="com.grahamrpugh.AutoPkg-Wizard" visible="false">
<pkg-ref id="com.grahamrpugh.AutoPkg-Wizard"/>
</choice>
<pkg-ref id="com.grahamrpugh.AutoPkg-Wizard" version="$VERSION" onConclusion="none">AutoPkgWizard-component.pkg</pkg-ref>
</installer-gui-script>
EOF
# Create distribution package
productbuild \
--distribution "$DIST_XML" \
--package-path artifacts \
--sign "${{ vars.SIGN_ID_PKG }}" \
"artifacts/AutoPkgWizard-${VERSION}.pkg"
rm -f "$COMPONENT" "$DIST_XML"
- name: Notarize package
run: |
xcrun notarytool submit "artifacts/AutoPkgWizard-${VERSION}.pkg" \
--keychain-profile "default" \
--wait
xcrun stapler staple "artifacts/AutoPkgWizard-${VERSION}.pkg"
- name: Build DMG
run: |
DMG_STAGING=$(mktemp -d)
cp -R "$APP_PATH" "$DMG_STAGING/AutoPkg Wizard.app"
ln -s /Applications "$DMG_STAGING/Applications"
hdiutil create \
-volname "AutoPkg Wizard" \
-srcfolder "$DMG_STAGING" \
-ov \
-format UDZO \
-imagekey zlib-level=9 \
"artifacts/AutoPkgWizard-${VERSION}.dmg"
xcrun stapler staple "artifacts/AutoPkgWizard-${VERSION}.dmg" || true
rm -rf "$DMG_STAGING"
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts
path: artifacts/