Jenkins Pipelines allow you to define your entire build, test, and deployment workflow as code stored alongside your application. On RHEL 8 with Jenkins already installed, the Declarative Pipeline syntax offers a structured, human-readable format that is easy to maintain and review. This tutorial covers creating a Pipeline job in the Jenkins UI, writing a Jenkinsfile, and implementing common stages including source checkout, build, test, deploy, environment variables, credentials binding, and post-action handlers.
Prerequisites
- Jenkins installed and running on RHEL 8 (see the Jenkins installation tutorial)
- The Pipeline and Git plugins installed (included in the suggested plugin set)
- A Git repository containing your project source code
- Maven (
mvn) or Node.js (npm) available on the Jenkins agent for the build stage
Step 1 — Create a Pipeline Job in the Jenkins UI
Log into the Jenkins dashboard at http://<server-ip>:8080 and create a new Pipeline project.
# In the Jenkins web UI:
# 1. Click "New Item" from the left sidebar
# 2. Enter a name such as "my-app-pipeline"
# 3. Select "Pipeline" as the item type → OK
# 4. Under "Pipeline" section, set Definition to "Pipeline script from SCM"
# 5. Choose "Git" as SCM and enter your repository URL
# 6. Set "Script Path" to Jenkinsfile (the default)
# 7. Click Save
Using Pipeline script from SCM means Jenkins reads the Jenkinsfile directly from your repository on each run, keeping pipeline definition in version control.
Step 2 — Write a Basic Declarative Jenkinsfile
Create a Jenkinsfile in the root of your repository. The Declarative syntax wraps everything in a pipeline block with an agent, environment, and stages section.
pipeline {
agent any
environment {
APP_NAME = 'my-app'
DEPLOY_ENV = 'staging'
JAVA_HOME = '/usr/lib/jvm/java-11-openjdk'
}
stages {
stage('Checkout') {
steps {
git branch: 'main',
url: 'https://github.com/your-org/your-repo.git'
}
}
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit 'target/surefire-reports/*.xml'
}
}
}
stage('Deploy') {
steps {
echo "Deploying ${APP_NAME} to ${DEPLOY_ENV}"
sh 'bash deploy.sh'
}
}
}
post {
success {
echo 'Pipeline completed successfully.'
}
failure {
echo 'Pipeline failed — check the console output.'
}
always {
cleanWs()
}
}
}
The agent any directive tells Jenkins to run on any available executor. Replace it with a specific node label if you have dedicated build agents.
Step 3 — Add Credentials Binding with withCredentials
Sensitive values such as deploy keys or API tokens should never be hard-coded. Store them in Jenkins Credentials and inject them at runtime with withCredentials.
# In Jenkins UI: Manage Jenkins → Credentials → System → Global credentials → Add Credential
# Kind: Secret text, ID: deploy-api-token, Secret:
# In Jenkinsfile:
stage('Deploy') {
steps {
withCredentials([string(credentialsId: 'deploy-api-token', variable: 'API_TOKEN')]) {
sh '''
curl -s -X POST https://deploy.example.com/release
-H "Authorization: Bearer $API_TOKEN"
-d "app=${APP_NAME}&env=${DEPLOY_ENV}"
'''
}
}
}
The value bound to API_TOKEN is masked in the Jenkins console log so it does not appear in plain text in build output.
Step 4 — Use Environment Variables and Parameters
Parameterized builds allow triggering the pipeline with different inputs without editing the Jenkinsfile.
pipeline {
agent any
parameters {
string(name: 'BRANCH', defaultValue: 'main', description: 'Git branch to build')
choice(name: 'TARGET_ENV', choices: ['staging', 'production'], description: 'Deployment target')
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Run the test suite?')
}
stages {
stage('Checkout') {
steps {
git branch: "${params.BRANCH}",
url: 'https://github.com/your-org/your-repo.git'
}
}
stage('Test') {
when { expression { return params.RUN_TESTS } }
steps {
sh 'mvn test'
}
}
stage('Deploy') {
steps {
echo "Deploying to ${params.TARGET_ENV}"
sh "bash deploy.sh ${params.TARGET_ENV}"
}
}
}
}
Parameters become available in the Jenkins UI under Build with Parameters after the first run of the pipeline.
Step 5 — Trigger Builds Automatically with a Webhook
For automatic builds on every push, configure a webhook in your Git host and enable the corresponding trigger in Jenkins.
# In Jenkins UI — Pipeline job → Configure:
# Under "Build Triggers", check "GitHub hook trigger for GITScm polling"
# (or "Generic Webhook Trigger" plugin for other Git hosts)
# In GitHub repository → Settings → Webhooks → Add webhook:
# Payload URL: http://:8080/github-webhook/
# Content type: application/json
# Events: Just the push event
# Verify the webhook delivered a 200 response in GitHub's Recent Deliveries tab
# To test locally without a webhook:
curl -X POST http://localhost:8080/job/my-app-pipeline/build
--user admin:
The Jenkins Generic Webhook Trigger plugin supports GitLab, Gitea, Bitbucket, and others using the same principle with host-specific payload formats.
Conclusion
You have defined a full Declarative Jenkins Pipeline with checkout, build, test, and deploy stages, secured credentials using withCredentials, added parameterized inputs, and set up automatic webhook-based triggers. Storing your Jenkinsfile in version control means pipeline changes go through the same review process as application code, improving auditability and team collaboration. Extend the pipeline further with parallel stages, Docker build steps, or notifications to Slack as your project grows.
Next steps: How to Install GitLab CE on RHEL 8, How to Configure GitLab CI/CD Pipelines on RHEL 8, and How to Set Up a Git Server with Gitea on RHEL 8.