github.com/verrazzano/verrazzano@v1.7.0/ci/a-la-carte/JenkensfileALaCarteTriggered (about) 1 // Copyright (c) 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 pipeline { 5 options { 6 skipDefaultCheckout true 7 timestamps () 8 } 9 10 agent { 11 docker { 12 image "${RUNNER_DOCKER_IMAGE}" 13 args "${RUNNER_DOCKER_ARGS}" 14 registryUrl "${RUNNER_DOCKER_REGISTRY_URL}" 15 registryCredentialsId 'ocir-pull-and-push-account' 16 label "pipeline-job-large" 17 } 18 } 19 20 parameters { 21 choice (name: 'KUBERNETES_CLUSTER_VERSION', 22 description: 'Kubernetes Version for KinD Cluster', 23 // 1st choice is the default value 24 choices: [ "1.27", "1.26", "1.25", "1.24" ]) 25 string (name: 'GIT_COMMIT_TO_USE', 26 defaultValue: 'NONE', 27 description: 'This is the full git commit hash from the source build to be used for all jobs', 28 trim: true) 29 string (name: 'VERRAZZANO_OPERATOR_IMAGE', 30 defaultValue: 'NONE', 31 description: 'Verrazzano platform operator image name (in ghcr.io repo). If not specified, the operator.yaml from Verrazzano repo will be used to create Verrazzano platform operator', 32 trim: true) 33 booleanParam (description: 'Whether to capture full cluster snapshot on test failure', name: 'CAPTURE_FULL_CLUSTER', defaultValue: false) 34 } 35 36 environment { 37 CLEAN_BRANCH_NAME = "${env.BRANCH_NAME.replace("/", "%2F")}" 38 GOPATH = '/home/opc/go' 39 GO_REPO_PATH = "${GOPATH}/src/github.com/verrazzano" 40 SERVICE_KEY = credentials('PAGERDUTY_SERVICE_KEY') 41 42 OCI_CLI_AUTH="instance_principal" 43 OCI_OS_NAMESPACE = credentials('oci-os-namespace') 44 OCI_OS_BUCKET="verrazzano-builds" 45 } 46 47 stages { 48 stage('Clean workspace and checkout') { 49 steps { 50 script { 51 if (params.GIT_COMMIT_TO_USE == "NONE") { 52 echo "Specific GIT commit was not specified, use current head" 53 def scmInfo = checkout([ 54 $class: 'GitSCM', 55 branches: [[name: env.BRANCH_NAME]], 56 doGenerateSubmoduleConfigurations: false, 57 extensions: [], 58 submoduleCfg: [], 59 userRemoteConfigs: [[url: env.SCM_VERRAZZANO_GIT_URL]]]) 60 env.GIT_COMMIT = scmInfo.GIT_COMMIT 61 env.GIT_BRANCH = scmInfo.GIT_BRANCH 62 } else { 63 echo "SCM checkout of ${params.GIT_COMMIT_TO_USE}" 64 def scmInfo = checkout([ 65 $class: 'GitSCM', 66 branches: [[name: params.GIT_COMMIT_TO_USE]], 67 doGenerateSubmoduleConfigurations: false, 68 extensions: [], 69 submoduleCfg: [], 70 userRemoteConfigs: [[url: env.SCM_VERRAZZANO_GIT_URL]]]) 71 env.GIT_COMMIT = scmInfo.GIT_COMMIT 72 env.GIT_BRANCH = scmInfo.GIT_BRANCH 73 // If the commit we were handed is not what the SCM says we are using, fail 74 if (!env.GIT_COMMIT.equals(params.GIT_COMMIT_TO_USE)) { 75 echo "SCM didn't checkout the commit we expected. Expected: ${params.GIT_COMMIT_TO_USE}, Found: ${scmInfo.GIT_COMMIT}" 76 exit 1 77 } 78 } 79 echo "SCM checkout of ${env.GIT_BRANCH} at ${env.GIT_COMMIT}" 80 } 81 82 script { 83 def props = readProperties file: '.verrazzano-development-version' 84 VERRAZZANO_DEV_VERSION = props['verrazzano-development-version'] 85 TIMESTAMP = sh(returnStdout: true, script: "date +%Y%m%d%H%M%S").trim() 86 SHORT_COMMIT_HASH = sh(returnStdout: true, script: "git rev-parse --short=8 HEAD").trim() 87 88 // update the description with some meaningful info 89 currentBuild.description = SHORT_COMMIT_HASH + " : " + env.GIT_COMMIT + " : " + params.GIT_COMMIT_TO_USE 90 def currentCommitHash = env.GIT_COMMIT 91 def commitList = getCommitList() 92 withCredentials([file(credentialsId: 'jenkins-to-slack-users', variable: 'JENKINS_TO_SLACK_JSON')]) { 93 def userMappings = readJSON file: JENKINS_TO_SLACK_JSON 94 SUSPECT_LIST = getSuspectList(commitList, userMappings) 95 echo "Suspect list: ${SUSPECT_LIST}" 96 } 97 } 98 } 99 } 100 101 stage ('Kick off a-la-carte tests') { 102 parallel { 103 stage('Wildcard DNS, Default CA, Cert-Manager default clusterResourceNamespace') { 104 steps { 105 retry(count: JOB_PROMOTION_RETRIES) { 106 script { 107 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 108 parameters: [ 109 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 110 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 111 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 112 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 113 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cert-manager"), 114 string(name: 'DNS_TYPE', value: "wildcard"), 115 string(name: 'CERTIFICATE_TYPE', value: "default"), 116 ], wait: true 117 } 118 } 119 } 120 } 121 stage('OCIDNS, Default CA, Cert-Manager default clusterResourceNamespace') { 122 steps { 123 retry(count: JOB_PROMOTION_RETRIES) { 124 script { 125 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 126 parameters: [ 127 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 128 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 129 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 130 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 131 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cert-manager"), 132 string(name: 'DNS_TYPE', value: "ocidns"), 133 string(name: 'CERTIFICATE_TYPE', value: "default"), 134 ], wait: true 135 } 136 } 137 } 138 } 139 stage('OCIDNS, LetEncypt staging, Cert-Manager default clusterResourceNamespace') { 140 steps { 141 retry(count: JOB_PROMOTION_RETRIES) { 142 script { 143 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 144 parameters: [ 145 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 146 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 147 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 148 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 149 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cert-manager"), 150 string(name: 'DNS_TYPE', value: "ocidns"), 151 string(name: 'CERTIFICATE_TYPE', value: "letsEncrypt"), 152 ], wait: true 153 } 154 } 155 } 156 } 157 stage('Wildcard DNS, Default CA, Cert-Manager custom clusterResourceNamespace') { 158 steps { 159 retry(count: JOB_PROMOTION_RETRIES) { 160 script { 161 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 162 parameters: [ 163 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 164 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 165 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 166 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 167 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cluster-resource"), 168 string(name: 'DNS_TYPE', value: "wildcard"), 169 string(name: 'CERTIFICATE_TYPE', value: "default"), 170 ], wait: true 171 } 172 } 173 } 174 } 175 stage('OCIDNS, Default CA, Cert-Manager custom clusterResourceNamespace') { 176 steps { 177 retry(count: JOB_PROMOTION_RETRIES) { 178 script { 179 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 180 parameters: [ 181 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 182 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 183 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 184 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 185 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cluster-resource"), 186 string(name: 'DNS_TYPE', value: "ocidns"), 187 string(name: 'CERTIFICATE_TYPE', value: "default"), 188 ], wait: true 189 } 190 } 191 } 192 } 193 stage('OCIDNS, LetEncypt staging, Cert-Manager custom clusterResourceNamespace') { 194 steps { 195 retry(count: JOB_PROMOTION_RETRIES) { 196 script { 197 build job: "/verrazzano-a-la-carte/${CLEAN_BRANCH_NAME}", 198 parameters: [ 199 string(name: 'KUBERNETES_CLUSTER_VERSION', value: params.KUBERNETES_CLUSTER_VERSION), 200 string(name: 'GIT_COMMIT_TO_USE', value: params.GIT_COMMIT_TO_USE), 201 string(name: 'VERRAZZANO_OPERATOR_IMAGE', value: params.VERRAZZANO_OPERATOR_IMAGE), 202 booleanParam(name: 'CAPTURE_FULL_CLUSTER', value: params.CAPTURE_FULL_CLUSTER), 203 string(name: 'CLUSTER_RESOURCE_NAMESPACE', value: "my-cluster-resource"), 204 string(name: 'DNS_TYPE', value: "ocidns"), 205 string(name: 'CERTIFICATE_TYPE', value: "letsEncrypt"), 206 ], wait: true 207 } 208 } 209 } 210 } 211 } 212 } 213 } 214 post { 215 failure { 216 script { 217 if (env.JOB_NAME == "verrazzano-a-la-carte-triggered/master" || env.JOB_NAME ==~ "errazzano-a-la-carte-triggered/release-1.*") { 218 if (isPagerDutyEnabled()) { 219 pagerduty(resolve: false, serviceKey: "$SERVICE_KEY", incDescription: "Verrazzano: ${env.JOB_NAME} - Failed", incDetails: "Job Failed - \"${env.JOB_NAME}\" build: ${env.BUILD_NUMBER}\n\nView the log at:\n ${env.BUILD_URL}\n\nBlue Ocean:\n${env.RUN_DISPLAY_URL}") 220 } 221 slackSend ( channel: "$SLACK_ALERT_CHANNEL", message: "Job Failed - \"${env.JOB_NAME}\" build: ${env.BUILD_NUMBER}\n\nView the log at:\n ${env.BUILD_URL}\n\nBlue Ocean:\n${env.RUN_DISPLAY_URL}\n\nSuspects:\n${SUSPECT_LIST}" ) 222 } 223 } 224 } 225 } 226 } 227 228 def isPagerDutyEnabled() { 229 // this controls whether PD alerts are enabled 230 if (NOTIFY_PAGERDUTY_TRIGGERED_FAILURES.equals("true")) { 231 echo "Pager-Duty notifications enabled via global override setting" 232 return true 233 } 234 return false 235 } 236 237 238 // Called in Stage Clean workspace and checkout steps 239 @NonCPS 240 def getCommitList() { 241 echo "Checking for change sets" 242 def commitList = [] 243 def changeSets = currentBuild.changeSets 244 for (int i = 0; i < changeSets.size(); i++) { 245 echo "get commits from change set" 246 def commits = changeSets[i].items 247 for (int j = 0; j < commits.length; j++) { 248 def commit = commits[j] 249 def id = commit.commitId 250 echo "Add commit id: ${id}" 251 commitList.add(id) 252 } 253 } 254 return commitList 255 } 256 257 def trimIfGithubNoreplyUser(userIn) { 258 if (userIn == null) { 259 echo "Not a github noreply user, not trimming: ${userIn}" 260 return userIn 261 } 262 if (userIn.matches(".*\\+.*@users.noreply.github.com.*")) { 263 def userOut = userIn.substring(userIn.indexOf("+") + 1, userIn.indexOf("@")) 264 return userOut; 265 } 266 if (userIn.matches(".*<.*@users.noreply.github.com.*")) { 267 def userOut = userIn.substring(userIn.indexOf("<") + 1, userIn.indexOf("@")) 268 return userOut; 269 } 270 if (userIn.matches(".*@users.noreply.github.com")) { 271 def userOut = userIn.substring(0, userIn.indexOf("@")) 272 return userOut; 273 } 274 echo "Not a github noreply user, not trimming: ${userIn}" 275 return userIn 276 } 277 278 def getSuspectList(commitList, userMappings) { 279 def retValue = "" 280 def suspectList = [] 281 if (commitList == null || commitList.size() == 0) { 282 echo "No commits to form suspect list" 283 } else { 284 for (int i = 0; i < commitList.size(); i++) { 285 def id = commitList[i] 286 try { 287 def gitAuthor = sh( 288 script: "git log --format='%ae' '$id^!'", 289 returnStdout: true 290 ).trim() 291 if (gitAuthor != null) { 292 def author = trimIfGithubNoreplyUser(gitAuthor) 293 echo "DEBUG: author: ${gitAuthor}, ${author}, id: ${id}" 294 if (userMappings.containsKey(author)) { 295 def slackUser = userMappings.get(author) 296 if (!suspectList.contains(slackUser)) { 297 echo "Added ${slackUser} as suspect" 298 retValue += " ${slackUser}" 299 suspectList.add(slackUser) 300 } 301 } else { 302 // If we don't have a name mapping use the commit.author, at least we can easily tell if the mapping gets dated 303 if (!suspectList.contains(author)) { 304 echo "Added ${author} as suspect" 305 retValue += " ${author}" 306 suspectList.add(author) 307 } 308 } 309 } else { 310 echo "No author returned from git" 311 } 312 } catch (Exception e) { 313 echo "INFO: Problem processing commit ${id}, skipping commit: " + e.toString() 314 } 315 } 316 } 317 def startedByUser = ""; 318 def causes = currentBuild.getBuildCauses() 319 echo "causes: " + causes.toString() 320 for (cause in causes) { 321 def causeString = cause.toString() 322 echo "current cause: " + causeString 323 def causeInfo = readJSON text: causeString 324 if (causeInfo.userId != null) { 325 startedByUser = causeInfo.userId 326 } 327 } 328 329 if (startedByUser.length() > 0) { 330 echo "Build was started by a user, adding them to the suspect notification list: ${startedByUser}" 331 def author = trimIfGithubNoreplyUser(startedByUser) 332 echo "DEBUG: author: ${startedByUser}, ${author}" 333 if (userMappings.containsKey(author)) { 334 def slackUser = userMappings.get(author) 335 if (!suspectList.contains(slackUser)) { 336 echo "Added ${slackUser} as suspect" 337 retValue += " ${slackUser}" 338 suspectList.add(slackUser) 339 } 340 } else { 341 // If we don't have a name mapping use the commit.author, at least we can easily tell if the mapping gets dated 342 if (!suspectList.contains(author)) { 343 echo "Added ${author} as suspect" 344 retValue += " ${author}" 345 suspectList.add(author) 346 } 347 } 348 } else { 349 echo "Build not started by a user, not adding to notification list" 350 } 351 echo "returning suspect list: ${retValue}" 352 return retValue 353 } 354 355 def getCronSchedule() { 356 if (env.BRANCH_NAME.equals("master")) { 357 return "H */2 * * *" 358 } else if (env.BRANCH_NAME.startsWith("release-1")) { 359 return "@daily" 360 } 361 return "" 362 }