Automate NewRelic dSYM upload outside Xcode? - ios

My iOS project uses New Relic for tracking. NewRelic requires uploading a dSYM file.
https://docs.newrelic.com/docs/mobile-monitoring/new-relic-mobile-ios/configuration/upload-dsyms-bitcode-apps
I'd like to automate the process through Fastlane, but the provided script complains with:
./NewRelicAgent.framework/Versions/A/Resources/newrelic_postbuild.sh must be run from an XCode build
How can I execute this from within my standard deploy script? I don't want to add this as an XCode post-compile run script or upload manually through the web site.

After some research, I learned that the provided newrelic_postbuild.sh script simply zips up the dSYM folder and uploads it with a curl script.
Fastlane should already do the first part with the gym action. Just specify the output directory in your normal Fastfile build lane.
gym({output_directory: "./build")
When execute, the action above dumps out the symbol file to: ./build/HelloWorld.app.dSYM.zip
To upload that, add it to a variable and execute the following:
NEWRELIC_URL="https://mobile-symbol-upload.newrelic.com/symbol"
NEWRELIC_KEY = "ABCd3fgH1JkLmN0PqRsTuVW8Yz"
DYSM_ZIP_FILE = "./build/HelloWorld.app.dSYM.zip"
Dir.chdir("..") do
sh "curl -F dsym=#\"#{DYSM_ZIP_FILE}\" -H \"x-app-license-key: #{NEWRELIC_KEY}\" \"#{NEWRELIC_URL}\""
end
That'll do it. If you want to just do it from within a bash script, that command would be:
curl -F dsym=#"${DYSM_ZIP_FILE}" -H "x-app-license-key: ${NEWRELIC_KEY}" "${NEWRELIC_URL}"
The benefit of this approach is that we don't have to clutter our Xcode build settings with extra scripts, and we can avoid executing unnecessary and redundant scripting code.

Related

Codemagic not working for custom run script in iOS?

I am trying to build a flutter app on Codemagic. The app uses multiple firebase project so I have configured it accordingly. I am able to run all flavors both for android and iOS locally. The android build is success on Codemagic as well but the iOS build fails.
In the below screenshot you can see after reaching the Firebase setup run script file the iOS build fails
Code for my Firebase Setup file is
environment="default"
# Regex to extract the scheme name from the Build Configuration
# We have named our Build Configurations as Debug-dev, Debug-prod etc.
# Here, dev and prod are the scheme names. This kind of naming is required by Flutter for flavors to work.
# We are using the $CONFIGURATION variable available in the XCode build environment to extract
# the environment (or flavor)
# For eg.
# If CONFIGURATION="Debug-prod", then environment will get set to "prod".
if [[ $CONFIGURATION =~ -([^-]*)$ ]]; then
environment=${BASH_REMATCH[1]}
fi
echo $environment
# Name and path of the resource we're copying
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
GOOGLESERVICE_INFO_FILE=${PROJECT_DIR}/config/${environment}/${GOOGLESERVICE_INFO_PLIST}
# Make sure GoogleService-Info.plist exists
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_FILE}"
if [ ! -f $GOOGLESERVICE_INFO_FILE ]
then
echo "No GoogleService-Info.plist found. Please ensure it's in the proper directory."
exit 1
fi
# Get a reference to the destination location for the GoogleService-Info.plist
# This is the default location where Firebase init code expects to find GoogleServices-Info.plist file
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"
# Copy over the prod GoogleService-Info.plist for Release builds
cp "${GOOGLESERVICE_INFO_FILE}" "${PLIST_DESTINATION}"
I am following https://medium.com/#animeshjain/build-flavors-in-flutter-android-and-ios-with-different-firebase-projects-per-flavor-27c5c5dac10b article for setup.
Here is another approach which I took as recommended by the Codemagic team
Instead of creating flavors,i uploaded my firebase files to codemagic as environment variables. Everything works fine for android but the iOS build fails saying Could not get GOOGLE_APP_ID. I know many people have asked question regarding this on stack but none of them works for me as they are not related to code magic and instead dragging the file to Xcode manually.
I also did an SSH to check if the firebase file gets added to iOS folder and it does get added with the help of prebuild scripts but iOS build still fails.
I used the same Medium article for setting up flavors (prod and dev) on my local machine.
I followed the Codemagic tutorial for setting up environment variables for the Google Service files, and I kept running into the same Could not get GOOGLE_APP_ID error.
The key insight for me was to replicate my local environment in Codemagic as closely as possible and leverage the Firebase setup script in Xcode during Codemagic builds.
In my case, it meant recreating the exact same folder and file structure for the Runner/Firebase/prod/GoogleService-Info.plist so that the Firebase Setup script in Build Phases could run without any issues.
First, I changed the pre-build script in Codemagic to ensure that the GoogleService-Info.plist could be found by the Firebase Setup script:
#!/bin/bash
set -e # exit on first failed commandset
rm -rf $FCI_BUILD_DIR/iOS/Runner/GoogleService-Info.plist
mkdir -p “${FCI_BUILD_DIR}/iOS/Runner/Firebase/${FCI_FLUTTER_SCHEME}”
echo $IOS_FIREBASE_SECRET | base64 —decode > $FCI_BUILD_DIR/iOS/Runner/Firebase/prod/GoogleService-Info.plist
Second, Xcode must be aware of these files. A file present in directory does not mean it is on Xcode. Add the Firebase/ directory into Xcode by File -> Add files to “Runner..” and make sure to uncheck ‘Copy if required’.
If you are already building locally without any issues, you might be able to skip this step.
Here is how my folders appear in Xcode
Then run a build on Codemagic with FCI_FLUTTER_SCHEME=prod.
Lastly, reading through xcodebuild.log in the Codemagic build Artifacts might give you more details.

Jmeter with ant - reports creation

I am trying to create report using ant in jmeter, meaning the full report.
I downloaded ant and it is installed as expected.
first I want to understand if ant command need to perform after test plan ran in the past? meaning it is offline process that creates the html reports? after the test plan finished?
Or is it command that actually used to run the test plan and create the html, meaning I do not need to run jmeter before?.
I used this command
jmeter -n -t C:\JMETER\Framework\Test_Fragment\Kung_Fu.jmx -l C:\Users\stackoverflow\Desktop\Jmeter_reports\results22_05_2018.csv
to run jmeter from command line, and create csv, so do I need two commands? one for creating csv and one for the ant? and if I create the csv where can I find the jtl of the testplan.
Name of test plan kung_fu
name of csv results22_05_2018.csv
what are the processes to run he ant, since I rename the Kung_Fu.jmx to test.jmx and put it in extras folder and when I command ant, it says test.jtl is not found.
can someone give a full explanation about the whole process
Rename results22_05_2018.csv into results22_05_2018.jtl and copy it to "extras" folder of your JMeter installation
Execute the following command in "extras" folder of your JMeter installation:
ant -Dtest=results22_05_2018 xslt-report
HTML report will be available as results22_05_2018.html
For more details see:
build.xml - reference Ant build file, by default it:
looks for Test.jmx file in the current folder
executes it and stores the result into Test.jtl file
applies XSLT transformation to the Test.jtl file and generates HTML file out of it.
JMeter Ant Task
Five Ways To Launch a JMeter Test without Using the JMeter GUI

How can I get the path of a newly built apk in gitlab after the code is checked in, which I need in the command 'curl' to upload it to ADF

I wrote a python script, which uses boto3 to schedule android app UI test on ADF. My next step is to make gitlab CI work. My test suite program is Java Appium with TestNG, not integrated with the android program.
My problem now is how to get the PATH of files(apk and test.zip) in gitlab repo which needed in curl command to upload the newly build apk(builded after new code checked in) and my test suite.
Actually, foremost, am I in the right track?
Can I use curl in gitlab like that?
If so, what's the path I could use? (if you could shortly explain the storage structure(or say namespace?) or give me some reference). Actually, is it just take the project home directory as '/'?
for test suite, its actually easier, if I figure out what's the path, I could just put it in the home directory.
for the newly built apk, I don't actually know where is it. We use the pipeline, I think the apk file is somewhere in the server. Below is the YAML snippet:
archive_project:
stage: archive
script:
- ./gradlew assembleRelease
only:
- master
- search
artifacts:
paths:
- main/build/outputs/
tags:
- android
- gradle
If not, how can I do that? This actually suit if I am not in the right track as well.
So after you check in code, the runner look at the .gitlab_ci.yml, and runs following its instruction. And this process, happens in the server machine(either yours or gitlab's), so everything is basically the same as you in your computer(sure you will need the right environment, just appoint the right image or docker).
so yes, we could use 'curl' there. For the directory structure, if you have the privilege to login your server(thru ssh, for instance), you could get it easily. Or we could just explore it like what we do locally(pwd, ls, cd). So what I did is I have a script which have some "pwd, ls, cd ", and call this script from yml, then I look at the info it print to help figure out the directory structure. Then I got what I want(the path), then problem solved.
Although I didn't use dependencies, but you might want to read it to get more about how to pass artifacts between jobs.
If you are looking for this problem, hope it helps you.

Jenkins "Console Output" log location in filesystem

I want to access and grep Jenkins Console Output as a post build step in the same job that creates this output. Redirecting logs with >> log.txt is not a solution since this is not supported by my build steps.
Build:
echo "This is log"
Post build step:
grep "is" path/to/console_output
Where is the specific log file created in filesystem?
#Bruno Lavit has a great answer, but if you want you can just access the log and download it as txt file to your workspace from the job's URL:
${BUILD_URL}/consoleText
Then it's only a matter of downloading this page to your ${Workspace}
You can use "Invoke ANT" and use the GET target
On Linux you can use wget to download it to your workspace
etc.
Good luck!
Edit:
The actual log file on the file system is not on the slave, but kept in the Master machine. You can find it under: $JENKINS_HOME/jobs/$JOB_NAME/builds/lastSuccessfulBuild/log
If you're looking for another build just replace lastSuccessfulBuild with the build you're looking for.
Jenkins stores the console log on master. If you want programmatic access to the log, and you are running on master, you can access the log that Jenkins already has, without copying it to the artifacts or having to GET the http job URL.
From http://javadoc.jenkins.io/archive/jenkins-1.651/hudson/model/Run.html#getLogFile(), this returns the File object for the console output (in the jenkins file system, this is the "log" file in the build output directory).
In my case, we use a chained (child) job to do parsing and analysis on a parent job's build.
When using a groovy script run in Jenkins, you get an object named "build" for the run. We use this to get the http://javadoc.jenkins.io/archive/jenkins-1.651/hudson/model/Build.html for the upstream job, then call this job's .getLogFile().
Added bonus; since it's just a File object, we call .getParent() to get the folder where Jenkins stores build collateral (like test xmls, environment variables, and other things that may not be explicitly exposed through the artifacts) which we can also parse.
Double added bonus; we also use matrix jobs. This sometimes makes inferring the file path on the system a pain. .getLogFile().getParent() takes away all the pain.
You can install this Jenkins Console log plugin to write the log in your workspace as a post build step.
You have to build the plugin yourself and install the plugin manually.
Next, you can add a post build step like that:
With an additional post build step (shell script), you will be able to grep your log.
I hope it helped :)
Log location:
${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_NUMBER}/log
Get log as a text and save to workspace:
cat ${JENKINS_HOME}/jobs/${JOB_NAME}/builds/${BUILD_NUMBER}/log >> log.txt
For very large output logs it could be difficult to open (network delay, scrolling). This is the solution I'm using to check big log files:
https://${URL}/jenkins/job/${jobName}/${buildNumber}/
in the left column you see: View as plain text. Do a right mouse click on it and choose save links as. Now you can save your big log as .txt file. Open it with notepad++ and you can go through your logs easily without network delays during scrolling.
I found the console output of my job in the browser at the following location:
http://[Jenkins URL]/job/[Job Name]/default/[Build Number]/console
This is designed for use when you have a shell script build step. Use only the first two lines to get the file name.
You can get the console log file (using bash magic) for the current build from a shell script this way and check it for some error string, failing the job if found:
logFilename=${JENKINS_HOME}/${JOB_URL:${#JENKINS_URL}}
logFilename=${logFilename//job\//jobs\/}builds/${BUILD_NUMBER}/log
grep "**Failure**" ${logFilename} ; exitCode=$?
[[ $exitCode -ne 1 ]] && exit 1
You have to build the file name by taking the JOB_URL, stripping off the leading host name part, adding in the path to JENKINS_HOME, replacing "/job/" to "/jobs/" to handle all nested folders, adding the current build number and the file name.
The grep returns 0 if the string is found and 2 if there is a file error. So a 1 means it found the error indication string. That makes the build fail.
Easy solution would be:
curl http://jenkinsUrl/job/<Build_Name>/<Build_Number>/consoleText -OutFile <FilePathToLocalDisk>
or for the last successful build...
curl http://jenkinsUrl/job/<Build_Name>/lastSuccessfulBuild/consoleText -OutFile <FilePathToLocalDisk>

How do you access Xcode environment (and build) variables from an external script?

I am writing a script to automate my iOS building. It will be run outside of Xcode, either via Terminal or from build automating software. Is there any way to have access to Xcode environment variables in my script, so I don't have to try and derive them myself?
For example, can I get access to PROJECT_DIR instead of assuming I'm in the current directory and running pwd?
I am currently hardcoding the product names for my different build configurations. (I'm also hard coding the build configs, but I could parse them them from xcodebuild -list.) Is there a way to get the app if you know the build config name?
(I saw this related question but it doesn't have an answer for me.)
The Xcode environment variables are only defined for child processes of the xcodebuildcommand-line tool.
One solution I used is to have a very simple script as part of my build process (Project->New Build Phase->Add Run Script Build Phase). All this script does is export the necessary variables and call a script in my path somewhere.
That script could be generated by your build script before calling xcodebuild and voilà! you have an external script that has access to Xcode build variables.

Resources