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