Process Integration and Artifact Management for Jenkins
You can set up continuous integration (CI) for your model-based design projects in Jenkins® by using the CI Support Package for Simulink. The support package allows you to run pipelines of tasks in Jenkins and manage artifacts by using network storage, JFrog Artifactory, Amazon S3™, or Azure® Blob storage.
This example shows how to:
Set up a Jenkins agent for running processes.
Define tasks for your project by using an example process model.
Connect your MATLAB® project to a remote GitLab® repository for source control integration.
Perform a one-time setup of Jenkins template files that enable you to automatically generate a Jenkins pipeline for your specific process model and pipeline settings.
Push changes to source control and inspect the automatically generated pipeline.
This example shows the recommended way to integrate your process into Jenkins by using pipeline generator version 2, which has enhanced file propagation and artifact management. For alternatives, see Approaches to Running Processes in CI.
Set Up Jenkins
Install Jenkins and the default suggested plugins by using the Jenkins installation documentation. If you already have Jenkins installed, make sure you have the default suggested plugins installed, including Git and Workspace Cleanup. The default suggested plugins are marked as
suggested
in the Jenkins platform plugins list. The pipeline generator was developed with Jenkins 2.462.2.Install these Jenkins plugins:
If you plan on using external artifact management systems such as JFrog Artifactory, also install Credentials Binding.
If you plan on using Docker® container images, also install Docker plugin.
For information on how to install plugins, see the Jenkins documentation Managing Plugins.
Install the required products and tools on your build agent by using one of these approaches:
Option 1: Manually Install Products and Tools on Build Agent
Install MATLAB, Simulink®, Simulink Check™, the CI Support Package for Simulink, and any other products that your process requires. For more information, see Tips for Setting Up CI Agents.
Install Python® with the alias
python3
available in your system path. The pipeline generator was developed with Python 3.11. Optionally, to add colors to CI job logs, you can also install the Python library colorlog.By default, the pipeline generator assumes that you have a shared network storage location for artifacts. However, if you plan to use an external artifact management system instead, make sure to install the CLI tool for your chosen system:
Option 2: Use Prebuilt Docker Image
You can simplify and automate build agent setup by using a prebuilt Docker image as your build environment. You can create a Docker image for pipeline generation by following the steps in Build and Use Docker Image to Run Processes. The image includes the CI support package, Python, artifact management CLIs, and other CI tools for pipeline generation.
Configure at least two executors on your Jenkins instance. Executors control the number of concurrent tasks or builds Jenkins can run. The pipeline generator requires at least two executors: one executor to generate the pipeline and load the children stages and another executor to execute those stages. If you decide to run model tasks in parallel using the pipeline architecture
IndependentModelPipelines
, you need additional executors to handle each of the generated parallel pipelines. For information on how to define Jenkins executors, see the Jenkins documentation on Managing Nodes.Create a Pipeline project in Jenkins using the default settings. For this example, you can follow the Jenkins documentation to create a basic Pipeline through the classic UI. In a later section, you return to these configuration settings to configure your Pipeline project to use the template
Jenkinsfile
from your source control management (SCM) system.
Before you continue, make sure MATLAB is available on the system PATH
so the build agent
can access MATLAB.
Connect MATLAB Project to Remote Repository
To set up your CI system, you must set up a source-controlled remote repository where you store your MATLAB project and you must connect that repository to your Jenkins project.
For this example, you can set up a GitLab repository and connect that repository to a MATLAB project.
Set up a remote GitLab repository by creating a new blank project. See the GitLab documentation for Create a project.
For this example, create a copy of the Process Advisor example project for Jenkins.
processAdvisorJenkinsExampleStart
Connect your project, remote repository, and CI platform by adding the remote URL to your local repository. For more information, see Share Git Repository to Remote. Typically, a remote URL in GitLab has the format,
https://gitlab.com/gitlab-org/gitlab.git
.
Optionally, you can configure GitLab integration with Jenkins to automatically trigger Jenkins builds on code commits or merge requests. See the GitLab documentation for Jenkins integration.
Add Template Files to MATLAB Project
To set up pipeline generation for a project, your project must contain these two files:
Jenkinsfile_pipeline_gen
— Sets up the Jenkins Pipeline, runs MATLAB, and loads the generated CI pipeline file.generate_jenkins_pipeline.m
— Configures pipeline generator options, such as the pipeline architecture and Jenkins agent labels, and generates a CI pipeline file for your specific project and process.
The template files are generic meaning you can update them to work with
any project. The example project,
processAdvisorJenkinsExampleStart
, already contains the
template files.
Update Jenkinsfile_pipeline_gen
File
Edit the Jenkinsfile_pipeline_gen
file to set the node agent
label and environment variables according to your Jenkins setup. The file configures the Jenkins Pipeline, runs MATLAB, calls the MATLAB function generate_jenkins_pipeline.m
, and loads the
generated pipeline file into Jenkins.
Note
The following example configuration files set environment variables inside
the Jenkinsfile_pipeline_gen
file itself. Alternatively,
you can set environment variables directly in Jenkins. You can configure global variables in the Jenkins system settings and node-specific variables in the node
properties.
Specify the Jenkins node agent by replacing
<Jenkins agent label>
with the label for your Jenkins agent. For example:// Copyright 2025 The MathWorks, Inc. node('my-jenkins-agent-label'){
Specify the MATLAB support package root path by specifying the environment variable
MW_SUPPORT_PACKAGE_ROOT
as the path to the MATLAB support package root on the Jenkins agent. You can get the path by runningmatlabshared.supportpkg.getSupportPackageRoot
in MATLAB on the agent. For example:env.MW_SUPPORT_PACKAGE_ROOT = 'C:\\ProgramData\\MATLAB\\SupportPackages\\R2025a\\bin';
Note
When you specify a path, use either forward slashes or double-backslashes.
If your project is in a subfolder of the repository root, uncomment and set the environment variable
MW_RELATIVE_PROJECT_PATH
. The path must end with/
.For example, if the full path to your project is
/home/user/repo-root/src/myproject
, you specify the relative project path as:If your project is at the repository root, you do not need to specify this variable.env.MW_RELATIVE_PROJECT_PATH = "src/myproject/";
Optionally, you can customize project directories by defining these environment variables.
Environment Variable Description env.MW_REMOTE_BUILD_CACHE_NAME
Name of remote build cache directory where the pipeline generator stores pipeline artifact caches on the remote build cache service. By default, the folder name is the name of your workflow.
Inside your artifact storage location, the pipeline generator can generate a folder structure such as:
<RemoteBuildCacheName>/ └── branchName/ └── folderForEachRunId/ └── folderForEachTaskIteration/ ├── Project/ ├── PA_Results/ ├── derived/ │ └── artifacts.dmr ├── ir_dag.json ├── simulink_pipeline └── __lastSuccessfulRunId__
For example,
Jenkins MATLAB Pipeline
.env.MW_PIPELINE_GEN_DIRECTORY
Directory for pipeline generator files. By default, the pipeline generator uses
_pipelineGen_
.For example,
_padvPipelineGen_
.Optionally, if you plan to integrate with one of the supported external artifact management systems, you must configure your Jenkins credentials for your chosen artifact management system by uncommenting the
withCredentials
code block that contains the environment variable for that artifact management system and setting the Jenkins credential secret. See the Jenkins documentation for Using credentials.Optionally, you can set up integration with an artifact management system by uncommenting and defining one of these secrets in your Jenkins credentials. Do not specify secrets or tokens directly in the
Jenkinsfile_pipeline_gen
file. See the Jenkins documentation for Using credentials.Artifact Storage Approach Uncomment the withCredentials
code block that containsRequired Jenkins Credential JFrog Artifactory
withCredentials([string( credentialsId: 'ARTIFACTORY_API_TOKEN_SECRET',variable: 'artifactory_api_token')]) { env.ARTIFACTORY_API_TOKEN = artifactory_api_token; }
Set
ARTIFACTORY_API_TOKEN_SECRET
to your JFrog API token.See the JFrog documentation for Access Tokens.
Amazon S3
withCredentials([string( credentialsId: 'S3_AWS_SECRET_ACCESS_KEY_SECRET',variable: 's3_access_key')]) { env.S3_AWS_SECRET_ACCESS_KEY = s3_access_key; }
Set
S3_AWS_SECRET_ACCESS_KEY_SECRET
to your Amazon S3 access key.Azure Blob
withCredentials([string( credentialsId: 'AZ_CONNECTION_STRING_SECRET',variable: 'az_connection_string')]) { env.AZ_CONNECTION_STRING = az_connection_string; }
Set
AZ_CONNECTION_STRING_SECRET
to your Azure storage account connection string.Note
Store your credentials in Jenkins credentials. Do not hardcode secrets or tokens into the
Jenkinsfile_pipeline_gen
file itself.Optionally, if you want to run the root job in a container, use a
docker.image
wrapper as shown in this code example:def pipelineGenerationPath = "${env.MW_RELATIVE_PROJECT_PATH}${env.MW_PIPELINE_GEN_DIRECTORY}"; stage('Pipeline Generation'){ cleanWs();def scmVars=checkout scm; docker.image('<Full Image Name>').inside("<Optional Containers Arguments>") { // Loading pipeline utilities script ... } }
Update generate_jenkins_pipeline.m
File
Edit the MATLAB function generate_jenkins_pipeline.m
to set
variables according to your Jenkins setup and to customize the pipeline generator options. The function
opens your MATLAB project, stores pipeline generator options by using a padv.pipeline.JenkinsOptions
object, and then generates a pipeline
file by calling the pipeline generator function padv.pipeline.generatePipeline
on that object. The
Jenkins_pipeline_gen
file loads the generated pipeline file,
simulink_pipeline
, to execute the tasks in your
process.
Specify which Jenkins agents can run the pipeline by replacing
<Jenkins agent label>
with the label for your Jenkins agent. For example:op.AgentLabel = "my-jenkins-agent-label";
Choose where the pipeline stores your artifacts by setting the
ArtifactServiceMode
property. Each artifact storage approach has its own specific configuration requirements as shown in ArtifactServiceMode. Depending on which artifact storage approach you choose, you need to specify additional properties and Jenkins credentials.Artifact Storage Approach Example Code Required Jenkins Credential Network storage
op.ArtifactServiceMode = "network"; op.NetworkStoragePath = "/artifactManagement/cacheStorage";
None.
JFrog Artifactory
op.ArtifactServiceMode = "jfrog"; op.ArtifactoryUrl = "http://localhost:8082/artifactory"; op.ArtifactoryRepoName = "example-repo-local";
Set
ARTIFACTORY_API_TOKEN_SECRET
to your JFrog API token.Amazon S3
op.ArtifactServiceMode = "s3"; op.S3BucketName = "my-artifacts-bucket"; op.S3AwsAccessKeyID = "AKIAIOSFODNN7EXAMPLE";
Set
S3_AWS_SECRET_ACCESS_KEY_SECRET
to your Amazon S3 access key.Azure Blob
op.ArtifactServiceMode = "azure_blob"; op.AzContainerName = "mycontainer";
Set
AZ_CONNECTION_STRING_SECRET
to your Azure storage account connection string.Optionally, if you want to runs tasks inside a containerized environment, such as a Docker container, uncomment and specify the properties
RunnerType
andImageTag
. For example:Depending on your setup, you might need to make adjustments to theop.RunnerType = "container"; op.ImageTag = 'my-docker-image-name';
MatlabLaunchCmd
,MatlabStartupOptions
,AddBatchStartupOption
properties. For example:% Docker image settings op.MatlabLaunchCmd = "xvfb-run -a matlab -batch"; op.MatlabStartupOptions = ""; op.AddBatchStartupOption = false;
Optionally, you can customize other pipeline generator options by specifying the other properties of the
padv.pipeline.JenkinsOptions
object in thegenerate_jenkins_pipeline
file.For example, the template
generate_jenkins_pipeline
file specifies the pipeline architecture"SerialStagesGroupPerTask"
which creates one stage for each task in the process. But you can change the number of stages and grouping of tasks in the generated pipeline by changing the PipelineArchitecture property value.Note
To generate code and perform code analysis tasks in parallel using the pipeline architecture
"IndependentModelPipelines"
, you must either switch to using the template parallel process model or update your existing process as shown in Considerations for Parallel Code Generation. These updates allow the tasks in your pipeline to properly handle shared utilities and code generated across parallel jobs.By default, the
generate_jenkins_pipeline
function generates a pipeline for the"CIPipeline"
process. To target a different process, specify a different process name in the call to thepadv.pipeline.generatePipeline
function in thegenerate_jenkins_pipeline
file. For example:padv.pipeline.generatePipeline(op,"myFastFailProcess");
Example Function
% Copyright 2025 The MathWorks, Inc. function generate_jenkins_pipeline() workspace = string(getenv('WORKSPACE')); % Reading Jenkins workspace environment variable supportPackageRoot = string(getenv('MW_SUPPORT_PACKAGE_ROOT')); relativeProjectPath = string(getenv('MW_RELATIVE_PROJECT_PATH')); remoteBuildCacheName = string(getenv('MW_REMOTE_BUILD_CACHE_NAME')); pipelineGenDirectory = string(getenv('MW_PIPELINE_GEN_DIRECTORY')); cp = openProject(strcat(workspace,filesep,string(relativeProjectPath))); op = padv.pipeline.JenkinsOptions; op.AgentLabel = "my-jenkins-agent-label"; op.PipelineArchitecture = "SerialStagesGroupPerTask"; op.GeneratorVersion = 2; op.SupportPackageRoot = supportPackageRoot; op.GeneratedPipelineDirectory = pipelineGenDirectory; op.StopOnStageFailure = true; op.RunprocessCommandOptions.GenerateJUnitForProcess = true; op.ReportPath = "$PROJECTROOT$/PA_Results/Report/ProcessAdvisorReport"; op.RelativeProjectPath = relativeProjectPath; op.RemoteBuildCacheName = remoteBuildCacheName; op.ArtifactServiceMode = 'network'; % network/jfrog/s3/azure_blob op.NetworkStoragePath = '/artifactManagement/cacheStorage'; % op.ArtifactoryUrl = 'http://localhost:8082/artifactory'; % op.ArtifactoryRepoName = 'example-repo-local'; % op.S3BucketName = 'my-artifacts-bucket'; % op.S3AwsAccessKeyID = 'AKIAIOSFODNN7EXAMPLE'; % op.AzContainerName = 'mycontainer'; % op.RunnerType = "container"; % default/container % op.ImageTag = 'mycompany/pipeline-runner:latest'; % op.ImageArgs = "-e MLM_LICENSE_FILE=27000@MyLicenseServer"; % Docker image settings % op.UseMatlabPlugin = false; % op.MatlabLaunchCmd = "xvfb-run -a matlab -batch"; % op.MatlabStartupOptions = ""; % op.AddBatchStartupOption = false; padv.pipeline.generatePipeline(op, "CIPipeline"); end
Configure Jenkins Pipeline Project to Use Template Files
To make your updated template files available to Jenkins, they must be in your project and source control system. Then, you
configure your Jenkins Pipeline project to find and use the
Jenkinsfile_pipeline_gen
file in source control.
For the purpose of this example, commit and push your copy of the
processAdvisorJenkinsExampleStart
project to source control.In Jenkins, in the Pipeline section of the project configuration window, select
Pipeline script from SCM
from the Definition list.Select your source control system from the SCM list.
Paste your repository URL into the Repository URL box.
For more information, see the Jenkins documentation for Defining a Pipeline in SCM.
Generate and Inspect Pipeline
With the template files configured, a Jenkins pipeline generates the next time a build runs. If you integrated GitLab and Jenkins, new code commits or merge requests can automatically trigger a Jenkins build. Alternatively, you can manually run a Jenkins build to view the generated pipeline.
The typical generated pipeline includes these stages:
Pipeline Generation — This stage uses your
Jenkins_pipeline_gen
file to run MATLAB, execute yourgenerate_jenkins_pipeline.m
file, and load the generated pipeline file into Jenkins.simulink_pipeline — This stage loads the generated pipeline file,
simulink_pipeline
, to execute the tasks in your process as stages of the Jenkins pipeline.
When the build finishes, the pipeline generator saves the task results,
Process Advisor report, and the artifacts.dmr
file
for the digital thread into file named padv_artifacts.zip
. You
can access the file as a build artifact in Jenkins. By default, the template files also generate JUnit results which
allow you to view and track task result outcomes as test results in Jenkins.
Enhance Visibility of Execution Data with OpenTelemetry Integration
To gather detailed timing and execution data when you run your process and improve the visibility of execution data for your Jenkins pipeline, particularly for single stage pipelines, you can enable OpenTelemetry integration.
Complete the required setup as shown in Collect Detailed Execution Data with OpenTelemetry Integration.
Install and configure the Jenkins OpenTelemetry plugin.
Configure the OTLP endpoint and, if needed, authentication.
In the OpenTelemetry section of Jenkins, select Export OpenTelemetry configuration as environment variables, so that MATLAB can find the relevant environment variables such as
OTLP_TRACES_ENDPOINT
, and send OpenTelemetry data to the same OTLP gRPC endpoint as Jenkins.
In your
padv.pipeline.JenkinsOptions
object, set the EnableOpenTelemetry property totrue
. The pipeline generator automatically enables OpenTelemetry for therunprocess
function and start spans for other stages in the generated pipeline such as report generation and artifact collection.Optionally, if you want to use custom resource attributes, such as a Git™ commit ID, you can specify those by using an
OTEL_RESOURCE_ATTRIBUTES
environment variable in yourJenkinsfile
.
After you set up this integration, each Jenkins build produces an OpenTelemetry trace that shows the detailed timing and execution data for each stage and step in your generated pipeline.
See Also
padv.pipeline.generatePipeline
| padv.pipeline.JenkinsOptions