Continuous Integration (CI) is the practice within software development that aims to detect source code integration errors sooner rather than later, enabling the development of stable code in a more expedient manner. The continuous cycle follows the pattern of phases that include: code, build, test, and deploy. The tenets of CI include a source code repository where a developer commits changes frequently, an automated process that builds code stored in the repository, testing of the build to ensure code behaves as expected, and deployment of the application once testing is deemed successful.

Tooling for MuleSoft CI

When developing a MuleSoft solution, CI best practices can be easily followed by taking advantage of tools such as GitHub, Maven, Bamboo, and Jenkins. Within this blog, we will walk through implementing the phases of CI utilizing these tools with MuleSoft.

Code Phase

MuleSoft has adopted and recommends Git for Source Code Management (SCM), utilizing cloud-based GitHub to host the repository. It has also become the de facto standard for open source projects, facilitating team development. A plugin for Anypoint Studio is available which enables executing Git commands (push, pull, commit, etc.) within the IDE:

Image removed.

This can also be done outside of Studio as well, using the Git command line functionality. To learn more about setting up a local Git repository, go to https://git-scm.com/. A GitHub guide is also available at https://github.com/ to walk you through getting started with the tool.

Build Phase

Not only is Maven recommended by MuleSoft to facilitate the build of your application, but also is integrated with Mule and Anypoint Studio.  The management of project dependencies via the Project Object Model (POM) ensures that teams use consistent libraries and dependencies, without the need to download and include jars within projects. To take advantage of Maven, the Mule Maven Plugin must be downloaded and installed in Studio. If not installed already, download and install the Apache Maven product.

To enable Maven for a MuleSoft project, be sure to check the ‘Use Maven’ check box, along with ‘Create a default .gitignore file’ when creating a new project.  Update the group id and artifact id as appropriate:

Image removed.

Test Phase

Along with facilitating builds, Maven also provides the ability to run automated tests. The level of testing in this phase can include unit and integration testing.

Unit testing consists of validation of an individual unit of source code, e.g. a Mule flow. This can be accomplished utilizing the testing framework, MUnit, which is fully integrated with Maven. It does require a plugin to Studio. The mocking functionality in MUnit provides the ability to define the behavior for a message processor, isolating the unit of code as much as possible (see my previous blog for further details). The unit tests are run prior to Maven packaging or deploying code to an environment, as noted in Maven Build Lifecycle basics. A build will be deemed to be in a failed state by Maven if any of the tests fail.

Integration tests are typically run after all unit tests have run successfully, validating that the units of code interact as intended. Leveraging the Maven failsafe plugin, integration testing can include deployment of a Mule application to a test environment (i.e. Sandbox), running of the tests, and if necessary, undeploying the application. This is all done via the settings defined within the POM which includes specifying the Maven phases pre-integration-test, post-integration-test and integration-test. Test cases are written in Java and need to extend the FunctionalTestCase defined in the MuleSoft provided package, org.mule.tck.junit4.FunctionalTestCase:

import org.junit.Test; import org.mule.api.MuleEvent; import org.mule.tck.junit4.FunctionalTestCase; public class TestHelloWorldTestITCase extends FunctionalTestCase

One thing to keep in mind is that the Java code developed for the integration test must be suffixed with ‘ITCase’ (i.e. TestHelloWorldITCase.java) and reside within src/test/java. Also, per Maven documentation, the ‘verify’ command should be used instead of ‘integration-test’, otherwise the post-integration-phase will not be executed.

Below is a sample of the configuration needed within the POM for integration testing. In this specific example, the testing is performed in an existing local environment:

<plugin> <groupId>org.mule.tools.maven</groupId> <artifactId>mule-maven-plugin</artifactId> <version>2.0</version> <configuration> <deploymentType>standalone</deploymentType> <muleVersion>3.7.2</muleVersion> <muleHome>C:Mulesoftmule-enterprise-standalone-3.7.3</muleHome> </configuration> <executions> <execution> <id>deploy</id> <phase>pre-integration-test</phase> <goals> <goal>deploy</goal> </goals> </execution> <execution> <id>undeploy</id> <phase>post-integration-test</phase> <goals> <goal>undeploy</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <executions> <execution> <id>integration-test</id> <phase>integration-test</phase> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> </plugin>

Deploy Phase

Deployment of applications can be done via Maven to a Mule local standalone server, Anypoint Runtime Manager, or to CloudHub. The POM provides the details necessary for the intended deployment target. For example, a CloudHub deployment needs the following included in the POM:

<plugin> <groupId>org.mule.tools.maven</groupId> <artifactId>mule-maven-plugin</artifactId> <version>2.0</version> <configuration> <deploymentType>cloudhub</deploymentType> <muleVersion>3.7.2</muleVersion> <username>AnypointUsername</username> <password>${password}</password> <workerType>Micro</workerType> <redeploy>true</redeploy> <environment>Production</environment> </configuration> <executions> <execution> <id>deploy</id> <phase>deploy</phase> <goals> <goal>deploy</goal> </goals> </execution> </executions> </plugin>

See the Mule Plugin for Maven documentation for other deployment examples using Maven.

Passwords in the POM

Any passwords needed for configuration (i.e. CloudHub password) should not be stored in clear text, especially if using a public GitHub repo. The password can be defined as a property (as shown in above POM, ${password}), then set using the Maven command line property ‘Dpassword’.

Orchestrating the Phases

The power of CI happens when each of these phases is orchestrated, providing feedback about the status of events within each phase. This is done via a CI tool, which ties the phases together, ensuring the tenets of CI are met. Both Jenkins and Bamboo provide this functionality. Jenkins is an on-premise solution while Bamboo is also available both on-premise and in the cloud.

Whether you choose Bamboo or Jenkins for your CI tool, each needs to be configured to do the following:

  • Listen for commits made to an application project residing in SCM
  • Pull application project code from SCM
  • Build application
  • Run Tests
  • Deploy application

Luckily, both CI products can be easily integrated with Git and Maven to enable this in a couple of steps.

Bamboo

Step 1:

To configure which source code repository a Bamboo build project plan will use, navigate to the Repositories tab and select ‘Add repository’ (note: this example is using cloud-based Bamboo):

Image removed.

You will then be able to select the Repository Host (i.e. GitHub), along with credentials and desired repository to use for the plan. Save the repository. 

Step 2:

Select the ‘Triggers’ tab (next to ‘Repositories’ from previous step). Select ‘Add trigger’, ‘Repository polling’:

Image removed.

Now configure the desired polling frequency defined by the polling strategy and schedule. This will dictate how frequently code changes will be built/tested/deployed.

Step 3:

Configure the build/test/deploy utilizing Maven. Navigate to the ‘Stages & jobs’ and select the ‘Task’ tab:

Image removed.

Add a task, selecting ‘Maven 3.x’. Specify the Maven goals to be included in the task. For example, to build, test (unit and integration), and deploy the code to CloudHub, the following Maven command is specified:

package verify mule:deploy -s settings.xml –Dpassword=myCloudhubPass –DserverPassword=MuleRepositoryPassword

Note: The above example has a couple extra parameters specified, -s settings.xml and –DserverPassword, that are needed when running Elastic Bamboo (Bamboo in the Cloud utilizing Amazon Web Services). This is needed to override Maven using the settings.xml default location (settings.xml provides MuleSoft repository details and the repository credentials), which is inaccessible in Elastic Bamboo. Include the settings.xml in your project SCM. As noted before regarding passwords in Git, include a property, serverPassword, for the Repository credentials.

Jenkins

Step 1:

Create a New Item in Jenkins, specify ‘Maven project’:

Image removed.

Step 2a:

The next screen displayed after ‘Ok’ is selected in the previous step contains several configuration steps. Select ‘Git’ radio button, then specify the repository URL (i.e.: https://github.com/{yourGitHubUsername}/{project-name}.git), along with your GitHub credentials:

Image removed.

Step 2b:

Select the check boxes as shown below, but also provide a schedule using Cron expression notation. This schedule will dictate how frequently code changes will be built/tested/deployed:

Image removed.

Step 2c:

Specify the desired Maven goals. For example, the below goal will package (build and unit test) then deploy to Cloudhub:

package mule:deploy –Dpassword=myCloudhubPass

Image removed.

Select Save, Apply

Conclusion

Following the principles of Continuous Integration is a best practice in software development. Implementing this best practice within your Mule projects can be done fairly easily utilizing Git, Maven, Bamboo/Jenkins.