CI/CD is an important piece of achieving a development process that is fast and flexible while remaining reliable.

Continuous Integration: This is the process of keeping code iterations as small as possible, and integrating them into the main codebase. By keeping our changes small, we can more quickly identify and fix new issues introduced into the codebase, as well as more quickly release stable updates. In this example, you will briefly touch on this process by automating unit testing via the MUnit plugin.

Continuous Delivery: This process ties back into continuous integration, and is the concept that our codebase should always remain deliverable. The main codebase should never enter a state which can not be deployed. As part of this process, we automate building and testing, typically via automatic deployment into QA and UAT environments. We will cover this by utilizing the mule-maven-plugin to automate deployment into our Sandbox environment.

Continuous Deployment: This is typically considered the next and final step in building out an automated pipeline; when a company is utilizing continuous deployment, the release management is tied into an automated process. While we will be taking a simplistic approach, we will touch on this today by creating a protected main branch, which requires that our build and test phases in Sandbox have passed before they can be merged into the master branch, and trigger a deployment to the Production environment.

What you'll build

In this codelab, we will build a MuleSoft API, which you will commit to a new GitHub repository. We will then walk through setting up GitHub Actions to act as our CI platform. Your project will:

What you'll learn

What you'll need

Create Trial Account

Test Nexus Access

In order to automate mule application testing and deployment, we first have to have an actual application to work with! We will be using the hello-world example in MuleSoft's exchange.

Import Project

  1. Open Anypoint Studio
  2. Set your workspace to cicid-with-github

  1. Click Open an Example from Exchange in the package explorer

  1. Click on Provided by MuleSoft on the left in the exchange window

  1. Search for hello world and click on the example

  1. Click Open in the top right

  1. In package explorer, you should now see a project called hello-world

Next, we will create a GitHub repository to house our code, and to run our CI/CD workflow. Everything we will be doing with GitHub can be performed with a free account.

Create GitHub Account

Create GitHub Repository

  1. Sign in to GitHub
  2. Click New to create a new repository

  1. Give your repository a name like hello-world-mule-lab

  1. On our new repo's landing page, copy the git remote add origin https://github.com/... command

  1. Open terminal/command prompt
  2. Change directory to cicd-with-github/hello-world
  3. Run command git init
  4. Paste the git remote add origin ... we copied earlier

  1. Before we make our first commit, we want to setup our .gitignore file first. In the hello-world directory, create a file called .gitignore and paste the following:

.gitignore

# ------------------------------------------------------------------------------ #
# Java defaults (https://github.com/github/gitignore/blob/master/Java.gitignore) #
# ------------------------------------------------------------------------------ #
*.class

# Package Files #
*.jar
*.war
*.ear

# ------------------------------------------------------------------------------------------- #
# Eclipse-specific (https://github.com/github/gitignore/blob/master/Global/Eclipse.gitignore) #
# ------------------------------------------------------------------------------------------- #
*.pydevproject
.metadata
bin/**
tmp/**
tmp/**/*
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.project
.classpath

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# CDT-specific
.cproject

# PDT-specific
.buildpath

# --------------- #
# Studio-specific #
# --------------- #
target/
.mule/**
.mule/**/*
.DS_Store
velocity.log
src/main/resources/config/*
  1. After saving the .gitignore file, run the command git add .
  2. Run command git commit -m "First commit"
  3. Run command git push -u origin master

  1. We can now check on GitHub, and should see the contents of hello-world

CI Environment Variables / Secrets

In order to deploy to CloudHub via an external CI platform, we need to setup some secrets to use as environment variables. For complete documentation on settings you can provide the plugin, see https://docs.mulesoft.com/mule-runtime/4.3/mmp-concept

You will need to add each of the environment variables below to your GitHub Repository's secrets. To add a repository secret:

  1. While viewing your GitHub Repository, click settings

  1. Click on Secrets

  1. Click New Repository Secret

  1. Fill in the name of the secret (use the same key names listed below) and the corresponding value. Click Add Secret

Add the following secrets to your repo:

When your done, your repository secrets should look like this:

Now that you've added all of your secrets to the repository, we're ready to setup the repository for automated builds and deployments!

------

To find your business group ID:

  1. Log into anypint.mulesoft.com
  2. Click on the business group in the top right corner

  1. Click on Business Groups

  1. Click on the business group in the access management window

  1. Copy the Business Group ID

Mule applications are, at the heart of things, mavenized java applications. In order to automate the build and deployment process, MuleSoft provides the mule-maven-plugin. Whether you're hosting your applications on CloudHub, AWS, Azure, GCP, on-prem, a raspberry pi in your closet, etc.. you can use the mule-maven-plugin to automate your deployments via the Anypoint Control Plane. In this workshop, to keep things as simple as possible, we will be deploying our application to a single .1vcore worker in CloudHub. For information about deployment to other platforms, check the documentation: https://docs.mulesoft.com/mule-runtime/4.3/mmp-concept

Back to Anypoint Studio!

  1. Open up the POM.xml
  2. Find the XML key mule.maven.plugin.version and update the version to the latest version on the release page to ensure we have the latest fixes. At the time of writing this, the latest version is 3.4.2.

pom.xml

<properties>
        <munit.version>2.1.2</munit.version>
        <mule.maven.plugin.version>3.4.2</mule.maven.plugin.version>
</properties>
  1. Add our cloudHubDeployment entry to the mule-maven-plugin entry in the plugins section of the pom.xml file.

pom.xml

<plugins>
  <plugin>
    <groupId>org.mule.tools.maven</groupId>
    <artifactId>mule-maven-plugin</artifactId>
    <version>${mule.maven.plugin.version}</version>
    <extensions>true</extensions>
    <configuration>
      <classifier>mule-application</classifier>
      <cloudHubDeployment>
        <muleVersion>4.3.0</muleVersion>
        <username>${env.PLATFORM_USERNAME}</username>
        <password>${env.PLATFORM_PASSWORD}</password>
        <applicationName>hello-world-SOMETHING-UNIQUE</applicationName>
        <environment>Sandbox</environment>
        <workers>1</workers>
        <workerType>MICRO</workerType>
        <objectStoreV2>true</objectStoreV2>
        <region>us-east-2</region>
        <businessGroupId>${env.BUS_GROUP_ID}</businessGroupId>
      </cloudHubDeployment>
    </configuration>
  </plugin>

  ...

</plugins>

We're specifying how we want the application deployed to CloudHub. For the complete list of available keys, see https://docs.mulesoft.com/mule-runtime/4.3/deploy-to-cloudhub

When authenticating with maven repositories, maven needs credentials (duh!). Typically, reusable credentials are stored in a shared settings.xml file located in your m2 folder. You can do the same thing with your CI platform; the majority of CI platforms (GitHub only offers these features for paid accounts) allow you to store shared organization credentials / configurations. As we're using a free GitHub repository, we'll go ahead and add a settings.xml file to our project.

  1. Create a new XML file: /cicd-with-github/hello-world/.maven/settings.xml

  1. Open settings.xml and paste the following code:

.maven/settings.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<settings>
  <servers>
    <server>
      <id>MuleRepository</id>
      <username>${env.NEXUS_USERNAME}</username>
      <password>${env.NEXUS_PASSWORD}</password>
    </server>
    <server>
      <id>anypoint-exchange-v2</id>
      <username>${env.PLATFORM_USERNAME}</username>
      <password>${env.PLATFORM_PASSWORD}</password>
    </server>
  </servers>
  <pluginGroups>
    <pluginGroup>org.mule.tools</pluginGroup>
  </pluginGroups>
  <profiles>
    <profile>
      <id>mule-extra-repos</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <repositories>
        <repository>
          <id>mule-public</id>
          <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
        </repository>
      </repositories>
      <pluginRepositories>
        <pluginRepository>
          <id>mule-public</id>
          <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
        </pluginRepository>
      </pluginRepositories>
    </profile>
    <profile>
      <id>Mule</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <repositories>
        <repository>
          <id>MuleRepository</id>
          <name>MuleRepository</name>
          <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
          <layout>default</layout>
          <releases>
            <enabled>true</enabled>
          </releases>
          <snapshots>
            <enabled>true</enabled>
          </snapshots>
        </repository>
      </repositories>
    </profile>
  </profiles>
</settings>
  1. Now that we've made our changes, commit the changes and push to your repository.

We're in the home stretch now! Now that we've created our repository, setup our secrets, and configured our application for automated deployment, we need to create the workflow. While we can do this just as easily from our local file system, for this lab we're going to use the GitHub web interface to create the workflow.

  1. Navigate to your repository on GitHub
  2. Click on Actions
  3. Find the Publish Java Application with Maven entry in the Continuous integration workflows section (remember! Mule applications are mavenized java applications) and click Setup this workflow.

Replace the default workflow code with the following:

.github/workflows/maven-publish.yml

name: Sandbox - Build and Deploy

on:
  push:
    branches: master 
#normally you wouldn't be deploying master branch pushes to Sandbox,
#but we're keeping things simple! 😁

jobs:
  buildAndDeploy:
    runs-on: ubuntu-latest
    steps:
#first, we need to checkout our mule application's code
      - name: Checkout repository
        uses: actions/checkout@v2
      - name: Build and deploy artifact to sandbox
#run the maven deploy lifecycle. The -B indicated a batch process,
#which reduces the amount of logging the deployment does
        run: mvn -B deploy -DmuleDeploy -s .maven/settings.xml
#Pass in the secrets we need for deployment as environment variables
        env:
          NEXUS_USERNAME: ${{ secrets.NEXUS_USERNAME }}
          NEXUS_PASSWORD: ${{ secrets.NEXUS_PASSWORD }}
          PLATFORM_USERNAME: ${{ secrets.PLATFORM_USERNAME }}
          PLATFORM_PASSWORD: ${{ secrets.PLATFORM_PASSWORD }}
          SANDBOX_CLIENT_ID: ${{ secrets.SANDBOX_CLIENT_ID }}
          SANDBOX_CLIENT_SECRET: ${{ secrets.SANDBOX_CLIENT_SECRET }}
          BUS_GROUP_ID: ${{ secrets.BUS_GROUP_ID }}
  1. Click Start Commit in the top right

  1. As soon as you commit the file, you can go back to the Actions tab and you should see our workflow running!

  1. The application has an MUnit test suite (src/test/munit) which will be automatically run:

  1. Once done building the application, the plugin will upload the artifact to CloudHub and then wait for the SLB to acknowledge the application has started up and is live.

  1. While the application is starting, if you navigate to Runtime Manager, you can see our new application starting

Today we created an automated deployment of a Mule Application using GitHub Actions. While our GitHub workflow and GitHub secrets are unique to GitHub, the concepts used are not. Whether your using Jenkins, Azure Pipelines, CircleCI, GitLab, etc, the process is largely the same:

  1. Establish source control
  2. Build tests & application
  3. Configure the maven application with the mule-maven-plugin
  4. Parameterize sensitive information; do NOT store directly in source code
  5. In CI platform pass in sensitive information from some form of vault
  6. Profit

This was an extremely simplistic example, but Mule Applications are standard mavenized java applications. This means you can make your CI processes as complicated or simple as your use case dictated, eg: multibranch pipelines, secure vaults trigger builds via webhooks, SonarQube for quality gates, etc.

If you had any issues with this lab, please feel free to open an issue: https://github.com/mikeacjones/hello-world-mule-lab/issues/new