github.com/verrazzano/verrazzano@v1.7.1/ci/cron/Jenkinsfile (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 import groovy.transform.Field 5 6 @Field 7 def GIT_COMMIT_TO_USE = "" 8 @Field 9 def LAST_CLEAN_PERIODIC_COMMIT = "" 10 @Field 11 def LAST_PERIODIC_RUN_COMMIT = "" 12 @Field 13 def VERRAZZANO_DEV_VERSION = "" 14 @Field 15 def periodicsUpToDate = false // If true, indicates that the periodics already passed at the latest commit 16 @Field 17 def periodicsUpToDateFailed = false // If true, indicates that the periodics already ran and failed at the latest commit 18 19 // Non Fields 20 def branchSpecificSchedule = getCronSchedule() 21 22 pipeline { 23 options { 24 timeout(time: 12, unit: 'HOURS') 25 skipDefaultCheckout true 26 disableConcurrentBuilds() 27 timestamps () 28 } 29 30 agent { 31 docker { 32 image "${RUNNER_DOCKER_IMAGE}" 33 args "${RUNNER_DOCKER_ARGS}" 34 registryUrl "${RUNNER_DOCKER_REGISTRY_URL}" 35 registryCredentialsId 'ocir-pull-and-push-account' 36 label "pipeline-job-large" 37 } 38 } 39 40 triggers { 41 cron(branchSpecificSchedule) 42 } 43 44 parameters { 45 booleanParam (description: 'Skip test execution (for debugging)', name: 'DRY_RUN', defaultValue: false) 46 } 47 48 environment { 49 OCI_CLI_AUTH = "instance_principal" 50 OCI_OS_NAMESPACE = credentials('oci-os-namespace') 51 52 CLEAN_BRANCH_NAME = "${env.BRANCH_NAME.replace("/", "%2F")}" 53 54 STABLE_COMMIT_OS_LOCATION = "${CLEAN_BRANCH_NAME}/last-stable-commit.txt" 55 LAST_PERIODIC_OS_LOCATION = "${CLEAN_BRANCH_NAME}/last-periodic-run-commit.txt" 56 CLEAN_PERIODIC_OS_LOCATION = "${CLEAN_BRANCH_NAME}-last-clean-periodic-test/verrazzano_periodic-commit.txt" 57 58 STABLE_COMMIT_LOCATION = "${WORKSPACE}/last-stable-commit.txt" 59 LAST_PERIODIC_LOCATION = "${WORKSPACE}/last-periodic-run-commit.txt" 60 CLEAN_PERIODIC_LOCATION = "${WORKSPACE}/last-clean-periodic-commit.txt" 61 62 OCI_OS_REGION = "us-phoenix-1" 63 } 64 65 stages { 66 stage('Check last clean periodic') { 67 steps { 68 sh """ 69 oci --region us-phoenix-1 os object get --namespace ${OCI_OS_NAMESPACE} -bn ${OCI_OS_BUCKET} --name ${STABLE_COMMIT_OS_LOCATION} --file ${STABLE_COMMIT_LOCATION} 70 """ 71 72 script { 73 // Check if there is already a clean periodic run at this commit already, and set the display name if 74 // it already is tested, or if doing a special run type (dry run, etc...) 75 preliminaryChecks() 76 } 77 } 78 } 79 80 stage('Clean workspace and checkout') { 81 when { 82 allOf { 83 expression { return runPipeline() } 84 } 85 } 86 steps { 87 script { 88 cleanWorkspaceAndCheckout() 89 } 90 } 91 } 92 93 stage ('Run Periodic Test Suite') { 94 when { 95 allOf { 96 expression { return runPipeline() } 97 } 98 } 99 100 steps { 101 script { 102 echo("Running periodics with commit ${GIT_COMMIT_TO_USE}") 103 build job: "/verrazzano-periodic-triggered-tests/${CLEAN_BRANCH_NAME}", wait: true 104 } 105 } 106 } 107 } 108 } 109 110 def cleanWorkspaceAndCheckout() { 111 scmCheckout() 112 def props = readProperties file: '.verrazzano-development-version' 113 VERRAZZANO_DEV_VERSION = props['verrazzano-development-version'] 114 TIMESTAMP = sh(returnStdout: true, script: "date +%Y%m%d%H%M%S").trim() 115 SHORT_COMMIT_HASH = sh(returnStdout: true, script: "git rev-parse --short=8 HEAD").trim() 116 // update the description with some meaningful info 117 currentBuild.description = SHORT_COMMIT_HASH + " : " + env.GIT_COMMIT 118 } 119 120 // Preliminary job checks and display updates 121 def preliminaryChecks() { 122 // Get the last stable commit ID to pass the triggered tests 123 def stableCommitProps = readProperties file: "${STABLE_COMMIT_LOCATION}" 124 GIT_COMMIT_TO_USE = stableCommitProps['git-commit'] 125 echo "Last stable commit: ${GIT_COMMIT_TO_USE}" 126 127 LAST_CLEAN_PERIODIC_COMMIT=getLastPeriodicRunCommit() 128 echo "Last clean periodics commit: ${LAST_CLEAN_PERIODIC_COMMIT}" 129 130 if (LAST_CLEAN_PERIODIC_COMMIT == GIT_COMMIT_TO_USE) { 131 // If we had a clean periodic run and the commit hasn't changed 132 periodicsUpToDate = true 133 } else { 134 // Check if we are still at the same commit previously run (if so we know it wasn't clean and it failed in some way) 135 LAST_PERIODIC_RUN_COMMIT=getLastPeriodicRunCommit() 136 if (LAST_PERIODIC_RUN_COMMIT != null && LAST_PERIODIC_RUN_COMMIT == GIT_COMMIT_TO_USE) { 137 periodicsUpToDateFailed = true 138 } 139 } 140 } 141 142 // Returns the last run commit for the periodics, or null if the commit file does not exist yet. 143 // - fails the pipeline if any error other than 404 is returned by the OCI CLI 144 def getLastPeriodicRunCommit() { 145 lastPeriodicCommitCommandOutput = sh ( 146 label: "Get last clean periodic commit ID", 147 script: "oci --region us-phoenix-1 os object get --namespace ${OCI_OS_NAMESPACE} -bn ${OCI_OS_BUCKET} --name ${LAST_PERIODIC_OS_LOCATION} --file ${LAST_PERIODIC_LOCATION} 2>&1 || true", 148 returnStdout: true 149 ).trim() 150 echo "command out: ${lastPeriodicCommitCommandOutput}" 151 if (lastPeriodicCommitCommandOutput.length() > 0) { 152 // We can get warning messages here as well even when the command succeeded, so be more precise on the checking 153 if (lastPeriodicCommitCommandOutput =~ /(.*)status(.*)\d{1,4}(.*)/) { 154 // If we think we had a status: NNN, we ignore 404 and fail for others 155 assert lastPeriodicCommitCommandOutput =~ /(.*)status(.*)404(.*)/ : "An unexpected error occurred getting last periodic commit from ObjectStore: ${lastPeriodicCommitCommandOutput}" 156 } else { 157 // If we got here, we have some message that may or may not be an error. If we don't see the file, we assume it was an error 158 sh """ 159 if [ ! -f ${LAST_PERIODIC_LOCATION} ]; then 160 echo "An unexpected error occurred getting last periodic run commit from ObjectStore: ${lastPeriodicCommitCommandOutput}" 161 exit 1 162 fi 163 """ 164 } 165 } 166 // Get the commit ID for the last known clean pass of the Periodic tests 167 def lastPeriodicsCommitProps = readProperties file: "${LAST_PERIODIC_LOCATION}" 168 return lastPeriodicsCommitProps['git-commit'] 169 } 170 171 def scmCheckout() { 172 echo "${NODE_LABELS}" 173 echo "Specific GIT commit was not specified, use current head" 174 def scmInfo = checkout([ 175 $class: 'GitSCM', 176 branches: [[name: env.BRANCH_NAME]], 177 doGenerateSubmoduleConfigurations: false, 178 extensions: [], 179 submoduleCfg: [], 180 userRemoteConfigs: [[url: env.SCM_VERRAZZANO_GIT_URL]]]) 181 env.GIT_COMMIT = scmInfo.GIT_COMMIT 182 env.GIT_BRANCH = scmInfo.GIT_BRANCH 183 echo "SCM checkout of ${env.GIT_BRANCH} at ${env.GIT_COMMIT}" 184 } 185 186 // Checks all the conditions gating test execution and collates the result 187 def runPipeline() { 188 return ! periodicsUpToDate && ! periodicsUpToDateFailed && ! params.DRY_RUN 189 } 190 191 def getCronSchedule() { 192 if (env.BRANCH_NAME.equals("master")) { 193 // scheduled for every 6 hours 194 return "H */6 * * *" 195 } else if (env.BRANCH_NAME.startsWith("release-")) { 196 return "H */6 * * *" 197 } 198 return "" 199 }