Jenkins Shared Library for running MultiFlexi applications from Jenkins pipeline.
- Schedule MultiFlexi runtemplate for immediate execution
- Automatic waiting for job completion with configurable timeout
- Get results including exit code, stdout and stderr
- Support for creating runtemplate if it doesn't exist
- Pass configuration and environment variables to MultiFlexi jobs
- Jenkins Pipeline
multiflexi-cli>= 2.2.0 installed on Jenkins agent- Access to MultiFlexi database from Jenkins agent
In Jenkins configuration (Manage Jenkins → Configure System → Global Pipeline Libraries):
- Add a new library with name e.g.
multiflexi - Set Source Code Management to Git
- Enter the URL of this repository
- Check "Load implicitly" if you want to load the library automatically
@Library('multiflexi') _
pipeline {
agent any
stages {
stage('Build') {
steps {
// Your build process
sh 'make build'
sh 'make publish-packages'
}
}
stage('Deploy & Test') {
steps {
script {
def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
createIfNotExists: true,
runtimeplateName: 'Deploy and Test',
config: [
'package_name': 'my-app',
'version': "${env.BUILD_NUMBER}"
],
timeout: 1800,
pollInterval: 10
)
echo "Job completed with exit code: ${result.exitcode}"
}
}
}
}
}Run an existing runtemplate:
def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456'
)Pass configuration to MultiFlexi application:
def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456',
config: [
'param1': 'value1',
'param2': 'value2',
'environment': 'production'
]
)def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456',
timeout: 3600, // 1 hour
pollInterval: 5 // check every 5 seconds
)If runtemplate doesn't exist, it will be created automatically:
def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
createIfNotExists: true,
runtimeplateName: 'CI/CD Deployment',
config: [
'deploy_target': 'production'
]
)def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456',
env: [
'CUSTOM_VAR': 'value',
'DEBUG': '1'
]
)def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456',
executor: 'Docker' // or 'Native', 'Kubernetes', etc.
)def result = runMultiFlexi(
company: 'mycompany',
appId: '123',
runtemplateId: '456'
)
echo "Job ID: ${result.id}"
echo "Status: ${result.status}"
echo "Exit code: ${result.exitcode}"
echo "Start time: ${result.begin}"
echo "End time: ${result.end}"
if (result.stdout) {
echo "=== Output ==="
echo result.stdout
}
if (result.stderr) {
echo "=== Errors ==="
echo result.stderr
}
// You can also process the output
if (result.stdout?.contains('SUCCESS')) {
echo "Deployment successful!"
}@Library('multiflexi') _
pipeline {
agent any
environment {
APP_ID = '123'
COMPANY = 'mycompany'
}
stages {
stage('Build') {
steps {
sh 'make build'
}
}
stage('Publish Packages') {
steps {
sh 'make publish-deb'
sh 'make publish-rpm'
}
}
stage('Install & Test') {
steps {
script {
try {
def result = runMultiFlexi(
company: env.COMPANY,
appId: env.APP_ID,
createIfNotExists: true,
runtimeplateName: "${env.JOB_NAME}-install-test",
config: [
'package': 'my-application',
'version': env.BUILD_NUMBER,
'test_suite': 'integration'
],
timeout: 1800,
pollInterval: 10
)
// Save results for archiving
writeFile file: 'multiflexi-output.txt', text: result.stdout ?: ''
writeFile file: 'multiflexi-errors.txt', text: result.stderr ?: ''
archiveArtifacts artifacts: 'multiflexi-*.txt', allowEmptyArchive: true
if (result.exitcode == 0) {
currentBuild.result = 'SUCCESS'
} else {
currentBuild.result = 'FAILURE'
error("MultiFlexi job failed with exit code ${result.exitcode}")
}
} catch (Exception e) {
currentBuild.result = 'FAILURE'
error("Failed to run MultiFlexi job: ${e.message}")
}
}
}
}
stage('Deploy Production') {
when {
branch 'main'
}
steps {
script {
def result = runMultiFlexi(
company: env.COMPANY,
appId: env.APP_ID,
runtemplateId: '789', // Production deployment template
config: [
'version': env.BUILD_NUMBER,
'environment': 'production'
],
timeout: 3600
)
echo "Deployed to production with exit code: ${result.exitcode}"
}
}
}
}
post {
always {
cleanWs()
}
}
}- company (String): Company slug in MultiFlexi
- appId (String): Application ID in MultiFlexi
- runtemplateId (String): RunTemplate ID. If not provided and
createIfNotExistsis true, a new one will be created - runtimeplateName (String): Name for new runtemplate (default:
${JOB_NAME}-${appId}) - createIfNotExists (Boolean): Create runtemplate if it doesn't exist (default: false)
- config (Map): Application configuration as key-value pairs
- env (Map): Environment variable overrides as key-value pairs
- executor (String): Executor for execution (default: 'Native')
- timeout (Integer): Timeout in seconds (default: 3600)
- pollInterval (Integer): Status check interval in seconds (default: 10)
The plugin returns a Map with the following data from MultiFlexi job:
- id: Job ID
- status: Job status ('success', 'failed', 'running', etc.)
- exitcode: Process exit code
- stdout: Standard output
- stderr: Error output
- begin: Start time
- end: End time
- other fields according to MultiFlexi API
Make sure that multiflexi-cli is installed on Jenkins agent and is available in PATH.
sh 'which multiflexi-cli'
sh 'multiflexi-cli --version'Increase the timeout parameter value:
runMultiFlexi(
company: 'mycompany',
appId: '123',
timeout: 7200 // 2 hours
)Check stderr output for details:
def result = runMultiFlexi(...)
if (result.exitcode != 0) {
echo "Job failed with errors:"
echo result.stderr
}jenkins-multiflexi/
├── src/
│ └── com/
│ └── vitexsoftware/
│ └── multiflexi/
│ └── MultiFlexiClient.groovy # Main class for calling multiflexi-cli
├── vars/
│ └── runMultiFlexi.groovy # Pipeline DSL step
└── README.md # Documentation
For testing you can use Jenkins Pipeline Unit Testing Framework or run in real Jenkins environment.
MIT
VitexSoftware
For bug reports and feature requests use the project's issue tracker.