MuleSoft - CI/CD with GitHub Actions

MuleSoft - CI/CD with GitHub Actions

With GitHub Actions, it makes it very easy to automate our build, test and deploy workflows providing a sustainable CI/CD solution, managed directly from the GitHub repository.

Let's get started

Prerequisites

  • Active Anypoint Platform access (Can be a trial account).
  • Access to deploy an application to the CloudHub Anypoint Environment Org/Business Group
  • Access to GitHub repository where the mule application source code resides.
  • The MUnit maven plugin is configured to run the MUnit test cases and generate code-coverage (Optional but good to have)
  • Mule maven plugin to deploy to CloudHub. Below is an example configuration
<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>
			<uri>https://anypoint.mulesoft.com</uri>
			<muleVersion>${app.runtime}</muleVersion>
			<username>${username}</username>
			<password>${password}</password>
			<applicationName>${project.name}</applicationName>
			<environment>Sandbox</environment>
			<workerType>MICRO</workerType>
			<region>us-east-2</region>
			<workers>1</workers>
			<objectStoreV2>true</objectStoreV2>
		</cloudHubDeployment>
	</configuration>
</plugin>


The variables that appear between ${} are externalized and supplied during GitHub Action execution using secrets.

GitHub Actions configuration

  • Login to the GitHub repository and navigate to the Actions tab. Click on "New workflow" and select the simple workflow.
No alt text provided for this image
  • Give a good name for your workflow/pipeline and paste the below content as the body and save it:
# This is a basic workflow to help you get started with Actions


name: MuleSoft deployment with GitHub Actions CI


# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ dev ]
  pull_request:
    branches: [ dev ]




jobs:


  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest


    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Cache
        uses: actions/cache@v2.1.5
        with:
    # A list of files, directories, and wildcard patterns to cache and restore
          path: /home/runner/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
              ${{ runner.os }}-maven-
      - name: Setup Java JDK
        uses: actions/setup-java@v1
        with:
    # The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file
          java-version: 1.8   
      - name: maven-settings-xml-action
        uses: whelk-io/maven-settings-xml-action@v16
        with:
         repositories: |
                [
                  {
                    "id": "MuleRepository",
                    "name": "MuleRepository",
                    "url": "https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/",
                    "releases": {
                      "enabled": "true"
                    },
                    "snapshots": {
                      "enabled": "true"
                    }
                  }
                ]
         servers: |
                [
                  {
                    "id": "anypoint-exchange-v2",
                    "username": "${{ secrets.ANYPOINT_USERNAME }}",
                    "password": "${{ secrets.ANYPOINT_PASSWORD }}",
                    "configuration": {
                      "httpConfiguration": {
                        "all": {
                          "usePreemptive": "true"
                        }
                      }
                    }
                  },
                  {
                    "id": "MuleRepository",
                    "username": "${{ secrets.ENT_ID }}",
                    "password": "${{ secrets.ENT_PASSWORD }}",
                    "configuration": {
                      "httpConfiguration": {
                        "all": {
                          "usePreemptive": "true"
                        }
                      }
                    }
                  }
                ]      
        
      
      
      # Runs a single command using the runners shell
      - name: Build
        run: mvn clean package


      # Runs a set of commands using the runners shell
      - name: Artifact file name with commit hash
        run: |
          artifactName1=$(ls target/*.jar | head -1)
          commitHash=$(git rev-parse -short "$GITHUB_SHA")
          artifactName2=$(ls target/*.jar | head -1 | sed "s/.jar/.$comitHash.jar/g")
          mv $artifactName1 $artifactName2
          
      - name: Upload a Build Artifact
        uses: actions/upload-artifact@v2.2.3
        with:
          # Artifact name
          name: build_artifact
          # A file, directory or wildcard pattern that describes what to upload
          path: target/*.jar
  deploy-dev:
    needs: build
    # The type of runner that the job will run on
    runs-on: ubuntu-latest


    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Cache
        uses: actions/cache@v2.1.5
        with:
    # A list of files, directories, and wildcard patterns to cache and restore
          path: /home/runner/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
              ${{ runner.os }}-maven-
      - name: Setup Java JDK
        uses: actions/setup-java@v1
        with:
    # The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file
          java-version: 1.8   
      - name: Download a Build Artifact
        uses: actions/download-artifact@v2.0.9
        with:
        # Artifact name
          name: build_artifact
          
      - name: Deploy to Anypoint Platform
        env:
          USERNAME: ${{ secrets.ANYPOINT_USERNAME }}
          PASSWORD: ${{ secrets.ANYPOINT_PASSWORD }}
          
        run: |
          artifactName=$(ls *.jar | head -1)
          mvn mule:deploy -Dmule.artifact=$artifactName -Dusername=$USERNAME -Dpassword=$PASSWORD






  deploy-test:
    needs: deploy-dev
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    environment: Test
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Cache
        uses: actions/cache@v2.1.5
        with:
    # A list of files, directories, and wildcard patterns to cache and restore
          path: /home/runner/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
              ${{ runner.os }}-maven-
      - name: Setup Java JDK
        uses: actions/setup-java@v1
        with:
    # The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file
          java-version: 1.8   
      - name: Download a Build Artifact
        uses: actions/download-artifact@v2.0.9
        with:
        # Artifact name
          name: build_artifact
          
      - name: Deploy to Anypoint Platform
        env:
          USERNAME: ${{ secrets.ANYPOINT_USERNAME }}
          PASSWORD: ${{ secrets.ANYPOINT_PASSWORD }}
          
        run: |
          artifactName=$(ls *.jar | head -1)
          mvn mule:deploy -Dmule.artifact=$artifactName -Dusername=$USERNAME -Dpassword=$PASSWORD


  deploy-production:
    needs: deploy-test
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    environment: Production
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Cache
        uses: actions/cache@v2.1.5
        with:
    # A list of files, directories, and wildcard patterns to cache and restore
          path: /home/runner/.m2/repository
          key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
          restore-keys: |
              ${{ runner.os }}-maven-
      - name: Setup Java JDK
        uses: actions/setup-java@v1
        with:
    # The Java version to set up. Takes a whole or semver Java version. See examples of supported syntax in README file
          java-version: 1.8   
      - name: Download a Build Artifact
        uses: actions/download-artifact@v2.0.9
        with:
        # Artifact name
          name: build_artifact
          
      - name: Deploy to Anypoint Platform
        env:
          USERNAME: ${{ secrets.ANYPOINT_USERNAME }}
          PASSWORD: ${{ secrets.ANYPOINT_PASSWORD }}
          
        run: |
          artifactName=$(ls *.jar | head -1)
          mvn mule:deploy -Dmule.artifact=$artifactName -Dusername=$USERNAME -Dpassword=$PASSWORD

So let's see what this workflow does:

  • It runs on any push/pull-request on branch dev
  • It has the jobs defined as build, deploy-dev, deploy-test and deploy-production running sequentially one after the other with certain conditions.

Build Stage

  • Here besides the usual checkout and caching of the .m2/repositories, we are also making use of the whelk-io/maven-settings-xml-action@v16 action to set the maven settings.xml file
  • This is necessary because, we need to have the Anypoint-exchange and Mule Enterprise Nexus repositories defined and also the credentials to connect to them.
  • Next we use the mvn clean package command to build our mule application and then create a unique name for the build artifact (appending the commitHash). Eg: "contactapi.2e34d9f.jar"
  • This artifact is then uploaded as a Build artifact for the subsequent workflow steps using the actions/upload-artifact@v2.2.3 action.

Deploy stage

  • All the subsequent deploy stages follows the same workflow - downloads the build artifact that was generated and uploaded as part of the build stage and then deploy to Anypoint platform using the mvn mule:deploy command.
  • The username and the password used in the mvn command are stored as secrets in the repository and passed during runtime to the workflow.
No alt text provided for this image
  • The deploy-test and deploy-production follows the Continuous Delivery principle wherein a manual intervention is required. For this, the workflow is configured to listen to environmental configuration
No alt text provided for this image
No alt text provided for this image

Running the workflow

  • As said earlier, this workflow gets triggered by doing any push or pull request on the dev branch. After the commit, click on the Actions tab to find the workflow run
No alt text provided for this image
  • So here you see, on push to dev branch the build and deploy-dev got executed but now its waiting for a review/manual approval to deploy to test.
  • The individual steps of the stages can be viewed clicking on the stage from the left side
No alt text provided for this image


  • The reviewer can click the "Review deployments" from the right corner of the summary page and provide his approval or rejection with his comments.
No alt text provided for this image
  • Similar review is also setup for production deployment, wherein it deploys only on manual approval.
  • It also shows who has approved the deployment and his according comments for the same under the Deployment reviews section of the summary page.
No alt text provided for this image


Conclusion

GitHub actions provides with an effective CI/CD solution where-in the complete orchestration is driven from the source control itself without involving any other CI/CD or artifact repository tools. This ensures us with a streamlined and effective CI/CD workflow for our mule applications.

To view or add a comment, sign in

More articles by Pralay Debroy

Others also viewed

Explore content categories