Skip to content

Commit

Permalink
👷 sign and notarize on CI (#3)
Browse files Browse the repository at this point in the history
closes #1
  • Loading branch information
leonardodino committed Jul 3, 2022
1 parent ff8e67e commit d323a3b
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 67 deletions.
67 changes: 17 additions & 50 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,65 +1,32 @@
name: Build

on:
push:
branches: ['main']
pull_request:
branches: ['main']
create:
tags: ['v[0-9]+.[0-9]+.[0-9]+']
push: { branches: ['main'] }
pull_request: { branches: ['main'] }

jobs:
build:
name: Xcode Build
runs-on: macos-latest
runs-on: macos-12
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Select Xcode Version
run: sudo xcrun xcode-select -s /Applications/Xcode_13.4.app

- name: Set Build Version
if: ${{ github.ref_type == 'tag' }}
run: 'agvtool new-marketing-version "${GITHUB_REF_NAME#v}" && agvtool new-version -all "$GITHUB_RUN_NUMBER"'
- name: Set Environment Variables
run: 'echo "XCARCHIVE_PATH=${PWD}/BeezyLight.xcarchive" >> $GITHUB_ENV'

- name: Run xcodebuild
run: 'xcodebuild -workspace ./BeezyLight.xcodeproj/project.xcworkspace -scheme BeezyLight -configuration Release -destination "generic/platform=macOS" -archivePath "$PWD/build/Release/BeezyLight.xcarchive" archive'
- name: Checkout repository
uses: actions/checkout@v3

- name: Compress app bundle
run: 'ditto -c -k --sequesterRsrc --keepParent "build/Release/BeezyLight.xcarchive/Products/Applications/BeezyLight.app" "build/Release/BeezyLight.zip"'
- name: Run xcode-build Script
run: './Scripts/xcode-build build "$XCARCHIVE_PATH"'

- name: Upload app artifact
- name: Upload Archive to Artifacts
uses: actions/upload-artifact@v3
with:
name: app
path: build/Release/BeezyLight.zip

- name: Create Release
if: ${{ github.ref_type == 'tag' }}
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: ${{ github.ref_name }}
draft: true
prerelease: false

- name: Upload Release Asset
if: ${{ github.ref_type == 'tag' }}
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ./build/Release/BeezyLight.zip
asset_name: BeezyLight.zip
asset_content_type: application/zip

- name: Publish Release
if: ${{ github.ref_type == 'tag' }}
run: "hub release edit --draft=false -m '' \"${GITHUB_REF_NAME}\""
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: BeezyLight.xcarchive
path: ${{ env.XCARCHIVE_PATH }}
if-no-files-found: error


- name: Check Git Status
run: git status --porcelain
131 changes: 131 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
name: Release

on:
create: { tags: ['v[0-9]+.[0-9]+.[0-9]+'] }

jobs:
release:
name: Xcode Build (Release)
runs-on: macos-12
steps:
- name: Select Xcode Version
run: sudo xcrun xcode-select -s /Applications/Xcode_13.4.app

- name: Set Environment Variables
run: |
APP_NAME="BeezyLight"
echo "XCARCHIVE_PATH=${PWD}/${APP_NAME}.xcarchive" >> $GITHUB_ENV
echo "APP_PATH=${PWD}/${APP_NAME}.xcarchive/Products/Applications/${APP_NAME}.app" >> $GITHUB_ENV
echo "ZIP_PATH=${RUNNER_TEMP}/${APP_NAME}.zip" >> $GITHUB_ENV
echo "BUILD_CERTIFICATE_PATH=${RUNNER_TEMP}/build_certificate.p12" >> $GITHUB_ENV
echo "NOTARIZATION_KEY_PATH=${RUNNER_TEMP}/notarization_key.p8" >> $GITHUB_ENV
echo "KEYCHAIN_PATH=${RUNNER_TEMP}/app-signing.keychain-db" >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v3

- name: Generate Release Config
run: './Scripts/generate-release-config "${{ secrets.PRODUCT_BUNDLE_IDENTIFIER }}" "${GITHUB_REF_NAME#v}" "$GITHUB_RUN_NUMBER" "${{ secrets.XCODE_DEVELOPMENT_TEAM }}"'

- name: Install Developer ID Certificate
run: |
# import build certificate from secrets
echo -n "${{ secrets.BUILD_CERTIFICATE_BASE64 }}" | base64 --decode --output "$BUILD_CERTIFICATE_PATH"
# create temporary keychain
security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" "$KEYCHAIN_PATH"
# import certificate to keychain
security import "$BUILD_CERTIFICATE_PATH" -P "${{ secrets.P12_PASSWORD }}" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH"
security list-keychain -d user -s "$KEYCHAIN_PATH"
rm "$BUILD_CERTIFICATE_PATH"
- name: Run xcode-build Script
run: './Scripts/xcode-build release "$XCARCHIVE_PATH"'

- name: Notarize App
run: |
# Save Notarization Credentials to Keychain
echo -n "${{ secrets.NOTARIZATION_KEY_BASE64 }}" | base64 --decode --output "$NOTARIZATION_KEY_PATH"
xcrun notarytool store-credentials "AppNotarization" \
-k "$NOTARIZATION_KEY_PATH" \
-d "${{ secrets.NOTARIZATION_KEY_ID }}" \
-i "${{ secrets.NOTARIZATION_KEY_ISSUER }}" \
--keychain "$KEYCHAIN_PATH"
# create temporary .zip for notarization purposes
ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ZIP_PATH"
# notarize the app and log the result to stdout
SUBMISSION_ID="$(xcrun notarytool submit "$ZIP_PATH" --keychain-profile "AppNotarization" | awk '$1 ~ /^id:$/ { id=$2 } END { print id }')"
xcrun notarytool wait "$SUBMISSION_ID" --keychain-profile "AppNotarization"
xcrun notarytool log "$SUBMISSION_ID" --keychain-profile "AppNotarization"
# staple .app bundle with the notarization ticket
xcrun stapler staple -vvv "$APP_PATH"
rm "$ZIP_PATH" "$NOTARIZATION_KEY_PATH"
- name: Validate .app bundle
run: |
xcrun stapler validate -vvv "$APP_PATH"
codesign --verify --deep --strict --verbose=1 "$APP_PATH"
spctl --assess --verbose --type open --type exec "$APP_PATH"
- name: Compress .app bundle
run: 'ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "$ZIP_PATH"'

- name: Upload App to Artifacts
uses: actions/upload-artifact@v3
with:
name: BeezyLight
path: ${{ env.ZIP_PATH }}
if-no-files-found: error

- name: Upload Archive to Artifacts
uses: actions/upload-artifact@v3
with:
name: BeezyLight.xcarchive
path: ${{ env.XCARCHIVE_PATH }}
if-no-files-found: error

- name: Check Git Status
run: git status --porcelain

- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref_name }}
release_name: ${{ github.ref_name }}
draft: true
prerelease: false

- name: Upload Release Asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: ${{ env.ZIP_PATH }}
asset_name: BeezyLight.zip
asset_content_type: application/zip

- name: Publish Release
run: "hub release edit --draft=false -m '' \"${GITHUB_REF_NAME}\""
env:
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Delete keychain
if: ${{ always() }}
run: |
security delete-keychain "$KEYCHAIN_PATH"
rm -f "$BUILD_CERTIFICATE_PATH" "$NOTARIZATION_KEY_PATH" "$KEYCHAIN_PATH"
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
xcuserdata/
build/
*.xcarchive
*.zip
Release.xcconfig
19 changes: 8 additions & 11 deletions BeezyLight.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
961F0D2F286F9F8400D35EB3 /* Default.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Default.xcconfig; sourceTree = "<group>"; };
962377FD27F4ECD8002D718F /* StatusItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusItem.swift; sourceTree = "<group>"; };
96A53DDC27C572B9002DA809 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = Info.plist; sourceTree = "<group>"; };
96B8901127F4E78D00C39B4A /* AboutWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutWindow.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -70,6 +71,7 @@
96C2A1EA27C5632E00768B18 /* BeezyLight.entitlements */,
96A53DDC27C572B9002DA809 /* Info.plist */,
96DC603427F0F7D000A5FE00 /* Main.storyboard */,
961F0D2F286F9F8400D35EB3 /* Default.xcconfig */,
);
path = BeezyLight;
sourceTree = "<group>";
Expand Down Expand Up @@ -278,58 +280,53 @@
};
96C2A1EE27C5632E00768B18 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 961F0D2F286F9F8400D35EB3 /* Default.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = BeezyLight/BeezyLight.entitlements;
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 0;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = BeezyLight/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2020 Leonardo Dino\nAll rights reserved.";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 0.0.0;
PRODUCT_BUNDLE_IDENTIFIER = app.BeezyLight;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Debug;
};
96C2A1EF27C5632E00768B18 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 961F0D2F286F9F8400D35EB3 /* Default.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = BeezyLight/BeezyLight.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 0;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = BeezyLight/Info.plist;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2020 Leonardo Dino\nAll rights reserved.";
INFOPLIST_KEY_NSMainStoryboardFile = Main;
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = 0.0.0;
PRODUCT_BUNDLE_IDENTIFIER = app.BeezyLight;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
};
Expand Down
9 changes: 9 additions & 0 deletions BeezyLight/Default.xcconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
PRODUCT_BUNDLE_IDENTIFIER = open-source.BeezyLight

CURRENT_PROJECT_VERSION = 0
MARKETING_VERSION = 0.0.0
VERSIONING_SYSTEM = apple-generic

CODE_SIGN_IDENTITY = -
CODE_SIGN_STYLE = Automatic
DEVELOPMENT_TEAM =
5 changes: 0 additions & 5 deletions BeezyLight/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>0.0.0</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Leonardo Dino
All rights reserved.</string>
<key>LSUIElement</key>
<true/>
</dict>
Expand Down
62 changes: 62 additions & 0 deletions Scripts/generate-release-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

RELEASE_CONFIG_PATH="${PWD}/BeezyLight/Release.xcconfig"

USAGE="Usage:
$(basename "$0") <bundle-id> <marketing-version> <build-version> <development-team>
Where:
bundle-id: App Bundle ID
marketing-version: Semantic Versioning
build-version: Build Number (Integer)
development-team: Apple Code-Signing Team ID"

NUMBER_OF_EXPECTED_PARAMETERS=4
PRODUCT_BUNDLE_IDENTIFIER="$1"
MARKETING_VERSION="$2"
CURRENT_PROJECT_VERSION="$3"
DEVELOPMENT_TEAM="$4"

if [ "$#" -ne "$NUMBER_OF_EXPECTED_PARAMETERS" ]; then
echo "Error: Invalid number of parameters
Expected: ${NUMBER_OF_EXPECTED_PARAMETERS} parameters
Received: $# parameters
${USAGE}" >&2
exit 1
fi

if [[ ! "$MARKETING_VERSION" =~ ^[0-9]+.[0-9]+.[0-9]+$ ]]; then
echo "Error: Marketing Version argument must be a SemVer string
Received: \"${MARKETING_VERSION}\"
${USAGE}" >&2
exit 1
fi

if [[ ! "$CURRENT_PROJECT_VERSION" =~ ^[0-9]+$ ]]; then
echo "Error: Build Number argument must be an Integer
Received: \"${CURRENT_PROJECT_VERSION}\"
${USAGE}" >&2
exit 1
fi

if [[ ! "$DEVELOPMENT_TEAM" =~ ^[0-9A-Z]{8,12}$ ]]; then
echo "Error: Development Team argument must be valid
Received: \"${DEVELOPMENT_TEAM}\"
${USAGE}" >&2
exit 1
fi

echo -n "PRODUCT_BUNDLE_IDENTIFIER = ${PRODUCT_BUNDLE_IDENTIFIER}
CURRENT_PROJECT_VERSION = ${CURRENT_PROJECT_VERSION}
MARKETING_VERSION = ${MARKETING_VERSION}
VERSIONING_SYSTEM = apple-generic
CODE_SIGN_IDENTITY = Developer ID Application
CODE_SIGN_STYLE = Manual
DEVELOPMENT_TEAM = ${DEVELOPMENT_TEAM}
" | tee "$RELEASE_CONFIG_PATH"
Loading

0 comments on commit d323a3b

Please sign in to comment.