CommandBox + TravisCI
with Dominic Watson
Presentation recording @ https://experts.adobeconnect.com/_a204547676/p354vjluqa9/


About me, briefly

Technical Lead at Pixl8 Interactive (PresideCMS)

My commute
(I work from home a lot)
My family
(I'll stop there)

Greta (4), Will (9), Sharron (age undisclosed, taking the pic)
Travis CI

Super easy CI
for

In a nutshell
A (free for open source) service that spins up environments (OSX/Linux) with your source code on so that you can do stuff with it.
Stuff includes:
 
- Running tests
- Packaging
- Deploying
- Notifying on completion



How it flows
1. Sign up with GitHub

2. Enable your repo

3. Configure your build
...with a .travis.yml file in the root of your project
language: java
rvm:
- 1.9.3
sudo: required
before_install:
- echo "deb http://downloads.ortussolutions.com/debs/noarch /" > commandbox.list
- sudo mv commandbox.list /etc/apt/sources.list.d/commandbox.list
- sudo apt-get update
install:
- sudo apt-get install -q -y --force-yes commandbox zip
- gem install s3_website
script:
- "./build.sh"
env:
  global:
  - secure: Ht3aOvyR/EZN...
  - secure: fvjEs8B0hDMK...
4. Push your code
my-project> git push5. See the build run

.travis.yml
- yml = Yet another Markup Language
- .travis.yml made up of logical "sections":
	- Environment (can be a matrix of environments)
- Lifecycle points
- Deployment
 

.travis.yml: Environment

- Operating system (OSX/Ubuntu)
- Available runtimes (OpenJDK, Ruby, etc)
- Datasources & engines
- Environment variables (can be encrypted)
- Multiple variables to create a matrix of environments
.travis.yml: Build lifecycle

- before_install
- install
- before_script
- script
- after_success/after_failure
- before_deploy
- deploy
- after_deploy
- after_script
.travis.yml: Deployments

- Lots of out of box options:
	- S3
- Heroku
- Ruby Gems
- NPM
- ... lots more!
 
deploy:
  provider: s3
  access_key_id: ...
  secret_access_key:
    secure: ...
  bucket: downloads.presidecms.com
  local-dir: support/build/artifacts
  upload-dir: presidecms
  skip_cleanup: true
  on:
    repo: pixl8/Preside-CMS
    all_branches: trueCommandBox


- Run CFML code
- Spin up a CFML server
- Package management
	- Install project dependencies
- etc.
 
- More (custom commands, build your own!)
From the command line:
Installing CommandBox
in a Travis Linux Environment


Option 1
Using apt-get
sudo: required
before_install:
- echo "deb http://downloads.ortussolutions.com/debs/noarch /" > commandbox.list
- sudo mv commandbox.list /etc/apt/sources.list.d/commandbox.list
- sudo apt-get update
install:
- sudo apt-get install -q -y --force-yes commandbox zipPros: nice and clean
Cons: requires sudo == runs on old Travis CI infrastructure
Remedies: CommandBox to register repo with Travis CI. This would mean we could do:
addons:
  apt:
    sources:
    - commandboxOption 2
Download binaries
before_install:
- mkdir /tmp/bin
- export PATH=$PATH:/tmp/bin
install:
- curl --location 'https://www.ortussolutions.com/parent/download/commandbox/type/bin' -o /tmp/box.zip
- unzip /tmp/box.zip -d /tmp/binPros: clean enough, runs on new infrastructure
Cons: Not really, but binary download may move???
Running tests



box.json
{
    "name":"Your application name",
    "slug":"your-application-slug",
    "version":"1.0.0",
    "author":"Dominic Watson",
    "private":false,
    "license":[
        {
            "type":"LGPL-2.1",
            "url":"http://opensource.org/licenses/LGPL-2.1"
        }
    ],
    "engines":[
        {
            "type":"lucee",
            "version":">=4.5.x"
        }
    ],
    "devDependencies":{
        "testbox":"2.0.0"
    },
    "installPaths":{
        "testbox":"tests/testbox"
    }
}.travis.yml
language: java
before_install:
- mkdir /tmp/bin
- export PATH=$PATH:/tmp/bin
install:
- curl --location 'https://www.ortussolutions.com/parent/download/commandbox/type/bin' -o /tmp/box.zip
- unzip /tmp/box.zip -d /tmp/bin
- box install
script:
- "./test"./test
#!/bin/bash
cd `dirname $0`/tests
CWD="`pwd`"
box $CWD/runtests.cfm
exitcode=$(<.exitcode)
rm -f .exitcode
exit $exitcode/tests folder

/Application.cfc
component {
	this.name = "tests" & Hash( GetCurrentTemplatePath() );
	this.mappings[ "/testbox" ] = ExpandPath( "./testbox" );
	this.mappings[ "/tests"   ] = ExpandPath( "./tests"   );
	public void function onRequest( required string requestedTemplate ) {
		include template=arguments.requestedTemplate;
	}
}/runtests.cfm
<cfscript>
	function exitCode( required numeric code ) {
		var exitcodeFile = GetDirectoryFromPath( GetCurrentTemplatePath() ) & "/.exitcode";
		FileWrite( exitcodeFile, code );
	}
	try {
		reporter = cgi.server_protocol == "CLI/1.0" ? "text" : "simple";
		testbox  = new testbox.system.TestBox( options={}, reporter=reporter, directory={
			  recurse  = true
			, mapping  = "tests"
			, filter   = function( required path ){ return true; }
		} );
		echo( Trim( testbox.run() ) );
		resultObject = testbox.getResult();
		errors       = resultObject.getTotalFail() + resultObject.getTotalError();
		exitCode( errors ? 1 : 0 );
	} catch ( any e ) {
		echo( "An error occurred running the tests. Message: [#e.message#], Detail: [#e.detail#]" );
		exitCode( 1 );
	}
</cfscript>Live coding demo!
Method 2
box start
.. wait for server to start
box testbox runAlternative method
language: java
env:
  matrix:
# currently the only way to do a multi-dimensional env matrix
    - PLATFORM=railo40 TESTFRAMEWORK=mxunit
    - PLATFORM=railo41 TESTFRAMEWORK=mxunit
    - PLATFORM=railo42 TESTFRAMEWORK=mxunit
    - PLATFORM=lucee451 TESTFRAMEWORK=mxunit
    - PLATFORM=lucee5_beta TESTFRAMEWORK=mxunit
    - PLATFORM=acf10-linux64 TESTFRAMEWORK=mxunit
    - PLATFORM=acf902-linux64 TESTFRAMEWORK=mxunit
    - PLATFORM=railo40 TESTFRAMEWORK=testbox
    - PLATFORM=railo41 TESTFRAMEWORK=testbox
    - PLATFORM=railo42 TESTFRAMEWORK=testbox
    - PLATFORM=lucee5_beta TESTFRAMEWORK=testbox
    - PLATFORM=lucee451 TESTFRAMEWORK=testbox
    - PLATFORM=acf10-linux64 TESTFRAMEWORK=testbox
install: ant -Dtest.framework=$TESTFRAMEWORK -Dsource=remote -Dwork.dir=$HOME/work -Dbuild.dir=$TRAVIS_BUILD_DIR -Dplatform=$PLATFORM install-ci-deps
script: ant -Dtest.framework=$TESTFRAMEWORK -Dsource=remote -Dwork.dir=$HOME/work -Dbuild.dir=$TRAVIS_BUILD_DIR -Dplatform=$PLATFORM test-ciBuilding dependencies


As simple as "box install"
{
    "name":"PresideCMS",
    "version":"10.2.4",
    "author":"Pixl8 Interactive",
    "createPackageDirectory":true,
    "packageDirectory":"preside",
 
// ... etc.
    "dependencies":{
        "sticker":"github:pixl8/sticker#v1.0.2",
        "coldbox-standalone-3.8.2":"http://integration.stg.ortussolutions.com/artifacts/ortussolutions/coldbox/3.8.2/coldbox-standalone-3.8.2.zip",
        "presidecmseditor":"github:pixl8/Preside-Editor"
    },
    "devDependencies":{
        "testbox":"2.2.0"
    },
    "installPaths":{
        "sticker":"system/externals/sticker",
        "coldbox-standalone-3.8.2":"system/externals/coldbox-standalone-3.8.2",
        "testbox":"support/tests/testbox",
        "presidecmseditor":"system/assets/ckeditor"
    }
}Build looks like this...

Other rad shizzle


Lucee/Preside Docs build
language: java
rvm:
- 1.9.3
sudo: required
before_install:
- echo "deb http://downloads.ortussolutions.com/debs/noarch /" > commandbox.list
- sudo mv commandbox.list /etc/apt/sources.list.d/commandbox.list
- sudo apt-get update
install:
- sudo apt-get install -q -y --force-yes commandbox zip
- gem install s3_website
script:
- "./build.sh"
env:
  global:
  - secure: Ht3aOvyR/EZNkySTQafQZ3qWxLh1FTDCHDWLT5J0icUYmAl0s9hnMuFfmCMTh8UHsmm+8TSYzyqA1+86NTogvaN9qKoXQNwBAe5SmNcxsK6+6YCxtJ/H7zRI9G1zpua7A+0iaJDF1ySW1aJ3FhdMZnSktA6UQ0lGbeX4bJSTn9n2dYoSKXm7ygVZ0Vzi/iX/c8Qg6Mll/+wWBCa0jnPOeY3CpxmL3kTXnQyzZkk/fv1GVx+fKmOnTbhO7Ftacrde4BlQpgJT4O0MiqTtVzA5gVn7Z3B1Cgaky0M30ftHZgaQkoFOlXn16paFDV7mYJWORDc/yiujtgt0GoWPWPnVZLuK9MYzwvHg9JzCeyRkoetwhLyoQbTDVliM+uEzwZPrlJX6tAVYs+3X+7Lc0oCnjYsR31qV801lj2exFqzJhIgLaATKElM8XtNcL7gzRup0q0UTy9rCgPuav6XilDNSFnoLM/eQ7JOe8i1SBsXjXfhEtb5uHr8k4HjLxQMObE60yUJFlE8RnAPArRen0DZwDixM0MlPwAfdk9/RYf7s0kwEonL/lzYUHvpaq1CSCZnq/y8tkTpY+9teiKeDRW4/PCFWbGlVjCnAWMv3yzxEpMmKNF8V/8aij+CCGgigDzgIthRfXsoYJCLm/os+bEq25SpWuTBIN95VAsU6ZEsFOSc=
  - secure: fvjEs8B0hDMKXDx8WT9w5WGZlBw3ZUxQAU/vAubBZr+HXt8QtWR3KpMaE001Ffy6aRPBEDqo4cLVs9GVkWzcQy2TK5IoZs/QSfb9utvrhtozcNKeBIHW4MhJfWUH5mAZlDb8ZFRKeBjTZ3enzV/aa4Z6Rrhm8ADow2wvlM59JsXpO7uGBe5fqL+ZSzlKc+Gj/QAD3eTLn6cLFMyhkzobgtaxNapCp+atNP0MBf2p0hgX5kVATUnaDGmsxbLdDRP9c/eEsIzkZOm7qTapq1CCLlTbRdS5N50uRt+FLyV3ksh4CfNvwT3/eLFDKuyCPpGSrwNYkvQ/QLWW6N6Lhxu78EzchHE4WR0mg5NBYfCIPQ2A7ALbA9QOvq3/lHwbUtSg0cK7HJWf6JDKI/Oz66wnINfsG3H0gD+HhKK0TSy9wnnYRdEZulu7JZigwBlXEMO5ENaWQmqFpZpVw6Ift+NtjpQlfYILW2tPMSVbhDAKGZ5TgUmIiWgtVpPOgZWG0Crs7a+nOfWvcxPrgFS5Ee89/v3bwvNlibul/Z+Rd6rI9DePJsEK1AKGPQuCM1FVENqM3MuG+qNUD2nDOTabr4hsKsvDc/c1NdBsEKUXMZLLN2HkPkNvBMAPVgBJm0e6915iZTv4sP4o7T2Ss9RkHOX0lZG51MRFHt1uo27ZcRY9XSk=
build.sh
#!/bin/bash
cd `dirname $0`
CWD="`pwd`"
echo "Building documentation with Lucee :)"
box $CWD/build.cfm
if [ -f .exitcode ]; then
  exitcode=$(<.exitcode)
  rm -f .exitcode
  echo "Exiting build, documentation build failed."
  exit $exitcode
fi
echo "Building complete"
if [ $TRAVIS_BRANCH == 'master' ] && [ $TRAVIS_PULL_REQUEST == 'false' ] ; then
  echo "Zipping up docs for offline download..."
  cd builds/html
  zip -q -r lucee-docs.zip *
  cd ../../
  echo "Zipped."
  echo "Preparing dash artifacts..."
  cp -r builds/html builds/artifacts
  mkdir builds/artifacts/dash
  cp builds/dash/lucee.xml builds/artifacts/dash/
  cd builds/dash
  tar -czf ../../builds/artifacts/dash/lucee.tgz lucee.docset
  cd ../../
  echo "Prepared."
  echo "Syncing with S3..."
  s3_website push
  echo "All done :)"
fibuild.cfm
<cfprocessingdirective suppressWhitespace="true" />
<cfsetting requesttimeout="1200" />
<cfscript>
	function exitCode( required numeric code ) {
		var exitcodeFile = GetDirectoryFromPath( GetCurrentTemplatePath() ) & "/.exitcode";
		FileWrite( exitcodeFile, code );
	}
	try {
		savecontent variable="suppressingwhitespacehere" {
			new api.build.BuildRunner().buildAll();
		}
	} catch ( any e ) {
		exitCode( 1 );
		newline = Chr( 10 );
		echo( "" & newline );
		echo( "Documentation build error" & newline );
		echo( "-------------------------" & newline );
		echo( "" & newline );
		echo( "[#e.type#] error occurred while building the docs. Message: [#e.message#]. Detail: [#e.detail#]." & newline );
		if ( ( e.tagContext ?: [] ).len() ) {
			echo( "" & newline );
			echo( "Stacktrace:" & newline );
			for( var tracePoint in e.tagContext ) {
				echo( "    " & tracepoint.template & " (line #tracepoint.line#)" & newline );
			}
		}
	}
</cfscript>
Pull requests


Persistant build numbers
build.number.remote.url=http://downloads.presidecms.com/presidecms/build.number
##############################
# MANUALLY UPDATE EACH VERSION
preside.version=10.4.0
##############################
ANT build.properties file
ANT build.xml
Persistant build numbers
ANT build.xml
<property name="artifacts.dir" value="./artifacts" />
<property name="build.number.file" value="${artifacts.dir}/build.number" />
<target name="incrementBuildNumber">
	<get src="${build.number.remote.url}" dest="${build.number.file}" ignoreerrors="true" />
	<propertyfile file="${build.number.file}" comment="Build Number for ANT. Edit not!">
		<entry key="build.number"
				type="int"
				operation="+"
				pattern="00000"
				default="1" />
	</propertyfile>
	<property file="${build.number.file}" />
</target>Persistant build numbers
.travis.yml
deploy:
  provider: s3
  access_key_id: AKIAJ3PTU73I...
  secret_access_key:
    secure: quj9MxIlfx43l9S6CXcchbpsKd43D...
  bucket: downloads.presidecms.com
  local-dir: support/build/artifacts
  upload-dir: presidecms
  skip_cleanup: true
  on:
    repo: pixl8/Preside-CMS
    all_branches: true

Using CommandBox with Travis CI
By Dominic Watson
Using CommandBox with Travis CI
In this talk, I'll show a couple of cases where I'm using CommandBox to drive builds and tests on Travis-CI. I'll cover: * Basics of Travis-CI * Installing CommandBox as part of travis build * What possibilities that opens up (running tests, building docs, etc.)
- 2,072
 
   
   
  