mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Implement macOS code-signing (not tested, let's see if CI works, very unlikely).
This commit is contained in:
32
.github/workflows/ecode-nightly.yml
vendored
32
.github/workflows/ecode-nightly.yml
vendored
@@ -271,6 +271,11 @@ jobs:
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
MACOS_CERTIFICATE_P12_B64: ${{ secrets.MACOS_CERTIFICATE_P12_B64 }}
|
||||
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
||||
MACOS_APPLE_ID: ${{ secrets.MACOS_APPLE_ID }}
|
||||
MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
|
||||
MACOS_TEAM_ID: ${{ secrets.MACOS_TEAM_ID }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
@@ -293,9 +298,20 @@ jobs:
|
||||
run: |
|
||||
bash projects/scripts/patch_commit_number.sh
|
||||
bash projects/macos/ecode/build.app.sh --version ${{ env.INSTALL_REF }}
|
||||
- name: Sign Application
|
||||
if: env.MACOS_CERTIFICATE_P12_B64 != ''
|
||||
working-directory: projects/macos/ecode
|
||||
run: |
|
||||
bash ./sign.sh ecode.app
|
||||
- name: Create DMG Image
|
||||
run: |
|
||||
bash projects/macos/ecode/create.dmg.sh --version ${{ env.INSTALL_REF }}
|
||||
- name: Notarize DMG
|
||||
if: env.MACOS_CERTIFICATE_P12_B64 != ''
|
||||
working-directory: projects/macos/ecode
|
||||
run: |
|
||||
DMG_NAME="ecode-macos-${{ env.INSTALL_REF }}-arm64.dmg"
|
||||
bash ./sign.sh "$DMG_NAME"
|
||||
- name: Upload Files
|
||||
uses: softprops/action-gh-release@v2.2.2
|
||||
with:
|
||||
@@ -315,6 +331,11 @@ jobs:
|
||||
env:
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
MACOS_CERTIFICATE_P12_B64: ${{ secrets.MACOS_CERTIFICATE_P12_B64 }}
|
||||
MACOS_CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }}
|
||||
MACOS_APPLE_ID: ${{ secrets.MACOS_APPLE_ID }}
|
||||
MACOS_NOTARIZATION_PASSWORD: ${{ secrets.MACOS_NOTARIZATION_PASSWORD }}
|
||||
MACOS_TEAM_ID: ${{ secrets.MACOS_TEAM_ID }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
@@ -341,9 +362,20 @@ jobs:
|
||||
run: |
|
||||
bash projects/scripts/patch_commit_number.sh
|
||||
bash projects/macos/ecode/cross.build.app.sh --version ${{ env.INSTALL_REF }}
|
||||
- name: Sign Application
|
||||
if: env.MACOS_CERTIFICATE_P12_B64 != ''
|
||||
working-directory: projects/macos/ecode
|
||||
run: |
|
||||
bash ./sign.sh ecode.app
|
||||
- name: Create DMG Image
|
||||
run: |
|
||||
bash projects/macos/ecode/cross.create.dmg.sh --version ${{ env.INSTALL_REF }}
|
||||
- name: Notarize DMG
|
||||
if: env.MACOS_CERTIFICATE_P12_B64 != ''
|
||||
working-directory: projects/macos/ecode
|
||||
run: |
|
||||
DMG_NAME="ecode-macos-${{ env.INSTALL_REF }}-x86_64.dmg"
|
||||
bash ./sign.sh "$DMG_NAME"
|
||||
- name: Upload Files
|
||||
uses: softprops/action-gh-release@v2.2.2
|
||||
with:
|
||||
|
||||
@@ -508,7 +508,7 @@ Generate the project:
|
||||
|
||||
And build it:
|
||||
|
||||
`make -C make/macosx config=release_x86_64` (or `config=debug_x86_64` for a debug build)
|
||||
`make -C make/macosx config=release_x86_64` (or `config=debug_x86_64` for a debug build, or `release_arm64`/`debug_arm64` if building from arm64)
|
||||
|
||||
##### Using premake4
|
||||
|
||||
|
||||
14
projects/macos/ecode/entitlements.plist
Normal file
14
projects/macos/ecode/entitlements.plist
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<false/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
143
projects/macos/ecode/sign.sh
Normal file
143
projects/macos/ecode/sign.sh
Normal file
@@ -0,0 +1,143 @@
|
||||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
|
||||
# Change to the script's directory to ensure relative paths are stable.
|
||||
CANONPATH=$(readlink -f "$0")
|
||||
DIRPATH="$(dirname "$CANONPATH")"
|
||||
cd "$DIRPATH" || exit
|
||||
|
||||
# This script handles code signing and notarization for the macOS app.
|
||||
# It's designed to be called from the CI environment.
|
||||
#
|
||||
# It expects the following environment variables to be set for real signing:
|
||||
# - MACOS_CERTIFICATE_P12_B64: The base64 encoded .p12 certificate.
|
||||
# - MACOS_CERTIFICATE_PASSWORD: The password for the .p12 certificate.
|
||||
# - MACOS_APPLE_ID: Your Apple ID email used for notarization.
|
||||
# - MACOS_NOTARIZATION_PASSWORD: An app-specific password for your Apple ID.
|
||||
# - MACOS_TEAM_ID: Your Apple Developer Team ID.
|
||||
#
|
||||
# If these variables are not set, it will fall back to ad-hoc (self) signing for .app bundles
|
||||
# and skip notarization for .dmg files.
|
||||
|
||||
# The first argument is the path to the artifact, relative to this script's location.
|
||||
ARTIFACT_PATH="$1"
|
||||
# The entitlements file is in the same directory as this script.
|
||||
ENTITLEMENTS_PATH="entitlements.plist"
|
||||
|
||||
if [[ -z "$ARTIFACT_PATH" ]]; then
|
||||
echo "Usage: $0 <path_to_app_or_dmg>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -e "$ARTIFACT_PATH" ]]; then
|
||||
echo "Error: Artifact not found at '$ARTIFACT_PATH'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- AD-HOC SIGNING (if no credentials) ---
|
||||
if [[ -z "$MACOS_CERTIFICATE_P12_B64" ]]; then
|
||||
if [[ "$ARTIFACT_PATH" == *.app ]]; then
|
||||
echo "No signing certificate found. Performing ad-hoc signing..."
|
||||
# Find and sign all binaries within the app bundle
|
||||
find "$ARTIFACT_PATH/Contents/MacOS/" -type f -exec codesign --force --sign - {} \;
|
||||
codesign --force --sign - "$ARTIFACT_PATH"
|
||||
echo "Ad-hoc signing complete."
|
||||
fi
|
||||
# For .dmg files, we just skip if no credentials
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Credentials found. Proceeding with official signing and notarization..."
|
||||
|
||||
# --- KEYCHAIN AND CERTIFICATE SETUP ---
|
||||
KEYCHAIN_NAME="build.keychain"
|
||||
KEYCHAIN_PASSWORD="a-very-secure-password"
|
||||
CERTIFICATE_P12_PATH="certificate.p12"
|
||||
|
||||
# Decode the certificate
|
||||
echo "$MACOS_CERTIFICATE_P12_B64" | base64 --decode > "$CERTIFICATE_P12_PATH"
|
||||
|
||||
# Create a temporary keychain
|
||||
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME"
|
||||
security default-keychain -s "$KEYCHAIN_NAME"
|
||||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME"
|
||||
security set-keychain-settings -t 3600 -u "$KEYCHAIN_NAME"
|
||||
|
||||
# Import the certificate into the keychain
|
||||
security import "$CERTIFICATE_P12_PATH" -k "$KEYCHAIN_NAME" -P "$MACOS_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
|
||||
|
||||
# Allow codesign to access the certificate
|
||||
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_NAME" > /dev/null
|
||||
|
||||
# Find the signing identity
|
||||
SIGNING_IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_NAME" | grep "Developer ID Application" | head -n 1 | awk -F '"' '{print $2}')
|
||||
if [[ -z "$SIGNING_IDENTITY" ]]; then
|
||||
echo "Error: Signing identity not found in keychain."
|
||||
exit 1
|
||||
fi
|
||||
echo "Using signing identity: $SIGNING_IDENTITY"
|
||||
|
||||
|
||||
# --- MAIN LOGIC ---
|
||||
|
||||
# Function to sign the .app bundle
|
||||
sign_app() {
|
||||
echo "Signing application bundle at: $ARTIFACT_PATH"
|
||||
# Sign all dylibs, frameworks and executables from the inside out
|
||||
find "$ARTIFACT_PATH" -depth -name "*.dylib" -o -name "*.framework" -o -path "$ARTIFACT_PATH/Contents/MacOS/*" -type f | while read -r comp; do
|
||||
echo "Signing component: $comp"
|
||||
codesign --force --verify --verbose --sign "$SIGNING_IDENTITY" --options runtime --timestamp "$comp"
|
||||
done
|
||||
|
||||
echo "Signing main application bundle with entitlements..."
|
||||
codesign --force --verify --verbose --sign "$SIGNING_IDENTITY" --entitlements "$ENTITLEMENTS_PATH" --options runtime --timestamp "$ARTIFACT_PATH"
|
||||
echo "App signing complete."
|
||||
}
|
||||
|
||||
# Function to notarize and staple the .dmg
|
||||
notarize_dmg() {
|
||||
echo "Notarizing DMG at: $ARTIFACT_PATH"
|
||||
|
||||
# Submit for notarization and wait for it to complete
|
||||
NOTARY_OUTPUT=$(xcrun notarytool submit "$ARTIFACT_PATH" \
|
||||
--apple-id "$MACOS_APPLE_ID" \
|
||||
--password "$MACOS_NOTARIZATION_PASSWORD" \
|
||||
--team-id "$MACOS_TEAM_ID" \
|
||||
--wait 2>&1)
|
||||
|
||||
echo "$NOTARY_OUTPUT"
|
||||
|
||||
# Check for success
|
||||
if ! echo "$NOTARY_OUTPUT" | grep -q "Status: Accepted"; then
|
||||
echo "Error: Notarization failed."
|
||||
# Attempt to get logs for debugging
|
||||
REQUEST_UUID=$(echo "$NOTARY_OUTPUT" | grep "id:" | awk '{print $2}')
|
||||
if [[ -n "$REQUEST_UUID" ]]; then
|
||||
echo "Fetching notarization logs for UUID: $REQUEST_UUID"
|
||||
xcrun notarytool log "$REQUEST_UUID" --apple-id "$MACOS_APPLE_ID" --password "$MACOS_NOTARIZATION_PASSWORD" --team-id "$MACOS_TEAM_ID"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Notarization successful. Stapling ticket to DMG..."
|
||||
xcrun stapler staple "$ARTIFACT_PATH"
|
||||
echo "Stapling complete."
|
||||
}
|
||||
|
||||
# --- CLEANUP ---
|
||||
cleanup() {
|
||||
echo "Cleaning up..."
|
||||
security delete-keychain "$KEYCHAIN_NAME" || true
|
||||
rm -f "$CERTIFICATE_P12_PATH"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# --- EXECUTION ---
|
||||
if [[ "$ARTIFACT_PATH" == *.app ]]; then
|
||||
sign_app
|
||||
elif [[ "$ARTIFACT_PATH" == *.dmg ]]; then
|
||||
notarize_dmg
|
||||
else
|
||||
echo "Unsupported artifact type: $ARTIFACT_PATH"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user