Skip to content

Commit

Permalink
Merge pull request #42 from RobotsAndPencils/enhancement/13-softwareU…
Browse files Browse the repository at this point in the history
…pdates

Enhancement 13: A software update mechanism (step 1 of 3)
  • Loading branch information
Brandon Evans authored Jan 19, 2021
2 parents 808dd02 + 6e0daa5 commit c2482d6
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ DerivedData/
*.ipa
*.dSYM.zip
*.dSYM
Archive/*
Product/*

## Playgrounds
timeline.xctimeline
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,42 @@ Notable design decisions are recorded in [DECISIONS.md](./DECISIONS.md). The App

[`xcode-install`](https://github.com/xcpretty/xcode-install) and [fastlane/spaceship](https://github.com/fastlane/fastlane/tree/master/spaceship) both deserve credit for figuring out the hard parts of what makes this possible.

## Releasing a new version

Follow the steps below to build and release a new version of Xcodes.app. For any of the git steps, you can use your preferred tool, but please sign the tag.

```sh
# Update the version number in Xcode and commit the change, if necessary

# Increment the build number
scripts/increment_build_number.sh

# Commit the change
git add Xcodes/Resources/Info.plist
git commit -asm "Increment build number"

# Tag the latest commit
# Replace $VERSION and $BUILD below with the latest real values
git tag -asm "v$VERSION.b$BUILD" "v$VERSION.b$BUILD"

# Push to origin
git push --follow-tags

# Build the app
scripts/package_release.sh

# Notarize the app
scripts/notarize.sh "test@example.com" "@keychain:altool" MyOrg Product/Xcodes.zip

# Go to https://github.com/RobotsAndPencils/XcodesApp/releases
# Edit the latest draft release
# Set its tag to the tag you just pushed
# Set its title to a string with the format "$VERSION ($BUILD)"
# Polish the draft release notes, if necessary
# Attach the zip that was created in the Product directory to the release
# Publish the release
```

## Contact

<a href="http://www.robotsandpencils.com"><img src="R&PLogo.png" width="153" height="74" /></a>
Expand Down
8 changes: 8 additions & 0 deletions Scripts/export_options.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?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>method</key>
<string>developer-id</string>
</dict>
</plist>
20 changes: 20 additions & 0 deletions Scripts/increment_build_number.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh
#
# Increment build number
#
# This will get the latest build number from git tags, add 1, then set it in the Info.plist.
# Assumes that build numbers are monotonically increasing positive integers, across version numbers.
# Tags must be named v$version_numberb$build_number, e.g. v1.2.3b456

infoplist_file="$(pwd)/Xcodes/Resources/Info.plist"

# Get latest tag hash matching pattern
hash=$(git rev-list --tags="v" --max-count=1)
# Get latest tag at hash that matches the same pattern as a prefix in order to support commits with multiple tags
last_tag=$(git describe --tags --match "v*" "$hash")
# Get build number from last component of tag name
last_build_number=$(echo "$last_tag" | grep -o "b.*" | cut -c 2-)

build_number=$(($last_build_number + 1))

/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $build_number" "${infoplist_file}"
69 changes: 69 additions & 0 deletions Scripts/notarize.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/sh
#
# Notarize
#
# Uploads to Apple's notarization service, polls until it completes, staples the ticket to the built app, then creates a new zip.
#
# Requires four arguments:
# - Apple ID username
# - Apple ID app-specific password (store this in your Keychain and use the @keychain:$NAME syntax to prevent your password from being added to your shell history)
# - App Store Connect provider name
# - Path to .app to upload
#
# Assumes that there's a .app beside the .zip with the same name so it can be stapled and re-zipped.
#
# E.g. notarize.sh "test@example.com" "@keychain:altool" MyOrg Xcodes.zip
#
# https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow
# Adapted from https://github.com/keybase/client/blob/46f5df0aa64ff19198ba7b044bbb7cd907c0be9f/packaging/desktop/package_darwin.sh

username="$1"
password="$2"
asc_provider="$3"
file="$4"

echo "Uploading to notarization service"

uuid=$(xcrun altool \
--notarize-app \
--primary-bundle-id "com.robotsandpencils.XcodesApp.zip" \
--username "$username" \
--password "$password" \
--asc-provider "$asc_provider" \
--file "$file" 2>&1 | \
grep 'RequestUUID' | \
awk '{ print $3 }')

echo "Successfully uploaded to notarization service, polling for result: $uuid"

sleep 15
while :
do
fullstatus=$(xcrun altool \
--notarization-info "$uuid" \
--username "$username" \
--password "$password" \
--asc-provider "$asc_provider" 2>&1)
status=$(echo "$fullstatus" | grep 'Status\:' | awk '{ print $2 }')
if [ "$status" = "success" ]; then
echo "Notarization success"
exit 0
elif [ "$status" = "in" ]; then
echo "Notarization still in progress, sleeping for 15 seconds and trying again"
sleep 15
else
echo "Notarization failed, full status below"
echo "$fullstatus"
exit 1
fi
done

# Remove .zip
rm $file

# Staple ticket to .app
app_path="$(basename -s ".zip" "$file").app"
xcrun stapler staple "$app_path"

# Zip the stapled app for distribution
zip -r "$file" "$app_path"
24 changes: 24 additions & 0 deletions Scripts/package_release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash
#
# Package release
#
# This will build and archive the app and then compress it in a .zip file at Product/Xcodes.zip
# You must already have all required code signing assets installed on your computer

PROJECT_NAME=Xcodes
PROJECT_DIR=$(pwd)/$PROJECT_NAME/Resources
SCRIPTS_DIR=$(pwd)/Scripts
INFOPLIST_FILE="Info.plist"

# Ensure a clean build
rm -rf Archive/*
rm -rf Product/*
xcodebuild clean -project $PROJECT_NAME.xcodeproj -configuration Release -alltargets

# Archive the app and export for release distribution
xcodebuild archive -project $PROJECT_NAME.xcodeproj -scheme $PROJECT_NAME -archivePath Archive/$PROJECT_NAME.xcarchive
xcodebuild -archivePath Archive/$PROJECT_NAME.xcarchive -exportArchive -exportPath Product/$PROJECT_NAME -exportOptionsPlist "${SCRIPTS_DIR}/export_options.plist"
cp -r "Product/$PROJECT_NAME/$PROJECT_NAME.app" "Product/$PROJECT_NAME.app"

# Create a ZIP archive suitable for altool.
/usr/bin/ditto -c -k --keepParent "Product/$PROJECT_NAME.app" "Product/$PROJECT_NAME.zip"
6 changes: 3 additions & 3 deletions Xcodes/Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT</key>
<string>$(CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
Expand All @@ -33,9 +35,7 @@
<key>SMPrivilegedExecutables</key>
<dict>
<key>com.robotsandpencils.XcodesApp.Helper</key>
<string>identifier &quot;com.robotsandpencils.XcodesApp.Helper&quot; and info [CFBundleShortVersionString] &gt;= &quot;1.0.0&quot; and anchor apple generic and certificate leaf[subject.OU] = &quot;$(CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT)&quot;</string>
<string>identifier "com.robotsandpencils.XcodesApp.Helper" and info [CFBundleShortVersionString] &gt;= "1.0.0" and anchor apple generic and certificate leaf[subject.OU] = "$(CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT)"</string>
</dict>
<key>CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT</key>
<string>$(CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT)</string>
</dict>
</plist>

0 comments on commit c2482d6

Please sign in to comment.