Xcode 9 bot integration ipa missing at XCS_PRODUCT path - ios

I am working on Continuous Integration with Xcode 9. I have successfully setup Server & Bot.
Integration works fine.
Requirement:
I required ipa path in Post Script to upload on my server.
Problem:
I am using XCS_PRODUCT variable for fetching ipa path.
Here is ENV Output from post trigger:
XCS_BOT_NAME=TestXCTest Bot
XCS=1
XCS_WARNING_CHANGE=0
XCS_SOURCE_DIR=/Users/xcodeserver/Library/Caches/XCSBuilder/Bots/b2642ba61e9ffe8554a9d17d1f0126d5/Source
SHELL=/bin/bash
XCS_INTEGRATION_RESULT=succeeded
TMPDIR=/var/folders/wv/33mqmjhn525clw9zzx2c0xq80000gs/T/
Apple_PubSub_Socket_Render=/private/tmp/com.apple.launchd.xHus0eJhWj/Render
XCS_TEST_FAILURE_COUNT=0
XCS_INTEGRATION_ID=51c2cf4d7b95c0c4a4f948f23001620e
XCS_BOT_TINY_ID=B705E6C
USER=xcodeserver
XCS_ARCHIVE=/Users/xcodeserver/Library/Caches/XCSBuilder/Integration-51c2cf4d7b95c0c4a4f948f23001620e/TestXCTest.xcarchive
XCS_TEST_FAILURE_CHANGE=0
XCS_INTEGRATION_TINY_ID=2C6684E
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.W6OUJYNErV/Listeners
__CF_USER_TEXT_ENCODING=0x1F9:0:0
XCS_PRIMARY_REPO_DIR=/Users/xcodeserver/Library/Caches/XCSBuilder/Bots/b2642ba61e9ffe8554a9d17d1f0126d5/Source/TestXCTest
PATH=/Applications/Xcode_9.3.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
XCS_BOT_ID=b2642ba61e9ffe8554a9d17d1f0126d5
PWD=/Users/xcodeserver/Library/Caches/XCSBuilder/Bots/b2642ba61e9ffe8554a9d17d1f0126d5/Source
XCS_XCODEBUILD_LOG=/Users/xcodeserver/Library/Caches/XCSBuilder/Integration-51c2cf4d7b95c0c4a4f948f23001620e/xcodebuild.log
XCS_PRODUCT=/Users/xcodeserver/Library/Caches/XCSBuilder/Integration-51c2cf4d7b95c0c4a4f948f23001620e/ExportedProduct/TestXCTest.ipa
XCS_PRIMARY_REPO_BRANCH=master
XPC_FLAGS=0x0
XCS_ERROR_COUNT=0
XCS_ANALYZER_WARNING_COUNT=0
XCS_TESTS_CHANGE=-2
XPC_SERVICE_NAME=0
XCS_ERROR_CHANGE=0
SHLVL=1
HOME=/Users/xcodeserver
XCS_DERIVED_DATA_DIR=/Users/xcodeserver/Library/Caches/XCSBuilder/Bots/b2642ba61e9ffe8554a9d17d1f0126d5/DerivedData
XCS_ANALYZER_WARNING_CHANGE=0
LOGNAME=xcodeserver
XCS_WARNING_COUNT=0
XCS_TESTS_COUNT=0
XCS_OUTPUT_DIR=/Users/xcodeserver/Library/Caches/XCSBuilder/Integration-51c2cf4d7b95c0c4a4f948f23001620e
XCS_INTEGRATION_NUMBER=13
_=/usr/bin/env
Here it show ipa at this path:
/Users/xcodeserver/Library/Caches/XCSBuilder/Integration-51c2cf4d7b95c0c4a4f948f23001620e/ExportedProduct/TestXCTest.ipa
But In finder There isn't any folder like Integration-.....
So Question is How can I get ipa path?
I have checked many questions regarding this like:
Continuous integration Xcode Server after trigger $XCS_PRODUCT not set
Xcode Bot: how to get .ipa path on a post trigger script?
but didn't get answer for Xcode 9.

Found issue
Xcode is deleting Integration folder after completion.
Solution:
I have added below post script to copy ipa:
rm -r "/Users/xcodeserver/Desktop/ipa/*"
cp -R "${XCS_OUTPUT_DIR}/ExportedProduct/" "/Users/xcodeserver/Desktop/ipa/"

Another tip, if $XCS_PRODUCT is empty make sure other triggers prior to this one did not fail. My pod file update script needed to be changed, the downstream upload trigger was still being run but it did not have this env variable set.

Related

iOS Sourcery with Flutter build

Im trying to build my flutter app for iOS it has a google maps key that I want to protect and not check in to source control it needs to be buildable from azure, to achieve this I'm storing my maps key as a secret variable in azure and as a system environment variable locally, I'm using Sourcery https://github.com/krzysztofzablocki/Sourcery to generate a class for me that contains this key, it all works but only the second time I build, the first build always fails.
So I'm building using this command
flutter build ios --flavor dev --verbose
Which the first run will give me the error
error: Build input file cannot be found:
'/Users/martin/xxx/xxx/xxx/ios/Runner/Credentials.generated.swift' (in target
'Runner'
Then issuing the same command again
** BUILD SUCCEEDED **
this is my run script its called before compile sources and after the flutter run script
this calls my script which calls another script to export the map api key and runs sourcery command using a .yml file as its config heres the script, (it also does some logging)
#!/bin/bash
echo "Generate Credentials Code"
CREDENTIALS_DIR="$SRCROOT/credentials"
# Set credentials if local script for adding environment variables exist
if [ -f "$CREDENTIALS_DIR/add_credentials_to_env.sh" ]; then
echo "Add credentials to environement"
source "$CREDENTIALS_DIR/add_credentials_to_env.sh"
echo "finished running add_credentials_to_env.sh"
fi
echo "RUN SOURCERY"
$SRCROOT/Pods/Sourcery/bin/sourcery --config "$SRCROOT/config.yml"
echo "FINISHED RUNNING SOURCERY"
for file in "$SRCROOT/Runner"/*; do
echo "$file"
done
and here is my config file
sources:
- .
project:
file: Runner.xcodeproj
target:
name: Runner
module: Runner
templates:
- credentials/Credentials.stencil
output:
path: ./Runner/
link:
project: Runner.xcodeproj
target: Runner
args:
mapsApiKey: ${MAPS_API_KEY_IOS}
this generates my class correctly on the first build and seems to be added correctly to the target (edited out my key) but the app will only compile if I run the build command again.
// Generated using Sourcery 1.4.2 — https://github.com/krzysztofzablocki/Sourcery
// DO NOT EDIT
public struct Credentials {
let mapsApiKey: String
}
public let credentials = Credentials(mapsApiKey:
"xxxxxxxxxxMY_KEYxxxxxxxxxxx")
Any ideas?
xcode 12.5 m1 macbook pro, swift 5
Looks like you generate the file too late. I'll suggest move your script to Aggregate and add it as a dependency to your target
Add Aggregate
Move your script to 'Run script' section
Add 'PreBuildScriptsRunner' as a dependency to your application target, make sure 'Dependencies' section on top of all other sections
Manually setting environment variables is an annoying thing developers would have to do on their own machines, and there are nicer/ more common ways of setting up private keys. After a few years of using environment variables/ bash, it still causes issues which are not easily detectable. You may want to automate/ document it, but then you have to consider developers using zsh, fish vs. bash? Also, I try to avoid using Xcode build phases where possible.
Solution? (This is what I have)
Why don't you use your CI (Azure pipeline?, I use Github workflows) to write a Xcode build configuration file (not a Swift file). The sensitive keys could be in a file Secrets.xcconfig, which is added to your Xcode as a build configuration. Then, in your Info.plist of your application, and your code can load them.
Create a file, Secrets.xcconfig:
SECRET_API_KEY = 12312rfiwhvde.wvascafsf.df325
Add it to your Xcode project, and then to the project's build configuration:
Add Secrets.xcconfig to your .gitignore
Make sure to git ignore the file before committing it to the repo. You can also keep an Example.Secrets.xcconfig which users can use. In the readme, tell users to run cp Example.Secrets.xcconfig Secrets.xcconfig and then to update values in it. Now you can clearly see what keys the application is using (its clearly in the directory). As a bonus, you can add this file the Xcode project, so that when the file is missing, it shows up in red (indicating to the user they really should acquire this file somehow):
In Info.plist, reference the variable:
<dict>
<key>SECRET_API_KEY</key>
<string>$(SECRET_API_KEY)</string>
</dict>
In your code, load the variable that was stored in Info.plist:
let key = Environment.infoDictionary["SECRET_API_KEY"] as? String
In your CI/ Azure pipeline:
Run echo "SECRET_API_KEY = $SECRET_API_KEY_SAVED_IN_CONTINUOUS_INTEGRATION" >> Secrets.xcconfig
Then you can just .gitignore the file instead of setting environment variables. When you work with other developers, you just give them this file, and nothing else needs to be done to build locally.
So I have answered your question not by solving your direct problem, but giving you a more common/ canonical way of solving this problem that many developers have faced before.

iOS Firebase Crash Reporting - Error running build script

I get the following error when running the script to upload symbol files (everytime I try and build my project):
upload-sym-util.bash:351: error: symbolFileUploadLocation: The API Key and the authentication
credential are from different projects.
Here is my build script:
if [ "$CONFIGURATION" == "Debug" ]; then
GOOGLE_APP_ID=<app-id>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}"/<app>/Firebase/CrashReportingKey-Dev.json
else
GOOGLE_APP_ID=<app-id>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}"/<app>/Firebase/CrashReportingKey.json
fi
Things I've done/checked:
The GOOGLE_APP_ID and CrashReportingKey*.json are associated with the same project.
My GoogleService-Info*.plist files have the API_KEY field.
Checking "Run script only when installing" box, which allows me to run the app, but doesn't actually run the script in a development environment. So crashes are sent to Firebase, but they aren't symbolicated.
I'm open to any ideas. Thanks!
You are correct that there's no way to override the GoogleService-Info.plist. However there's still a way to override the pieces of information the upload script uses from that file.
Open the GoogleService-Info.plist corresponding to the .json.
Search for GOOGLE_APP_ID and API_KEY.
Adjust the build script like so:
export FIREBASE_APP_ID=<GOOGLE_APP_ID>
export FIREBASE_API_KEY=<API_KEY>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "ServiceAccount.json"
In your case, your final script should look something like:
if [ "$CONFIGURATION" == "Debug" ]; then
export FIREBASE_APP_ID=<app-id>
export FIREBASE_API_KEY=<API_KEY for dev>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}"/<app>/Firebase/CrashReportingKey-Dev.json
else
export FIREBASE_APP_ID=<app-id>
export FIREBASE_API_KEY=<API_KEY for release>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}"/<app>/Firebase/CrashReportingKey.json
fi
I resolved :
in terminal :
rm $HOME/Library/Preferences/com.google.SymbolUpload*
Xcode :
Product -> Clean
The issue is with the name of GoogleService-Info.plist file.
In my project, I had the following files:
GoogleService-Info.plist
GoogleService-Info-Dev.plist
CrashReportingKey.json
CrashReportingKey-Dev.json
Firebase Crash Reporting upload script always looks for a file named GoogleService-Info.plist exactly. Since it found one, and I was telling the script to use CrashReportingKey-Dev.json, it threw the project mismatch error.
From my research, there is no way to tell the Firebase Crash Reporting upload script which *Info.plist file you want to use, so I have decided to only upload symbol files for release builds, which is fine.
My run script is now the following, and works as it should.
if [ "$CONFIGURATION" == "Release" ]; then
GOOGLE_APP_ID=<app-id>
"${PODS_ROOT}"/FirebaseCrash/upload-sym "${SRCROOT}"/<app>/Firebase/CrashReportingKey.json
fi
I then removed CrashReportingKey-Dev.json from my project.
In my case, I had to reset my OAuth credentials by running this command :
rm $HOME/Library/Preferences/com.google.SymbolUpload*
as described here : https://firebase.google.com/docs/crash/ios
Works fine for me now !
I have this error today.
And I found this config, simply replace this GOOGLE_APP_ID with the value in your GoogleService-Info.plist
View image here, sorry I don't have permission to post image
Replace GOOGLE_APP_ID

Firebase iOS multiple errors when uploading symbol files

I'm trying to setup Firebase Crash Reporting on a Swift project. I'm using Xcode 7.3. Firebase Crash Reporting version is 1.0.7.
After following all steps properly, this is the error I'm getting on Xcode, which isn't allowing my project to run:
http://imgur.com/a/DtHTH
I've also tried to manually upload it using batch-upload, but it gives me an error:
./batch-upload: line 121: FIREBASE_API_KEY: environment variable empty or unset
Explicitly add to environment or set GoogleService-Info.plist (-p)
and Info.plist (-i) flags to extract values from the files.
Try "./batch-upload -h" for details.
Am I missing anything?
To get the Xcode script to work, the invocation in your run script phase needs to look something like
# Replace this with the GOOGLE_APP_ID from your GoogleService-Info.plist file
GOOGLE_APP_ID=1:1234567890123:ios:1234abc567de89
# Replace the /Path/To/ServiceAccount.json with the path to the key you just downloaded
"${PODS_ROOT}"/FirebaseCrash/upload-sym "/Users/yourname/yourproject/Your Project Name-5632e387efda6.json"
The JSON file is a file you've downloaded after creating a service account in the Firebase Console. Here's instructions on how to do that.
To get batch-upload to work, the invocation of that script is more complicated and might look something like
batch-upload -p path/to/your/project/GoogleService-Info.plist -i path/to/your/project/Info.plist path/to/your/service/account/file/Your\ Project\ Name-abc123def456.json path/to/something.dSYM/DWARF/SomeBinaryName
I'm apologize for this process being a bit arduous and arcane--it's definitely something we're aware of and working on fixing!
Answer from: firebase-support#google.com
Can you go over the following items and see it will work:
reset your OAuth credentials, run below command:
rm $HOME/Library/Preferences/com.google.SymbolUpload*
create new service account and make sure it has editor permission
Revise your script into below format:
# Replace this with the GOOGLE_APP_ID from your GoogleService-Info.plist file
GOOGLE_APP_ID=1:my:app:id
# Replace the /Path/To/ServiceAccount.json with the path to the key you just downloaded
"${PODS_ROOT}"/FirebaseCrash/upload-sym "/Path/To/ServiceAccount.json"
Remember to follow the instructions on this link
Please make sure your app id and json file path are correct.
I hope this helps.

Xcode Bot: how to get .ipa path on a post trigger script?

I'm using a bot to archive an iOS app, and I need to get the .ipa product path in order to publish it into our distribution system.
Bot settings:
And using a script to print all env variables, non of them contains a path to the ipa file. In addition, some of the variables are pointed to directory that does not exist, i.e: XCS_OUTPUT_DIR
Here the env variable output:
XCS=1
XCS_ANALYZER_WARNING_CHANGE=-31
XCS_ANALYZER_WARNING_COUNT=0
XCS_ARCHIVE=/Library/Developer/XcodeServer/Integrations/Integration-771867708dfac45bba10a1998c118912/MyApp.xcarchive
XCS_BOT_ID=771867708dfac45bba10a1998c007d43
XCS_BOT_NAME='MyApp Distribution'
XCS_BOT_TINY_ID=DBB85BD
XCS_DERIVED_DATA_DIR=/Library/Developer/XcodeServer/Integrations/Caches/771867708dfac45bba10a1998c007d43/DerivedData
XCS_ERROR_CHANGE=-1
XCS_ERROR_COUNT=0
XCS_INTEGRATION_ID=771867708dfac45bba10a1998c118912
XCS_INTEGRATION_NUMBER=19
XCS_INTEGRATION_RESULT=warnings
XCS_INTEGRATION_TINY_ID=F7D4469
XCS_OUTPUT_DIR=/Library/Developer/XcodeServer/Integrations/Integration-771867708dfac45bba10a1998c118912
XCS_SOURCE_DIR=/Library/Developer/XcodeServer/Integrations/Caches/771867708dfac45bba10a1998c007d43/Source
XCS_TESTS_CHANGE=0
XCS_TESTS_COUNT=0
XCS_TEST_FAILURE_CHANGE=0
XCS_TEST_FAILURE_COUNT=0
XCS_WARNING_CHANGE=0
XCS_WARNING_COUNT=26
XCS_XCODEBUILD_LOG=/Library/Developer/XcodeServer/Integrations/Integration-771867708dfac45bba10a1998c118912/xcodebuild.log
XPC_FLAGS=0x0
XPC_SERVICE_NAME=com.apple.xcsbuildd
In addition to that, I was able to confirm that .ipa files are being created in another folder (<path to server>/IntegrationAssets/<integration id>/<integration number>/), but that path is not accessible from an env variable.
Any ideas?
Well, after a lot of research and testing and all, apparently there is something wrong with bots in the latest Xcode (7.2) + Server version (5.0.15) not loading the correct environment variables.
My current solution was to create the path manually based on existing env variables:
ARCHIVE_PATH="${XCS_ARCHIVE}"
ARCHIVE_NAME="${ARCHIVE_PATH##*/}"
IPA_NAME="${ARCHIVE_NAME%.*}.ipa"
IPA_PATH="${XCS_OUTPUT_DIR}/ExportedProduct/Apps/${IPA_NAME}"
Which I did based on:
Continuous integration Xcode Server after trigger $XCS_PRODUCT not set
Just a small update--In Xcode 9.4.1 at least $XCS_PRODUCT is set correctly, so you can just use that, e. g. for HockeyApp:
curl -F "status=2" -F "notify=1" -F "ipa=#${XCS_PRODUCT}" -H "X-HockeyAppToken: <token>" https://rink.hockeyapp.net/api/2/apps/upload

Some questions of automate the process of iOS builds

Recently,I try to automate the process of iOS builds using bash scripts.
I'm building the app,code signing the file using xcodebuild, and then pack the project using xcrun.
In xcode,we can set some information easily,(Summary->iOS Application Target->...)
but,how can I set the information without Xcode,I want to do that using bash scripts,like modify info-plist or other configuration files,does it works? how can I solve this question?
The second question:
Because I want to automate iOS builds in server, I need to import certificates(.p12) which clients give me into keychain automatically,the question is how can I export .p12 file automatically from keychain when clients give me the name of code signing.
Can you provide me some information of automating the process of iOS builds using bash scripts? Or do you have realize the function? Please give me some clues about that, or the program.
You can inject custom build settings by passing KEY=VALUE arguments to xcodebuild. You can then put these into Info.plist values with ${MY_BUILD_SETTING}.
I found that we can use plistbuddy to set values about info.plist,like that /usr/libexec/PlistBuddy -c "set:CFBundleShortVersionString ${version_version}" ${plist_path}
plistbuddy is a tool which can modify plist file well,using /usr/libexec/PlistBuddy -h to find help.
Hope that can help other people!

Resources