Maximizing MuleSoft CI/CD Efficiency: Integrating JFrog Artifactory with GitHub Actions

Kseniia Tarantsova
Another Integration Blog
8 min readMay 29, 2024

After a deep dive into GitHub Actions in the previous two articles Level Up Your MuleSoft DevOps: Master CI/CD with GitHub Actions and Integrating Custom GitHub Actions with MuleSoft Projects, I enhanced the pipeline by adding a crucial step for each CI/CD process: uploading artifacts to a remote repository.

Today, we’ll expand our focus to include JFrog Artifactory, a robust repository manager that supports a wide range of software artifacts, including those used in MuleSoft. Integrating JFrog Artifactory into the pipeline ensures secure storage, version consistency, and enhanced metadata management, which are vital for efficient development and deployment processes.

JFrog: Introduction

JFrog Artifactory is a binary repository manager that serves as a central hub for versioned packages, improving the automation of software development processes, particularly in Continuous Integration/Continuous Deployment (CI/CD) environments. Integrating JFrog Artifactory with MuleSoft brings several advantages:

  • Artifact Versioning: Ensures the consistent use of appropriate artifact versions across different environments for MuleSoft applications.
  • Secure Storage: Provides a secure, centralized repository that is easily accessible by CI/CD tools.
  • Metadata Management: Improves deployment automation and traceability by storing critical metadata alongside artifacts.

JFrog integration with GitHub Actions and Mulesoft

Let’s delve into the practical steps and strategies for integrating JFrog Artifactory with GitHub Actions and MuleSoft. To begin this exploration, it’s important to recognize that the MuleSoft API, managed as a Maven project, requires a Maven repository to store its artifacts. This involves creating two Maven repositories in JFrog: one for releases and another for snapshots. Follow these steps:

  1. Navigate to Artifactory on JFrog Platform.
  2. Go to Artifacts -> Manage Repositories -> Create Repository -> Local.
  3. Select ‘Maven’.
  4. Assign a name.
  5. Save the repository.

Integrating a JFrog Maven repository with GitHub Actions and the MuleSoft API can be achieved through several methods and technologies, including:

  • JFrog CLI: A command-line tool that simplifies the management of artifacts and repositories directly from your development environment.
  • Maven Distribution Management: A section in your Maven project’s POM file where you specify the repositories for deploying and distributing your project’s artifacts, assisting in managing the publishing process to Artifactory.

With a clear direction in mind, let’s delve into the detailed implementation and effective use of these tools to ensure success in DevOps.

Implementing GitHub Actions with JFrog CLI

To be able to leverage JFrog CLI within the GitHub Actions workflow we need to follow several steps:

  1. Explore the GitHub Actions Marketplace at https://github.com/marketplace. This platform is packed with actions that streamline the integration of different tools into workflows.

It’s important to use caution: always look for actions marked with a ‘Verified Creator’ badge to ensure security. If an action doesn’t have this verification, it’s essential to review the GitHub repository of the action for any potentially risky code blocks. You can find the repository under the Links section.

Marketplace offers a ‘Setup JFrog CLI’ action which we plan to leverage:

2. Add the ‘Setup JFrog CLI’ action to your workflow to authenticate with Artifactory. This can be done either through secrets or the OpenID protocol. Today, we’ll focus on implementing authentication using secrets.

Configure the connection details by setting secrets for one of the following sets of environment variables:

  • JF_URL (no authentication required)
  • JF_URL, JF_USER, JF_PASSWORD (for basic authentication)
  • JF_URL, JF_ACCESS_TOKEN (for authentication using a JFrog Access Token). You can retrieve the token from the ‘Set Me Up’ menu tab in the JFrog Platform.
- name: JFrog CLI Setup
uses: jfrog/setup-jfrog-cli@v4
env:
# JFrog platform url (for example: https://acme.jfrog.io)
JF_URL: ${{ secrets.JFOG_URL }}

# Basic authentication credentials
JF_USER: ${{ secrets.JFROG_USER }}
JF_PASSWORD: ${{ secrets.JFROG_PASSWORD }}
or
# JFrog Platform access token
JF_ACCESS_TOKEN: ${{ secrets.JFROG_ACCESS_TOKEN }}

3. Configure Maven for the JFrog server. This step involves defining the repository name to which the artifacts will be deployed. Ensure the name is specified exactly as it appears in the JFrog platform.

- name: JFrog Maven Configuration
run: |
jf mvn-config --repo-deploy-releases mule-libs-release-local \
--repo-deploy-snapshots mule-libs-snapshot-local

4. Upload artifact to JFrog repository. This step will deploy the artifact .jar and .pom files to the JFrog’s repository.

- name: Upload artifact to JFrog repository
run: |
jf mvn clean install -DskipTests

5. Additionally, we can add 2 more steps:

  • define build variables: this step sets the build name and build number as environment variables for use in subsequent steps.
- name: Set build variables
run: |
echo "build_name=$(echo ${GITHUB_REPOSITORY#*/})" >> "$GITHUB_ENV"
echo "build_number=$GITHUB_RUN_NUMBER" >> "$GITHUB_ENV"
  • collect the build info before the upload: this step uses the JFrog CLI to collect build information, which is useful for tracking and managing builds in Artifactory.
- name: Collect build info
run: |
jf rt bag ${{ env.build_name }} ${{ env.build_number }} .

Here’s how these steps fit into a complete GitHub Actions workflow:

#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-jfrog-cli-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

# Setup Java
- name: Setup JDK 8
uses: actions/setup-java@v4
with:
distribution: 'adopt-hotspot'
java-version: '8'
#Cache dependencies to speed up workflow runs.
cache: maven

# Setup JFrog CLI
- name: Setup JFrog CLI
uses: jfrog/setup-jfrog-cli@v4
env:
# JFrog platform url (for example: https://acme.jfrog.io)
JF_URL: ${{ secrets.JF_URL }}
# Basic authentication credentials
JF_USER: ${{ secrets.JF_USER }}
JF_PASSWORD: ${{ secrets.JF_PASSWORD }}

# Configure JFrog server and print the version
- name: Config JFrog Server
run: |
jf mvn-config --repo-deploy-releases mule-libs-release-local \
--repo-deploy-snapshots mule-libs-snapshot-local

# Set build variables
- name: Set build variables
run: |
echo "BUILD_NAME=$(echo ${GITHUB_REPOSITORY#*/})" >> "$GITHUB_ENV"
echo "BUILD_NUMBER=$GITHUB_RUN_NUMBER" >> "$GITHUB_ENV"

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

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

# Deploy to CloudHub
- name: Deploy
continue-on-error: true
run: |
mvn -U -V -e -B -DskipTests deploy --file pom.xml -DmuleDeploy \
-Dconn.app.client.id=${{ env.CLOUHUB_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}} \

# Collect build info
- name: Collect build info
run: |
jf rt bag ${{ env.BUILD_NAME }} ${{ env.BUILD_NUMBER }} .

# Upload artifact
- name: Upload artifact to JFrog repository
run: |
jf mvn clean install -DskipTests --build-name=${{ env.BUILD_NAME}} --build-number=${{ env.BUILD_NUMBER }}

Maven Distribution Management

Maven Distribution Management serves as an alternative approach for deploying both release and snapshot versions of your artifacts. This functionality is controlled through the distributionManagement tag in your project’s pom.xml file. Artifactory facilitates this process by providing a code snippet that you can use to configure your deployment. Simply navigate to the Artifact Repository Browser, select Tree, pick the repository where you intend to deploy, and then click on Set Me Up. You’ll find the appropriate code snippet conveniently displayed under the Deploy section.

This setup ensures that Maven knows where to deploy both release and snapshot artifacts, facilitating effective artifact management.

Edit your pom.xml to include distributionManagement:

<distributionManagement>
<repository>
<id>central</id>
<name>a0uav6dvpdny9-artifactory-primary-0-releases</name>
<url>https://muleorg.jfrog.io/artifactory/mule-libs-release-local</url>
</repository>
<snapshotRepository>
<id>snapshots</id>
<name>a0uav6dvpdny9-artifactory-primary-0-snapshots</name>
<url>https://muleorg.jfrog.io/artifactory/mule-libs-snapshot-local</url>
</snapshotRepository>
</distributionManagement>

When deploying your Maven builds via Artifactory, it’s crucial to confirm that each repository element within your distributionManagement settings corresponds to a server element in your settings.xml file. Each server element should include a valid username and password. For instance, based on the provided example, the Maven client anticipates discovering server elements in the settings.xml file with id snapshots and central. This setup is vital for authenticating and securely deploying your artifacts.

To update the settings.xml file through a GitHub Actions workflow, we’ll define the following workflow step:

            # Add servers to settings.xml
- uses: s4u/maven-settings-action@v3.0.0
with:
servers: |
[{
"id": "central",
"username": "${{ secrets.JF_USER }}",
"password": "${{ secrets.JF_PASSWORD }}"
},
{
"id": "snapshots",
"username": "${{ secrets.JF_USER }}",
"password": "${{ secrets.JF_PASSWORD }}"
}]

Here is a complete GitHub Actions workflow:

#Optional - The name of the workflow as it will appear in the "Actions" tab of the GitHub repository. 
name: mulesoft-jfrog-dist-management-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

# Setup Java
- name: Setup JDK 8
uses: actions/setup-java@v4
with:
distribution: 'adopt-hotspot'
java-version: '8'
#Cache dependencies to speed up workflow runs.
cache: maven

# Add servers to settings.xml
- uses: s4u/maven-settings-action@v3.0.0
with:
servers: |
[{
"id": "central",
"username": "${{ secrets.JF_USER }}",
"password": "${{ secrets.JF_PASSWORD }}"
},
{
"id": "snapshots",
"username": "${{ secrets.JF_USER }}",
"password": "${{ secrets.JF_PASSWORD }}"
}]
# Run the tests
- name: Test the compiled source code
run: mvn clean test

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

# Deploy to CloudHub
- name: Deploy
continue-on-error: true
run: |
mvn -U -V -e -B -DskipTests deploy --file pom.xml -DmuleDeploy \
-Dconn.app.client.id=${{ env.CLOUHUB_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}} \

# Upload artifact
- name: Upload artifact to JFrog repository
run: |
mvn deploy -DskipTests

Conclusion

Wrapping up, the integration of JFrog Artifactory with GitHub Actions for MuleSoft CI/CD pipelines presents a considerable boost in automation and workflow management within software development. Through the utilization of JFrog CLI and the setup of Maven Distribution Management, organizations can effectively handle artifact storage, management, and secure deployment. These practices are essential for maintaining robust and scalable CI/CD pipelines, crucial components of modern DevOps workflows.

I’m interested in hearing your thoughts.

--

--

Kseniia Tarantsova
Another Integration Blog

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