Authored by: Ryan Feeney
Deployment Manager provides a suite of APIs for a wide variety of implementation strategies with third-party orchestration tools, including Jenkins. These design patterns outline various strategies to begin incorporating a Deployment Manager pipeline in Jenkins. Although this document is specific to Jenkins, you can apply the same concepts to other third-party tools.
Use case examples
Approach 1: Deployment Manager as primary orchestrator
- In this approach, the application uses a typical Deployment Manager configuration consisting of merge and deployment pipelines. However, each deployment triggers a Jenkins job that collects deployment metrics for consolidated reporting.
- This approach is easier to set up, but provides less visibility into the status of ongoing deployments in Deployment Manager.
Approach 2: Jenkins as Primary Orchestrator
- In this approach, Jenkins is the primary orchestrator of the entire process, delegating all Pega-specific tasks to Deployment Manager.
- Merge pipelines trigger the Jenkins job, allowing Pega developers to trigger deployments directly from Dev studio without any additional configuration.
- This approach requires additional effort to set up, but provides greater visibility into the status of ongoing deployments in Deployment Manager.
Before you begin
Review the following documentation before proceeding with these approaches.
Process/Steps to achieve objective
Approach 1: Deployment Manager as Primary Orchestrator
Create a deployment pipeline and a merge pipeline in Deployment Manager to promote your application. See Creating pipelines in Deployment Manager for more information. Next, call a Jenkins job as the final step of a deployment pipeline. This Jenkins job will connect to Deployment Manager using the APIs to collect information, such as:
- Agile workbench items
- Branch names
- Test coverage percentages
- Test executions
- Artifact locations
- Approvers
See the code from the Jenkins approach below as a starting point for metric collection.
Approach 2: Jenkins as Primary Orchestrator
Although this approach requires more effort, using Jenkins provides greater visibility of your deployment status.
- Create a deployment pipeline in Deployment Manager, and capture the pipeline ID.
- Create a Jenkins pipeline project and follow all the guidance from the Jenkins configuration document.
- Add additional parameters:
- DeployPipelineId - Set the default value to the pipeline ID from step 1.
- BranchName
- CallBackURL
- Populate the pipeline definition as a script using the boilerplate code below.
- Trigger the pipeline and ensure that the Deployment Manager pipeline starts.
- Abort the Deployment Manager pipeline and the Jenkins pipeline should end.
- Create a merge pipeline and add a Jenkins task to the final step, invoking the Jenkins job from step #2.
- Trigger the merge pipeline, starting the deployment process in Jenkins when it completes.
The following boilerplate code can be added to a Jenkins pipeline definition to get you started.
1import groovy.json.JsonSlurper 2 3def deploymentStatus 4def deploymentId 5pipeline { 6 agent any 7 environment { 8 DM_AUTH = credentials('DM_AUTH') 9 } 10 stages { 11 stage('Trigger Deployment') { 12 steps{ 13 script { 14 if(env.BranchName != ""){ 15 echo "Completing the merge deployment" 16 resolveMergeDeployment(env.CallBackURL) 17 } 18 deploymentId = startDeployment(env.DeployPipelineId) 19 } 20 } 21 } 22 23 stage('Wait for deployment complete'){ 24 steps{ 25 waitUntil{ 26 script{ 27 deploymentStatus = getDeploymentStatus("Pipeline-CNVQW", deploymentId) 28 if(deploymentStatus.contains("Resolved-")){ 29 return true 30 } 31 return false 32 } 33 } 34 script{ 35 if(deploymentStatus.contains("Resolved-Aborted")){ 36 error('The deployment manager deployment was aborted') 37 } 38 } 39 } 40 } 41 stage('Collect deploment metrics'){ 42 steps{ 43 echo 'TODO' 44 } 45 } 46 } 47} 48 49def getPipeline() { 50 def token = getToken(); 51 def pipelineDef = sh(script: "curl --insecure -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"Authorization:Bearer ${token}\" -k -X GET $OrchestratorURL/PRRestService/DeploymentManager/v1/pipelines/${pipelineId}", returnStdout:true).trim() 52 return pipelineDef 53} 54 55def addStagesFromPipeline(){ 56 def stagesJSON = getPipelineStages() 57 new JsonSlurper().parseText(stagesJSON).each { pipelineStage -> 58 stage(pipelineStage.name) { 59 steps{ 60 echo pipelineStage.name 61 } 62 } 63 } 64} 65 66def startDeployment(pipelineId){ 67 def token = getToken(); 68 deploymentId = sh(script: "curl -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"Authorization:Bearer ${token}\" -k -X POST $OrchestratorURL/PRRestService/DeploymentManager/v1/pipelines/${pipelineId}/deployments | jq -r .deploymentID", returnStdout:true).trim() 69 return deploymentId 70} 71 72def getDeployment(pipelineId, deploymentId){ 73 def token = getToken(); 74 deployment = sh(script:"curl -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"Authorization:Bearer ${token}\" -k -X GET $OrchestratorURL/PRRestService/DeploymentManager/v1/pipelines/${pipelineId}/deployments/${deploymentId}", returnStdout:true) 75 return deployment 76} 77 78def getDeploymentStatus(pipelineId, deploymentId){ 79 deployment = getDeployment(pipelineId, deploymentId) 80 deploymentStatus = sh(script:"jq .status <<<'${deployment}'", returnStdout:true) 81 return deploymentStatus 82} 83 84def getToken(){ 85 sh(script: "curl -d \"client_id=$DM_AUTH_USR&client_secret=$DM_AUTH_PSW&grant_type=client_credentials\" $OrchestratorURL/PRRestService/oauth2/v1/token | jq -r .access_token", returnStdout:true).trim() 86} 87 88def resolveMergeDeployment(CallBackURL){ 89 def token = getToken(); 90 sh(script:"curl -H \"Content-Type: application/json\" -H \"Accept: application/json\" -H \"Authorization:Bearer ${token}\" -k -X PUT --data '{\"taskStatus\":\"Resolved-Completed\",\"taskInfo\":{\"outputParameters\":[{\"name\": \"BuildNumber\",\"type\": \"Text\",\"value\": \"%BUILD_NUMBER%\"},{\"name\": \"JenkinsBuildURL\",\"type\": \"Text\",\"value\": \"%BUILD_URL%\"}]}}' ${CallBackURL}", returnStdout:true) 91}
Results
You now have everything you need to create a simple Jenkins pipeline to expose ongoing Pega deployments from within the Jenkins dashboard.