Blog

Jon Clausen

February 15, 2016

Spread the word


Share your thoughts

Let's say you've got a great idea for a new Coldbox or CommandBox module.  You've spent hours writing and testing the code, you're proud of your efforts, and now it's time to introduce it to the greater CFML community!  

In its early stages, shipping your new module isn't such a big deal.  The .zip link provided by GitHub works fine for the Forgebox link, and it's not a big deal to update the entry whenever you release a new version.  Once you release it and other developers actually start using and depending on your software, however, the need to automate aspects of the build and deployment process become apparent.

Meet Travis CI (If you're not already acquainted), your new, inexpensive (free for open source!) friend for building, testing, and deploying your module.   In this entry, we'll walk you through the steps to set up Travis CI integration with your project, which will allow you to spend your free development time on adding features and fixing bugs, rather than on packaging and deployment.

In this example we'll use the CBMongoDB module, which uses Travis to build and test new branch pushes and pull requests.  Head on over to GitHub to check out the source and view the .travis-ci.yml file, which is where all of the instructions reside. 

First things first, head on over to travis-ci.org and create an account.   Sign in using your GitHub account and, once your signup is complete, you'll see a list of all your repos, which may be switched on if you wish to use Travis builds.  

Switch on your module's repo and configure the settings.   You'll notice there are also additional environment variables, where you can add secret keys.  In the case of CBMongoDB, builds are published to an AWS S3 bucket so I have the variables AWS_ACCESS_KEY and AWS_ACCESS_SECRET set for authentication during the build process.  

Note: for any confidential information, such as passwords, make sure the "Display value in build log" is set as off.

Now it's time to configure your project.  Open it up in your favorite IDE and create the file .travis-ci.yml (On a separate note, if you use GitLab, the .gitlab-cy.yml used there is nearly 100 interchangeable with the Travis file, so you can use the majority of these instructions for private repos hosted on GitLab).

Now it's time to configure your build steps in your YAML file.  First, we need to add our language, and OS information.  Travis has Docker container support, so if you'd like to configure your build to run on a separate OS, you can use those instructions.  For our purposes, builds on the default OS of Ubuntu is fine.

language: java
sudo: required
dist: trusty

In this case, we've specified builds to use Ubuntu Trusty, which I found mitigated some build errors caused on Travis' old Precise build system.  

Next add your installation steps which, for this module, include adding the repos for CommandBox and MongoDB in the "before_install" step and then install them once the repos are available.  Because Travis' current version of Mongo for builds is 2.6, we needed to use a custom install of MongoDB, to ensure full forward compatibility.   If your projects rely on DBMS support, additional documentation is available for configuring your build file.

before_install:
  - sudo apt-key adv --keyserver keys.gnupg.net --recv 6DA70622
  - sudo echo "deb http://downloads.ortussolutions.com/debs/noarch /" | sudo tee -a /etc/apt/sources.list.d/commandbox.list
  - sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv EA312927
  - sudo echo "deb http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.2 multiverse" | sudo tee -a /etc/apt/sources.list.d/mongodb-org-3.2.list

install:
  # MongoDB Manual Install
  - sudo apt-get update && sudo apt-get --assume-yes install mongodb-org zip unzip commandbox
  - mongo --version
  #Commandbox setup
  - box install
  - box server start port=49616 rewritesEnable=false openBrowser=false

Note that we've hard-coded the CommandBox server port in our build file.  You may omit this if the variables are specified in the root box.json file for your project.

The next three steps configured in the build file prepare, test, and set the versions information in the module's box.json file.  

First use curl to hit the root URL of the project to make sure ColdBox has been loaded:

before_script:
  - curl http://localhost:49616/

Now run our tests.  Note that I'm testing the output of TestBox's command runner using GREP.  If TestBox's output contains any test failure quantity greater than 0 or html, denoting a Lucee error, an exit code of 1 is delivered and the build is aborted.

script: > 
    testResults="echo $(box testbox run)";
    echo "$testResults";
    if grep -i "\[Failures: [1-9][0-9]\?\]\|<t[^>]*>\|<b[^>]*>" <<< $testResults;  then exit 1; fi

Note: the ">" character after the "script:" declaration saves us from having to do some additional quoting of variables.

Assuming that our test passed, we can now set our version information in our box.json file.  You'll note two sleeps are added to prevent concurrent reading or writing of the file, as sometimes the bash command exits before the writing of the file is complete.

after_success:
  - sudo sed -i "s/$RELEASE_PLACEHOLDER/${Setting: RELEASE_VERSION not found}/g;" 'modules/cbmongodb/box.json'
  - sleep 2
  - sudo sed -i "s/$BUILD_PLACEHOLDER/${Setting: TRAVIS_BUILD_NUMBER not found}/g" 'modules/cbmongodb/box.json'
  - sleep 2

Once the version information is set, we'll .zip up the appropriate directories and prepare to send them off to S3:

before_deploy:
  - mkdir deploy
  - cp README.md modules/cbmongodb/  && cp LICENSE modules/cbmongodb
  - cd modules/cbmongodb && sudo zip -r "../../deploy/cbmongodb-$TRAVIS_BRANCH-v$RELEASE_VERSION+$TRAVIS_BUILD_NUMBER.zip" ./* && cd ../../
  - cp "deploy/cbmongodb-$TRAVIS_BRANCH-v$RELEASE_VERSION+$TRAVIS_BUILD_NUMBER.zip" "deploy/cbmongodb-$TRAVIS_BRANCH-latest.zip"

Lastly, Travis has built-in support for DPL deployments, with options to use a a variety of providers.  In our case, we simply use the S3 Provider, and set the configuration options, using the variables for our secrets set earlier in the project settings:

deploy:
  skip_cleanup: true
  provider: s3
  #AWS Credentials need to be set in Travis
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key: $AWS_ACCESS_SECRET
  bucket: "oss.silowebworks.com"
  local-dir: deploy
  acl: public_read
  all_branches: true

That's it!  Once a commit is pushed to one of the project branches, and it passes all of its tests, the latest version is sent up to S3, where the CommandBox command, box install cbmongodb , will install it "automagically"! 

As for yourself, you can focus more time on writing great software!   You'll find that one of your new joys in life will be the result of successful build and deployment:

Add Your Comment

(3)

Mar 28, 2016 11:29:09 UTC

by Grant Copley

Thanks Jon. This helped me a bunch and not just w/ my ColdBox apps.

Mar 28, 2016 11:44:54 UTC

by Grant Copley

I do see one downside to using this method though. Since you can't specify which Lucee engine is used when running 'box server start', your tests will run against the current version of Lucee that CommandBox uses.

Mar 28, 2016 12:03:14 UTC

by Luis Majano

Thanks Grant! Yes that is correct. We currently are working on supporting multi-engine support in CommandBox. For now, you could use the cfml-ci project as well with this approach: https://github.com/coldfumonkeh/cfml-ci

Recent Entries

Partner with BoxLang and Ortus at Into the Box 2025: Empowering the Future of Modern Software Development!

Partner with BoxLang and Ortus at Into the Box 2025: Empowering the Future of Modern Software Development!

At Ortus Solutions, we’ve always been at the forefront of innovation in the ColdFusion ecosystem. From pioneering modern ColdFusion practices to developing cutting-edge tools and frameworks, we’ve been passionate to help and sup[port the community into shaping the future of web development.That’s why we decided to build BoxLang, our new JVM programming language that not only builds on the strengths of ColdFusion but takes modern software development to the next level.

Maria Jose Herrera
Maria Jose Herrera
December 23, 2024
Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

Why BoxLang When You Have Kotlin, Groovy, Scala, and more…

As we approach a stable release of BoxLang and our continued marketing reaches more folks, many have asked about its purpose. Why create a new language when the JVM ecosystem already includes established languages like Kotlin, Groovy, and Scala, to name a few.

Luis Majano
Luis Majano
December 18, 2024