Skip to main content

GitHub Actions

Automate build, test, and deployment of your WSO2 Integrator projects using GitHub Actions workflows.

Overview

GitHub Actions uses YAML workflow files stored in .github/workflows/ to define CI/CD pipelines. For WSO2 Integrator projects, a workflow typically installs Java and Ballerina, builds the project, runs tests, creates a Docker image, and deploys to a target environment.

Prerequisites

  • A GitHub repository containing your WSO2 Integrator (Ballerina) project
  • A container registry (GitHub Container Registry, Docker Hub, or a cloud provider registry)
  • Deployment target configured (Kubernetes, cloud service, or WSO2 Devant)
  • Repository secrets configured under Settings > Secrets and variables > Actions

Workflow configuration

Create .github/workflows/deploy.yml in your repository:

# .github/workflows/deploy.yml
name: Build and Deploy

on:
push:
branches: [main]
pull_request:
branches: [main]

env:
BAL_VERSION: "2201.10.0"
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}/wso2-integrator-app

jobs:
build-and-test:
name: Build & Test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Java 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"

- name: Install Ballerina
run: |
wget -q https://dist.ballerina.io/downloads/${{ env.BAL_VERSION }}/ballerina-${{ env.BAL_VERSION }}-swan-lake-linux-x64.deb
sudo dpkg -i ballerina-${{ env.BAL_VERSION }}-swan-lake-linux-x64.deb

- name: Build
run: bal build

- name: Run tests
run: bal test --code-coverage

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: target/report/

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: target/bin/*.jar

docker:
name: Build & Push Docker Image
runs-on: ubuntu-latest
needs: build-and-test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Java 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"

- name: Install Ballerina
run: |
wget -q https://dist.ballerina.io/downloads/${{ env.BAL_VERSION }}/ballerina-${{ env.BAL_VERSION }}-swan-lake-linux-x64.deb
sudo dpkg -i ballerina-${{ env.BAL_VERSION }}-swan-lake-linux-x64.deb

- name: Build project
run: bal build

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: target/docker/wso2-integrator-app/Dockerfile
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: docker
environment: staging
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up kubectl
uses: azure/setup-kubectl@v3

- name: Configure kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config

- name: Deploy to staging
run: |
kubectl set image deployment/wso2-integrator-app \
app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-n staging
kubectl rollout status deployment/wso2-integrator-app \
-n staging --timeout=300s

deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: deploy-staging
environment: production
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up kubectl
uses: azure/setup-kubectl@v3

- name: Configure kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config

- name: Deploy to production
run: |
kubectl set image deployment/wso2-integrator-app \
app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} \
-n production
kubectl rollout status deployment/wso2-integrator-app \
-n production --timeout=300s

Build step details

The build job installs Java 17 and the Ballerina distribution, then runs bal build to compile the project. Build artifacts (the executable JAR) are uploaded for downstream jobs and for manual download.

If your project includes a Cloud.toml, the build also generates Docker and Kubernetes artifacts under target/docker/ and target/kubernetes/.

Test step details

Tests run with coverage enabled. The if: always() condition on the upload step ensures test results are available even when tests fail.

- name: Run tests
run: bal test --code-coverage

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: target/report/

To display test results directly in pull request checks, add a test reporting action:

- name: Publish test report
if: always()
uses: dorny/test-reporter@v1
with:
name: Ballerina Tests
path: target/report/**/TEST-*.xml
reporter: java-junit

Deploy step details

The workflow uses GitHub Environments to manage deployment approvals. Configure the production environment under Settings > Environments with required reviewers to enforce manual approval before production deployments.

Each environment can have its own set of secrets, allowing different Config.toml values per target.

Secrets management

Configure repository and environment secrets under Settings > Secrets and variables > Actions:

SecretScopeDescription
GITHUB_TOKENRepository (automatic)Used for GHCR authentication
KUBE_CONFIGEnvironmentBase64-encoded kubeconfig file
DB_PASSWORDEnvironmentDatabase connection password
API_KEYEnvironmentExternal service API key

Use environment-specific secrets to maintain different credentials per deployment target:

deploy-staging:
environment: staging # Uses staging secrets
deploy-production:
environment: production # Uses production secrets

Pull request workflow

For pull requests, only the build and test jobs run. Docker build and deployment stages are skipped due to the if condition:

if: github.event_name == 'push' && github.ref == 'refs/heads/main'

This provides fast feedback on code changes without triggering deployments.

Reusable workflow

For organizations managing multiple Ballerina projects, extract the common pipeline into a reusable workflow:

# .github/workflows/ballerina-ci.yml
name: Ballerina CI (Reusable)

on:
workflow_call:
inputs:
bal-version:
required: false
type: string
default: "2201.10.0"

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
- run: |
wget -q https://dist.ballerina.io/downloads/${{ inputs.bal-version }}/ballerina-${{ inputs.bal-version }}-swan-lake-linux-x64.deb
sudo dpkg -i ballerina-${{ inputs.bal-version }}-swan-lake-linux-x64.deb
- run: bal build
- run: bal test --code-coverage

Call it from other repositories:

jobs:
ci:
uses: my-org/.github/.github/workflows/ballerina-ci.yml@main
with:
bal-version: "2201.10.0"

What's next