Register for messages from collabd like XCSBuildService to receive Xcode Bots integration number - ios

During an Xcode Bots build each run gets an integration number assigned. This number does not show in the build logs but would be convenient to create http links back to the individual Xcode Bots build in an CI environment or enterprise app store.
In the /Library/Server/Xcode/Logs/xcsbuildd.log I found that XCSBuildService gets a message/event from collabd with a structure that contains the integration number.
Is there a way to register to the same event in an own (OSX) program and receive this message/event?
The only ugly way I found so far to get the Xcode Bots integration number was by parsing the xcsbuildd.log file with the drawback that I can't be sure that the latest integration number corresponds with my current build when several builds are executing in parallel.
This log file is also located in an read protected folder/file so that I have to either change the permissions (ugh!) or use sudo (I don't really want to do that)!?
Example:
sudo grep -r "integration =" /Library/Server/Xcode/Logs/xcsbuildd.log | tail -1 | cut -d'=' -f 2| cut -d';' -f 1 |tr -d '\040\011\012\015'
Gives me the latest integration number stripped from whitespace ...
Edit:
Just found out that if you actually include the following script in your scheme as Build-post-action it will create a file (e.g. /Library/Server/Xcode/Data/BotRuns/Cache/22016b1e-2f91-4757-b3b8-322233e87587/source/integration_number.txt) with the integration number without requiring sudo. Xcode Bots seems to serialize the different builds so that they are not executed in parallel and so the created integration number in the file could be used.
grep -r "integration =" /Library/Server/Xcode/Logs/xcsbuildd.log | tail -1 | cut -d'=' -f 2| cut -d';' -f 1 |tr -d '\040\011\012\015' > ${PROJECT_DIR}/integration_number.txt

For specifically the case of getting the integration build number, I've added a simple answer here.
To repeat myself (and keep this from being down voted as a 1-line answer):
I implemented this using a Shell Script Build Phase in my Xcode project. In my case, I used the integration number to set the internal version of my built product. My script looks like this:
if [ "the$XCS_INTEGRATION_NUMBER" == "the" ]; then
echo "Not an integration build…"
xcrun agvtool new-version "10.13"
else
echo "Setting integration build number: $XCS_INTEGRATION_NUMBER"
xcrun agvtool new-version "$XCS_INTEGRATION_NUMBER"
fi
Note that XCS_INTEGRATION_NUMBER exists by default in the Xcode Server build environment. If you want to simulate an integration build (for the purposes of this script), you can simply add it to your build settings as a custom variable.

Related

.NET core docker - how to find the entry app after dotnet publish

Following all .NET Core guides basically boils down to a dotnet publish and copying the output of that to /app, then running dotnet myapp.dll.
I have about 40+ (and growing) products running in this setup, and so modifying all dockerfiles with myapp.dll gets quite laborious.
I was wondering if there is some way to find out what the entry dll is during publish? (e.g. with --self-contained the cli generates an arch specific entry file, so you can use that name, but it seems like an unnecessary step given that publish takes longer)
You can create a bash script which will extract project name, and next create a valid path with replacing it in script file.
If you are in solution folder just run: (bash)
PROJECT_NAME=`find ./ -name "*.sln" | head -n 1 | cut -d '/' -f 2 | sed 's/.sln//'`
If you have solution file myapp.sln , this command will return value myapp
Then you pass this value to script:
./runScript.sh "$PROJECT_NAME"
And inside this script:
dotnet "/app/$1.dll"
For dockerfiles you have replace all occurences of eg. {{PROJECT_NAME}} in file to value of variable. Now i don't remember command, but sed is useful for that.

How to stop Fabric from running

I've went through documentation: http://support.crashlytics.com
It doesn't seem to question the purpose of the app, so I will ask here :)
I have Fabric integrated in my app. As per installation process, I've installed Fabric app on the Mac I am working on.
Now, from time to time, I have Fabric app that keeps opening, which I personally find very annoying. It's too much for a 3rd party service (even for a great one as Fabric Analytics).
In the build steps in Xcode I've found a script, but doesn't seem that it does the thing:
#!/bin/sh
# run
#
# Copyright (c) 2015 Crashlytics. All rights reserved.
# Figure out where we're being called from
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
# Quote path in case of spaces or special chars
DIR="\"${DIR}"
PATH_SEP="/"
VALIDATE_COMMAND="uploadDSYM\" $# validate run-script"
UPLOAD_COMMAND="uploadDSYM\" $# run-script"
# Ensure params are as expected, run in sync mode to validate
eval $DIR$PATH_SEP$VALIDATE_COMMAND
return_code=$?
if [[ $return_code != 0 ]]; then
exit $return_code
fi
# Verification passed, upload dSYM in background to prevent Xcode from waiting
# Note: Validation is performed again before upload.
# Output can still be found in Console.app
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
So what is Fabric App is really for? Can it be excluded from the workflow? Can I actually erase it and continue the management through Pods? What's the trick behind it?
Because this question is still relevant, to prevent Fabric from launching, you got two options:
1. Stop it after uploading your project’s DSYM file.
Open up the run script: Pods/Fabric/run and change:
eval $DIR$PATH_SEP$UPLOAD_COMMAND > /dev/null 2>&1 &
To:
eval $DIR$PATH_SEP$UPLOAD_COMMAND;killall Fabric > /dev/null 2>&1 &
2. Stop it and only upload DSYM when archiving builds for release:
Check the “Run script only when installing” option under Build Phases:

Parse Crash Reporting - Script Does not End

I just enabled ParseCrashReporting in my app, and now when I build the app, Xcode stays on "Running 2 of 2 custom shell scripts" (i have another simple script for HockeyApp integration, placing it before that does not change anything).
My script is below:
export PATH=/usr/local/bin:$PATH
cd ~/OneDrive/AppName
parse symbols AppName -p "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
My AppName folder is also where I started my parse cloud repo, it contains the folders cloud, config and public. I tried changing the path to AppName/cloud but no change.
Xcode stays running that script for a long time...i've waited 10 minutes for it before and it doesn't continue beyond that. Once I stop the build, I get an error: Shell script invocation error:
Uploading iOS symbol files...
Command /bin/sh failed with exit code 1
I assume the error just shows because I cancel the task. Why would this be sticking like so? I have looked at several questions on parse crash reporting and have not seen any similar issues.
Just use the following script instead, I just tested it and it works:
echo "Parse Crash Reporting"
export PATH=/usr/local/bin:$PATH
CLOUD_CODE_DIR=${PROJECT_DIR}/helloKittyAdventureTimeCloudCodeFolder
if [ -d ${CLOUD_CODE_DIR} ]; then
cd ${CLOUD_CODE_DIR}
parse symbols YOUR_PARSE_APP_NAME --path="${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
echo "Finished uploading symbol"
else
echo "Unable to upload symbols"
fi
IMPORTANT:
The following line needs to be changed based on your folder name, that's it, keep everything else the same:
CLOUD_CODE_DIR=${PROJECT_DIR}/helloKittyAdventureTimeCloudCodeFolder <===this should be the
name or your own folder!!, so, if your folder is named theAdventuresOfCaptainCookCloudCode,
then you would type this:
CLOUD_CODE_DIR=${PROJECT_DIR}/theAdventuresOfCaptainCookCloudCode
Also, one more thing to note, you don't need the echos and such if your run this as a Run Script in Xcode, but you don't have to take them out either, you can just run it like this and you won't have a build error.
One more thing, make sure to change YOUR_PARSE_APP_NAME to the name or your app, sorry about that, this also needs to be changed

Create a dynamic preprocessor macro in Xcode

I often work on iOS projects alongside a development server, which is always running on the same machine that I'm using to build the app. A typical scenario is that I have a rails app running on http://localhost:3000 and I'm testing on the device. In order to test on the device, I need a resolved IP address so that my app can talk to my development server on the local network.
I know that I can use GCC_PREPROCESSOR_DEFINITIONS to set some environment variable into a preprocessor macro, and I know that I can get the build machine's IP address by running ifconfig | grep -E 'inet.[0-9]' | grep -v '127.0.0.1' | awk '{ print $2}' in a bash script.
What I want to do is define MY_SERVER_URL in GCC_PREPROCESSOR_DEFINITIONS using a value such as '#"http://${BUILD_MACHINE_IP_ADDRESS}:3000"', but what I can't figure out is how to set ${BUILD_MACHINE_IP_ADDRESS} using the ifconfig script above.
I have considered editing a configuration file using a run script build phase, but the ramifications of a change like this are irritating. For example, I wouldn't want the file included in source control because my IP address changes frequently and it would cause conflicts. But I would need it to be included in the project file so that the application can access it. This would lead to a file that's required for the project to build but isn't included in the source control, which is ugly.
I've also tried running export BUILD_MACHINE_IP_ADDRESS=`ifconfig | grep -E 'inet.[0-9]' | grep -v '127.0.0.1' | awk '{ print $2}` in a run script build phase but that doesn't yield a result.
One way of doing this is to have a run-script build phase which writes a .h file that #defines the macro and is included your sources.
I don't believe that writing a .xcconfig during build will have any effect on that build.
Exporting environment variables from run-script build phases won't work for multiple reasons. First of all, environment variables may be created from build settings but don't work the other way around. Second, even if they did, a child process can't set environment variables in its parent.
For another approach entirely, have you looked into using the .local host name of your development machine instead of a numeric IP address? Check the Sharing pane of System Preferences, which will show you the domain name for your system.

Automating frank from jenkins

I am trying to automate a test session from jenkins using Frank.
this is the error message I receive.
(Frank::Cucumber::FrankNetworkError)
./step_definitions/test_steps.rb:30:in `/^I navigate to button V\303\244der$/'
test.feature:41:in `When I navigate to <link>'
| Radar | Norrland |
*********************************************
Oh dear. Your app fell over and can't get up.
*********************************************
Jenkins checks out the code from git, besides this I have added a shell command as follows.
cd ios #<--this is so that I go to the root folder, the one with the .xcodeproj project
frank setup
frank build
frank launch
mv features/*.feature Frank/features/. #<--- this is the testscript
mv features/step_definitions/*.rb Frank/features/step_definitions/. #<--here it is moved to the newly created frank/features & Frank/features/step_definitions folder
cd Frank/features
cucumber test.feature
Everything is built the way it should and if I go to the server
and manually type the last row from my shell command will the tests be executed.
Best Regards
I have personally had many problems running Jenkins on Mac. Especially if you used the Jenskins Mac image installer, Jenkins is always run under the "jenkins" user that is created during installation.
This has given me many headaches with running cucumber from inside jobs or for starting the iOS simulator.
I have finally learned to start Jenkins under my own user, like this:
"nohup java -jar /Applications/Jenkins/jenkins.war --httpPort=8080
Since then, I was able to run cucumber without any problems. Hope this helps.
This happens every time your application crashes. When the application crashes, frank stops receiving events and cucumber ends with the error you see.
There are two possible reasons:
You have a bug in your app that made the app crash
Frank has a bug that made your app crash
You should inspect the crash/application log to see the exact reason.
I learned that is very helpful to capture the application log by the jenkins job, e.g.
function grab_log_and_fail {
APP_NAME = "MyApplication"
# get the PID of the last process with the given name
PID=$( cat /var/log/system.log | grep "$APP_NAME\[" | tail -n 1 | sed -e "s/^.*$APP_NAME\ [\([^\]*\)\].*/\1/g" )
# grab all the messages from the process with the PID
cat /var/log/system.log | grep "$APP_NAME\[$PID\]" >"$WORKSPACE/$APP_NAME.log"
#fail the job
exit 1
}
You can call it using
cucumber test.feature || grab_log_and_fail
(will grab the log only if cucumber ends with an error)

Resources