From b5d3ea8b919b0bf1ff57ff71f7572af6c0ccc03c Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Sat, 6 Nov 2021 16:55:59 -0700 Subject: [PATCH] Attempt to get signing working for the macOS build - Updates CI instructions to match Ishiiruka - Copies over necessary signing and notarization build files - Updates name from `Slippi_Dolphin` to `Slippi Dolphin (Beta)`. This may not work and might still need some tweaking due to project ID mismatch, but testing CI without pushing directly is a pain. --- .github/workflows/main.yml | 43 +- Tools/create-dmg/LICENSE | 22 + Tools/create-dmg/README.md | 8 + Tools/create-dmg/builder/create-dmg.builder | 26 + Tools/create-dmg/run.sh | 478 ++++++++++++++++++ .../support/eula-resources-template.xml | 105 ++++ Tools/create-dmg/support/template.applescript | 74 +++ Tools/load-macos-certs-ci.sh | 28 + Tools/notarize_netplay.sh | 76 +++ 9 files changed, 853 insertions(+), 7 deletions(-) create mode 100644 Tools/create-dmg/LICENSE create mode 100644 Tools/create-dmg/README.md create mode 100644 Tools/create-dmg/builder/create-dmg.builder create mode 100755 Tools/create-dmg/run.sh create mode 100644 Tools/create-dmg/support/eula-resources-template.xml create mode 100644 Tools/create-dmg/support/template.applescript create mode 100644 Tools/load-macos-certs-ci.sh create mode 100644 Tools/notarize_netplay.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2718aff5c5..8272c49798 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -226,21 +226,50 @@ jobs: if: success() shell: bash working-directory: ${{ github.workspace }} + env: + CERTIFICATE_MACOS_APPLICATION: ${{ secrets.CERTIFICATE_MACOS_APPLICATION }} run: | + export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/lib chmod +x ./build-mac.sh && ./build-mac.sh ${{ matrix.build_config }} - - name: Package ${{ matrix.build_type }} - if: success() + mkdir artifact + FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-${{ matrix.artifact_name }} + echo "FILE_NAME=$FILE_NAME" >> $GITHUB_ENV + - name: "Package, Sign and Notarize Netplay Release DMG" + if: success() && env.CERTIFICATE_MACOS_APPLICATION != null shell: bash working-directory: ${{ github.workspace }} + env: + APPLE_API_KEY: ${{ secrets.APPLE_API_KEY_ID }} + APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} + CERTIFICATE_MACOS_APPLICATION: ${{ secrets.CERTIFICATE_MACOS_APPLICATION }} run: | - FILE_NAME=${{ env.CURR_DATE }}-${{ env.GIT_HASH }}-${{ env.GIT_TAG }}-${{ matrix.artifact_name }}.tar.gz - mkdir artifact - cd ./build/Binaries/ - zip -r "${FILE_NAME}" "Slippi_Dolphin.app" - mv "${FILE_NAME}" ../../artifact/ + rm build/Binaries/traversal_server + chmod +x Tools/create-dmg/run.sh + ./Tools/create-dmg/run.sh --no-internet-enable \ + --volname "Slippi Dolphin Beta Installer" \ + --volicon "Data/slippi_dmg_icon.icns" \ + --background "Data/slippi_dmg_background.png" \ + --text-size 14 \ + --window-pos 200 120 \ + --window-size 590 610 \ + --icon-size 100 \ + --app-drop-link 440 196 \ + --icon "Slippi_Dolphin.app" 140 196 \ + --hide-extension "Slippi_Dolphin.app" \ + "${{ env.FILE_NAME }}.dmg" \ + "./build/Binaries/" + mv "${{ env.FILE_NAME }}.dmg" artifact/ + /usr/bin/codesign -f -s "${{ secrets.APPLE_IDENTITY_HASH }}" --deep --options runtime ./artifact/${{ env.FILE_NAME }}.dmg + chmod +x Tools/notarize_netplay.sh && ./Tools/notarize_netplay.sh ./artifact/${{ env.FILE_NAME }}.dmg - name: "Publish" if: success() uses: actions/upload-artifact@v3 with: name: ${{ matrix.artifact_name }} path: "./artifact/" + #- name: "Enable Admin Debugging via SSH (if failed)" + # if: failure() + # uses: luchihoratiu/debug-via-ssh@main + # with: + # NGROK_AUTH_TOKEN: ${{ secrets.NGROK_TOKEN }} + # SSH_PASS: ${{ secrets.NGROK_PASS }} diff --git a/Tools/create-dmg/LICENSE b/Tools/create-dmg/LICENSE new file mode 100644 index 0000000000..deb407f2ee --- /dev/null +++ b/Tools/create-dmg/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2008-2014 Andrey Tarantsov +Copyright (c) 2020 Andrew Janke + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Tools/create-dmg/README.md b/Tools/create-dmg/README.md new file mode 100644 index 0000000000..4b03274cf9 --- /dev/null +++ b/Tools/create-dmg/README.md @@ -0,0 +1,8 @@ +## create-dmg +A small fork of create-dmg, which has an edited `hidutil detach` call. Why the fork? + +- GitHub Actions will sometimes just die on trying to detach properly. +- We don't want to have to retry the entire create-dmg flow just to get it right. +- Forking is just easier to get the inner loop for what we want. + +See the project here: https://github.com/create-dmg/create-dmg diff --git a/Tools/create-dmg/builder/create-dmg.builder b/Tools/create-dmg/builder/create-dmg.builder new file mode 100644 index 0000000000..d4285280f1 --- /dev/null +++ b/Tools/create-dmg/builder/create-dmg.builder @@ -0,0 +1,26 @@ +SET app_name create-dmg + +VERSION create-dmg.cur create-dmg heads/master + +NEWDIR build.dir temp %-build - + +NEWFILE create-dmg.zip featured %.zip % + + +COPYTO [build.dir] + INTO create-dmg [create-dmg.cur]/create-dmg + INTO sample [create-dmg.cur]/sample + INTO support [create-dmg.cur]/support + +SUBSTVARS [build.dir]/create-dmg [[]] + + +ZIP [create-dmg.zip] + INTO [build-files-prefix] [build.dir] + + +PUT megabox-builds create-dmg.zip +PUT megabox-builds build.log + +PUT s3-builds create-dmg.zip +PUT s3-builds build.log diff --git a/Tools/create-dmg/run.sh b/Tools/create-dmg/run.sh new file mode 100755 index 0000000000..162b0defae --- /dev/null +++ b/Tools/create-dmg/run.sh @@ -0,0 +1,478 @@ +#!/usr/bin/env bash +# +# Pulled from https://github.com/create-dmg/create-dmg/blob/master/create-dmg, with +# minor edits to make unmounting on GitHub actions less of a pain. + +# Create a read-only disk image of the contents of a folder + +# Bail out on any unhandled errors +set -e; + +CDMG_VERSION='1.0.9-SNAPSHOT' + +# The full path to the "support/" directory this script is using +# (This will be set up by code later in the script.) +CDMG_SUPPORT_DIR="" + +WINX=10 +WINY=60 +WINW=500 +WINH=350 +ICON_SIZE=128 +TEXT_SIZE=16 +FORMAT="UDZO" +ADD_FILE_SOURCES=() +ADD_FILE_TARGETS=() +IMAGEKEY="" +HDIUTIL_VERBOSITY="" +SANDBOX_SAFE=0 +SKIP_JENKINS=0 + +function pure_version() { + echo "$CDMG_VERSION" +} + +function version() { + echo "create-dmg $(pure_version)" +} + +function usage() { + version + cat < +All contents of will be copied into the disk image. +Options: + --volname + set volume name (displayed in the Finder sidebar and window title) + --volicon + set volume icon + --background + set folder background image (provide png, gif, or jpg) + --window-pos + set position the folder window + --window-size + set size of the folder window + --text-size + set window text size (10-16) + --icon-size + set window icons size (up to 128) + --icon file_name + set position of the file's icon + --hide-extension + hide the extension of file + --app-drop-link + make a drop link to Applications, at location x,y + --ql-drop-link + make a drop link to user QuickLook install dir, at location x,y + --eula + attach a license file to the dmg (plain text or RTF) + --no-internet-enable + disable automatic mount & copy + --format + specify the final image format (default is UDZO) + --add-file | + add additional file or folder (can be used multiple times) + --disk-image-size + set the disk image size manually to x MB + --hdiutil-verbose + execute hdiutil in verbose mode + --hdiutil-quiet + execute hdiutil in quiet mode + --sandbox-safe + execute hdiutil with sandbox compatibility and do not bless + --version + show create-dmg version number + -h, --help + display this help screen +EOHELP + exit 0 +} + +# Argument parsing + +while [[ "${1:0:1}" = "-" ]]; do + case $1 in + --volname) + VOLUME_NAME="$2" + shift; shift;; + --volicon) + VOLUME_ICON_FILE="$2" + shift; shift;; + --background) + BACKGROUND_FILE="$2" + BACKGROUND_FILE_NAME="$(basename "$BACKGROUND_FILE")" + BACKGROUND_CLAUSE="set background picture of opts to file \".background:$BACKGROUND_FILE_NAME\"" + REPOSITION_HIDDEN_FILES_CLAUSE="set position of every item to {theBottomRightX + 100, 100}" + shift; shift;; + --icon-size) + ICON_SIZE="$2" + shift; shift;; + --text-size) + TEXT_SIZE="$2" + shift; shift;; + --window-pos) + WINX=$2; WINY=$3 + shift; shift; shift;; + --window-size) + WINW=$2; WINH=$3 + shift; shift; shift;; + --icon) + POSITION_CLAUSE="${POSITION_CLAUSE}set position of item \"$2\" to {$3, $4} + " + shift; shift; shift; shift;; + --hide-extension) + HIDING_CLAUSE="${HIDING_CLAUSE}set the extension hidden of item \"$2\" to true + " + shift; shift;; + -h | --help) + usage;; + --version) + version; exit 0;; + --pure-version) + pure_version; exit 0;; + --ql-drop-link) + QL_LINK=$2 + QL_CLAUSE="set position of item \"QuickLook\" to {$2, $3} + " + shift; shift; shift;; + --app-drop-link) + APPLICATION_LINK=$2 + APPLICATION_CLAUSE="set position of item \"Applications\" to {$2, $3} + " + shift; shift; shift;; + --eula) + EULA_RSRC=$2 + shift; shift;; + --no-internet-enable) + NOINTERNET=1 + shift;; + --format) + FORMAT="$2" + shift; shift;; + --add-file | --add-folder) + ADD_FILE_TARGETS+=("$2") + ADD_FILE_SOURCES+=("$3") + POSITION_CLAUSE="${POSITION_CLAUSE} + set position of item \"$2\" to {$4, $5} + " + shift; shift; shift; shift; shift;; + --disk-image-size) + DISK_IMAGE_SIZE="$2" + shift; shift;; + --hdiutil-verbose) + HDIUTIL_VERBOSITY='-verbose' + shift;; + --hdiutil-quiet) + HDIUTIL_VERBOSITY='-quiet' + shift;; + --sandbox-safe) + SANDBOX_SAFE=1 + shift;; + --rez) + echo "REZ is no more directly used. You can remove the --rez argument." + shift; shift;; + --skip-jenkins) + SKIP_JENKINS=1 + shift;; + -*) + echo "Unknown option: $1. Run 'create-dmg --help' for help." + exit 1;; + esac + case $FORMAT in + UDZO) + IMAGEKEY="-imagekey zlib-level=9";; + UDBZ) + IMAGEKEY="-imagekey bzip2-level=9";; + *) + echo >&2 "Unknown format: $FORMAT" + exit 1;; + esac +done + +if [[ -z "$2" ]]; then + echo "Not enough arguments. Run 'create-dmg --help' for help." + exit 1 +fi + +DMG_PATH="$1" +SRC_FOLDER="$(cd "$2" > /dev/null; pwd)" + +# Argument validation checks + +if [[ "${DMG_PATH: -4}" != ".dmg" ]]; then + echo "Output file name must end with a .dmg extension. Run 'create-dmg --help' for help." + exit 1 +fi + +# Main script logic + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +DMG_DIRNAME="$(dirname "$DMG_PATH")" +DMG_DIR="$(cd "$DMG_DIRNAME" > /dev/null; pwd)" +DMG_NAME="$(basename "$DMG_PATH")" +DMG_TEMP_NAME="$DMG_DIR/rw.${DMG_NAME}" + +# Detect where we're running from +# Our fork can just assume this folder, since we have it locally. +echo $SCRIPT_DIR +CDMG_SUPPORT_DIR="$SCRIPT_DIR/support" +#sentinel_file="$SCRIPT_DIR/.this-is-the-create-dmg-repo" +#if [[ -f "$sentinel_file" ]]; then +# # We're running from inside a repo +# CDMG_SUPPORT_DIR="$SCRIPT_DIR/support" +#else +# # We're running inside an installed location +# bin_dir="$SCRIPT_DIR" +# prefix_dir=$(dirname "$bin_dir") +# CDMG_SUPPORT_DIR="$prefix_dir/share/create-dmg/support" +#fi + +if [[ -z "$VOLUME_NAME" ]]; then + VOLUME_NAME="$(basename "$DMG_PATH" .dmg)" +fi + +if [[ ! -d "$CDMG_SUPPORT_DIR" ]]; then + echo >&2 "Cannot find support/ directory: expected at: $CDMG_SUPPORT_DIR" +# exit 1 +fi + +if [[ -f "$SRC_FOLDER/.DS_Store" ]]; then + echo "Deleting .DS_Store found in source folder" + rm "$SRC_FOLDER/.DS_Store" +fi + +# Create the image +echo "Creating disk image..." +if [[ -f "${DMG_TEMP_NAME}" ]]; then + rm -f "${DMG_TEMP_NAME}" +fi + +# Use Megabytes since hdiutil fails with very large byte numbers +function blocks_to_megabytes() { + # Add 1 extra MB, since there's no decimal retention here + MB_SIZE=$((($1 * 512 / 1000 / 1000) + 1)) + echo $MB_SIZE +} + +function get_size() { + # Get block size in disk + bytes_size=$(du -s "$1" | sed -e 's/ .*//g') + echo $(blocks_to_megabytes $bytes_size) +} + +# Create the DMG with the specified size or the hdiutil estimation +CUSTOM_SIZE='' +if [[ -n "$DISK_IMAGE_SIZE" ]]; then + CUSTOM_SIZE="-size ${DISK_IMAGE_SIZE}m" +fi + +if [[ $SANDBOX_SAFE -eq 0 ]]; then + hdiutil create ${HDIUTIL_VERBOSITY} -srcfolder "$SRC_FOLDER" -volname "${VOLUME_NAME}" \ + -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW ${CUSTOM_SIZE} "${DMG_TEMP_NAME}" +else + hdiutil makehybrid ${HDIUTIL_VERBOSITY} -default-volume-name "${VOLUME_NAME}" -hfs -o "${DMG_TEMP_NAME}" "$SRC_FOLDER" + hdiutil convert -format UDRW -ov -o "${DMG_TEMP_NAME}" "${DMG_TEMP_NAME}" + DISK_IMAGE_SIZE_CUSTOM=$DISK_IMAGE_SIZE +fi + +# Get the created DMG actual size +DISK_IMAGE_SIZE=$(get_size "${DMG_TEMP_NAME}") + +# Use the custom size if bigger +if [[ $SANDBOX_SAFE -eq 1 ]] && [[ ! -z "$DISK_IMAGE_SIZE_CUSTOM" ]] && [[ $DISK_IMAGE_SIZE_CUSTOM -gt $DISK_IMAGE_SIZE ]]; then + DISK_IMAGE_SIZE=$DISK_IMAGE_SIZE_CUSTOM +fi + +# Estimate the additional soruces size +if [[ -n "$ADD_FILE_SOURCES" ]]; then + for i in "${!ADD_FILE_SOURCES[@]}"; do + SOURCE_SIZE=$(get_size "${ADD_FILE_SOURCES[$i]}") + DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + $SOURCE_SIZE) + done +fi + +# Add extra space for additional resources +DISK_IMAGE_SIZE=$(expr $DISK_IMAGE_SIZE + 20) + +# Make sure target image size is within limits +MIN_DISK_IMAGE_SIZE=$(hdiutil resize -limits "${DMG_TEMP_NAME}" | awk 'NR=1{print int($1/2048+1)}') +if [ $MIN_DISK_IMAGE_SIZE -gt $DISK_IMAGE_SIZE ]; then + DISK_IMAGE_SIZE=$MIN_DISK_IMAGE_SIZE +fi + +# Resize the image for the extra stuff +hdiutil resize ${HDIUTIL_VERBOSITY} -size ${DISK_IMAGE_SIZE}m "${DMG_TEMP_NAME}" + +# Mount the new DMG + +MOUNT_DIR="/Volumes/${VOLUME_NAME}" + +# Unmount leftover dmg if it was mounted previously (e.g. developer mounted dmg, installed app and forgot to unmount it) +if [[ -d "${MOUNT_DIR}" ]]; then + echo "Unmounting old disk image from $MOUNT_DIR..." + DEV_NAME=$(hdiutil info | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}') + hdiutil detach "${DEV_NAME}" +fi + +echo "Mounting disk image..." + +echo "Mount directory: $MOUNT_DIR" +DEV_NAME=$(hdiutil attach -readwrite -noverify -noautoopen "${DMG_TEMP_NAME}" | egrep --color=never '^/dev/' | sed 1q | awk '{print $1}') +echo "Device name: $DEV_NAME" + +if [[ -n "$BACKGROUND_FILE" ]]; then + echo "Copying background file..." + [[ -d "$MOUNT_DIR/.background" ]] || mkdir "$MOUNT_DIR/.background" + cp "$BACKGROUND_FILE" "$MOUNT_DIR/.background/$BACKGROUND_FILE_NAME" +fi + +if [[ -n "$APPLICATION_LINK" ]]; then + echo "Making link to Applications dir..." + echo $MOUNT_DIR + ln -s /Applications "$MOUNT_DIR/Applications" +fi + +if [[ -n "$QL_LINK" ]]; then + echo "Making link to QuickLook install dir..." + echo $MOUNT_DIR + ln -s "/Library/QuickLook" "$MOUNT_DIR/QuickLook" +fi + +if [[ -n "$VOLUME_ICON_FILE" ]]; then + echo "Copying volume icon file '$VOLUME_ICON_FILE'..." + cp "$VOLUME_ICON_FILE" "$MOUNT_DIR/.VolumeIcon.icns" + SetFile -c icnC "$MOUNT_DIR/.VolumeIcon.icns" +fi + +if [[ -n "$ADD_FILE_SOURCES" ]]; then + echo "Copying custom files..." + for i in "${!ADD_FILE_SOURCES[@]}"; do + echo "${ADD_FILE_SOURCES[$i]}" + cp -a "${ADD_FILE_SOURCES[$i]}" "$MOUNT_DIR/${ADD_FILE_TARGETS[$i]}" + done +fi + +# Run AppleScript to do all the Finder cosmetic stuff +APPLESCRIPT_FILE=$(mktemp -t createdmg.tmp.XXXXXXXXXX) +if [[ $SANDBOX_SAFE -eq 1 ]]; then + echo "Skipping Finder-prettifying AppleScript because we are in Sandbox..." +else + if [[ $SKIP_JENKINS -eq 0 ]]; then + cat "$CDMG_SUPPORT_DIR/template.applescript" \ + | sed -e "s/WINX/$WINX/g" -e "s/WINY/$WINY/g" -e "s/WINW/$WINW/g" \ + -e "s/WINH/$WINH/g" -e "s/BACKGROUND_CLAUSE/$BACKGROUND_CLAUSE/g" \ + -e "s/REPOSITION_HIDDEN_FILES_CLAUSE/$REPOSITION_HIDDEN_FILES_CLAUSE/g" \ + -e "s/ICON_SIZE/$ICON_SIZE/g" -e "s/TEXT_SIZE/$TEXT_SIZE/g" \ + | perl -pe "s/POSITION_CLAUSE/$POSITION_CLAUSE/g" \ + | perl -pe "s/QL_CLAUSE/$QL_CLAUSE/g" \ + | perl -pe "s/APPLICATION_CLAUSE/$APPLICATION_CLAUSE/g" \ + | perl -pe "s/HIDING_CLAUSE/$HIDING_CLAUSE/" \ + > "$APPLESCRIPT_FILE" + sleep 2 # pause to workaround occasional "Can’t get disk" (-1728) issues + echo "Running AppleScript to make Finder stuff pretty: /usr/bin/osascript \"${APPLESCRIPT_FILE}\" \"${VOLUME_NAME}\"" + if /usr/bin/osascript "${APPLESCRIPT_FILE}" "${VOLUME_NAME}"; then + # Okay, we're cool + true + else + echo >&2 "Failed running AppleScript" + hdiutil detach "${DEV_NAME}" + exit 64 + fi + echo "Done running the AppleScript..." + sleep 4 + rm "$APPLESCRIPT_FILE" + fi +fi + +# Make sure it's not world writeable +echo "Fixing permissions..." +chmod -Rf go-w "${MOUNT_DIR}" &> /dev/null || true +echo "Done fixing permissions" + +# Make the top window open itself on mount: +if [[ $SANDBOX_SAFE -eq 0 ]]; then + echo "Blessing started" + bless --folder "${MOUNT_DIR}" --openfolder "${MOUNT_DIR}" + echo "Blessing finished" +else + echo "Skipping blessing on sandbox" +fi + +if [[ -n "$VOLUME_ICON_FILE" ]]; then + # Tell the volume that it has a special file attribute + SetFile -a C "$MOUNT_DIR" +fi + +# Unmount +echo "Unmounting disk image..." +for n in `seq 1 5` +do + hdiutil detach "${DEV_NAME}" && break + + if [ $n = 5 ]; then + echo "Alright I guess we'll force unmount" + # This is dangerous. + hdiutil detach -force "${DEV_NAME}" + else + # Wait a second and retry I guess + echo "Waiting a second and retrying..." + sleep 1 + fi +done + +# Compress image +echo "Compressing disk image..." +hdiutil convert ${HDIUTIL_VERBOSITY} "${DMG_TEMP_NAME}" -format ${FORMAT} ${IMAGEKEY} -o "${DMG_DIR}/${DMG_NAME}" +rm -f "${DMG_TEMP_NAME}" + +# Adding EULA resources +if [[ -n "${EULA_RSRC}" && "${EULA_RSRC}" != "-null-" ]]; then + echo "Adding EULA resources..." + # + # Use udifrez instead flatten/rez/unflatten + # https://github.com/create-dmg/create-dmg/issues/109 + # + # Based on a thread from dawn2dusk & peterguy + # https://developer.apple.com/forums/thread/668084 + # + EULA_RESOURCES_FILE=$(mktemp -t createdmg.tmp.XXXXXXXXXX) + EULA_FORMAT=$(file -b ${EULA_RSRC}) + if [[ ${EULA_FORMAT} == 'Rich Text Format data'* ]] ; then + EULA_FORMAT='RTF ' + else + EULA_FORMAT='TEXT' + fi + # Encode the EULA to base64 + # Replace 'openssl base64' with 'base64' if Mac OS X 10.6 support is no more needed + # EULA_DATA="$(base64 -b 52 "${EULA_RSRC}" | sed s$'/^\(.*\)$/\t\t\t\\1/')" + EULA_DATA="$(openssl base64 -in "${EULA_RSRC}" | tr -d '\n' | awk '{gsub(/.{52}/,"&\n")}1' | sed s$'/^\(.*\)$/\t\t\t\\1/')" + # Fill the template with the custom EULA contents + eval "cat > \"${EULA_RESOURCES_FILE}\" </dev/null 2>/dev/null; then + hdiutil internet-enable -yes "${DMG_DIR}/${DMG_NAME}" + else + echo "hdiutil does not support internet-enable. Note it was removed in macOS 10.15." + fi +fi + +# All done! +echo "Disk image done" +exit 0 diff --git a/Tools/create-dmg/support/eula-resources-template.xml b/Tools/create-dmg/support/eula-resources-template.xml new file mode 100644 index 0000000000..7495632b0d --- /dev/null +++ b/Tools/create-dmg/support/eula-resources-template.xml @@ -0,0 +1,105 @@ + + + + + LPic + + + Attributes + 0x0000 + Data + + AAAAAgAAAAAAAAAAAAQAAA== + + ID + 5000 + Name + + + + STR# + + + Attributes + 0x0000 + Data + + AAYNRW5nbGlzaCB0ZXN0MQVBZ3JlZQhEaXNhZ3JlZQVQcmludAdT + YXZlLi4ueklmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0 + aGlzIGxpY2Vuc2UsIGNsaWNrICJBZ3JlZSIgdG8gYWNjZXNzIHRo + ZSBzb2Z0d2FyZS4gIElmIHlvdSBkbyBub3QgYWdyZWUsIHByZXNz + ICJEaXNhZ3JlZS4i + + ID + 5000 + Name + English buttons + + + Attributes + 0x0000 + Data + + AAYHRW5nbGlzaAVBZ3JlZQhEaXNhZ3JlZQVQcmludAdTYXZlLi4u + e0lmIHlvdSBhZ3JlZSB3aXRoIHRoZSB0ZXJtcyBvZiB0aGlzIGxp + Y2Vuc2UsIHByZXNzICJBZ3JlZSIgdG8gaW5zdGFsbCB0aGUgc29m + dHdhcmUuICBJZiB5b3UgZG8gbm90IGFncmVlLCBwcmVzcyAiRGlz + YWdyZWUiLg== + + ID + 5002 + Name + English + + + ${EULA_FORMAT} + + + Attributes + 0x0000 + Data + +${EULA_DATA} + + ID + 5000 + Name + English + + + TMPL + + + Attributes + 0x0000 + Data + + E0RlZmF1bHQgTGFuZ3VhZ2UgSUREV1JEBUNvdW50T0NOVAQqKioq + TFNUQwtzeXMgbGFuZyBJRERXUkQebG9jYWwgcmVzIElEIChvZmZz + ZXQgZnJvbSA1MDAwRFdSRBAyLWJ5dGUgbGFuZ3VhZ2U/RFdSRAQq + KioqTFNURQ== + + ID + 128 + Name + LPic + + + styl + + + Attributes + 0x0000 + Data + + AAMAAAAAAAwACQAUAAAAAAAAAAAAAAAAACcADAAJABQBAAAAAAAA + AAAAAAAAKgAMAAkAFAAAAAAAAAAAAAA= + + ID + 5000 + Name + English + + + + diff --git a/Tools/create-dmg/support/template.applescript b/Tools/create-dmg/support/template.applescript new file mode 100644 index 0000000000..fee634d319 --- /dev/null +++ b/Tools/create-dmg/support/template.applescript @@ -0,0 +1,74 @@ +on run (volumeName) + tell application "Finder" + tell disk (volumeName as string) + open + + set theXOrigin to WINX + set theYOrigin to WINY + set theWidth to WINW + set theHeight to WINH + + set theBottomRightX to (theXOrigin + theWidth) + set theBottomRightY to (theYOrigin + theHeight) + set dsStore to "\"" & "/Volumes/" & volumeName & "/" & ".DS_STORE\"" + + tell container window + set current view to icon view + set toolbar visible to false + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY} + set statusbar visible to false + REPOSITION_HIDDEN_FILES_CLAUSE + end tell + + set opts to the icon view options of container window + tell opts + set icon size to ICON_SIZE + set text size to TEXT_SIZE + set arrangement to not arranged + end tell + BACKGROUND_CLAUSE + + -- Positioning + POSITION_CLAUSE + + -- Hiding + HIDING_CLAUSE + + -- Application and QL Link Clauses + APPLICATION_CLAUSE + QL_CLAUSE + close + open + -- Force saving of the size + delay 1 + + tell container window + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX - 10, theBottomRightY - 10} + end tell + end tell + + delay 1 + + tell disk (volumeName as string) + tell container window + set statusbar visible to false + set the bounds to {theXOrigin, theYOrigin, theBottomRightX, theBottomRightY} + end tell + end tell + + --give the finder some time to write the .DS_Store file + delay 3 + + set waitTime to 0 + set ejectMe to false + repeat while ejectMe is false + delay 1 + set waitTime to waitTime + 1 + + if (do shell script "[ -f " & dsStore & " ]; echo $?") = "0" then set ejectMe to true + end repeat + log "waited " & waitTime & " seconds for .DS_STORE to be created." + end tell +end run diff --git a/Tools/load-macos-certs-ci.sh b/Tools/load-macos-certs-ci.sh new file mode 100644 index 0000000000..8d0035317d --- /dev/null +++ b/Tools/load-macos-certs-ci.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env sh + +KEY_CHAIN=build.keychain +CERTIFICATE_P12=certificate.p12 + +# Recreate the certificate from the secure environment variable +echo $CERTIFICATE_MACOS_APPLICATION | base64 --decode > $CERTIFICATE_P12 + +# Create a temporary keychain +security create-keychain -p actions $KEY_CHAIN + +# Remove the relock timeout, which can happen if our builds take forever. +security set-keychain-settings $KEY_CHAIN + +# Import certificate +security import $CERTIFICATE_P12 -k $KEY_CHAIN -P $CERTIFICATE_MACOS_PASSWORD -T /usr/bin/codesign; + +# Mark this as okay to be accessed from command line tools +security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k actions $KEY_CHAIN + +# Make the keychain the default so identities are found +security default-keychain -s $KEY_CHAIN + +# Unlock the keychain +security unlock-keychain -p actions $KEY_CHAIN + +# remove certs +rm -fr *.p12 diff --git a/Tools/notarize_netplay.sh b/Tools/notarize_netplay.sh new file mode 100644 index 0000000000..fe1cc11831 --- /dev/null +++ b/Tools/notarize_netplay.sh @@ -0,0 +1,76 @@ +#!/bin/zsh +# +# Signing and notarizing only happens on builds where the CI has access +# to the necessary secrets; this avoids builds in forks where secrets +# shouldn't be. + +version="$(echo $GIT_TAG)" +identifier="com.project-slippi.dolphin" + +requeststatus() { # $1: requestUUID + requestUUID=${1?:"need a request UUID"} + req_status=$(xcrun altool --notarization-info "$requestUUID" \ + --apiKey "${APPLE_API_KEY}" \ + --apiIssuer "${APPLE_ISSUER_ID}" 2>&1 \ + | awk -F ': ' '/Status:/ { print $2; }' ) + echo "$req_status" +} + +logstatus() { # $1: requestUUID + requestUUID=${1?:"need a request UUID"} + xcrun altool --notarization-info "$requestUUID" \ + --apiKey "${APPLE_API_KEY}" \ + --apiIssuer "${APPLE_ISSUER_ID}" + echo +} + +notarizefile() { # $1: path to file to notarize, $2: identifier + filepath=${1:?"need a filepath"} + identifier=${2:?"need an identifier"} + + # upload file + echo "## uploading $filepath for notarization" + requestUUID=$(xcrun altool --notarize-app \ + --primary-bundle-id "$identifier" \ + --apiKey "${APPLE_API_KEY}" \ + --apiIssuer "${APPLE_ISSUER_ID}" \ + --file "$filepath" 2>&1 \ + | awk '/RequestUUID/ { print $NF; }') + + echo "Notarization RequestUUID: $requestUUID" + + if [[ $requestUUID == "" ]]; then + echo "could not upload for notarization" + exit 1 + fi + + # wait for status to be not "in progress" any more + # Checks for up to ~10 minutes ((20 * 30s = 600) / 60s) + for i ({0..20}); do + request_status=$(requeststatus "$requestUUID") + echo "Status: ${request_status}" + + # Why can this report two different cases...? + if [ $? -ne 0 ] || [[ "${request_status}" =~ "invalid" ]] || [[ "${request_status}" =~ "Invalid" ]]; then + logstatus "$requestUUID" + echo "Error with notarization. Exiting!" + exit 1 + fi + + if [[ "${request_status}" =~ "success" ]]; then + logstatus "$requestUUID" + echo "Successfully notarized! Stapling notarization status to ${filepath}" + xcrun stapler staple "$filepath" + exit 0 + fi + + echo "Still in progress, will check again in 30s" + sleep 30 + done + + echo "Notarization request timed out - status below; maybe it needs more time?" + logstatus "$requestUUID" +} + +echo "Attempting notarization" +notarizefile "$1" "$identifier"