3

Is it possible to change Xcode BuildSettings environment variable on a build phase in a script?

The whole idea is the following: I want to publish an open source project with unit tests. My tests require sensitive data like "login" and "password", so I can't hardcode them. I want to pass login through process environment to be able to do something like this:

let login = ProcessInfo().environment["login"]!

I've found the way how to pass a variable from a build settings environment to a tests process: select "Tests" scheme, go to environment variables and add a new value with name "login" and value "$(login)". If I set value for "login" right in the build settings tab – it will be accessible from the ProcessInfo just like I expected.

But what I want is to set "login" from a project's root folder script file "SetupCreds.sh" which is in .gitignore, so it's safe to keep login and password in it. So the idea is:

  1. Add Build Phase script
  2. This script runs "SetupCreds.sh"
  3. "SetupCreds.sh" consist of export lines like export login="MyLogin

If I add echo ${login} in a Build Phase script it tells me that the "login" really has value "MyLogin". But this export does not affect Build Settings environment, only the Build Phase script environment.

How to do exports that override Build Settings environment variables? Or maybe there is another way to do what I want?

Vladlex
  • 845
  • 8
  • 16
  • Would using a xcconfig-file be an option? Otherwise it might be possible to include the setting as a file in the test bundle. E.g. copy it in a run script build phase. – Mats Jan 16 '19 at 14:52
  • Thank you for your answer. 1. "Xcconfig" is a very good proposal, but my configs are generated by the pods. Also, if I try to change a project config in script – git will notice that. I try to figure out how to do this without projects changes noticed by git. 2. Copying is also will be noticed by git. But I like the idea and try to understand whether is possible to optionally add a git-ignored file to Tests target if this file exists at the build time, and not to fail if this file is missing, and then get this file in tests by Bundle's method. Thank you! – Vladlex Jan 16 '19 at 15:13
  • 1
    Yep, it works. Steps: 1. Add a script phase right after "Copy Resources" script. 2. Script's content: ``` file="${SRCROOT}/${Tests.cfg}" if test -f $file then copy_target="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.xctest/Tests.cfg" cp -r $file $copy_target echo "Tests.cfg file copied to ${copy_target}" else echo "warning: No Tests.cfg file found. Some tests will be ignored." fi ``` 3. Put "Tests.cfg" to gitignore. 4. Create "Tests.cfg" file and fill it with sensitive or config-specific values. 5. In tests use `Bundle.for(type(of: self).self)` to get "Tests.cfg" url. – Vladlex Jan 16 '19 at 15:46
  • Can you put your last comment as an answer? It's quite difficult to read in its present form. – Declan McKenna Nov 20 '19 at 09:27

1 Answers1

1

I've copied the answer @Vladex mentioned in the comments here so it's more easily readable.

  1. Add the following script phase right after the "Copy Resources" script.
    $file then
    copy_target="${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.xctest/Tests.cfg"
    cp -r $file $copy_target echo "Tests.cfg file copied to
    ${copy_target}" else echo "warning: No Tests.cfg file found. Some
    tests will be ignored." fi 
  1. Put "Tests.cfg" to gitignore.
  2. Create "Tests.cfg" file and fill it with sensitive or config-specific values.
  3. In tests use Bundle.for(type(of: self).self) to get "Tests.cfg" url.
Declan McKenna
  • 4,321
  • 6
  • 54
  • 72