Override environment variable when running on Jenkins - ant

I'm testing a Zend Framework application using PHPUnit and Jenkins. I need to override the APPLICATION_ENV environment variable which is access using PHP's getenv in the PHPUnit bootstrap.php file:
<?php
// Define application environment
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));
... use APPLICATION_ENV to pick database, configuration, etc. ...
I have two environments: testing (for local machines) and testing-ci (for Jenkins machine). How can I set the variable to testing-ci when it runs in Jenkins? Is there any way to set it in build.xml for Ant or Phing?

Step 1: Add the environment variables to Jenkins.
Open either the global or project-specific configuration page depending on your needs and scan down for the Environment variables section. Check the checkbox and use the Add button to add key/value pairs.
These will be passed by Jenkins to your Ant build script.
Step 2: Load them into Ant.
Near the top of your Ant build.xml script, load all environment variables with an env prefix so they don't interfere with other properties.
<property environment="env"/>
Now all imported variables will be available using the env prefix, e.g. ${env.HOME}.
Step 3: Pass them to PHPUnit.
Assuming you're using the <exec> task to run PHPUnit, you can pass each needed variable to it using the <env> child element.
<exec taskname="test" executable="phpunit">
<env key="APPLICATION_ENV" value="${env.APPLICATION_ENV}"/>
...
</exec>
Note: You might want to try just the first step to see if Ant will pass the environment variables along to executed child processes, but I think the other two steps are good for making it clear what is required to other developers.

OK.
Here's what you do...
First, create a new file called bootstrap.php.
Next, in boostrap.php, put the following code:
if (!empty($argv) &&
($key = array_search('--environment', $argv)) !== FALSE)
{
$env = $argv[$key + 1];
putenv('APPLICATION_ENV=' . $env);
}
Load the bootstrap.php into your testsuite or (even better) phpunit.xml.
Finally, via your CI build config, or via the console or wherever, execute your unit tests like phpunit UnitTest.php --environment dev.
You're good to go.

Related

Jenkins auto-prepends PATH with path to java and ant. How to disable?

In a Free-form project I use "Inject environment variables":
JAVA_HOME=/u01/jenkins/jdk1.8.0_181/jre
PATH=/u01/jenkins/jdk1.8.0_181/jre/bin:/u01/jenkins/apache-maven-3.0.5/bin:${PATH}
However, in shell scripts $PATH gets an additional prefix:
++ echo PATH=/u01/jenkins/jdk1.7.0_55/bin:\
/u01/jenkins/apache-ant-1.9.6/bin:/u01/jenkins/apache-maven-3.0.5/bin:\
/u01/jenkins/DependencyFinder-1.2.1-beta4/bin:\
/bin:/u01/jenkins/fly:/u01/jenkins/jdk1.7.0_55/bin:\
/u01/jenkins/jdk1.8.0_181/jre/bin:<the-original-path>
How to find what's causing it and finally have my java 8 in path?
Upd: all entries except /u01/jenkins/jdk1.7.0_55/bin were being added by jenkins_shell script. This is now fixed. But I still don't know who's adding the first entry - path to java.
If a JDK is configured in Manage Jenkins -> Global Tool Configuration then a global environment variable is created: PATH+JDK=/u01/jenkins/jdk1.7.0_55/bin and right before the execution of shell scripts Jenkins prepends PATH with PATH+JDK (actually, any variable that starts with "PATH+"
https://github.com/jenkinsci/jenkins/blob/c904989067aa699ea63d043c44f6ea905cb9c5d5/core/src/main/java/hudson/EnvVars.java#L144
The workaround is to inject an empty PATH+JDK= variable to disable the prepending completely or to inject PATH+JDK=/path/to/proper/jdk.
Additionally, since EnvVars extends TreeMap you can inject another variable: PATH+ZZZ=/path/to/something which is prepended later than PATH+JDK because Jenkins iterates such vars in alphabetic order.
Finally, it's possible to configure a dummy JDK without executables and select this dummy JDK in a dropdown in the Job.

Unable to access environment variable in Bamboo Build Plan

I have a Bamboo Build Plan, with the following set of tasks.
Source Code Checkout
Artifactory Generic Resolve (To Get the zip file from Artifactory)
Script (To Extract the contents of zip file and to set to CATALINA_HOME & PATH environment variable)
Ant (For Build)
Task 3 has the following content in it:
APP_HOME=${bamboo.build.working.directory}
unzip $APP_HOME/tomcat/apache-tomcat-6.0.45-windows-x64.zip
export CATALINA_HOME=$APP_HOME/tomcat/apache-tomcat-6.0.45
export PATH="$PATH:$CATALINA_HOME/bin"
But when I execute 4th Task (Ant), the Build is not considering the CATALINA_HOME & PATH variable which is set as part of Task 3. What is wrong here? Why am I not able to access the environment variable that is set in Task 3?
Every Script Task runs in its own non-interactive shell, eventually invoked through the ExternalProcessBuilder. Existing environment variables are made available to the process (i.e. shell), as well as the additional environment variables defined in the task itself as documented. However, newly exported variables are not carried over to the next task as it is an entirely new, isolated shell.
What you could do is to dump the export statements to a file, and 'source' that file at the start of the next script task.

Could I override the grails.env during runtime

Grails seems to build the artefacts per env.
with the command "grails -Dgrails.env=test war
Is it possible for me to override the running environment programmatically?
The issue here is that we produce the war file using production env config. But I want to run the same war file in other environments, like Test, Staging, DR etc.
There are two options:
1. set grails.env in command line
2. programmatically set the current env in the code.
I wonder how could I achieve option2. Our deploy script is shared, not grails specific. There is a generic environment variable named SYSTEM is passed in command line. If I could map that env to the grails.env in code, that would be idea.

How to declare a global variable in Jenkins and use it in an MSBuild task within each individual project

I am converting our CI platform from CruiseControl to Jenkins, and can't seem to figure something out that seems like it should be relatively simple to do (Disclaimer - I'm no CI or build automation expert, but this was dumped into my lap and I find it interesting)
In CruiseControl, I am able to declare variables like this:
<cb:define rootdir="J:\SOURCES\" />
<cb:define logdir="J:\SOURCES\buildlogs" />
<cb:define iisdir="J:\IIS\" />
<cb:define artifacts="artifacts\" />
Then use them as part of an MSBuild task
<msbuild>
<executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
<workingDirectory>$(rootdir)$(ProjectName)</workingDirectory>
<projectFile>$(ProjectName).sln</projectFile>
<buildArgs>/p:BuildDate="1";OutDir="$(iisdir)$(ProjectName)\bin\\";WebProjectOutputDir="$(iisdir)$(ProjectName)\\"</buildArgs>
<targets>Rebuild;$(ProjectName)</targets>
<timeout>180</timeout>
<logger>C:\Program Files (x86)\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MsBuild.dll</logger>
</msbuild>
If the root or IIS directories change, it can easily be applied to all projects at once. We have ~60 projects setup, so doing this project by project would be very time consuming. Migrating this to Jenkins, the MSBuild command line arguments now look like this (partial sample but includes what is relevant):
OutDir="J:\IIS\ProjectName\bin\\";WebProjectOutputDir="J:\IIS\ProjectName\\"
The IIS directory is hard coded. I need that to be something more like this:
OutDir="${IIS_DIR}\ProjectName\bin\\";WebProjectOutputDir="${ITEM_ROOTDIR}\ProjectName\\"
Is there a way to do that? I tried the configuration slicing plugin, which is useful, but doesn't fit this need from what I see
You can do this with built-in Jenkins' functionality:
Then you need to expand your variable. This, actually, depends on where you would use it.
For example: %MSBuild% and %IIS_DIR% for "Execute windows batch command" build step. Other build steps (and plugins) may use it differently.
For global variables, you need EnvInject plugin. This allows you (among other things) to setup variables at the Global (node) level, at job level or as a step. You can set variables directly, or from properties file, or from scripts.
Once set, the variables are available as environment variables to the rest of Jenkins and its steps (within scope).
For passing arguments to MSBuild, when you configure an MSBuild step, there is an option to pass "Command line arguments" in the format /p:Param=Value.
The "value" could be an environment variable. On Windows environment you would reference it as %myvar%
So, if you configure a global GLOBAL_IIS_DIR=C:\path\to\IIS using EnvInject, you can then reference it on command line with /p:IIS_DIR=%GLOBAL_IIS_DIR%

Set a Jenkins variable after reading console log line / value --OR-- using the variables used by scripts / commands what Jenkins calls

I DONT need the following:
How to set a Jenkins env variable or
How to use a environment variables in Jenkins / windows shell / ant / etc scripts.
What I need is opposite of that.
Summary:
1. I have a Jenkins job: ABC_Build
2. This job calls a .bat file (which calls an ANT code / target for packaging / building a
build). As we are creating a build, this job know what's the new build label name and
ANT is storing it in a variable called "new.build.label". File used is build.xml.
(A NOTE to novice users: If you want to call many Windows commands (.bat / .cmd or
commands which creates a windows shell) then, you should call it using "call
script.bat -Dparam1 -Dparam2...." way).
Now, this job calls an another .bat file (which calls an ANT code /target) and uses one
of the parameter value which gets generated by first .bat file / ANT package target
call (i.e. "new.build.label"). As this is a separate .bat command call to call a new
session of ANT code/target, I need to pass the value of "new.build.label" during the
call of this step. File used here is deploy.xml.
Basically, I'm trying to see how can I set a variable in Jenkins, either by using:
a. reading the console output of my Jenkins job as I'm echoing the value of
new build label in the standard output / console output.
b. any other way, where I can set a jenkins variable using "new.build.label" ANT
variable (once first .bat / ANT package target is finished) and I'm ready to call
the 2nd .bat / .cmd / ANT call for doing deployment. Unfortunately, I can't do both
package / deploy at the same time.
I'm also not interested in knowing WHY CAN'T I call target deploy from first ANT
session when I already know the value of "new.build.label" as my main request is:
HOW TO set a jenkins variable using a "variable" which was used by one of the scripts (ANT/Jelly/Groovy/Maven/etc) that Jenkins called.
You can pass environment variables among Jenkins build steps via EnvInject plugin. In your particular case the following is probably the best way:
The first ANT should echo new.build.label into a properties file that can be read by EnvInject plugin, e.g.:
<echo message="new.build.label=${new.build.label}" file="envars.props" />
Create an Inject environment variables build step and set "Properties File Path" to envars.props (make sure you are dealing with paths correctly). Then new.build.label will be available as an environment variable to the rest of your build steps.
By the way, I think it is not a good practice to call ANT from batch files in Jenkins. Use ANT build step instead.

Resources