Level Up Your MuleSoft DevOps: Master CI/CD with GitHub Actions

Kseniia Tarantsova
Another Integration Blog
9 min readMar 12, 2024

CI/CD, short for Continuous Integration and Continuous Delivery, revolutionizes software development by automating code integration and deployment processes. CI ensures regular testing and merging of code changes, while CD automates successful change deployments.

CI/CD pipelines play a crucial role in MuleSoft API development lifecycle. This article examines how to build MuleSoft’s CI/CD pipelines with GitHub Actions. GitHub Actions streamlines tasks such as building, testing, and deploying MuleSoft applications, enabling teams to innovate rapidly while maintaining API reliability. With intuitive YAML syntax and a range of pre-built actions, developers can create tailored workflows within the familiar GitHub interface. By embracing this combination, organizations can expedite API delivery and meet the evolving demands of modern software development confidently.

Now, it’s time to delve into it!

GitHub Actions: Availability

For those using public repositories, GitHub Actions are available at no cost. However, for private repositories, there’s a limit to the free monthly usage, and additional usage beyond that requires payment.

The specific quotas and payment details vary based on your GitHub plan. For a comprehensive overview, refer to this link: GitHub Actions Billing Details. If you don’t see an “Actions” tab in your GitHub repository, you’ll need to enable it. Follow the instructions provided here: Enabling GitHub Actions.

GitHub Actions: Key elements

In order to begin utilizing GitHub Actions effectively, it’s essential to grasp its core components. These components consist of three primary building blocks:

1️⃣ Workflows:

  • Initiated by specific events.
  • Contain one or more jobs.
  • Linked to a GitHub repository.

2️⃣ Jobs:

  • Define a Runner, which serves as the execution environment.
  • Comprise one or more steps.
  • Executed either concurrently or sequentially.

3️⃣ Steps:

  • Perform tasks such as running shell scripts or actions.
  • Can utilize custom or third-party actions.
  • Executed sequentially in the specified order.

GitHub Actions: Workflow pre-requisites

To start building a pipeline for MuleSoft’s API using GitHub Actions, we’ll begin by setting up a basic API without any business logic, as this isn’t the main focus of our article. Once the API is created, the subsequent step involves creating the GitHub repository.

Once the code is stored in the GitHub repository, we should navigate to the “Actions” tab. This is the primary hub where all workflows are displayed, executed, and tracked. From here, we can easily identify any failed jobs and review the logs to understand the reasons behind their failure.

Actions tab

GitHub Actions utilizes YAML syntax for defining workflows. Each workflow is stored as a separate YAML file in your code repository, typically within a directory named .github/workflows. There are two methods to create a workflow:

  1. Using Starter Workflows: These are templates designed to assist you in creating your GitHub Actions workflows for a repository. They provide an alternative to starting from scratch and are beneficial as they already include some preconfigured settings. To access a starter workflow, locate the one you wish to use, then click on “Configure.” You can search for specific keywords or filter by category to find the desired starter workflow.
  2. Creating and Setting Up Workflows Yourself: Within your repository or project, create a directory named .github/workflows/ to store your workflow files. Inside this directory, create a new file named {any-name}.yml, where {any-name} can be any descriptive name of your choice.

GitHub Actions: Create Workflow

To create a workflow, it’s essential to understand how YAML syntax is utilized. Firstly, let’s begin by creating the “name” and “run-name” keys. Both are optional but highly useful.

The “name” is a name of the workflow as it will appear in the “Actions” tab of the GitHub repository.

The “run-name” is a name for workflow runs generated from the workflow. We can include here any details retailed to the github object also known as context which contains information about the workflow run and the event that triggered the run. In our example we will use an actor field of the github context — username of the user that triggered the initial workflow run.

#Optional - The name of the workflow as it will appear in the "Actions" tab.
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

The next key to consider is “on”. This key determines the trigger event for the workflow. Workflows can be triggered in various ways, either manually or automatically. Today, we’ll utilize the “workflow_dispatch” event, which can be triggered manually from the “Actions” tab. This event is particularly useful when managing different environments, as we can specify inputs.

#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

#Specifies the trigger for this workflow.
on: workflow_dispatch

Now, we’re prepared to specify the jobs. They’re organized under the “jobs” key, with each job name customizable and defined by developer. Additionally, we are going to incorporate env properties within the job. These properties can remain encrypted if they don’t affect security, but sensitive information should be concealed using secrets.

GitHub Secrets can be configured at the organization, repository, or environment level, enabling you to securely store sensitive information within GitHub. We can add them either from:

  • the Settings/Actions tab (repository level):
  • the Settings/Environments tab (environment level):
  • Organizations tab which is available only if you have such account (organizational level).
#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

#Specifies the trigger for this workflow.
on: workflow_dispatch

jobs:
#Custom name of the job.
build:
#Properties
env:
CLOUDHUB_ENVIRONMENT: "Sandbox"
CLOUDHUB_WORKERS: "1"
CLOUDHUB_WORKER_TYPE: "MICRO"
CLOUDHUB_REGION: "us-east-2"
CLOUDHUB_ID: ${{ secrets.CLOUDHUB_ID }}
CLOUDHUB_SECRET: ${{ secrets.CLOUDHUB_SECRET }}

Every job in a GitHub Actions workflow needs a runner. These runners execute tasks such as locally cloning the repository, installing required testing software, and running commands to assess the code. Runner should be defined under the “runs-on” key of the YAML file.

#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

#Specifies the trigger for this workflow.
on: workflow_dispatch

jobs:
#Custom name of the job.
build:
#Properties
env:
CLOUDHUB_ENVIRONMENT: "Sandbox"
CLOUDHUB_WORKERS: "1"
CLOUDHUB_WORKER_TYPE: "MICRO"
CLOUDHUB_REGION: "us-east-2"
CLOUDHUB_ID: ${{ secrets.CLOUDHUB_ID }}
CLOUDHUB_SECRET: ${{ secrets.CLOUDHUB_SECRET }}
#Runner
runs-on: ubuntu-latest

Next in the pipeline, we can manage permissions. You have the ability to customize permissions for the GITHUB_TOKEN, granting or limiting access as necessary. This ensures minimal required access.

Permissions can be configured:

  • globally,
  • for specific jobs.

Available scopes:

  • read,
  • write,
  • none.

For instance, contents:write allows actions to create a release, while packages:write permits them to upload and publish packages on GitHub Packages. These are the goals we aim to accomplish within the steps. The default value is set to read, so if such permissions aren’t granted, the job will fail.

#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

#Specifies the trigger for this workflow.
on: workflow_dispatch

jobs:
#Custom name of the job.
build:
#Properties
env:
CLOUDHUB_ENVIRONMENT: "Sandbox"
CLOUDHUB_WORKERS: "1"
CLOUDHUB_WORKER_TYPE: "MICRO"
CLOUDHUB_REGION: "us-east-2"
CLOUDHUB_ID: ${{ secrets.CLOUDHUB_ID }}
CLOUDHUB_SECRET: ${{ secrets.CLOUDHUB_SECRET }}
#Runner
runs-on: ubuntu-latest
permissions:
packages: write
contents: write

The last we define the “steps”. Each step contains of the name and action which should be executed: either get one from the GitHub marketplace or write your own.

Our pipeline will include the following steps:

1️⃣ Get the code:

  • This step check-outs repository under $GITHUB_WORKSPACE, so your workflow can access it.

2️⃣ Setup Java:

  • This step is responsible for configuring the execution environment required for building, testing, and deploying the MuleSoft API. Here, we set up Java, utilize caching to reduce the time of downloading dependencies, and define the distribution management ID, which essentially points to the environment where we want to upload the artifact.

3️⃣ Test:

  • This step executes MUnit tests to verify the functionality of the MuleSoft API.

4️⃣ Build:

  • This step builds the MuleSoft API from the source code, compiling, resolving dependencies, and packaging the application into an artifact.

5️⃣ Configure Git user:

  • This step grants permission to upload artifacts to GitHub and create commits to change the POM version. All of these actions will occur in the next step.

6️⃣ Release/Upload Artifact:

  • This step is responsible for uploading any necessary artifacts or files generated during the build process, making them available for further processing or distribution. Also, creating RELEASE and generating the next SNAPSHOT version.

7️⃣ Deploy:

  • This step handles the deployment of the MuleSoft API to the desired environment, whether it’s staging, production, or any other target environment.
#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-pipeline

#Optional - The name for workflow runs generated from the workflow.
run-name: run by ${{ github.actor }}

#Specifies the trigger for this workflow.
on: workflow_dispatch

jobs:
#Custom name of the job.
build:
env:
CLOUDHUB_ENVIRONMENT: "Sandbox"
CLOUDHUB_WORKERS: "1"
CLOUDHUB_WORKER_TYPE: "MICRO"
CLOUDHUB_REGION: "us-east-2"
CLOUDHUB_ID: ${{ secrets.CLOUDHUB_ID }}
CLOUDHUB_SECRET: ${{ secrets.CLOUDHUB_SECRET }}
permissions:
packages: write
contents: write
#Runner
runs-on: ubuntu-latest
steps:
# This action checks-out your repository under $GITHUB_WORKSPACE, so your workflow can access it.
- name: Get the code
uses: actions/checkout@v4
# Set up Java
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
distribution: 'adopt-hotspot'
java-version: '8'
#Cache dependencies to speed up workflow runs.
cache: maven
#Value of the distributionManagement/repository/id field of the pom.xml
server-id: github

# Run the tests
- name: Test the compiled source code
run: mvn clean test

# Package
- name: Build the jar
run: mvn package -DskipTests

# # Configure user for the next step
- name: Configure Git user
run: |
git config user.email "actions@github.com"
git config user.name "GitHub Actions"

# Replace the snapshot version with a release candidate version.
# Deploy the jar to GitHub registry
# Build next snapshot version.
- name: Prepare and perform release
run: mvn -B release:prepare release:perform
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Deploy to CloudHub
- name: Deploy
run: |
mvn -U -V -e -B -DskipTests deploy --file pom.xml -DmuleDeploy \
-Dconn.app.client.id=${{ env.CLOUDHUB_ID}} \
-Dconn.app.client.secret=${{ env.CLOUDHUB_SECRET}} \
-Dcloudhub.environment=${{ env.CLOUDHUB_ENVIRONMENT}} \
-Dcloudhub.workerType=${{ env.CLOUDHUB_WORKER_TYPE}} \
-Dcloudhub.workers=${{ env.CLOUDHUB_WORKERS}} \
-Dcloudhub.region=${{ env.CLOUDHUB_REGION}} \

GitHub Actions: Run Workflow

Let’s push the code and initiate the workflow. To manually trigger the workflow, use the green “Run workflow” button.

Now, let’s delve into the steps and verify if all of them were executed successfully.

Next, we can verify the deployment.

After that, we can observe that the version of the POM file has been modified, and two additional commits have been added.

Finally, let’s verify the deployed Release tag on GitHub.

We’re all set! Congratulations on successfully setting up and executing your GitHub Actions workflow for MuleSoft API development. Keep exploring and optimizing your workflow to streamline your development process even further.

Happy coding!

--

--

Kseniia Tarantsova
Another Integration Blog

Passionate about MuleSoft and API development, I share insights and tutorials to help developers integrate, automate, and innovate.