-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The template now has: * An AppDelegate * Localization for English and Dutch * Default tint color and icon * Unit tests, UI tests with Salad and a test plan * GitHub Actions configuration * Default files for: Info.plist, launch screen storyboard, entitlements * Rename script * Linting and formatting configuration
- Loading branch information
Showing
26 changed files
with
779 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
name: Set up Apple code signing | ||
description: Installs code signing certificate(s) to a temporary keychain | ||
inputs: | ||
build-certificate-base64: | ||
required: true | ||
description: The base64-encoded p12 build certificate | ||
p12-password: | ||
required: true | ||
description: The password for the p12 build certificate | ||
keychain-password: | ||
required: true | ||
description: The password for the temporary keychain | ||
runs: | ||
using: "composite" | ||
steps: | ||
- name: Install code signing certificate | ||
env: | ||
BUILD_CERTIFICATE_BASE64: ${{ inputs.build-certificate-base64 }} | ||
P12_PASSWORD: ${{ inputs.p12-password }} | ||
KEYCHAIN_PASSWORD: ${{ inputs.keychain-password }} | ||
shell: bash | ||
# Source: | ||
# https://docs.github.com/en/actions/deployment/deploying-xcode-applications/installing-an-apple-certificate-on-macos-runners-for-xcode-development | ||
run: | | ||
# Create variables | ||
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12 | ||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | ||
# Import certificate from secrets | ||
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode -o $CERTIFICATE_PATH | ||
# Create temporary keychain | ||
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | ||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH | ||
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH | ||
# Import certificate to keychain | ||
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH | ||
security list-keychain -d user -s $KEYCHAIN_PATH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
name: Run tests and deploy to TestFlight | ||
|
||
on: | ||
workflow_dispatch: | ||
# Uncomment this to run the workflow on every push to the main branch: | ||
# push: | ||
# branches: ["main"] | ||
|
||
concurrency: | ||
group: ${{ github.workflow }}-${{ github.ref }} | ||
cancel-in-progress: true | ||
|
||
env: | ||
XCODE_PROJECT: TemplateApp.xcodeproj | ||
SCHEME: TemplateApp | ||
TEST_PLAN: AllTests | ||
TEST_RESULT_BUNDLE: TestResults.xcresult | ||
ARCHIVE_PATH: TemplateApp.xcarchive | ||
EXPORT_OPTIONS_PLIST: ExportOptions.plist | ||
|
||
jobs: | ||
build: | ||
name: Run tests and deploy to TestFlight | ||
runs-on: [macOS] | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Cache Swift Package Manager dependencies | ||
uses: actions/cache@v4 | ||
with: | ||
path: ${{ runner.temp }}/SourcePackages | ||
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} | ||
restore-keys: | | ||
${{ runner.os }}-spm- | ||
- name: Install Swift packages | ||
run: | | ||
xcodebuild -project "${{ env.XCODE_PROJECT }}" \ | ||
-scheme "${{ env.SCHEME }}" \ | ||
-onlyUsePackageVersionsFromResolvedFile \ | ||
-resolvePackageDependencies \ | ||
-clonedSourcePackagesDirPath "${{ runner.temp }}/SourcePackages" | ||
- name: Install code signing certificate | ||
uses: "./.github/actions/code-signing-setup" | ||
with: | ||
build-certificate-base64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} | ||
p12-password: ${{ secrets.P12_PASSWORD }} | ||
keychain-password: ${{ secrets.KEYCHAIN_PASSWORD }} | ||
|
||
- name: Install App Store Connect API key | ||
run: | | ||
echo -n "${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }}" | base64 --decode -o "${{ runner.temp }}/AuthKey.p8" | ||
- name: Run tests | ||
env: | ||
PLATFORM: ${{ 'iOS Simulator' }} | ||
run: | | ||
# xcrun xctrace returns via stderr, not the expected stdout (see https://developer.apple.com/forums/thread/663959) | ||
DEVICE=`xcrun xctrace list devices 2>&1 | grep -oE 'iPhone.*?[^\(]+' | head -1 | awk '{$1=$1;print}' | sed -e "s/ Simulator$//"` | ||
xcodebuild test -project "${{ env.XCODE_PROJECT }}" \ | ||
-scheme "${{ env.SCHEME }}" \ | ||
-testPlan "${{ env.TEST_PLAN }}" \ | ||
-destination "platform=$PLATFORM,name=$DEVICE" \ | ||
-resultBundlePath "${{ env.TEST_RESULT_BUNDLE }}" \ | ||
-clonedSourcePackagesDirPath "${{ runner.temp }}/SourcePackages" \ | ||
-disableAutomaticPackageResolution | ||
- name: Upload test result bundle | ||
uses: actions/upload-artifact@v4 | ||
if: ${{ failure() }} | ||
with: | ||
name: ${{ env.SCHEME }}-${{ github.ref_name }}-${{ github.sha }}.xcresult | ||
path: ${{ env.TEST_RESULT_BUNDLE }} | ||
|
||
- name: Archive build | ||
run: | | ||
xcodebuild clean archive -project "${{ env.XCODE_PROJECT }}" \ | ||
-scheme "${{ env.SCHEME }}" \ | ||
-destination generic/platform=iOS \ | ||
-archivePath "${{ runner.temp }}/${{ env.ARCHIVE_PATH }}" \ | ||
-allowProvisioningUpdates \ | ||
-authenticationKeyPath "${{ runner.temp }}/AuthKey.p8" \ | ||
-authenticationKeyID ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} \ | ||
-authenticationKeyIssuerID ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} \ | ||
-clonedSourcePackagesDirPath "${{ runner.temp }}/SourcePackages" \ | ||
-disableAutomaticPackageResolution | ||
- name: Upload to TestFlight | ||
run: | | ||
xcodebuild -exportArchive \ | ||
-allowProvisioningUpdates \ | ||
-authenticationKeyPath "${{ runner.temp }}/AuthKey.p8" \ | ||
-authenticationKeyID ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }} \ | ||
-authenticationKeyIssuerID ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} \ | ||
-archivePath "${{ runner.temp }}/${{ env.ARCHIVE_PATH }}" \ | ||
-exportPath ${{ env.ARCHIVE_PATH }} \ | ||
-exportOptionsPlist ${{ env.EXPORT_OPTIONS_PLIST }} | ||
# To add Crashlytics dSYM upload, grap the `upload-symbols` script from the Firebase SDK from here: | ||
# https://github.com/firebase/firebase-ios-sdk/blob/main/Crashlytics/upload-symbols | ||
# and add it to the repository in a folder called `scripts`. Then uncomment the following lines: | ||
|
||
# - name: Upload dSYM files to Firebase Crashlytics | ||
# run: | | ||
# ./scripts/upload-symbols -p ios \ | ||
# -gsp "TemplateApp/GoogleService-Info.plist" \ | ||
# "${{ runner.temp }}/${{ env.ARCHIVE_PATH }}/dSYMs" | ||
|
||
- name: Upload build artifact | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: ${{ env.SCHEME }}-${{ github.ref_name }}-${{ github.sha }}.xcarchive | ||
path: ${{ runner.temp }}/${{ env.ARCHIVE_PATH }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
name: Run tests | ||
|
||
on: | ||
pull_request: | ||
branches: ["main"] | ||
|
||
env: | ||
XCODE_PROJECT: TemplateApp.xcodeproj | ||
SCHEME: TemplateApp | ||
TEST_PLAN: AllTests | ||
TEST_RESULT_BUNDLE: TestResults.xcresult | ||
|
||
jobs: | ||
build: | ||
name: Run tests | ||
runs-on: [macOS] | ||
|
||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Cache Swift Package Manager dependencies | ||
uses: actions/cache@v4 | ||
with: | ||
path: ${{ runner.temp }}/SourcePackages | ||
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} | ||
restore-keys: | | ||
${{ runner.os }}-spm- | ||
- name: Install Swift packages | ||
run: | | ||
xcodebuild -project "${{ env.XCODE_PROJECT }}" \ | ||
-scheme "${{ env.SCHEME }}" \ | ||
-onlyUsePackageVersionsFromResolvedFile \ | ||
-resolvePackageDependencies \ | ||
-clonedSourcePackagesDirPath "${{ runner.temp }}/SourcePackages" | ||
- name: Run tests | ||
env: | ||
PLATFORM: ${{ 'iOS Simulator' }} | ||
run: | | ||
# xcrun xctrace returns via stderr, not the expected stdout (see https://developer.apple.com/forums/thread/663959) | ||
DEVICE=`xcrun xctrace list devices 2>&1 | grep -oE 'iPhone.*?[^\(]+' | head -1 | awk '{$1=$1;print}' | sed -e "s/ Simulator$//"` | ||
xcodebuild test -project "${{ env.XCODE_PROJECT }}" \ | ||
-scheme "${{ env.SCHEME }}" \ | ||
-testPlan "${{ env.TEST_PLAN }}" \ | ||
-destination "platform=$PLATFORM,name=$DEVICE" \ | ||
-resultBundlePath "${{ env.TEST_RESULT_BUNDLE }}" \ | ||
-clonedSourcePackagesDirPath "${{ runner.temp }}/SourcePackages" \ | ||
-disableAutomaticPackageResolution | ||
- name: Upload test result bundle | ||
uses: actions/upload-artifact@v4 | ||
if: ${{ failure() }} | ||
with: | ||
name: ${{ env.SCHEME }}-${{ github.ref_name }}-${{ github.sha }}.xcresult | ||
path: ${{ env.TEST_RESULT_BUNDLE }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--disable unusedArguments | ||
--disable redundantRawValues | ||
--indent 4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
disabled_rules: | ||
- trailing_comma | ||
- line_length | ||
- unused_closure_parameter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?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>destination</key> | ||
<string>upload</string> | ||
<key>manageAppVersionAndBuildNumber</key> | ||
<true/> | ||
<key>method</key> | ||
<string>app-store</string> | ||
<key>signingStyle</key> | ||
<string>automatic</string> | ||
<key>stripSwiftSymbols</key> | ||
<true/> | ||
<key>teamID</key> | ||
<string>XXXXXXXXXX</string> | ||
<key>testFlightInternalTestingOnly</key> | ||
<false/> | ||
<key>uploadSymbols</key> | ||
<true/> | ||
</dict> | ||
</plist> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Q42 iOS template | ||
|
||
This is a template for creating iOS projects at Q42. It has opinionated defaults and boilerplate, based on how we do iOS projects at Q42. | ||
|
||
## How to use it | ||
|
||
1. In GitHub, press "use this template" to create a new repository. | ||
2. Rename your project using the included Python script. | ||
|
||
## Features | ||
|
||
Only basic features that almost all projects use, were added in this template: | ||
|
||
* SwiftUI using the SwiftUI lifecycle with an AppDelegate | ||
* Dependency injection using Factory | ||
* Unit tests and UI tests using Salad | ||
* GitHub Actions CI configuration that runs the tests and submits the app to TestFlight | ||
|
||
Xcode 15.3 or higher is required. | ||
|
||
## Code style | ||
|
||
The Xcode project is configured to use 4 spaces for indentation. | ||
For linting Swift source code, we use [SwiftLint](https://github.com/realm/SwiftLint). | ||
A configuration for [SwiftFormat](http://github.com/nicklockwood/SwiftFormat) is also included. | ||
|
||
## Continuous integration | ||
|
||
GitHub Actions is used for continuous integration (CI). The CI runs the automated tests when you make a pull request. | ||
On a push to the `main` branch, it will also run the tests, and if they pass, a build of the app is made and uploaded to TestFlight. | ||
|
||
### CI configuration | ||
|
||
Five environment secrets are needed for the workflow to run on GitHub Actions. | ||
You may configure these in the repository secret settings on GitHub. | ||
|
||
* `BUILD_CERTIFICATE_BASE64` contains a base64-encoded string of the .p12 certificate bundle, used to code sign the app. This bundle needs to contain two certificates: **development** and **distribution**. | ||
* `P12_PASSWORD` contains the password of the certificate bundle. | ||
* `APP_STORE_CONNECT_API_KEY_BASE64` contains a base64-encoded string of the .p8 App Store Connect API key. | ||
* `APP_STORE_CONNECT_API_KEY_ID` contains the key ID of the App Store Connect API key. | ||
* `APP_STORE_CONNECT_API_KEY_ISSUER_ID` contains the issuer ID of the App Store Connect API key. | ||
|
||
To create such a certificate bundle, open Keychain Access. Unfold the entries for the development and distribution certificate. Select the certificates and their private keys using shift, then right-click and select "Export 4 items...". | ||
|
||
You can encode a file to base64 on the command line like this: `base64 -i ~/Desktop/Certificates.p12 | pbcopy`. This automatically puts the result on your clipboard. |
Oops, something went wrong.