What is it?
In essence CI is an aggressive build strategy requiring the isolated work of project developers to be integrated immediately following code commits to a shared source-code control system. Regression tests are run automatically, surfacing build errors or code inconsistency at an early stage.
CI is viewed as an Agile practice and is typically characteristic of a mature development process, and experienced developers. There is a definite learning curve and mindset adjustment for developers to be considered.
The manual alternative, which I term staged integration (SI), involves periodic integration testing of the HEAD revision from the source code control (SCC) system. The difference being the immediacy of performing the integration tests, and therefore verifying the integrity of the current build status. With the manual approach it can be difficult to instil team discipline, minor changes can often be viewed as not warranting a build and test.
Basic tenets
1. Developers work on an isolated copy of the code (i.e. branch) to avoid contention on shared resources, utility classes etc.
2. Developers commit unit-tested code to the shared SCC repository – often many times per-day.
3. An automated build process is triggered by the commit which takes the HEAD revision, deploys to a dedicated org running the full suite of unit tests. Test failures are reported proactively, naming and shaming the individual responsible for the failing commit. It’s key to note that pre-commit the developer should merge the current HEAD revision into their local branch and resolve conflicts (GIT for example will enforce this).
4. The HEAD revision represents a consistent “code complete” status. Development will typically take place in a isolated branch, with the master branch holding the production ready code.
Typical steps
1. Code is committed, this triggers a deployment to the INT org with unit test execution during the deployment.
2. Once deployment completes successfully, functional acceptance tests are executed, possibly via a tool like Selenium where functional tests at the UI level can be scripted (perhaps to verify a particular user story).
Why do it?
1.Daily builds have long been an industry best-practice, continuous integration is an evolutionary improvement.
2.The more frequently code is integrated the less painful it is.
3.Build errors are surfaced early, while the developer is still “in the zone” and can resolve the problem expediently.
4.Builds trust within the development team and a sense of collective ownership.
5.Driver for technical excellence, a key agile principle.
6.Encourages quality unit tests (code coverage and test case).
Obstacles
1.Big unit test suites can often take hours to run. To mitigate this obstacle, a smoke test could be executed on commit (current sprint related unit tests only), followed by a full test scheduled every 1/2 day, or overnight. The Force.com Migration tool enables executing test classes to be defined by name – so this is a feasible option.
2.Unit tests are an afterthought. Switch the team to TDD – perhaps with some education first.
3.Unsupported Metadata Types. Certain salesforce configuration elements (metadata types) can’t be deployed via the Force.com Migration Tool. Such elements must be recorded in a audit log and manually applied to the target org, or for automation a Selenium script could be utilised.
4.Standing Data. New features may require standing data (custom settings etc.). Use the Apex Data Loader in command-line mode (CLI), and invoke data manipulation operations within the build file.
Tools and process
A CI implementation requires fit-for-purpose tooling, for Force.com development the following stack is typical:
- SCC = Subversion or Git
- Build Automation Server = Jenkins or Hudson
- Scripting = ANT plus the Force.com Migration Tool (scriptable ANT task)
In simple terms CI works as follows. Within the build server (Jenkins for example) a job is defined that on each commit connects to the SCC repository and copies the HEAD revision to a working folder, then runs an ANT script. The script invokes a build.xml file which is held in SCC and therefore copied into the working folder. The build file runs whatever tasks are required including folder manipulation, static resource zipping, but ultimately (in context) the intent is to run the deploy target in the Force.com Migration Tool task, to deploy to a specific salesforce.com org. Connection details can be passed in via the job configuration or read from a build.properties file. A Jenkins plug-in can also be used to post build results to a Chatter post in a another org – very useful for notifications.
Exemplar Scenario – Single Project Org Strategy
Exemplar Scenario – Multiple Project Org Strategy
Related Concepts (for future posts)
TDD – Test Driven Development
Pair Programming
SCC Branching Strategy