mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
This should be faster than the Intel runners. Seems to be at least twice as fast for uncached builds compared to `ubuntu-22.04`. - [x] ~~Move elixir checks to `macos-14`~~ can't; Depends on `docker` and `erlef/setup-beam` - [x] Add macOS targets to rust checks - [x] Move swift build to macos-14 - [x] Move kotlin build to macos-14 - [x] Name all jobs that are required for merge group to not depend on job config - [x] Update PR branch protection rules
172 lines
7.8 KiB
YAML
172 lines
7.8 KiB
YAML
name: Swift
|
|
on:
|
|
workflow_call:
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
build:
|
|
name: build-${{ matrix.sdk }}
|
|
runs-on: ${{ matrix.runs-on }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- sdk: macosx
|
|
runs-on: macos-14
|
|
platform: macOS
|
|
destination: platform=macOS
|
|
- sdk: iphoneos
|
|
runs-on: macos-14
|
|
platform: iOS
|
|
destination: generic/platform=iOS
|
|
permissions:
|
|
contents: read
|
|
id-token: 'write'
|
|
defaults:
|
|
run:
|
|
working-directory: ./swift/apple
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: ./.github/actions/setup-rust
|
|
with:
|
|
targets: aarch64-apple-darwin aarch64-apple-ios x86_64-apple-darwin
|
|
- uses: actions/cache/restore@v4
|
|
name: Restore Swift DerivedData Cache
|
|
with:
|
|
path: ~/Library/Developer/Xcode/DerivedData
|
|
key: ${{ matrix.runs-on }}-${{ runner.arch }}-swift-${{ hashFiles('swift/*', 'rust/**/*.rs', 'rust/**/*.toml', 'rust/**/*.lock}') }}
|
|
restore-keys: |
|
|
${{ matrix.runs-on }}-${{ runner.arch }}-swift-
|
|
- name: Install the Apple build certificate and provisioning profile
|
|
env:
|
|
BUILD_CERT: ${{ secrets.APPLE_BUILD_CERTIFICATE_BASE64 }}
|
|
BUILD_CERT_PASS: ${{ secrets.APPLE_BUILD_CERTIFICATE_P12_PASSWORD }}
|
|
INSTALLER_CERT: ${{ secrets.APPLE_MAC_INSTALLER_CERTIFICATE_BASE64 }}
|
|
INSTALLER_CERT_PASS: ${{ secrets.APPLE_MAC_INSTALLER_CERTIFICATE_P12_PASSWORD }}
|
|
KEYCHAIN_PASS: ${{ secrets.APPLE_RUNNER_KEYCHAIN_PASSWORD }}
|
|
IOS_APP_PP: ${{ secrets.APPLE_IOS_APP_PROVISIONING_PROFILE }}
|
|
IOS_NE_PP: ${{ secrets.APPLE_IOS_NE_PROVISIONING_PROFILE }}
|
|
MACOS_APP_PP: ${{ secrets.APPLE_MACOS_APP_PROVISIONING_PROFILE }}
|
|
MACOS_NE_PP: ${{ secrets.APPLE_MACOS_NE_PROVISIONING_PROFILE }}
|
|
run: |
|
|
BUILD_CERT_PATH=$RUNNER_TEMP/build_certificate.p12
|
|
INSTALLER_CERT_PATH=$RUNNER_TEMP/installer_certificate.cer
|
|
|
|
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
|
PP_PATH=~/Library/MobileDevice/Provisioning\ Profiles
|
|
mkdir -p "$PP_PATH"
|
|
|
|
# import certificate and provisioning profiles from secrets
|
|
echo -n "$BUILD_CERT" | base64 --decode -o $BUILD_CERT_PATH
|
|
|
|
# Matrix won't let us access secrets (for good reason), so use an explicit conditional here instead
|
|
if [ "${{ matrix.platform }}" = "iOS" ]; then
|
|
echo -n "$IOS_APP_PP" | base64 --decode -o "$PP_PATH"/app.mobileprovision
|
|
echo -n "$IOS_NE_PP" | base64 --decode -o "$PP_PATH"/ne.mobileprovision
|
|
elif [ "${{ matrix.platform }}" = "macOS" ]; then
|
|
echo -n "$MACOS_APP_PP" | base64 --decode -o "$PP_PATH"/app.provisionprofile
|
|
echo -n "$MACOS_NE_PP" | base64 --decode -o "$PP_PATH"/ne.provisionprofile
|
|
|
|
# Submission to the macOS app store requires an installer package
|
|
# which must be signed separately.
|
|
echo -n "$INSTALLER_CERT" | base64 --decode -o $INSTALLER_CERT_PATH
|
|
else
|
|
echo "Platform not supported"
|
|
exit 1
|
|
fi
|
|
|
|
# create temporary keychain
|
|
security create-keychain -p "$KEYCHAIN_PASS" $KEYCHAIN_PATH
|
|
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
|
security unlock-keychain -p "$KEYCHAIN_PASS" $KEYCHAIN_PATH
|
|
|
|
# import certificate to keychain
|
|
security import $BUILD_CERT_PATH -P "$BUILD_CERT_PASS" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
|
|
if [ "${{ matrix.platform }}" = "macOS" ]; then
|
|
security import $INSTALLER_CERT_PATH -P "$INSTALLER_CERT_PASS" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
fi
|
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
|
- name: Build and sign app
|
|
id: build
|
|
env:
|
|
# Build universal binary
|
|
ONLY_ACTIVE_ARCH: no
|
|
# Needed because `productbuild` doesn't support picking this up automatically like Xcode does
|
|
INSTALLER_CODE_SIGN_IDENTITY: "3rd Party Mac Developer Installer: Firezone, Inc. (47R2M6779T)"
|
|
run: |
|
|
# Copy xcconfig
|
|
cp Firezone/xcconfig/release.xcconfig Firezone/xcconfig/config.xcconfig
|
|
|
|
# App Store Connect requires a new build version on each upload and it must be an integer.
|
|
# See https://developer.apple.com/documentation/xcode/build-settings-reference#Current-Project-Version
|
|
seconds_since_epoch=$(date +%s)
|
|
sed -i '' "s/CURRENT_PROJECT_VERSION = [0-9]/CURRENT_PROJECT_VERSION = $seconds_since_epoch/" \
|
|
Firezone.xcodeproj/project.pbxproj
|
|
|
|
# Unfortunately the macOS app requires an installer package to make it into the App Store,
|
|
# while iOS requires an ipa. The process for building each of these is slightly different.
|
|
if [ "${{ matrix.platform }}" = "iOS" ]; then
|
|
# Build archive
|
|
xcodebuild archive \
|
|
-archivePath $RUNNER_TEMP/Firezone.xcarchive \
|
|
-configuration Release \
|
|
-scheme Firezone \
|
|
-sdk ${{ matrix.sdk }} \
|
|
-destination '${{ matrix.destination }}'
|
|
# Export IPA
|
|
xcodebuild \
|
|
-exportArchive \
|
|
-archivePath $RUNNER_TEMP/Firezone.xcarchive \
|
|
-exportPath $RUNNER_TEMP/ \
|
|
-exportOptionsPlist Firezone/ExportOptions.plist
|
|
|
|
# Save resulting file to use for upload
|
|
echo "app_bundle=$RUNNER_TEMP/Firezone.ipa" >> "$GITHUB_OUTPUT"
|
|
elif [ "${{ matrix.platform }}" = "macOS" ]; then
|
|
# Build app bundle
|
|
xcodebuild build \
|
|
-configuration Release \
|
|
-scheme Firezone \
|
|
-sdk ${{ matrix.sdk }} \
|
|
-destination '${{ matrix.destination }}'
|
|
# Move it from randomized build output dir to somewhere we can find it
|
|
mv ~/Library/Developer/Xcode/DerivedData/Firezone-*/Build/Products/Release/Firezone.app $RUNNER_TEMP/.
|
|
# Create signed installer pkg
|
|
productbuild \
|
|
--sign "${{ env.INSTALLER_CODE_SIGN_IDENTITY }}" \
|
|
--component $RUNNER_TEMP/Firezone.app /Applications $RUNNER_TEMP/Firezone.pkg
|
|
|
|
# Save resulting file to use for upload
|
|
echo "app_bundle=$RUNNER_TEMP/Firezone.pkg" >> "$GITHUB_OUTPUT"
|
|
else
|
|
echo "Unsupported platform"
|
|
exit 1
|
|
fi
|
|
- name: Upload build to App Store Connect
|
|
if: ${{ github.event_name == 'workflow_dispatch' || (github.ref == 'refs/heads/main' && contains(github.event.head_commit.modified, 'elixir/VERSION')) }}
|
|
env:
|
|
ISSUER_ID: ${{ secrets.APPLE_APP_STORE_CONNECT_ISSUER_ID }}
|
|
API_KEY_ID: ${{ secrets.APPLE_APP_STORE_CONNECT_API_KEY_ID }}
|
|
API_KEY: ${{ secrets.APPLE_APP_STORE_CONNECT_API_KEY }}
|
|
run: |
|
|
# set up private key from env
|
|
mkdir -p ~/private_keys
|
|
echo "$API_KEY" > ~/private_keys/AuthKey_$API_KEY_ID.p8
|
|
|
|
# Submit app to App Store Connect
|
|
xcrun altool \
|
|
--upload-app \
|
|
-f ${{ steps.build.outputs.app_bundle }} \
|
|
-t ${{ matrix.platform }} \
|
|
--apiKey $API_KEY_ID \
|
|
--apiIssuer $ISSUER_ID
|
|
- uses: actions/cache/save@v4
|
|
if: ${{ github.ref == 'refs/heads/main' }}
|
|
name: Save Swift DerivedData Cache
|
|
with:
|
|
path: ~/Library/Developer/Xcode/DerivedData
|
|
# Swift benefits heavily from build cache, so aggressively write a new one
|
|
# on each build on `main` and attempt to restore it in PR builds with broader restore-key.
|
|
key: ${{ matrix.runs-on }}-${{ runner.arch }}-swift-${{ hashFiles('swift/*', 'rust/**/*.rs', 'rust/**/*.toml', 'rust/**/*.lock}') }}
|