-
Notifications
You must be signed in to change notification settings - Fork 146
standalone deployment pipeline for Jenkins #376
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 5 commits
4cfe856
391587d
1e4cf8e
eb31867
66d806e
7dc4cfe
a600d2f
6b39572
fb62a5e
db6d0b0
12456c1
2387082
5db8f5d
0ced6de
3b8007e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,222 @@ | ||
| def JenkinsAgent = "ztec-201-STC" | ||
| def pipeverbose = true | ||
|
|
||
| pipeline { | ||
| agent { label JenkinsAgent } | ||
|
|
||
| environment { | ||
| GIT_STRATEGY = "none" | ||
| GIT_CHECKOUT = "false" | ||
| wdEnvironmentFile = "EOLEB7-${params.application}-${params.targetEnvironment.capitalize()}.yaml" //Make sure the referenced file matches the required naming convention | ||
| wdEvidencePath = "deploy/evidences" | ||
| wdEvidencesRoot = "/var/work/wazi_deploy_evidences_jenkins/" | ||
| wdEvidencesIndex = "/var/work/wazi_deploy_evidences_jenkins_index/" | ||
| uniqueWorkspaceId = "${env.WORKSPACE}/${params.application}/deploy-${params.buildId}" | ||
| deployOutputDirectory = "${env.WORKSPACE}/${params.application}/DEPLOY-OUTPUT" | ||
| } | ||
|
|
||
| parameters { | ||
| string(name: 'application', defaultValue: '', description: 'Application name (e.g., retirementCalculator, MortgageApplication)') | ||
| string(name: 'releaseVersion', defaultValue: '', description: 'Release version to deploy (only for release eg: rel-1.6.1 )') | ||
| string(name: 'buildId', defaultValue: '', description: 'Build pipeline ID (e.g., 00000018)') | ||
| choice(name: 'targetEnvironment', choices: ['integration', 'acceptance', 'production'], description: 'Deployment target environment') | ||
| string(name: 'branchName', defaultValue: 'main', description: 'Branch name (e.g., main, feature/test-utility-script)') | ||
|
||
| choice(name: 'pipelineType', choices: ['build', 'release'], description: 'Pipeline type: build or release') | ||
|
||
| } | ||
|
|
||
| options { | ||
| disableConcurrentBuilds() | ||
| timestamps() | ||
| } | ||
|
|
||
| stages { | ||
| stage('Validate Parameters') { | ||
| steps { | ||
| script { | ||
| echo "===============================" | ||
| echo "Deployment Pipeline Parameters" | ||
| echo "===============================" | ||
| echo "[INFO] Application: ${params.application}" | ||
|
||
| echo "[INFO] Build ID: ${params.buildId}" | ||
| echo "[INFO] Release Version: ${params.releaseVersion}" | ||
| echo "[INFO] Target Environment: ${params.targetEnvironment}" | ||
| echo "[INFO] Branch: ${params.branchName}" | ||
| echo "[INFO] Pipeline Type: ${params.pipelineType}" | ||
| echo "[INFO] Workspace: ${env.uniqueWorkspaceId}" | ||
| echo "===============================" | ||
|
|
||
| def errors = [] | ||
| if (!params.application) errors << "application is required" | ||
| if (!params.buildId) errors << "buildId is required" | ||
| if (!params.branchName) errors << "branchName is required" | ||
| if (!['build', 'release'].contains(params.pipelineType)) errors << "pipelineType must be 'build' or 'release'" | ||
| if (params.pipelineType == 'release' && !params.releaseVersion) | ||
| errors << "releaseVersion is required for release pipeline type" | ||
| if (errors) { | ||
| errors.each { echo "[ERROR] ${it}" } | ||
| error("[ERROR] Validation failed. Please fix input errors.") | ||
| } | ||
| echo "[SUCCESS] All validations passed" | ||
| } | ||
| } | ||
| } | ||
|
|
||
| stage('Generate Plan') { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @thadbeeraf - The stages need a Today, they just continue to execute. |
||
| steps { | ||
| script { | ||
|
|
||
| echo "[INFO] Generating deployment plan for ${params.targetEnvironment}" | ||
| echo "[INFO] Pipeline type: ${params.pipelineType}" | ||
|
|
||
| def CMD = "" | ||
|
|
||
| if (params.pipelineType == "release") { | ||
|
|
||
| CMD = "wazideploy-generate.sh -w ${env.uniqueWorkspaceId} -a ${params.application} -b ${params.branchName} -P release -R ${releaseVersion} -I ${params.buildId}" | ||
thadbeeraf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| } else { | ||
|
|
||
| CMD = "wazideploy-generate.sh -w ${env.uniqueWorkspaceId} -a ${params.application} -b ${params.branchName} -P build -I ${params.buildId}" | ||
| } | ||
|
|
||
| echo "[INFO] Executing command: ${CMD}" | ||
|
|
||
| def rc = sh(script: CMD, returnStatus: true) | ||
|
|
||
| if (rc == 0) { | ||
| echo "[INFO]: Plan generation passed (RC=0)" | ||
| } else { | ||
| echo "[ERROR]: Plan generation failed (RC=${rc})" | ||
| } | ||
| } | ||
| } | ||
| post { | ||
| failure { | ||
| echo "[ERROR] Deployment plan generation failed." | ||
| } | ||
| success { | ||
| echo "[INFO] Deployment plan generation passed." | ||
| } | ||
| } | ||
| } | ||
|
|
||
| stage('Deploy') { | ||
| steps { | ||
| script { | ||
| echo "[INFO] Deploying to ${params.targetEnvironment} environment" | ||
| echo "[INFO] Using environment file: ${env.wdEnvironmentFile}" | ||
| echo "[INFO] Evidence path: ${env.wdEvidencePath}" | ||
| def CMD = "" | ||
| CMD = "wazideploy-deploy.sh -w ${env.uniqueWorkspaceId} -e ${env.wdEnvironmentFile} -i ${params.application}.tar -l ${env.wdEvidencePath}/evidence.yaml < /dev/null" | ||
thadbeeraf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| echo "[INFO] Executing command: ${CMD}" | ||
|
|
||
| def rc = sh(script: CMD, returnStatus: true) | ||
|
|
||
| if (rc == 0) { | ||
| echo "[INFO]: Deployment passed. (RC=0)" | ||
| } else { | ||
| echo "[ERROR]: Deployment failed. (RC=${rc})" | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| stage('Report') { | ||
| steps { | ||
| script { | ||
|
|
||
| def reportDir = "${env.deployOutputDirectory}/deploy-${params.targetEnvironment}" | ||
| def sourceOutputFile = "${env.uniqueWorkspaceId}/deployPkgDir/deploy/deployment-report.html" | ||
| def sourceEvidenceFile = "${env.uniqueWorkspaceId}/deployPkgDir/deploy/evidences/evidence.yaml" | ||
| def wdEvidencesDir = "${env.wdEvidencesRoot}/${params.application}/${params.targetEnvironment}" | ||
| def wdEvidencesIndex = "${env.wdEvidencesIndex}" | ||
|
|
||
| echo "[INFO] Generating deployment report for ${params.targetEnvironment}" | ||
|
|
||
| def evidenceCmd = "" | ||
|
|
||
| evidenceCmd = "wazideploy-evidence.sh -w ${env.uniqueWorkspaceId} -l ${env.wdEvidencePath}/evidence.yaml -o deploy/deployment-report.html" | ||
|
||
|
|
||
| echo "[INFO] Executing command: ${evidenceCmd}" | ||
|
|
||
|
|
||
| sh "mkdir -p ${env.deployOutputDirectory}" | ||
| sh "mkdir -p ${reportDir}" | ||
| echo "[INFO] Using report directory: ${reportDir}" | ||
|
|
||
| // Persist evidence | ||
| sh "mkdir -p ${wdEvidencesDir} && mkdir -p ${wdEvidencesIndex}" | ||
| sh "cp ${sourceEvidenceFile} ${wdEvidencesDir}/evidence-${params.buildId}.yaml" | ||
thadbeeraf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| echo "[INFO] Persisted evidence file at ${wdEvidencesDir}" | ||
|
|
||
| // Update Wazi Deploy index | ||
|
|
||
| def indexCmd = "" | ||
|
|
||
| indexCmd = "wazideploy-evidence --index ${wdEvidencesIndex} --dataFolder ${env.wdEvidencesRoot} i" | ||
|
|
||
| echo "[INFO] Executing command: ${indexCmd}" | ||
|
|
||
| def rc = sh(script: indexCmd, returnStatus: true) | ||
|
|
||
| if (rc == 0) { | ||
| echo "[INFO]: Deployment report generated. (RC=0)" | ||
| } else { | ||
| echo "[ERROR]: Deployment report generation failed. (RC=${rc})" | ||
| } | ||
| sourceEvidenceFilePath = "${env.uniqueWorkspaceId}/deployPkgDir/deploy/evidences" | ||
|
|
||
| } | ||
| } | ||
| post { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| always { | ||
| // Pick up files created by the deployment. | ||
| dir ("${sourceEvidenceFilePath}") { | ||
| archiveArtifacts allowEmptyArchive: true, | ||
| artifacts: '*.yml,*.yaml', | ||
| excludes: '*clist', | ||
| onlyIfSuccessful: false | ||
| } | ||
| dir ("${env.WORKSPACE}/deployPkgDir/deploy") { | ||
| archiveArtifacts allowEmptyArchive: true, | ||
| artifacts: '*.html', | ||
| excludes: '*clist', | ||
| onlyIfSuccessful: false | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| stage ('Workspace Cleanup') { | ||
| steps { | ||
| script { | ||
| if (pipeverbose) { | ||
| println("[DEBUG]: Final Cleanup before deletes.") | ||
|
|
||
| dir("${env.WORKSPACE}") { | ||
| sh "pwd ; ls -al" | ||
| } | ||
| } | ||
|
|
||
| if (pipeverbose) { | ||
| println("[DEBUG]: Final Cleanup after deletes.") | ||
|
|
||
| dir("${env.WORKSPACE}") { | ||
| sh "pwd ; ls -al" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| post { | ||
| // Clean after build | ||
| always { | ||
| cleanWs(cleanWhenNotBuilt: false, | ||
| deleteDirs: true, | ||
| disableDeferredWipeout: true, | ||
| notFailBuild: true) | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| # Jenkins Deployment Pipeline Template | ||
|
|
||
| This template provides a [Jenkinsfile](Jenkinsfile) to set up a **Continuous Deployment (CD) pipeline** for applications managed in a Git repository. | ||
thadbeeraf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ## Overview and Capabilities | ||
|
|
||
| This Jenkins pipeline implements the [Git-based process and branching model for mainframe development](https://ibm.github.io/z-devops-acceleration-program/docs/git-branching-model-for-mainframe-dev) and leverages [Common Backend Scripts](https://github.com/IBM/dbb/blob/main/Templates/Common-Backend-Scripts/README.md) along with **IBM Wazi Deploy** to automate deployments of pre-built application packages from an artifact repository into integration, acceptance, and production environments on z/OS. | ||
|
|
||
| The pipeline supports **manual or automated triggers** and implements the following stages: | ||
|
||
|
|
||
| * **Validate Parameters** | ||
| - Validates pipeline input parameters passed during manual trigger or via API. | ||
| - Determines the appropriate environment configuration file based on the selected target environment. | ||
| - Ensures required parameters (e.g., `application`, `buildId`, `pipelineType`) are defined. | ||
|
||
|
|
||
| * **Generate Plan** | ||
| - Uses [`wazideploy-generate.sh`](../../Common-Backend-Scripts/wazideploy-generate.sh) to create the deployment plan in z/OS Unix System Services (USS). | ||
| - Supports both **build-based** and **release-based** deployments depending on `pipelineType`. | ||
thadbeeraf marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| * **Deploy** | ||
| - Executes [`wazideploy-deploy.sh`](../../Common-Backend-Scripts/wazideploy-deploy.sh) to deploy the application to the selected target environment. | ||
| - Produces initial evidence files and deployment logs. | ||
| - Uses `returnStatus` for robust error handling (`sh(script: ..., returnStatus: true)`). | ||
|
|
||
| * **Report** | ||
| - Invokes [`wazideploy-evidence.sh`](../../Common-Backend-Scripts/wazideploy-evidence.sh) to generate deployment reports and evidence summaries. | ||
| - Persists evidence files to centralized directories. | ||
| - Updates the Wazi Deploy evidence index for traceability. | ||
|
|
||
| * **Workspace Cleanup** | ||
| - Cleans up intermediate files and temporary deployment directories | ||
| --- | ||
|
|
||
| The pipeline supports controlled deployments to **integration**, **acceptance**, or **production** environments. | ||
| It uses Jenkins **stages**, **steps**, and **post conditions** for robust execution and error handling. | ||
|
|
||
|  | ||
|
|
||
| --- | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| To leverage this Jenkinsfile: | ||
|
|
||
| * A **Jenkins environment** with agents capable of running shell scripts and connecting to the z/OS UNIX System Services (USS) environment. | ||
| * Access to **IBM Wazi Deploy** scripts and **Common Backend Scripts** installed on the deployment agent. | ||
| * Appropriate workspace permissions for reading/writing deployment directories and evidence files. | ||
|
|
||
| --- | ||
|
|
||
| ## Installation and Setup | ||
|
|
||
| * Place the [Jenkinsfile](Jenkinsfile) in the root directory of your project repository. | ||
| * Please review the definitions thoroughly with your Jenkins administrator and adjust pipeline environment variables, workspace paths, and script locations according to your environment. | ||
|
|
||
| ### Required Parameters | ||
|
|
||
| | Parameter | Required | Description | | ||
| | ------------------- | ----------------------------- | ------------------------------------------------------------------------- | | ||
| | `application` | Yes | Application name to deploy. | | ||
| | `buildId` | Yes | Build pipeline ID corresponding to the artifact. | | ||
| | `releaseVersion` | Only for release pipelines | Release version (e.g., `rel-2.6.0`). | | ||
|
||
| | `targetEnvironment` | Yes | Deployment target (`integration`, `acceptance`, `production`). | | ||
| | `branchName` | Yes | Source branch name used for the build. | | ||
| | `pipelineType` | Yes | Pipeline type: `build` or `release`. | | ||
|
|
||
| --- | ||
|
|
||
| ## Pipeline Usage | ||
|
|
||
| This Jenkinsfile can be executed: | ||
|
|
||
| * **Manually** via Jenkins → Build with Parameters | ||
| * **Automatically** via Jenkins API or upstream jobs | ||
|
|
||
| ### Example Manual Trigger | ||
|
|
||
| 1. Open Jenkins → select the job → **Build with Parameters** | ||
| 2. Enter values: | ||
| Eg: | ||
| ``` | ||
| application: retirementCalculator | ||
| buildId: 12247 | ||
| releaseVersion: rel-1.6.1 | ||
| targetEnvironment: integration | ||
| branchName: main | ||
| pipelineType: release | ||
| ``` | ||
|
|
||
| 3. Click **Build** | ||
|
|
||
| The pipeline will: | ||
|
|
||
| 1. Validate input parameters | ||
| 2. Generate a deployment plan | ||
| 3. Deploy the application | ||
| 4. Generate deployment report and evidence | ||
| 5. Clean up workspace | ||
|
|
||
| --- | ||
|
|
||
| ## Error Handling and Return Codes | ||
|
|
||
| * Shell commands are executed with `returnStatus: true` to capture **exit codes** without failing the pipeline immediately. | ||
| * Custom logic handles deployment errors, evidence generation failures, and workspace cleanup issues. | ||
| * Jenkins `post` blocks ensure **always-run cleanup** and artifact archiving. | ||
|
|
||
| --- | ||
|
|
||
|
|
||
| ## Summary | ||
|
|
||
| This Jenkinsfile provides a **robust deployment CD pipeline** for mainframe applications: | ||
|
|
||
| * Automates deployments of prebuilt packages to multiple environments | ||
| * Maintains auditable deployment evidence and reports | ||
| * Provides detailed logging and error handling | ||
| * Cleans workspace to maintain agent hygiene | ||
|
|
||
| It integrates **Common Backend Scripts** into enterprise Jenkins pipelines for automated, traceable deployment workflows. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,4 @@ | ||
| This folder contains templates for standalone deployment pipelines. | ||
|
|
||
| Refer to [Deploy_Pipeline/REDME.md](../Deploy_Pipeline/README.md) | ||
| Refer to [Gitlab/REDME.md](./Gitlab/README.md) | ||
|
||
| and [Jenkins/REDME.md](./Jenkins/README.md) | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a previous version the description of the input parms were more details. Can we please add that back in?