Trigger internal Jenkins jobs from a Workflow using Axon Relay

You can use Cortex Workflows and Axon Relay to trigger Jenkins jobs running inside your private network without exposing your CI/CD tools to the public internet. This guide walks you through setting up a Docker-based Jenkins instance, configuring Axon Relay to communicate with it securely, and building a Workflow that listens for the job result via callback URL.

Prerequisites

Before getting started:

Considerations

  • This guide describes using a Docker compose file, but note that Axon Relay can be run in Kubernetes or other container systems.

Step 1: Configure Jenkins

  1. Start a basic Jenkins instance in Docker:

docker run -p 9090:8080 -p 50000:50000 jenkins/jenkins:lts
  1. Once Jenkins starts, follow the UI to unlock and configure it. Create a new job, and use the following example simple pipeline:

This script includes a Hello World stage for lightweight setup and testing. Replace it with your own build, test, or deployment logic.

pipeline {
    agent any
    
    parameters {
        string(
            name: 'callbackURL',
            defaultValue: '',
            description: 'The callback URL to POST to'
        )
    }
    
    stages {
        stage('Hello World') {
            steps {
                echo 'Hello World'
            }
        }
        
    }
    
    post {
        always {
            script {
                if (params.callbackURL?.trim()) {
                    def status = currentBuild.currentResult ?: 'SUCCESS'
                    def message = ""
                    def statusCode = ""
                    
                    if (status == 'SUCCESS') {
                        message = "Pipeline completed successfully"
                        statusCode = "success"
                    } else {
                        message = "Pipeline failed during execution"
                        statusCode = "failure"
                    }
                    
                    withCredentials([string(credentialsId: 'cortex_api_token', variable: 'API_TOKEN')]) {
                        sh """
                            curl -X POST "${params.callbackURL}"\
                                 -H "Content-Type: application/json" \
                                 -H "Authorization: Bearer \${API_TOKEN}" \
                                 -d '{
                                     "status": "update",
                                     "message": "${message}",
                                     "response": {
                                     "build_number": "${env.BUILD_NUMBER}",
                                     "job_name": "${env.JOB_NAME}",
                                     "timestamp": "'"\$(date -Iseconds)"'"}
                                 }' \
                                 --fail \
                                 --show-error
                                 
                            curl -X POST "${params.callbackURL}"\
                                 -H "Content-Type: application/json" \
                                 -H "Authorization: Bearer \${API_TOKEN}" \
                                 -d '{
                                     "status": "${statusCode}",
                                     "message": "${message}"
                                 }' \
                                 --fail \
                                 --show-error
                        """
                    }
                    echo "Sent ${statusCode} notification to ${params.callbackURL}"
                } else {
                    echo "No callback URL provided, skipping POST request"
                }
            }
        }
        
        failure {
            echo "Pipeline failed!"
        }
        success {
            echo "Pipeline completed successfully!"
        }
    }
}

Step 2: Set up and run Axon Relay

To call a Jenkins instance behind a firewall, you’ll need to run the Cortex Axon Relay locally or within your infrastructure.

Step 2.1: Create the .env file

In your project directory, create a file called .env. It should include:

CORTEX_API_TOKEN=<your_cortex_api_token>
JENKINS_URL=<https://your.jenkins.url>
JENKINS_TOKEN=<admin:your_jenkins_api_token>

Make sure these environment variables match the configuration of your Jenkins instance.

If Jenkins and Axon are running on the same machine, Axon Relay may have issues reaching Jenkins using http://localhost or 127.0.0.1, since those addresses refer to the container’s internal network.

A workaround is to use a tunneling service like ngrok to expose Jenkins with a public HTTPS URL. If you do so, use the generated public HTTPS URL as the value for JENKINS_URL.

Step 2.2: Create accept.json

In your project directory, create a file called accept.json, which controls what endpoints the Relay is allowed to forward requests to:

{
  "private": [
    {
      "method": "any",
      "path": "/*",
      "origin": "${JENKINS_URL}",
      "auth": {
        "scheme": "basic",
        "value": "${JENKINS_TOKEN}"
      }
    }
  ]
}

Step 2.3: Create docker-compose.yml

The docker-compose.yml file defines how to run the Cortex Axon agent (Relay) using Docker Compose. This file tells Docker how to configure and launch the Relay service so it can securely connect to your internal Jenkins instance and communicate with Cortex.

In your project directory, create the following file:

services:
  jenkins-relay:
    image: ghcr.io/cortexapps/cortex-axon-agent:latest
    env_file: .env
    volumes:
      - "./accept.json:/app/accept.json:rw"
    command: [
      "relay",
      "-a", "jenkins-relay",  # This must match the alias used in the Workflow block
      "-f", "/app/accept.json"
    ]

Step 2.4: Run Axon Relay

From your terminal, run:

docker compose up

Axon Relay will start and register with Cortex using your API token.

Step 3: Create the Workflow in Cortex

  1. Add an Async HTTP request block to your Workflow. Configure the block:

    • Block name: Enter a descriptive name, e.g., Trigger Jenkins job.

    • Slug: Enter a unique identifier for the block.

    • HTTP method: POST

    • URL: Enter the relay URL for your Jenkins job, in the following format: https://<relay-alias>.relays.cortex.io/job/<jenkins-job-name>/buildWithParameters?callbackURL={{callbackUrl}}

      • Replace <relay-alias> with the alias you assigned to the Relay in your docker-compose.yml file (e.g., jenkins-relay).

      • Replace <jenkins-job-name> with the name of the job you want to trigger in Jenkins.

      • {{callbackUrl}} is a dynamic value provided by Cortex and required for async blocks.

  2. Save the block.

  3. In the upper right corner of the page, click Save Workflow.

Step 4: Run the Workflow

  • Click Run on your Workflow.

When you run the Workflow, the following actions happen:

  1. Cortex will POST to Jenkins via Axon.

  2. Jenkins starts the job and makes two POSTs back to Cortex:

    • One update while in progress.

    • One success or failure when done.

  3. The Workflow resumes and displays output in the Async HTTP block results:

    • Metadata about the initial outbound request to Jenkins (e.g., status, headers)

    • A callback with the job name, build number, and timestamp

    • A final result with success or failure

Last updated

Was this helpful?