Integrating Custom GitHub Actions with MuleSoft Projects

Kseniia Tarantsova
Another Integration Blog
8 min readMay 6, 2024

Last time, we explored the integration of GitHub Actions with MuleSoft, focusing on its core features and how they facilitate CI/CD processes.

Today, we’ll expand our focus to custom actions. These are designed to automate and streamline specific tasks not addressed by the existing actions available in the GitHub Marketplace, providing tailored solutions for more complex workflows.

Let’s start!

Custom Actions: Purpose

Let’s consider why custom actions are necessary. Although the GitHub Actions Marketplace offers a vast selection of pre-built actions that help integrate different tools into workflows, there are still specific needs that these actions do not address, making custom actions invaluable.

Another point to consider is that not all actions in the GitHub Actions Marketplace are verified by GitHub. If an action lacks this verification, it’s crucial to carefully examine the action’s GitHub repository for any potentially risky code. You can usually find the repository in the Links section of the action’s page. To ensure security, it’s advisable to use actions that display a ‘Verified Creator’ badge when selecting from the marketplace.

Additionally, custom actions enable the automation of repetitive tasks. They allow you to create reusable actions that encapsulate multiple jobs, which can then be utilized across different workflows. This helps reduce manual processes by automating them.

Isn’t this aligned with MuleSoft’s best practices of reusability, agility, and ease of management? Indeed, this is precisely what we strive to achieve.

Custom Actions: Types

There are three main types of custom actions you can build:

  1. JavaScript Actions: These involve writing JavaScript code that runs each time the action is triggered, using the NodeJS runtime and its available packages. This approach is straightforward if you are proficient in JavaScript.
  2. Docker Actions: Docker actions are containerized applications defined by a Dockerfile, which outlines how to build and configure the image. This method offers flexibility in choosing programming languages and setting up environments but requires basic Docker knowledge.
  3. Composite Actions: Composite actions combine multiple workflow steps into a single action, similar to writing them directly in a workflow file. This method groups reusable steps without the need for programming skills, focusing instead on defining workflow steps.

Today, I suggest we take a closer look at composite actions. We’ll examine how they enable us to combine multiple steps into one action or create reusable components, aiming to enhance and streamline our workflows for MuleSoft API. This exploration will help us optimize our processes for better efficiency and effectiveness.

Custom Actions: Implementation

Let’s take a look at the example of the workflow we will use:

#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: Retrieve 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}} \

This workflow includes two crucial preliminary steps needed for successful execution. They are:

  1. Set up JDK 8
  2. Configure Git user.

These steps are the prerequisites that prepare the environment for the workflow to run effectively. Combining these steps into a single action is an excellent opportunity to create a custom composite action. This action can be further enhanced by incorporating additional configurations and setups, such as JFrog, Sonar, and others.

When building custom actions, we have a couple of options:

  1. Create a New Project and Repository: Start by establishing a new GitHub repository specifically for your custom action. If this repository is public, your action can be accessed by any workflow in any other repository, providing your actions with their own dedicated repositories and direct accessibility.
  2. Add Actions to Existing Projects: you can add custom actions to projects you already manage, limiting their availability to those specific projects.

In this discussion, we’ll concentrate on the second option: creating an action that is specific to the project.

First, we need to create a new folder named actions in the .github directory, adjacent to the workflows folder. While you can choose any name for this folder, 'actions' is frequently used for its clear descriptive nature.

Second, within the actions folder, create a subfolder called mule-env-config which is focused on efficiently setting up the environment. This approach of consolidating essential setup tasks into one reusable action aims to streamline workflow processes and improve overall efficiency.

Finally, it is necessary to include an action.yml file, which holds the configuration and definition of the action. This file is crucial for any action you create and must be present in any repository that contains an action. In this file, we will outline the specifics of the composite action.

Folder structure

Let’s begin working on the action.yml file. Here are the steps to configure it:

1️⃣ Specify a name and a description for the action.

name: 'Set Up Environment'
desciption: 'Get the code, set up java, maven and config git user.'

2️⃣ Include the runs key and nest a using key with the value of composite—this indicates to GitHub Actions that it is a custom composite action.

name: 'Set Up Environment'
desciption: 'Get the code, set up java, maven and config git user.'
runs:
using: 'composite'

3️⃣ Insert the steps key.

4️⃣ Copy all configuration and setup steps from the main workflow and paste them under the steps key in action.yml.

name: 'Set Up Environment'
desciption: 'Get the code, set up java, maven and config git user.'
runs:
using: 'composite'
steps:
# 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
# Configure user for the next step
- name: Configure Git user
run: |
git config user.email "actions@github.com"
git config user.name "GitHub Actions"

5️⃣ Add a shell key to each step that contains a run key to specify the shell to be used for executing the step. In our example, we will use bash.

name: 'Set Up Environment'
desciption: 'Get the code, set up java, maven and config git user.'
runs:
using: 'composite'
steps:
# 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
# Configure user for the next step
- name: Configure Git user
run: |
git config user.email "actions@github.com"
git config user.name "GitHub Actions"
shell: bash

6️⃣ Remove the detailed steps from the main workflow.

7️⃣ Incorporate the step into the main workflow by referencing the custom action. To add a step using a custom action in your workflow configuration, use the uses key, just as you would for any other GitHub action. For actions stored within your project, the value for uses should be a path to the action folder, starting with ./ to indicate the path is relative to the project root, not the workflow file. For our example, we will navigate to .github/actions/mule-env-config. We don't need to specify the action.yml file in the path, as GitHub Actions will automatically locate this file in the directory.

# Custom action to set up env
- name: Set up env
uses: ./.github/actions/mule-env-config

Now, we can integrate the action into our workflow. Here’s what the final workflow file configuration will look like:

#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

# Custom action to set up env
- name: Set up env
uses: ./.github/actions/mule-env-config

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

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

# 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}} \

If we execute the pipeline, we will observe the step labeled ‘Set up env’, which includes setting up Java and configuring Git.

Great! Now we know how to create reusable actions and maintain a simple and readable workflow file.

--

--

Kseniia Tarantsova
Another Integration Blog

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