Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically Release to TestFlight & Add Feature Flags to Control the Firebase Environment #48

Merged
merged 7 commits into from
Feb 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 7 additions & 47 deletions .github/workflows/beta-deployment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,11 @@ jobs:
secrets: inherit
iosapptestflightdeployment:
name: iOS App TestFlight Deployment
runs-on: macos-12
needs: buildandtest
steps:
- uses: actions/checkout@v3
with:
lfs: true
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Check Environment
run: |
xcodebuild -version
swift --version
- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db

# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_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

# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Build and test
run: bundler install && bundle exec fastlane beta
env:
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY_BASE64: ${{ secrets.APP_STORE_CONNECT_API_KEY_BASE64 }}
APPLE_ID: ${{ secrets.APPLE_ID }}
uses: StanfordBDHG/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
secrets: inherit
with:
artifactname: Utah.xcresult
runsonlabels: '["macos-latest"]'
fastlanelane: beta
setupsigning: true
58 changes: 14 additions & 44 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,47 +20,17 @@ jobs:
swiftlint:
name: SwiftLint
uses: StanfordBDHG/.github/.github/workflows/swiftlint.yml@v1
buildandtestiosapp:
name: Build and Test iOS App
runs-on: macos-12
steps:
- uses: actions/checkout@v3
with:
lfs: true
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Check Environment
run: |
xcodebuild -version
swift --version
- name: Cache Firebase Emulators
uses: actions/cache@v3
with:
path: ~/.cache/firebase/emulators
key: ${{ runner.os }}-firebase-emulators-${{ hashFiles('~/.cache/firebase/emulators/**') }}
- name: Setup NodeJS
uses: actions/setup-node@v3
- name: Setup Java
uses: actions/setup-java@v3
with:
distribution: 'microsoft'
java-version: '17'
- name: Install Firebase CLI Tools
run: npm install -g firebase-tools
- name: Build and Test Example App
run: |
firebase emulators:exec 'bundler install && bundle exec fastlane test'
- name: Upload Artifact
if: always()
uses: actions/upload-artifact@v3
with:
name: Utah.xcresult
path: Utah.xcresult
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}
xcode: true
xcode_archive_path: Utah.xcresult
buildandtest:
name: Build and Test
uses: StanfordBDHG/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
with:
artifactname: Utah.xcresult
runsonlabels: '["macos-latest"]'
setupfirebaseemulator: true
customcommand: "firebase emulators:exec 'fastlane test'"
uploadcoveragereport:
name: Upload Coverage Report
needs: buildandtest
uses: StanfordBDHG/.github/.github/workflows/create-and-upload-coverage-report.yml@v2
with:
coveragereports: Utah.xcresult
1 change: 1 addition & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ deployment_target: # Availability checks or attributes shouldn’t be using olde
excluded: # paths to ignore during linting. Takes precedence over `included`.
- .build
- .swiftpm
- .derivedData

closure_body_length: # Closure bodies should not span too many lines.
- 35 # warning - default: 20
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ The application includes the following feature flags that can be configured in t
- ``--skipOnboarding``: Skips the onboarding flow to enable easier development of features in the application and to allow UI tests to skip the onboarding flow.
- ``--showOnboarding``: Always show the onboarding when the application is launched. Makes it easy to modify and test the onboarding flow without the need to manually remove the application or reset the simulator.
- ``--disableFirebase``: Disables the Firebase interactions, including the login/sign-up step and the Firebase Firestore upload.
- ``--useFirebaseEmulator``: Defines if the application should connect to the local firebase emulator. Always set to true when using the iOS simulator.


## Continous Delivery Workflows

Expand Down
25 changes: 21 additions & 4 deletions Utah.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
2F905711299E3E0D003D3802 /* FirebaseAccount in Frameworks */ = {isa = PBXBuildFile; productRef = 2F905710299E3E0D003D3802 /* FirebaseAccount */; };
2F905713299E3E0D003D3802 /* FirestoreDataStorage in Frameworks */ = {isa = PBXBuildFile; productRef = 2F905712299E3E0D003D3802 /* FirestoreDataStorage */; };
2F905715299E3E0D003D3802 /* FirestoreStoragePrefixUserIdAdapter in Frameworks */ = {isa = PBXBuildFile; productRef = 2F905714299E3E0D003D3802 /* FirestoreStoragePrefixUserIdAdapter */; };
2F9A484C29AAFB0D0041F064 /* FirebaseFirestore in Frameworks */ = {isa = PBXBuildFile; productRef = 2F9A484B29AAFB0D0041F064 /* FirebaseFirestore */; };
2FC9759F2978E39600BA99FE /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2FC9759E2978E39600BA99FE /* Localizable.strings */; };
2FC975A82978F11A00BA99FE /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2FC975A72978F11A00BA99FE /* Home.swift */; };
653A2551283387FE005D4D48 /* Utah.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653A2550283387FE005D4D48 /* Utah.swift */; };
Expand Down Expand Up @@ -107,6 +108,7 @@
93E00346298DCF6400D6E494 /* UtahTrends in Frameworks */,
2F49B784298041F300BCB272 /* Contact in Frameworks */,
2F905713299E3E0D003D3802 /* FirestoreDataStorage in Frameworks */,
2F9A484C29AAFB0D0041F064 /* FirebaseFirestore in Frameworks */,
2F49B7782980407C00BCB272 /* FHIR in Frameworks */,
2F49B7802980418400BCB272 /* Onboarding in Frameworks */,
2F905711299E3E0D003D3802 /* FirebaseAccount in Frameworks */,
Expand Down Expand Up @@ -249,6 +251,7 @@
2F905712299E3E0D003D3802 /* FirestoreDataStorage */,
2F905714299E3E0D003D3802 /* FirestoreStoragePrefixUserIdAdapter */,
93CD053629A0430400CC9DFB /* ResearchKit */,
2F9A484B29AAFB0D0041F064 /* FirebaseFirestore */,
);
productName = UtahApplication;
productReference = 653A254D283387FE005D4D48 /* Utah.app */;
Expand Down Expand Up @@ -331,6 +334,7 @@
2F4E237F2989C5930013F3D9 /* XCRemoteSwiftPackageReference "XCTHealthKit" */,
2F90570B299E3C69003D3802 /* XCRemoteSwiftPackageReference "XCTestExtensions" */,
93CD053529A0430400CC9DFB /* XCRemoteSwiftPackageReference "ResearchKit" */,
2F9A484A29AAFB0D0041F064 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
);
productRefGroup = 653A254E283387FE005D4D48 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -925,15 +929,15 @@
repositoryURL = "https://github.com/StanfordBDHG/CardinalKit";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.3.1;
minimumVersion = 0.3.2;
};
};
2F4E237F2989C5930013F3D9 /* XCRemoteSwiftPackageReference "XCTHealthKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/StanfordBDHG/XCTHealthKit";
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.3.0;
minimumVersion = 0.3.3;
};
};
2F90570B299E3C69003D3802 /* XCRemoteSwiftPackageReference "XCTestExtensions" */ = {
Expand All @@ -944,12 +948,20 @@
minimumVersion = 0.3.0;
};
};
2F9A484A29AAFB0D0041F064 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/firebase/firebase-ios-sdk.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 10.5.0;
};
};
93CD053529A0430400CC9DFB /* XCRemoteSwiftPackageReference "ResearchKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "git@github.com:StanfordBDHG/ResearchKit.git";
repositoryURL = "https://github.com/StanfordBDHG/ResearchKit";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
minimumVersion = 2.2.8;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down Expand Up @@ -1041,6 +1053,11 @@
package = 2F49B7742980407B00BCB272 /* XCRemoteSwiftPackageReference "CardinalKit" */;
productName = FirestoreStoragePrefixUserIdAdapter;
};
2F9A484B29AAFB0D0041F064 /* FirebaseFirestore */ = {
isa = XCSwiftPackageProductDependency;
package = 2F9A484A29AAFB0D0041F064 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
productName = FirebaseFirestore;
};
93CD053629A0430400CC9DFB /* ResearchKit */ = {
isa = XCSwiftPackageProductDependency;
package = 93CD053529A0430400CC9DFB /* XCRemoteSwiftPackageReference "ResearchKit" */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/CardinalKit",
"state" : {
"revision" : "9519bbbe8d74719c8315a23cc96e0d5f0355b835",
"version" : "0.3.1"
"revision" : "5ad27f4b7c47d9d3ab1435eb55bcd3db139dbd8b",
"version" : "0.3.2"
}
},
{
Expand All @@ -41,17 +41,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/firebase-ios-sdk",
"state" : {
"revision" : "dce2e1abc6c0d5e830ff1cffe3f8633fda64001e",
"version" : "10.3.0"
"revision" : "f567ed9a2b30e29159df258049a9c662c517688e",
"version" : "10.5.0"
}
},
{
"identity" : "googleappmeasurement",
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleAppMeasurement.git",
"state" : {
"revision" : "71eb6700dd53a851473c48d392f00a3ab26699a6",
"version" : "10.1.0"
"revision" : "9a09ece724128e8d1e14c5133b87c0e236844ac0",
"version" : "10.4.0"
}
},
{
Expand Down Expand Up @@ -122,8 +122,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/promises.git",
"state" : {
"revision" : "3e4e743631e86c8c70dbc6efdc7beaa6e90fd3bb",
"version" : "2.1.1"
"revision" : "ec957ccddbcc710ccc64c9dcbd4c7006fcf8b73a",
"version" : "2.2.0"
}
},
{
Expand All @@ -140,17 +140,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/ResearchKitOnFHIR",
"state" : {
"revision" : "efb23f31a79a0b914af6a4a3c90ef2608c95bfeb",
"version" : "0.1.5"
"revision" : "1bc7a15760916ade4c5058fa798a871e80c2955c",
"version" : "0.1.6"
}
},
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-protobuf.git",
"state" : {
"revision" : "ab3a58b7209a17d781c0d1dbb3e1ff3da306bae8",
"version" : "1.20.3"
"revision" : "0af9125c4eae12a4973fb66574c53a54962a9e1e",
"version" : "1.21.0"
}
},
{
Expand All @@ -167,8 +167,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StanfordBDHG/XCTHealthKit",
"state" : {
"revision" : "70b79e67339da1174e6f7dcd58d6c041388ded96",
"version" : "0.3.1"
"revision" : "19395bbd14a2554e4c9d3fe5cf38aa626c807269",
"version" : "0.3.3"
}
}
],
Expand Down
6 changes: 6 additions & 0 deletions Utah.xcodeproj/xcshareddata/xcschemes/Utah.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@
ReferencedContainer = "container:Utah.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "--useFirebaseEmulator"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
24 changes: 18 additions & 6 deletions Utah/UtahAppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import CardinalKit
import FHIR
import FHIRToFirestoreAdapter
import FirebaseAccount
import FirebaseAuth
import FirebaseCore
import class FirebaseFirestore.FirestoreSettings
import FirestoreDataStorage
import FirestoreStoragePrefixUserIdAdapter
import HealthKit
Expand All @@ -22,13 +21,18 @@ import Scheduler
import SwiftUI
import UtahMockDataStorageProvider
import UtahSchedule
import UtahSharedContext


class UtahAppDelegate: CardinalKitAppDelegate {
override var configuration: Configuration {
Configuration(standard: FHIR()) {
if !CommandLine.arguments.contains("--disableFirebase") {
FirebaseAccountConfiguration()
if !FeatureFlags.disableFirebase {
if FeatureFlags.useFirebaseEmulator {
FirebaseAccountConfiguration(emulatorSettings: (host: "localhost", port: 9099))
} else {
FirebaseAccountConfiguration()
}
firestore
}
if HKHealthStore.isHealthDataAvailable() {
Expand All @@ -42,11 +46,19 @@ class UtahAppDelegate: CardinalKitAppDelegate {


private var firestore: Firestore<FHIR> {
Firestore(
let settings = FirestoreSettings()
if FeatureFlags.useFirebaseEmulator {
settings.host = "localhost:8080"
settings.isPersistenceEnabled = false
settings.isSSLEnabled = false
}

return Firestore(
adapter: {
FHIRToFirestoreAdapter()
FirestoreStoragePrefixUserIdAdapter()
}
},
settings: settings
)
}

Expand Down
4 changes: 2 additions & 2 deletions Utah/UtahAppTestingSetup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ private struct UtahTestingSetup: ViewModifier {
func body(content: Content) -> some View {
content
.task {
if CommandLine.arguments.contains("--skipOnboarding") {
if FeatureFlags.skipOnboarding {
completedOnboardingFlow = true
}
if CommandLine.arguments.contains("--showOnboarding") {
if FeatureFlags.showOnboarding {
completedOnboardingFlow = false
}
}
Expand Down
3 changes: 2 additions & 1 deletion UtahModules/Sources/UtahOnboardingFlow/Welcome.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import Onboarding
import SwiftUI
import UtahSharedContext


struct Welcome: View {
Expand Down Expand Up @@ -37,7 +38,7 @@ struct Welcome: View {
],
actionText: "Next".moduleLocalized,
action: {
if !CommandLine.arguments.contains("--disableFirebase") {
if !FeatureFlags.disableFirebase {
onboardingSteps.append(.accountSetup)
} else {
onboardingSteps.append(.consent)
Expand Down
Loading