Skip to content

Commit

Permalink
Add usability study TestFlight deployment with secure OpenAI config
Browse files Browse the repository at this point in the history
  • Loading branch information
jdisho committed Feb 26, 2025
1 parent 8562309 commit 6a861be
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 2 deletions.
54 changes: 54 additions & 0 deletions .github/workflows/user-study-beta-deployment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#
# This source file is part of the Stanford LLM on FHIR project
#
# SPDX-FileCopyrightText: 2025 Stanford University
#
# SPDX-License-Identifier: MIT
#


name: User Study Beta Deployment
on:
push:
branches:
- user-study-deployment
workflow_dispatch:
jobs:
buildandtest:
name: Build and Test
uses: ./.github/workflows/build-and-test.yml
permissions:
contents: read
actions: read
security-events: write
secrets: inherit
setup-openai-config:
name: Setup OpenAI Configuration
runs-on: macos-latest
needs: buildandtest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup OpenAI Configuration
run: >
echo -n "${{ secrets.OPENAI_CONFIG_PLIST_BASE64 }}" | base64 --decode -o
"LLMonFHIR/Supporting Files/OpenAIConfig.plist"
- name: Upload Configuration as Artifact
uses: actions/upload-artifact@v3
with:
name: openai-config
path: LLMonFHIR/Supporting Files/OpenAIConfig.plist
retention-days: 1
userstudytestflightdeployment:
name: User Study TestFlight Deployment
needs:
- buildandtest
- setup-openai-config
uses: StanfordBDHG/.github/.github/workflows/xcodebuild-or-fastlane.yml@v2
permissions:
contents: read
with:
runsonlabels: '["macOS", "self-hosted"]'
setupsigning: true
fastlanelane: beta_user_study
secrets: inherit
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@
//

import SpeziAccessGuard
import SpeziLLMOpenAI
import SwiftUI


struct UserStudyWelcomeView: View {

Check failure on line 14 in LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

File Types Order Violation: A 'main_type' should not be placed amongst the file type(s) 'supporting_type' (file_types_order)
@Environment(LLMOpenAITokenSaver.self) private var tokenSaver
@State private var isPresentingSettings = false
@State private var isPresentingStudy = false

Expand All @@ -34,6 +36,9 @@ struct UserStudyWelcomeView: View {
UserStudyChatView(survey: Survey(.defaultTasks))
}
}
.onAppear {
tokenSaver.token = OpenAIPlistConfiguration.shared.apiKey
}

Check warning on line 41 in LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift

View check run for this annotation

Codecov / codecov/patch

LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift#L39-L41

Added lines #L39 - L41 were not covered by tests
}
}

Expand Down Expand Up @@ -193,3 +198,20 @@ extension [SurveyTask] {
])
]
}

private struct OpenAIPlistConfiguration {
static let shared = OpenAIPlistConfiguration()

let apiKey: String

private init() {
guard let path = Bundle.main.path(forResource: "OpenAIConfig", ofType: "plist"),
let dict = NSDictionary(contentsOfFile: path) as? [String: Any],

Check failure on line 209 in LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift

View workflow job for this annotation

GitHub Actions / SwiftLint / SwiftLint

Legacy Objective-C Reference Type Violation: Prefer Swift value types to bridged Objective-C reference types (legacy_objc_type)
let key = dict["OpenAI_API_Key"] as? String
else {
fatalError("Failed to load OpenAI configuration")
}

self.apiKey = key
}

Check warning on line 216 in LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift

View check run for this annotation

Codecov / codecov/patch

LLMonFHIR/FHIRInterpretation/MultipleResources/UserStudy/UserStudyWelcomeView.swift#L207-L216

Added lines #L207 - L216 were not covered by tests
}
4 changes: 3 additions & 1 deletion LLMonFHIR/Onboarding/OnboardingFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ struct OnboardingFlow: View {
OnboardingStack(onboardingFlowComplete: $completedOnboardingFlow) {
Welcome()
Disclaimer()
OpenAIAPIKey()
if !FeatureFlags.isUserStudyEnabled {
OpenAIAPIKey()
}
if HKHealthStore.isHealthDataAvailable() && !healthKitAuthorization {
HealthKitPermissions()
}
Expand Down
8 changes: 7 additions & 1 deletion LLMonFHIR/SharedContext/FeatureFlags.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
// SPDX-License-Identifier: MIT
//

import Foundation


/// A collection of feature flags for the PAWS app.
enum FeatureFlags {
/// Skips the onboarding flow to enable easier development of features in the application and to allow UI tests to skip the onboarding flow.
Expand All @@ -15,5 +18,8 @@ enum FeatureFlags {
/// Sets the application in test mode
static let testMode = CommandLine.arguments.contains("--testMode")
/// Sets the application in user study mode
static let isUserStudyEnabled = CommandLine.arguments.contains("--userStudy")
static var isUserStudyEnabled: Bool {
CommandLine.arguments.contains("--userStudy") ||
Bundle.main.infoDictionary?["UserStudyEnabled"] as? Bool == true
}
}
31 changes: 31 additions & 0 deletions fastlane/Fastfile
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,35 @@ platform :ios do
changelog: commit[:message]
)
end

desc "Publish a user study build to TestFlight"
lane :beta_user_study do
signin
increment_build_number(
{
build_number: latest_testflight_build_number + 1
}
)

update_info_plist(
plist_path: "LLMonFHIR/Supporting Files/Info.plist",
block: proc do |plist|
plist["UserStudyEnabled"] = true
end
)

build

commit = last_git_commit
upload_to_testflight(
distribute_external: true,
groups: [
"External Testers"
],
submit_beta_review: true,
notify_external_testers: true,
expire_previous_builds: true,
changelog: commit[:message]
)
end
end

0 comments on commit 6a861be

Please sign in to comment.