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

feat: configuration management #158

Merged
merged 12 commits into from
Nov 21, 2023
Merged

Conversation

mumer92
Copy link
Contributor

@mumer92 mumer92 commented Nov 13, 2023

Project Configuration Management

This PR introduces a way to integrate and manage config files for iOS project.

  • Build Phase Script Integration: Adds a script to Build Phase of Xcode. It calls Xcode build phase run script, which takes care of virtual environment and installing dependencies and calls a python script process_config.py with $CONFIGURATION and scheme_mappings argument.
  • Python Script for Configuration: Utilizes process_config.py for:
    • Adding essential keys to Info.plist (e.g., Facebook, Microsoft keys).
    • CreatingGoogleServices.plist with Firebase keys.
    • Generating config.plist from ios.yaml and shared.yaml.

Inside Config.swift parsing and populating relevant keys and classes are done, e.g. AgreementConfig.swift and FirebaseConfig.swift

Get started:
Edit a config_settings.yaml in the default_config folder.
It should contain data as follows

config_directory: '{path_to_confiig_folder}'
config_mapping:
  prod: 'prod'
  stage: 'stage'
  dev: 'dev'
# These mappings are configurable, e.g. dev: 'prod_test'
  • config_directory provides path of config directory
  • config_mappings provides provides mappings that can be utilized to map Xcode build scheme map to a defined folder within config directory and it will be referenced.

Config files are separated out in 2 files

ios.yaml and shared.yaml

both configs should be placed under a folder which will be referenced inside config_settings.yaml inside of the key config_mappings:{config_directory_name}

inside config_directory, mappings.yaml which contains yaml files that will be used to read available yaml files and processed inside script.

it is structure will be as follows:

ios:
    files:
      - {file_one.yaml}
      - {file_two.yaml}
  • ios.yaml will contain config data specific to iOS, e.g. Firebase keys, Facebook keys, etc.
  • shared.yaml will contain config data that is shared, e.g. API_HOST_URL, OAUTH_CLIENT_ID, TOKEN_TYPE, etc

Future Support:

  • To add config related to some other service, create a class, e.g. ServiceNameConfig.swift to be able to populate related fields
  • Create extension to Config.swift to be able to add the newly created service as a varable to main Config.
  • If needed, make a protocol to be reference inside the scope of ConfigProtocol so that config is available using ConfigProtocol service.

e.g.

private let key = "KEY"
extension Config {
    public var serviceNameConfig: ServiceNameConfig {
        return ServiceNameConfig(dictionary: self[key] as? [String: AnyObject] ?? [:])
    }
}

Note
This PR also updates FirebaseCrashlytics build phase
Updated build phase script extracts googleAppID from the newly generated GoogleService-Info.plist and runs the crashlytics script with the provided id.

Examples of config files:

ios.yaml

OAUTH_CLIENT_ID: ''

FIREBASE:
  ENABLED: true
  API_KEY: "testApiKey"
  BUNDLE_ID: "testBundleID"
  CLIENT_ID: "testClientID"
  DATABASE_URL: "https://test.database.url"
  GCM_SENDER_ID: "testGCMSenderID"
  GOOGLE_APP_ID: "testGoogleAppID"
  PROJECT_ID: "testProjectID"
  REVERSED_CLIENT_ID: "testReversedClientID"
  STORAGE_BUCKET: "testStorageBucket"
  ANALYTICS_SOURCE: "firebase"
  CLOUD_MESSAGING_ENABLED: true

MICROSOFT:
  ENABLED: true
  APP_ID: "microsoftAppID"

shared.yaml

API_HOST_URL: "https://www.example.com"
FEEDBACK_EMAIL_ADDRESS: "[email protected]"
TOKEN_TYPE: "JWT"

AGREEMENT_URLS:
  PRIVACY_POLICY_URL: "https://www.example.com/privacy"
  TOS_URL: "https://www.example.com/tos"

# Features
WHATS_NEW_ENABLED: false

default_config directory is added to project to get an idea on how to write config yaml files.

OpenEdX/Environment.swift Outdated Show resolved Hide resolved
…shlytics google app id, remove process_config.sh in favour of build script
@mumer92 mumer92 marked this pull request as draft November 14, 2023 08:00
@mumer92 mumer92 marked this pull request as ready for review November 14, 2023 11:41
@mumer92
Copy link
Contributor Author

mumer92 commented Nov 14, 2023

@rnr @volodymyr-chekyrta @saeedbashir I have updated the implementation to use Xcode schemes that are currently being used. i have updated the description with these changes.

@touchapp
Copy link

@volodymyr-chekyrta would like your opinion here. What @rnr is proposing is more elegant and straight forward that involves less steps. I suggest we go with that. The concerns about community raised by @saeedbashir can be addressed if we make clear documentation on how to configure. @rnr can add these changes but want to make sure we are aligned.

@saeedbashir
Copy link
Contributor

@volodymyr-chekyrta would like your opinion here. What @rnr is proposing is more elegant and straight forward that involves less steps. I suggest we go with that. The concerns about community raised by @saeedbashir can be addressed if we make clear documentation on how to configure. @rnr can add these changes but want to make sure we are aligned.

I and @rnr had a discussion on it, and we agreed on a structure. Today we'll be making the changes and then this PR will be ready for final pass.

fix: fix documentation link

fix: fix documentation link

fix: remove type

fix: remove type

fix: cleanup
@mumer92 mumer92 force-pushed the umer/config branch 2 times, most recently from b57e313 to dbb2155 Compare November 20, 2023 11:40
@mumer92 mumer92 requested a review from rnr November 20, 2023 12:07
@mumer92
Copy link
Contributor Author

mumer92 commented Nov 20, 2023

@rnr @volodymyr-chekyrta i have made the changes that we agreed on, the PR is ready for review.


extension Config: ConfigProtocol {
public var baseURL: URL {
return URL(string: string(for: ConfigKeys.baseURL.rawValue)!)!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @mumer92
Could we avoid force unwrapping here?
Thank you

Copy link
Contributor

@rnr rnr Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand baseURL is important part and we need to have this
maybe it can be something like

    public var baseURL: URL {
        if let string = string(for: ConfigKeys.baseURL.rawValue),
            let url = URL(string: string) {
            return url
        }
        fatalError("Can't find baseURL in Config!")
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i used convention that was being followed in project, i think we can use guard let here and return URL(string "") instead of doing fataError, what are your thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not in favour of fataError(), i think app should handle issue gracefully.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mumer92 code we have now (with force unwrapping) will just crash if baseURL is not present in config.
URL(string: "") also returns nil and will crash with force unwrapping
I understand app can't work without baseURL - we need to try to show what is the problem exactly (fatalError show a message at least). It could be some Log etc. Just provide issue description.
I'm open to any options without force unwrapping.
What do you think?

Copy link
Contributor

@rnr rnr Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL(string: "")! produces crash
why this Crash is better than "Crash with message"? )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alright i will add fatalError("Can't find baseURL in Config!"), in the mean time you can continue with other changes for the review.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all other looks good for me. good work @mumer92 !

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rnr i have updated it. please have a look.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mumer92 approved
thank you

rnr
rnr previously approved these changes Nov 20, 2023
@volodymyr-chekyrta
Copy link
Contributor

Let's move config files from the Combine folder, probably it's been placed here by mistake.
image

@volodymyr-chekyrta
Copy link
Contributor

We should place the Combine framework files back in it's folder
image

@volodymyr-chekyrta
Copy link
Contributor

I played around with configurations a bit and it works amazing 🚀🚀🚀

@mumer92
Copy link
Contributor Author

mumer92 commented Nov 21, 2023

@volodymyr-chekyrta i have addressed the feedback.

@volodymyr-chekyrta
Copy link
Contributor

Green light from me 🟢 🚀
I see we are still waiting for approval from @saeedbashir
@saeedbashir, Could you please provide a review/approval?

@volodymyr-chekyrta volodymyr-chekyrta merged commit d8267da into openedx:develop Nov 21, 2023
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants