From ee793c6d839576b9d016326a8977011477b6b51e Mon Sep 17 00:00:00 2001 From: Paul Schmiedmayer Date: Sat, 10 Aug 2024 10:39:14 -0700 Subject: [PATCH] Improve GitHub Actions & Upload to App Store Connect Metadata In The Repo (#74) # Improve GitHub Actions & Upload to App Store Connect Metadata In The Repo ## :gear: Release Notes - Improve GitHub Actions - Upload to App Store Connect Metadata In The Repo ### Code of Conduct & Contributing Guidelines By submitting creating this pull request, you agree to follow our [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md): - [x] I agree to follow the [Code of Conduct](https://github.com/StanfordBDHG/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributing Guidelines](https://github.com/StanfordBDHG/.github/blob/main/CONTRIBUTING.md). --- .github/workflows/beta-deployment.yml | 37 ++-- .github/workflows/build-and-test.yml | 3 +- .reuse/dep5 | 5 + PAWS.xcodeproj/project.pbxproj | 182 ++---------------- .../xcshareddata/xcschemes/PAWS.xcscheme | 4 +- PAWS/Onboarding/InvitationCodeView.swift | 30 ++- PAWSUITests/AccountCreationTests.swift | 46 +++-- PAWSUITests/DataManagementTests.swift | 2 +- README.md | 3 - fastlane/.gitignore | 2 +- fastlane/Fastfile | 93 +++++++-- fastlane/README.md | 20 +- fastlane/Snapfile | 37 ---- fastlane/metadata/copyright.txt | 1 + .../en-US/apple_tv_privacy_policy.txt | 1 + fastlane/metadata/en-US/description.txt | 4 + fastlane/metadata/en-US/keywords.txt | 1 + fastlane/metadata/en-US/marketing_url.txt | 1 + fastlane/metadata/en-US/name.txt | 1 + fastlane/metadata/en-US/privacy_url.txt | 1 + fastlane/metadata/en-US/promotional_text.txt | 1 + fastlane/metadata/en-US/release_notes.txt | 1 + fastlane/metadata/en-US/subtitle.txt | 1 + fastlane/metadata/en-US/support_url.txt | 1 + fastlane/metadata/primary_category.txt | 1 + .../metadata/primary_first_sub_category.txt | 1 + .../metadata/primary_second_sub_category.txt | 1 + fastlane/metadata/secondary_category.txt | 1 + .../metadata/secondary_first_sub_category.txt | 1 + .../secondary_second_sub_category.txt | 1 + firebase/firebase-export-metadata.json | 8 +- .../all_namespaces_all_kinds.export_metadata | Bin 52 -> 52 bytes .../all_namespaces/all_kinds/output-0 | Bin 214 -> 428 bytes .../firestore_export.overall_export_metadata | Bin 95 -> 95 bytes functions/index.js | 4 +- 35 files changed, 210 insertions(+), 286 deletions(-) delete mode 100644 fastlane/Snapfile create mode 100644 fastlane/metadata/copyright.txt create mode 100644 fastlane/metadata/en-US/apple_tv_privacy_policy.txt create mode 100644 fastlane/metadata/en-US/description.txt create mode 100644 fastlane/metadata/en-US/keywords.txt create mode 100644 fastlane/metadata/en-US/marketing_url.txt create mode 100644 fastlane/metadata/en-US/name.txt create mode 100644 fastlane/metadata/en-US/privacy_url.txt create mode 100644 fastlane/metadata/en-US/promotional_text.txt create mode 100644 fastlane/metadata/en-US/release_notes.txt create mode 100644 fastlane/metadata/en-US/subtitle.txt create mode 100644 fastlane/metadata/en-US/support_url.txt create mode 100644 fastlane/metadata/primary_category.txt create mode 100644 fastlane/metadata/primary_first_sub_category.txt create mode 100644 fastlane/metadata/primary_second_sub_category.txt create mode 100644 fastlane/metadata/secondary_category.txt create mode 100644 fastlane/metadata/secondary_first_sub_category.txt create mode 100644 fastlane/metadata/secondary_second_sub_category.txt diff --git a/.github/workflows/beta-deployment.yml b/.github/workflows/beta-deployment.yml index fc903ae1..2ec5a434 100644 --- a/.github/workflows/beta-deployment.yml +++ b/.github/workflows/beta-deployment.yml @@ -6,7 +6,7 @@ # SPDX-License-Identifier: MIT # -name: Beta Deployment +name: Deployment on: push: @@ -34,27 +34,38 @@ on: default: staging concurrency: - group: main + group: deployment cancel-in-progress: false jobs: determineenvironment: + name: Determine Environment runs-on: ubuntu-latest outputs: environment: ${{ steps.set-env.outputs.environment }} steps: - name: Checkout code uses: actions/checkout@v4 - - name: Determine environment + - name: Determine Environment id: set-env run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then - echo "::set-output name=environment::${{ inputs.environment }}" + echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT elif [[ "${{ github.event_name }}" == "workflow_call" ]]; then - echo "::set-output name=environment::${{ inputs.environment }}" + echo "environment=${{ inputs.environment }}" >> $GITHUB_OUTPUT else - echo "::set-output name=environment::staging" + echo "environment=staging" >> $GITHUB_OUTPUT fi + vars: + name: Inject Environment Variables In Deployment Workflow + needs: determineenvironment + runs-on: ubuntu-latest + environment: ${{ needs.determineenvironment.outputs.environment }} + outputs: + FIREBASE_PROJECT_ID: ${{ vars.FIREBASE_PROJECT_ID }} + steps: + - run: | + echo "Injecting Environment Variables In Deployment Workflow: ${{ vars.FIREBASE_PROJECT_ID }}" buildandtest: name: Build and Test needs: determineenvironment @@ -66,7 +77,7 @@ jobs: secrets: inherit iosapptestflightdeployment: name: iOS App TestFlight Deployment - needs: [determineenvironment, buildandtest] + needs: [determineenvironment, vars, buildandtest] uses: StanfordBDHG/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2 permissions: contents: read @@ -75,16 +86,10 @@ jobs: environment: ${{ needs.determineenvironment.outputs.environment }} googleserviceinfoplistpath: 'PAWS/Supporting Files/GoogleService-Info.plist' setupsigning: true - fastlanelane: beta + setupfirebaseemulator: true + firebaseemulatorimport: ./firebase --project ${{ needs.vars.outputs.FIREBASE_PROJECT_ID }} + fastlanelane: deploy environment:"${{ needs.determineenvironment.outputs.environment }}" secrets: inherit - vars: - name: Inject Environment Variables In Deployment Workflow - runs-on: ubuntu-latest - environment: ${{ needs.determineenvironment.outputs.environment }} - outputs: - FIREBASE_PROJECT_ID: ${{ vars.FIREBASE_PROJECT_ID }} - steps: - - run: echo "Injecting Environment Variables In Deployment Workflow ..." deployfirebase: name: Deploy Firebase Project needs: [determineenvironment, vars, iosapptestflightdeployment] diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 4200f991..5ff95419 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -38,7 +38,7 @@ jobs: uses: StanfordBDHG/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2 with: codeql: true - fastlanelane: codeql + fastlanelane: build permissions: security-events: write actions: read @@ -147,4 +147,3 @@ jobs: with: name: ECGReviewer_ColabBasic.pdf path: ECGReviewer_ColabBasic.pdf - diff --git a/.reuse/dep5 b/.reuse/dep5 index 5d3da8cb..d44d29a0 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -19,3 +19,8 @@ Files: PAWS/Resources/Assets.xcassets/* Copyright: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) License: MIT Comment: All files are part of the Stanford Spezi Data Pipeline Template open source project. + +Files: fastlane/metadata/* +Copyright: 2024 Stanford University and the project authors (see CONTRIBUTORS.md) +License: MIT +Comment: All files are part of the Stanford Spezi Data Pipeline Template open source project. \ No newline at end of file diff --git a/PAWS.xcodeproj/project.pbxproj b/PAWS.xcodeproj/project.pbxproj index 67ff9579..4060fd16 100644 --- a/PAWS.xcodeproj/project.pbxproj +++ b/PAWS.xcodeproj/project.pbxproj @@ -418,8 +418,8 @@ buildRules = ( ); dependencies = ( - 2FCC1DD02B6A2CF000C686BE /* PBXTargetDependency */, - 566155222AB83CF200209B80 /* PBXTargetDependency */, + 2FDF443B2C65DB4A0075AFC1 /* PBXTargetDependency */, + 2FDF443D2C65DB4A0075AFC1 /* PBXTargetDependency */, ); name = PAWS; packageProductDependencies = ( @@ -498,7 +498,7 @@ attributes = { BuildIndependentTargetsInParallel = 1; LastSwiftUpdateCheck = 1340; - LastUpgradeCheck = 1520; + LastUpgradeCheck = 1600; TargetAttributes = { 653A254C283387FE005D4D48 = { CreatedOnToolsVersion = 13.4; @@ -651,13 +651,13 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 2FCC1DD02B6A2CF000C686BE /* PBXTargetDependency */ = { + 2FDF443B2C65DB4A0075AFC1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - productRef = 2FCC1DCF2B6A2CF000C686BE /* SwiftLintPlugin */; + productRef = 2FDF443A2C65DB4A0075AFC1 /* SwiftPackageListJSONPlugin */; }; - 566155222AB83CF200209B80 /* PBXTargetDependency */ = { + 2FDF443D2C65DB4A0075AFC1 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - productRef = 566155212AB83CF200209B80 /* SwiftPackageListJSONPlugin */; + productRef = 2FDF443C2C65DB4A0075AFC1 /* SwiftLintPlugin */; }; 653A255F28338800005D4D48 /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -672,154 +672,6 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 2FEE10302998C89C000822E1 /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = NO; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - LOCALIZATION_PREFERS_STRING_CATALOGS = YES; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = TEST; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Test; - }; - 2FEE10312998C89C000822E1 /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_ENTITLEMENTS = "PAWS/Supporting Files/PAWS.entitlements"; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = ""; - ENABLE_PREVIEWS = YES; - GENERATE_INFOPLIST_FILE = YES; - INFOPLIST_FILE = "PAWS/Supporting Files/Info.plist"; - INFOPLIST_KEY_NSCameraUsageDescription = "This message should never appear. Please adjust this when you start using camera information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSHealthShareUsageDescription = "The PAWS uses the step count to demonstrate Spezi's integration with HealthKit."; - INFOPLIST_KEY_NSHealthUpdateUsageDescription = "The PAWS uses the step count to demonstrate Spezi's integration with HealthKit."; - INFOPLIST_KEY_NSLocationAlwaysAndWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "This message should never appear. Please adjust this when you start using location information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSMicrophoneUsageDescription = "This message should never appear. Please adjust this when you start using microphone information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSMotionUsageDescription = "This message should never appear. Please adjust this when you start using motion information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_NSSpeechRecognitionUsageDescription = "This message should never appear. Please adjust this when you start using speecg information. We have to put this in here as ResearchKit has the possibility to use it and not putting it here returns an error on AppStore Connect."; - INFOPLIST_KEY_UILaunchScreen_Generation = YES; - INFOPLIST_KEY_UIPAWSlicationSceneManifest_Generation = YES; - INFOPLIST_KEY_UIPAWSlicationSupportsIndirectInputEvents = YES; - INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait; - INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown"; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.cs342.2023.paws; - PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; - SUPPORTS_MACCATALYST = NO; - SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - "SWIFT_ELicenseRef-PAWS_LOC_STRINGS" = YES; - SWIFT_EMIT_LOC_STRINGS = YES; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = 1; - }; - name = Test; - }; - 2FEE10322998C89C000822E1 /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 637867499T; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.cs342.2023.paws.tests; - PRODUCT_NAME = "$(TARGET_NAME)"; - "SWIFT_ELicenseRef-PAWS_LOC_STRINGS" = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PAWS.app/PAWS"; - }; - name = Test; - }; - 2FEE10332998C89C000822E1 /* Test */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = 637867499T; - GENERATE_INFOPLIST_FILE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 17.0; - MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = edu.stanford.cs342.2023.pawsuitests; - PRODUCT_NAME = "$(TARGET_NAME)"; - "SWIFT_ELicenseRef-PAWS_LOC_STRINGS" = NO; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - TEST_TARGET_NAME = PAWS; - }; - name = Test; - }; 653A256F28338800005D4D48 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1038,7 +890,6 @@ 653A257528338800005D4D48 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -1058,7 +909,6 @@ 653A257628338800005D4D48 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -1078,7 +928,6 @@ 653A257828338800005D4D48 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 637867499T; @@ -1097,7 +946,6 @@ 653A257928338800005D4D48 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 637867499T; @@ -1120,7 +968,6 @@ isa = XCConfigurationList; buildConfigurations = ( 653A256F28338800005D4D48 /* Debug */, - 2FEE10302998C89C000822E1 /* Test */, 653A257028338800005D4D48 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1130,7 +977,6 @@ isa = XCConfigurationList; buildConfigurations = ( 653A257228338800005D4D48 /* Debug */, - 2FEE10312998C89C000822E1 /* Test */, 653A257328338800005D4D48 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1140,7 +986,6 @@ isa = XCConfigurationList; buildConfigurations = ( 653A257528338800005D4D48 /* Debug */, - 2FEE10322998C89C000822E1 /* Test */, 653A257628338800005D4D48 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1150,7 +995,6 @@ isa = XCConfigurationList; buildConfigurations = ( 653A257828338800005D4D48 /* Debug */, - 2FEE10332998C89C000822E1 /* Test */, 653A257928338800005D4D48 /* Release */, ); defaultConfigurationIsVisible = 0; @@ -1316,7 +1160,12 @@ isa = XCSwiftPackageProductDependency; productName = SpeziScheduler; }; - 2FCC1DCF2B6A2CF000C686BE /* SwiftLintPlugin */ = { + 2FDF443A2C65DB4A0075AFC1 /* SwiftPackageListJSONPlugin */ = { + isa = XCSwiftPackageProductDependency; + package = 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */; + productName = "plugin:SwiftPackageListJSONPlugin"; + }; + 2FDF443C2C65DB4A0075AFC1 /* SwiftLintPlugin */ = { isa = XCSwiftPackageProductDependency; package = 2FCC1DCE2B6A2CE000C686BE /* XCRemoteSwiftPackageReference "SwiftLint" */; productName = "plugin:SwiftLintPlugin"; @@ -1386,11 +1235,6 @@ package = 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */; productName = SwiftPackageList; }; - 566155212AB83CF200209B80 /* SwiftPackageListJSONPlugin */ = { - isa = XCSwiftPackageProductDependency; - package = 5661551B2AB8384200209B80 /* XCRemoteSwiftPackageReference "swift-package-list" */; - productName = "plugin:SwiftPackageListJSONPlugin"; - }; 9739A0C52AD7B5730084BEA5 /* FirebaseStorage */ = { isa = XCSwiftPackageProductDependency; package = 2FE5DC9029EDD9C3004B9AB4 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */; diff --git a/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme b/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme index faa9ccd0..c0155923 100644 --- a/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme +++ b/PAWS.xcodeproj/xcshareddata/xcschemes/PAWS.xcscheme @@ -1,6 +1,6 @@ diff --git a/PAWS/Onboarding/InvitationCodeView.swift b/PAWS/Onboarding/InvitationCodeView.swift index 4f737b62..e03b4039 100644 --- a/PAWS/Onboarding/InvitationCodeView.swift +++ b/PAWS/Onboarding/InvitationCodeView.swift @@ -34,21 +34,19 @@ struct InvitationCodeView: View { .padding(.top, -8) .padding(.bottom, -12) Divider() - OnboardingActionsView( - primaryText: "Redeem Invitation Code", - primaryAction: { - guard validation.validateSubviews() else { - return - } - - await verifyOnboardingCode() - }, - secondaryText: "I Already Have an Account", - secondaryAction: { - try Auth.auth().signOut() - onboardingNavigationPath.nextStep() + OnboardingActionsView("Redeem Invitation Code") { + guard validation.validateSubviews() else { + return } - ) + + await verifyOnboardingCode() + } + .disabled(invitationCode.isEmpty) + Button("I Already Have an Account") { + try? Auth.auth().signOut() + onboardingNavigationPath.nextStep() + } + .padding(.top, -12) } .padding(.horizontal) .padding(.bottom) @@ -90,7 +88,7 @@ struct InvitationCodeView: View { private var invitationCodeValidationRule: ValidationRule { ValidationRule( rule: { invitationCode in - invitationCode.count >= 8 + invitationCode.isEmpty || invitationCode.count >= 8 }, message: "An invitation code is at least 8 characters long." ) @@ -115,7 +113,7 @@ struct InvitationCodeView: View { try await Auth.auth().signInAnonymously() let checkInvitationCode = Functions.functions().httpsCallable("checkInvitationCode") - let result = try await checkInvitationCode.call(["invitationCode": invitationCode]) + _ = try await checkInvitationCode.call(["invitationCode": invitationCode]) Logger().info("Inviation Code Verification Successful") } diff --git a/PAWSUITests/AccountCreationTests.swift b/PAWSUITests/AccountCreationTests.swift index 9e0432e4..c00e9fea 100644 --- a/PAWSUITests/AccountCreationTests.swift +++ b/PAWSUITests/AccountCreationTests.swift @@ -27,9 +27,9 @@ final class AccountCreationTests: XCTestCase { func testOnboardingFlow() throws { let app = XCUIApplication() - let email = "johndoe@stanford.edu" + let email = "lelandstanford\(Int.random(in: 0...42000))@stanford.edu" - try app.navigateOnboardingFlow(email: email, code: "gdxRWF6G") + try app.navigateOnboardingFlow(email: email, code: "QDXRWF6G") app.assertOnboardingComplete() app.assertStudyGroupAdult() @@ -39,8 +39,8 @@ final class AccountCreationTests: XCTestCase { extension XCUIApplication { func navigateOnboardingFlow( - email: String = "johndoe@stanford.edu", - code: String = "gdxRWF6G", + email: String = "lelandstanford\(Int.random(in: 0...42000))@stanford.edu", + code: String = "QDXRWF6G", repeated skippedIfRepeated: Bool = false ) throws { try navigateOnboardingFlowWelcome() @@ -78,12 +78,33 @@ extension XCUIApplication { } private func navigateOnboardingInvitationCode(code: String) throws { - XCTAssertTrue(staticTexts["Invitation Code"].waitForExistence(timeout: 5)) PAWSUITests.snapshot("1InvitationCode") - try textFields["Invitation Code"].enter(value: code) + let alternativeInvitationCodes = ["ALAAVMVB", "QKGCPEQQ"] + try enterInvitationCode(withRemainingOptions: [code] + alternativeInvitationCodes) + } + + private func enterInvitationCode(withRemainingOptions: [String]) throws { + var withRemainingOptions = withRemainingOptions + let invitationCode = withRemainingOptions.removeFirst() + + XCTAssertTrue(staticTexts["Invitation Code"].waitForExistence(timeout: 5)) + try textFields["Invitation Code"].enter(value: invitationCode) XCTAssertTrue(buttons["Redeem Invitation Code"].waitForExistence(timeout: 2)) buttons["Redeem Invitation Code"].tap() + let alert = alerts["Error"] + if alert.waitForExistence(timeout: 3.0) { + print("Warning: Initial invitation code is invalid, please esure to reset your simulator.") + alert.buttons["OK"].tap() + try textFields["Invitation Code"].delete(count: 8, dismissKeyboard: false) + + if !withRemainingOptions.isEmpty { + try enterInvitationCode(withRemainingOptions: withRemainingOptions) + } else { + XCTFail("Failed to redeem invitation code.") + } + } + sleep(3) } @@ -99,8 +120,8 @@ extension XCUIApplication { try collectionViews.textFields["E-Mail Address"].enter(value: email) try collectionViews.secureTextFields["Password"].enter(value: "HelloWorld") - try textFields["enter first name"].enter(value: "John") - try textFields["enter last name"].enter(value: "Doe") + try textFields["enter first name"].enter(value: "Leland") + try textFields["enter last name"].enter(value: "Stanford") let datePicker = datePickers.firstMatch XCTAssertTrue(datePicker.waitForExistence(timeout: 2)) datePicker.tap() @@ -111,6 +132,9 @@ extension XCUIApplication { XCTAssertTrue(dateWheel.waitForExistence(timeout: 2)) dateWheel.adjust(toPickerWheelValue: "1970") + datePicker.tap() + swipeUp() + XCTAssertTrue(collectionViews.buttons["Signup"].waitForExistence(timeout: 2)) collectionViews.buttons["Signup"].tap() @@ -121,10 +145,10 @@ extension XCUIApplication { XCTAssertTrue(staticTexts["Consent"].waitForExistence(timeout: 5)) XCTAssertTrue(staticTexts["First Name"].waitForExistence(timeout: 2)) - try textFields["Enter your first name ..."].enter(value: "John") + try textFields["Enter your first name ..."].enter(value: "Leland") XCTAssertTrue(staticTexts["Last Name"].waitForExistence(timeout: 2)) - try textFields["Enter your last name ..."].enter(value: "Doe") + try textFields["Enter your last name ..."].enter(value: "Stanford") XCTAssertTrue(scrollViews["Signature Field"].waitForExistence(timeout: 2)) scrollViews["Signature Field"].swipeRight() @@ -176,7 +200,7 @@ extension XCUIApplication { navigationBars.buttons["Your PAWS Account"].tap() XCTAssertTrue(staticTexts["Account Overview"].waitForExistence(timeout: 5.0)) - XCTAssertTrue(staticTexts["John Doe"].exists) + XCTAssertTrue(staticTexts["Leland Stanford"].exists) XCTAssertTrue(staticTexts[email].exists) XCTAssertTrue(staticTexts["Gender Identity, Choose not to answer"].exists) PAWSUITests.snapshot("3AccountInformation") diff --git a/PAWSUITests/DataManagementTests.swift b/PAWSUITests/DataManagementTests.swift index aad0425d..90a15edb 100644 --- a/PAWSUITests/DataManagementTests.swift +++ b/PAWSUITests/DataManagementTests.swift @@ -24,7 +24,7 @@ final class DataManagementTests: XCTestCase { func testPullToRefresh() throws { let app = XCUIApplication() - try app.navigateOnboardingFlow(email: "johndoe@stanford.edu", code: "Xkdyv3DF") + try app.navigateOnboardingFlow(email: "lelandstanford\(Int.random(in: 0...42000))@stanford.edu", code: "XKDYV3DF") try self.exitAppAndOpenHealth(.electrocardiograms) app.activate() diff --git a/README.md b/README.md index 0020c5eb..af59efe9 100644 --- a/README.md +++ b/README.md @@ -55,9 +55,6 @@ PAWS uses [Fastlane Snapshots](https://docs.fastlane.tools/getting-started/ios/s To generate new screenshots, you will likewise need to set the proper environment variables for your shell session. ```bash -export FIRESTORE_EMULATOR_HOST="localhost:8080" -export GCLOUD_PROJECT= - firebase emulators:start --import=./firebase ``` diff --git a/fastlane/.gitignore b/fastlane/.gitignore index f7cdaa40..e941ca1a 100644 --- a/fastlane/.gitignore +++ b/fastlane/.gitignore @@ -8,4 +8,4 @@ test_output report.xml -screenshots \ No newline at end of file +screenshots diff --git a/fastlane/Fastfile b/fastlane/Fastfile index c47b0e08..f0ea52f8 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -32,8 +32,47 @@ platform :ios do ) end - desc "CodeQL" - lane :codeql do + desc "Screenshots" + lane :screenshots do + run_tests( + destination: "generic/platform=iOS Simulator", + configuration: "Debug", + derived_data_path: ".derivedData", + xcargs: "-skipPackagePluginValidation -skipMacroValidation", + build_for_testing: true + ) + + snapshot( + test_without_building: true, + derived_data_path: ".derivedData", + devices: [ + "iPhone 15 Pro", + "iPhone SE (3rd generation)" + ], + languages: [ + "en-US", + ], + scheme: "PAWS", + output_directory: "./fastlane/screenshots", + clear_previous_screenshots: true, + concurrent_simulators: false, + stop_after_first_error: true, + skip_open_summary: true + ) + + # Workaround for https://github.com/fastlane/fastlane/issues/21759 and + Dir.glob("./screenshots/**/iPhone 15 Pro-*.png").each do |file| + sh("sips --resampleHeightWidth 2778 1284 '#{file}'") + end + + # Scale to 1242 x 2208 as there are no iOS 18 Simulators supporting this screen size. + Dir.glob("./screenshots/**/iPhone SE (3rd generation)-*.png").each do |file| + sh("sips --resampleHeightWidth 2208 1242 '#{file}'") + end + end + + desc "Build app" + lane :build do build_app( skip_archive: true, skip_codesigning: true, @@ -42,11 +81,11 @@ platform :ios do ) end - desc "Build app" - lane :build do + desc "Archive app" + lane :archive do build_app( derived_data_path: ".derivedData", - xcargs: "-skipPackagePluginValidation", + xcargs: "-skipPackagePluginValidation -skipMacroValidation", export_options: { provisioningProfiles: { "edu.stanford.cs342.2023.paws" => "CS342 2023 PAWS" @@ -65,24 +104,44 @@ platform :ios do ) end - desc "Publish a beta release to internal TestFlight testers" - lane :beta do + desc "Publish a release to TestFlight or the App Store depending on the environment" + lane :deploy do |options| + environment = options[:environment] || "staging" + + if environment == "production" + screenshots + end + signin increment_build_number( { build_number: latest_testflight_build_number + 1 } ) - build + archive commit = last_git_commit - upload_to_testflight( - distribute_external: true, - groups: [ - "External Testers" - ], - submit_beta_review: true, - notify_external_testers: true, - changelog: commit[:message] - ) + + if environment == "production" + deliver( + submit_for_review: true, + force: true, + reject_if_possible: true, + overwrite_screenshots: true, + automatic_release: true, + precheck_include_in_app_purchases: false, + metadata_path: "./fastlane/metadata", + screenshots_path: "./fastlane/screenshots" + ) + else + upload_to_testflight( + distribute_external: true, + groups: [ + "External Testers" + ], + submit_beta_review: true, + notify_external_testers: true, + changelog: commit[:message] + ) + end end end diff --git a/fastlane/README.md b/fastlane/README.md index 140582f7..d5ea4fe3 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -23,13 +23,13 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do Build and test -### ios codeql +### ios screenshots ```sh -[bundle exec] fastlane ios codeql +[bundle exec] fastlane ios screenshots ``` -CodeQL +Screenshots ### ios build @@ -39,6 +39,14 @@ CodeQL Build app +### ios archive + +```sh +[bundle exec] fastlane ios archive +``` + +Archive app + ### ios signin ```sh @@ -47,13 +55,13 @@ Build app Sign in to the App Store Connect API -### ios beta +### ios deploy ```sh -[bundle exec] fastlane ios beta +[bundle exec] fastlane ios deploy ``` -Publish a beta release to internal TestFlight testers +Publish a release to TestFlight or the App Store depending on the environment ---- diff --git a/fastlane/Snapfile b/fastlane/Snapfile deleted file mode 100644 index f58ce3ec..00000000 --- a/fastlane/Snapfile +++ /dev/null @@ -1,37 +0,0 @@ -# -# This source file is part of the PAWS application based on the Stanford Spezi Template Application project -# -# SPDX-FileCopyrightText: 2023 Stanford University -# -# SPDX-License-Identifier: MIT -# - -# A list of devices you want to take the screenshots from -devices([ - "iPhone 15 Pro Max", - "iPhone 14 Plus", - "iPhone 8 Plus", -]) - -languages([ - "en-US", -]) - -# The name of the scheme which contains the UI Tests -scheme("PAWS") - -# Where should the resulting screenshots be stored? -output_directory("./.screenshots") - -clear_previous_screenshots(true) - -erase_simulator(true) - -# Set the status bar to 9:41 AM, and show full battery and reception. See also override_status_bar_arguments for custom options. -override_status_bar(true) - -# Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments -launch_arguments(["--showOnboarding", "--useFirebaseEmulator"]) - -# For more information about all available options run -# fastlane action snapshot diff --git a/fastlane/metadata/copyright.txt b/fastlane/metadata/copyright.txt new file mode 100644 index 00000000..b2528c18 --- /dev/null +++ b/fastlane/metadata/copyright.txt @@ -0,0 +1 @@ +(c) 2024 Stanford University diff --git a/fastlane/metadata/en-US/apple_tv_privacy_policy.txt b/fastlane/metadata/en-US/apple_tv_privacy_policy.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/en-US/apple_tv_privacy_policy.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/en-US/description.txt b/fastlane/metadata/en-US/description.txt new file mode 100644 index 00000000..fdbb691e --- /dev/null +++ b/fastlane/metadata/en-US/description.txt @@ -0,0 +1,4 @@ +This is an app for the participants in the Pediatric Apple Watch Study. +The Pediatric Apple Watch Study is designed to understand how the Apple Watch can be used to detect and follow heart conditions in children. + +Please only download if you were directed to do so by your healthcare provider. diff --git a/fastlane/metadata/en-US/keywords.txt b/fastlane/metadata/en-US/keywords.txt new file mode 100644 index 00000000..b15229ff --- /dev/null +++ b/fastlane/metadata/en-US/keywords.txt @@ -0,0 +1 @@ +Pediatrics, healthcare, heart, health diff --git a/fastlane/metadata/en-US/marketing_url.txt b/fastlane/metadata/en-US/marketing_url.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/en-US/marketing_url.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/en-US/name.txt b/fastlane/metadata/en-US/name.txt new file mode 100644 index 00000000..330a50dc --- /dev/null +++ b/fastlane/metadata/en-US/name.txt @@ -0,0 +1 @@ +Pediatric Apple Watch Study diff --git a/fastlane/metadata/en-US/privacy_url.txt b/fastlane/metadata/en-US/privacy_url.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/en-US/privacy_url.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/en-US/promotional_text.txt b/fastlane/metadata/en-US/promotional_text.txt new file mode 100644 index 00000000..0473eab2 --- /dev/null +++ b/fastlane/metadata/en-US/promotional_text.txt @@ -0,0 +1 @@ +An app for the Pediatric Apple Watch Study. diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/en-US/release_notes.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/en-US/subtitle.txt b/fastlane/metadata/en-US/subtitle.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/en-US/subtitle.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/en-US/support_url.txt b/fastlane/metadata/en-US/support_url.txt new file mode 100644 index 00000000..871b7114 --- /dev/null +++ b/fastlane/metadata/en-US/support_url.txt @@ -0,0 +1 @@ +https://profiles.stanford.edu/scott-ceresnak diff --git a/fastlane/metadata/primary_category.txt b/fastlane/metadata/primary_category.txt new file mode 100644 index 00000000..16340f75 --- /dev/null +++ b/fastlane/metadata/primary_category.txt @@ -0,0 +1 @@ +HEALTH_AND_FITNESS diff --git a/fastlane/metadata/primary_first_sub_category.txt b/fastlane/metadata/primary_first_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/primary_first_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/primary_second_sub_category.txt b/fastlane/metadata/primary_second_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/primary_second_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/secondary_category.txt b/fastlane/metadata/secondary_category.txt new file mode 100644 index 00000000..a0bed0bf --- /dev/null +++ b/fastlane/metadata/secondary_category.txt @@ -0,0 +1 @@ +MEDICAL diff --git a/fastlane/metadata/secondary_first_sub_category.txt b/fastlane/metadata/secondary_first_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/secondary_first_sub_category.txt @@ -0,0 +1 @@ + diff --git a/fastlane/metadata/secondary_second_sub_category.txt b/fastlane/metadata/secondary_second_sub_category.txt new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/fastlane/metadata/secondary_second_sub_category.txt @@ -0,0 +1 @@ + diff --git a/firebase/firebase-export-metadata.json b/firebase/firebase-export-metadata.json index f7928479..5a37fc8d 100644 --- a/firebase/firebase-export-metadata.json +++ b/firebase/firebase-export-metadata.json @@ -1,16 +1,16 @@ { - "version": "13.7.2", + "version": "13.15.0", "firestore": { - "version": "1.19.4", + "version": "1.19.7", "path": "firestore_export", "metadata_file": "firestore_export/firestore_export.overall_export_metadata" }, "auth": { - "version": "13.7.2", + "version": "13.15.0", "path": "auth_export" }, "storage": { - "version": "13.7.2", + "version": "13.15.0", "path": "storage_export" } } \ No newline at end of file diff --git a/firebase/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata b/firebase/firestore_export/all_namespaces/all_kinds/all_namespaces_all_kinds.export_metadata index 4d01f4e5bd80d75514f4b2fa3efd3f4fc5350c3a..f08c46732b3464836b3ccc456a5065b225b73b8a 100644 GIT binary patch delta 36 ocmXppnII~E{ab72^ylr&62B(3ff+(PTns`S`K2WVr6sxs03SpS8vp0#;>XCqXna#?&!mYw{wypCYnTC5nFhlE delta 23 ecma!#=h>0#;>XCqXnZtTM0O&NKMRw>HAVnU5e4}G diff --git a/functions/index.js b/functions/index.js index 2d4a2acd..a7448cd5 100644 --- a/functions/index.js +++ b/functions/index.js @@ -61,7 +61,7 @@ exports.checkInvitationCode = https }); }); - logger.debug(`User (${userId}) successfully enrolled in study (PAWS) with invitation code: ${invitationCode}`); + logger.debug(`User (${userId}) successfully enrolled in the PAWS study with invitation code: ${invitationCode}`); return {}; } catch (error) { @@ -101,6 +101,8 @@ exports.beforecreated = beforeUserCreated( if (!userDoc.exists || userDoc.data().invitationCode !== invitationQuerySnapshot.docs[0].id) { throw new https.HttpsError("failed-precondition", "User document does not exist or contains incorrect invitation code."); } + + logger.info("User Creation Permitted"); } catch (error) { logger.error(`Error processing request: ${error.message}`); if (!error.code) {