#!/bin/bash # Copyright 2015 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This script uploads metadata and test results to Google Cloud Storage, in the # location indicated by JENKINS_GCS_LOGS_PATH. By default, we use the Google # kubernetes-jenkins bucket. # # The script looks for one of two environment variables to be set: # JENKINS_BUILD_STARTED: set to a nonempty string to upload version # information to 'started.json'. The value of the variable is not # currently used. # JENKINS_BUILD_FINISHED: set to the Jenkins build result to upload the build # result to 'finished.json', any test artifacts, and update the # 'latest-build.txt' file pointer. Since this script uses gsutil directly, # it's a bit faster at uploading large numbers of files than the GCS Jenkins # plugin. It also makes use of gsutil's gzip functionality. # # Note: for magicfile support to work correctly, the "file" utility must be # installed. # TODO(rmmh): rewrite this script in Python so we can actually test it! set -o errexit set -o nounset set -o pipefail if [[ -n "${JENKINS_BUILD_STARTED:-}" && -n "${JENKINS_BUILD_FINISHED:-}" ]] { echo "Error: JENKINS_BUILD_STARTED and JENKINS_BUILD_FINISHED should not both be set!" exit 1 } if [[ ! ${JENKINS_UPLOAD_TO_GCS:-y} =~ ^[yY]$ ]] { exit 0 } # Attempt to determine if we're running against a repo other than # kubernetes/kubernetes to determine whether to place PR logs in a different # location. # # In the current CI system, the tracked repo is named remote. This is not true # in general for most devs, where origin and upstream are more common. global GCS_SUBDIR := ''setconst global FOO = "bar""" readonly remote_git_repo = $[git config --get remote.remote.url | sed 's:.*github.com/::' || true] if [[ -n "${remote_git_repo}" ]] { matchstr $(remote_git_repo) { # main repo: nothing extra kubernetes/kubernetes { global GCS_SUBDIR := ''"" } # a different repo on the k8s org: just the repo name (strip kubernetes/) kubernetes/* { global GCS_SUBDIR := ""$(remote_git_repo#kubernetes/)/"" } # any other repo: ${org}_${repo} (replace / with _) * { global GCS_SUBDIR := ""$(remote_git_repo/\//_)/"" } } if [[ "${remote_git_repo}" != "kubernetes/kubernetes" ]] { # also store the repo in started.json, so Gubernator can link it properly. export BUILD_METADATA_REPO="$(remote_git_repo)" } } if [[ ${JOB_NAME} =~ -pull- ]] { : $(JENKINS_GCS_LOGS_PATH:="gs://kubernetes-jenkins/pr-logs/pull/${GCS_SUBDIR}${ghprbPullId:-unknown}") : $(JENKINS_GCS_LATEST_PATH:="gs://kubernetes-jenkins/pr-logs/directory") : $(JENKINS_GCS_LOGS_INDIRECT:="gs://kubernetes-jenkins/pr-logs/directory/${JOB_NAME}") } else { : $(JENKINS_GCS_LOGS_PATH:="gs://kubernetes-jenkins/logs") : $(JENKINS_GCS_LATEST_PATH:="gs://kubernetes-jenkins/logs") : $(JENKINS_GCS_LOGS_INDIRECT:="") }setconst global FOO = "bar" readonly artifacts_path = ""$(WORKSPACE)/_artifacts"setconst global FOO = "bar"" readonly gcs_job_path = ""$(JENKINS_GCS_LOGS_PATH)/$(JOB_NAME)"setconst global FOO = "bar"" readonly gcs_build_path = ""$(gcs_job_path)/$(BUILD_NUMBER)"setconst global FOO = "bar"" readonly gcs_latest_path = ""$(JENKINS_GCS_LATEST_PATH)/$(JOB_NAME)"setconst global FOO = "bar"" readonly gcs_indirect_path = $(JENKINS_GCS_LOGS_INDIRECT)setconst global FOO = "bar" readonly gcs_acl = '"public-read'setconst global FOO = "bar"" readonly results_url = $(gcs_build_path//"gs:/"/"https://console.cloud.google.com/storage/browser")setconst global FOO = "bar" readonly timestamp = $[date +%s] ######################################################################### # $0 is called from different contexts so figure out where kubernetes is. # Sets non-exported global kubernetes_base_path and defaults to "." proc set_kubernetes_base_path { for kubernetes_base_path in [kubernetes go/src/k8s.io/kubernetes .] { # Pick a canonical item to find in a kubernetes tree which could be a # raw source tree or an expanded tarball. [[ -f ${kubernetes_base_path}/cluster/common.sh ]] && break } } ######################################################################### # Try to discover the kubernetes version. # prints version proc find_version { shell { # Where are we? # This could be set in the global scope at some point if we need to # discover the kubernetes path elsewhere. set_kubernetes_base_path cd $(kubernetes_base_path) if [[ -e "version" ]] { cat version } elif [[ -e "hack/lib/version.sh" ]] { export KUBE_ROOT="." source "hack/lib/version.sh" kube::version::get_version_vars echo $(KUBE_GIT_VERSION-) } else { # Last resort from the started.json gsutil cat $(gcs_build_path)/started.json !2 >/dev/null |\ sed -n 's/ *"version": *"\([^"]*\)",*/\1/p' } } } # Output started.json. Use test function below! proc print_started { var metadata_keys = $[compgen -e | grep ^BUILD_METADATA_] echo "{" echo " \"version\": \"$(version)\"," # TODO(fejta): retire echo " \"job-version\": \"$(version)\"," echo " \"timestamp\": $(timestamp)," if [[ -n "${metadata_keys}" ]] { # Any exported variables of the form BUILD_METADATA_KEY=VALUE # will be available as started["metadata"][KEY.lower()]. echo " \"metadata\": {" var sep = ''"" # leading commas are easy to track for env_var in [$metadata_keys] { var var_upper = $(env_var#BUILD_METADATA_) echo " $sep\"$(var_upper,,)\": \"$(!env_var)\"" sep := '",'" } echo " }," } echo " \"jenkins-node\": \"$(NODE_NAME:-)\"" echo "}" } # Use this to test changes to print_started. if [[ -n "${TEST_STARTED_JSON:-}" ]] { global version := $[find_version] cat $[print_started] | jq . exit } proc upload_version { var -r version = $[find_version] var upload_attempt = '' echo -n 'Run starting at '; date -d "@$(timestamp)" if [[ -n "${version}" ]] { echo "Found Kubernetes version: $(version)" } else { echo "Could not find Kubernetes version" } var -r json_file = ""$(gcs_build_path)/started.json"" for upload_attempt in [{1..3}] { echo "Uploading version to: $(json_file) (attempt $(upload_attempt))" gsutil -q -h "Content-Type:application/json" cp -a $(gcs_acl) $[print_started] $(json_file) || continue break } } ######################################################################### # Maintain a single file storing the full build version, Jenkins' job number # build state. Limit its size so it does not grow unbounded. # This is primarily used for and by the # github.com/kubernetes/release/find_green_build tool. # @param build_result - the state of the build # proc update_job_result_cache { var -r build_result = $1 var -r version = $[find_version] var -r job_results = "$(gcs_job_path)/jobResultsCache.json" var -r tmp_results = ""$(WORKSPACE)/_tmp/jobResultsCache.tmp"" # TODO: This constraint is insufficient. The boundary for secondary # job cache should be date based on the last primary build. # The issue is we are trying to find a matched green set of results # at a given hash, but all of the jobs run at wildly different lengths. var -r cache_size = '300' var upload_attempt = '' if [[ -n "${version}" ]] { echo "Found Kubernetes version: $(version)" } else { echo "Could not find Kubernetes version" } mkdir -p $(tmp_results%/*) # Construct a valid json file echo "[" > $(tmp_results) for upload_attempt in [$[seq 3]] { echo "Copying $(job_results) to $(tmp_results) (attempt $(upload_attempt))" # The sed construct below is stripping out only the "version" lines # and then ensuring there's a single comma at the end of the line. gsutil -q cat $(job_results) !2 > !- |\ sed -n 's/^\({"version".*}\),*/\1,/p' |\ tail -$(cache_size) >> $(tmp_results) || continue break } echo "{\"version\": \"$(version)\", \"buildnumber\": \"$(BUILD_NUMBER)\"," \ "\"result\": \"$(build_result)\"}" >> $(tmp_results) echo "]" >> $(tmp_results) for upload_attempt in [$[seq 3]] { echo "Copying $(tmp_results) to $(job_results) (attempt $(upload_attempt))" gsutil -q -h "Content-Type:application/json" cp -a $(gcs_acl) \ $(tmp_results) $(job_results) || continue break } rm -f $(tmp_results) } proc upload_artifacts_and_build_result { var -r build_result = $1 var upload_attempt = '' echo -n 'Run finished at '; date -d "@$(timestamp)" for upload_attempt in [{1..3}] { echo "Uploading to $(gcs_build_path) (attempt $(upload_attempt))" echo "Uploading build result: $(build_result)" gsutil -q -h "Content-Type:application/json" cp -a $(gcs_acl) $[ echo "{" echo " \"result\": \"$(build_result)\"," echo " \"timestamp\": $(timestamp)" echo "}] "$(gcs_build_path)/finished.json" || continue if [[ -d "${artifacts_path}" && -n $(ls -A "${artifacts_path}") ]] { echo "Uploading artifacts" gsutil -m -q -o "GSUtil:use_magicfile=True" cp -a $(gcs_acl) -r -c \ -z log,txt,xml $(artifacts_path) "$(gcs_build_path)/artifacts" || continue } if [[ -e "${WORKSPACE}/build-log.txt" ]] { echo "Uploading build log" gsutil -q cp -Z -a $(gcs_acl) "$(WORKSPACE)/build-log.txt" $(gcs_build_path) } # For pull jobs, keep a canonical ordering for tools that want to examine # the output. if [[ "${gcs_indirect_path}" != "" ]] { echo "Writing $(gcs_build_path) to $(gcs_indirect_path)/$(BUILD_NUMBER).txt" echo $(gcs_build_path) | \ gsutil -q -h "Content-Type:text/plain" \ cp -a $(gcs_acl) - "$(gcs_indirect_path)/$(BUILD_NUMBER).txt" || continue echo "Marking build $(BUILD_NUMBER) as the latest completed build for this PR" echo $(BUILD_NUMBER) | \ gsutil -q -h "Content-Type:text/plain" -h "Cache-Control:private, max-age=0, no-transform" \ cp -a $(gcs_acl) - "$(gcs_job_path)/latest-build.txt" || continue } # Mark this build as the latest completed. echo "Marking build $(BUILD_NUMBER) as the latest completed build" echo $(BUILD_NUMBER) | \ gsutil -q -h "Content-Type:text/plain" -h "Cache-Control:private, max-age=0, no-transform" \ cp -a $(gcs_acl) - "$(gcs_latest_path)/latest-build.txt" || continue break # all uploads succeeded if we hit this point } echo -e "\n\n\n*** View logs and artifacts at $(results_url) ***\n\n" } if [[ -z "${BOOTSTRAP_MIGRATION:-}" ]] { if [[ -n "${JENKINS_BUILD_STARTED:-}" ]] { upload_version } elif [[ -n "${JENKINS_BUILD_FINISHED:-}" ]] { upload_artifacts_and_build_result $(JENKINS_BUILD_FINISHED) update_job_result_cache $(JENKINS_BUILD_FINISHED) } else { echo "ERROR: Called without JENKINS_BUILD_STARTED or JENKINS_BUILD_FINISHED set." echo "ERROR: this should not happen" exit 1 } } (CommandList children: [ (C {(set)} {(-o)} {(errexit)}) (C {(set)} {(-o)} {(nounset)}) (C {(set)} {(-o)} {(pipefail)}) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalAnd left: (BoolUnary op_id: BoolUnary_n child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [123 126] ) ) } ) right: (BoolUnary op_id: BoolUnary_n child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [134 137] ) ) } ) ) ) terminator: ) ] action: [ (C {(echo)} { (DQ ( "Error: JENKINS_BUILD_STARTED and JENKINS_BUILD_FINISHED should not both be set!" ) ) } ) (C {(exit)} {(1)}) ] spids: [-1 143] ) ] spids: [-1 157] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalNot child: (BoolBinary op_id: BoolBinary_EqualTilde left: { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(y)}) spids: [166 170] ) } right: {(Lit_Other "^") (Lit_Other "[") (yY) (Lit_Other "]") (Lit_Other "$")} ) ) ) terminator: ) ] action: [(C {(exit)} {(0)})] spids: [-1 183] ) ] spids: [-1 190] ) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:GCS_SUBDIR) op:Equal rhs:{(DQ )} spids:[211])] spids: [211] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:remote_git_repo) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (AndOr children: [ (Pipeline children: [ (C {(git)} {(config)} {(--get)} {(remote.remote.url)}) (C {(sed)} {(SQ <"s:.*github.com/::">)}) ] negated: False ) (C {(true)}) ] op_id: Op_DPipe ) ] ) left_token: spids: [218 238] ) } spids: [217] ) ] spids: [215] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_n child:{(DQ (${ VSub_Name remote_git_repo))}) ) terminator: ) ] action: [ (Case to_match: {(DQ (${ VSub_Name remote_git_repo))} arms: [ (case_arm pat_list: [{(kubernetes/kubernetes)}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:GCS_SUBDIR) op: Equal rhs: {(DQ )} spids: [276] ) ] spids: [276] ) ] spids: [273 274 280 -1] ) (case_arm pat_list: [{(kubernetes/) (Lit_Other "*")}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:GCS_SUBDIR) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VOp1_Pound arg_word: {(kubernetes) (Lit_Slash /)} ) spids: [293 298] ) (/) ) } spids: [291] ) ] spids: [291] ) ] spids: [287 289 302 -1] ) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:GCS_SUBDIR) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (PatSub pat: {(EscapedLiteralPart token:)} replace: {(_)} do_all: False do_prefix: False do_suffix: False ) spids: [314 320] ) (/) ) } spids: [312] ) ] spids: [312] ) ] spids: [309 310 324 -1] ) ] spids: [258 266 327] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobNEqual left: {(DQ (${ VSub_Name remote_git_repo))} right: {(DQ (kubernetes/kubernetes))} ) ) terminator: ) ] action: [ (C {(export)} {(Lit_VarLike "BUILD_METADATA_REPO=") (DQ (${ VSub_Name remote_git_repo))} ) ] spids: [-1 349] ) ] spids: [-1 366] ) ] spids: [-1 255] ) ] spids: [-1 368] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_EqualTilde left: {(${ VSub_Name JOB_NAME)} right: {(-pull-)} ) ) terminator: ) ] action: [ (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonEquals arg_word: { (DQ ("gs://kubernetes-jenkins/pr-logs/pull/") (${ VSub_Name GCS_SUBDIR) (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(unknown)}) spids: [399 403] ) ) } ) spids: [391 405] ) } ) (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonEquals arg_word: {(DQ ("gs://kubernetes-jenkins/pr-logs/directory"))} ) spids: [410 416] ) } ) (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonEquals arg_word: {(DQ ("gs://kubernetes-jenkins/pr-logs/directory/") (${ VSub_Name JOB_NAME))} ) spids: [421 430] ) } ) ] spids: [-1 386] ) ] else_action: [ (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonEquals arg_word: {(DQ ("gs://kubernetes-jenkins/logs"))} ) spids: [437 443] ) } ) (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonEquals arg_word: {(DQ ("gs://kubernetes-jenkins/logs"))} ) spids: [448 454] ) } ) (C {(Lit_Other ":")} { (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonEquals arg_word:{(DQ )}) spids: [459 464] ) } ) ] spids: [432 466] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:artifacts_path) op: Equal rhs: {(DQ (${ VSub_Name WORKSPACE) (/_artifacts))} spids: [471] ) ] spids: [469] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:gcs_job_path) op: Equal rhs: {(DQ (${ VSub_Name JENKINS_GCS_LOGS_PATH) (/) (${ VSub_Name JOB_NAME))} spids: [481] ) ] spids: [479] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:gcs_build_path) op: Equal rhs: {(DQ (${ VSub_Name gcs_job_path) (/) (${ VSub_Name BUILD_NUMBER))} spids: [494] ) ] spids: [492] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:gcs_latest_path) op: Equal rhs: {(DQ (${ VSub_Name JENKINS_GCS_LATEST_PATH) (/) (${ VSub_Name JOB_NAME))} spids: [507] ) ] spids: [505] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:gcs_indirect_path) op: Equal rhs: {(DQ (${ VSub_Name JENKINS_GCS_LOGS_INDIRECT))} spids: [520] ) ] spids: [518] ) (Assignment keyword: Assign_Readonly pairs: [(assign_pair lhs:(LhsName name:gcs_acl) op:Equal rhs:{(DQ (public-read))} spids:[529])] spids: [527] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:results_url) op: Equal rhs: { (BracedVarSub token: suffix_op: (PatSub pat: {(DQ ("gs:/"))} replace: {(DQ ("https://console.cloud.google.com/storage/browser"))} do_all: True do_prefix: False do_suffix: False ) spids: [537 548] ) } spids: [536] ) ] spids: [534] ) (Assignment keyword: Assign_Readonly pairs: [ (assign_pair lhs: (LhsName name:timestamp) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [(C {(date)} {(Lit_Other "+") (Lit_Other "%") (s)})] ) left_token: spids: [553 559] ) } spids: [552] ) ] spids: [550] ) (FuncDef name: set_kubernetes_base_path body: (BraceGroup children: [ (ForEach iter_name: kubernetes_base_path iter_words: [{(kubernetes)} {(go/src/k8s.io/kubernetes)} {(.)}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (DBracket expr: (BoolUnary op_id: BoolUnary_f child: {(${ VSub_Name kubernetes_base_path) (/cluster/common.sh)} ) ) (ControlFlow token:) ] op_id: Op_DAmp ) ] spids: [594 622] ) spids: [586 592] ) ] spids: [578] ) spids: [571 577] ) (FuncDef name: find_version body: (BraceGroup children: [ (Subshell child: (CommandList children: [ (C {(set_kubernetes_base_path)}) (C {(cd)} {(${ VSub_Name kubernetes_base_path)}) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr:(BoolUnary op_id:BoolUnary_e child:{(DQ (version))})) terminator: ) ] action: [(C {(cat)} {(version)})] spids: [-1 685] ) (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_e child:{(DQ (hack/lib/version.sh))}) ) terminator: ) ] action: [ (C {(export)} {(Lit_VarLike "KUBE_ROOT=") (DQ (.))}) (C {(source)} {(DQ (hack/lib/version.sh))}) (C {(kube) (Lit_Other ":") (Lit_Other ":") (version) (Lit_Other ":") (Lit_Other ":") (get_version_vars) } ) (C {(echo)} { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_Hyphen arg_word:{(SQ )}) spids: [736 739] ) ) } ) ] spids: [693 706] ) ] else_action: [ (Pipeline children: [ (SimpleCommand words: [{(gsutil)} {(cat)} {(${ VSub_Name gcs_build_path) (/started.json)}] redirects: [ (Redir op_id: Redir_Great fd: 2 arg_word: {(/dev/null)} spids: [759] ) ] ) (C {(sed)} {(-n)} {(SQ <"s/ *\"version\": *\"\\([^\"]*\\)\",*/\\1/p">)}) ] negated: False ) ] spids: [743 774] ) ] ) spids: [645 777] ) ] spids: [642] ) spids: [636 641] ) (FuncDef name: print_started body: (BraceGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:metadata_keys) op: Equal rhs: { (CommandSubPart command_list: (CommandList children: [ (Pipeline children: [ (C {(compgen)} {(-e)}) (C {(grep)} {(Lit_Other "^") (BUILD_METADATA_)}) ] negated: False ) ] ) left_token: spids: [797 808] ) } spids: [796] ) ] spids: [794] ) (C {(echo)} {(DQ ("{"))}) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token:) (version) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (${ VSub_Name version) (EscapedLiteralPart token:) (",") ) } ) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token:) (job-version) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (${ VSub_Name version) (EscapedLiteralPart token:) (",") ) } ) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token:) (timestamp) (EscapedLiteralPart token:) (": ") (${ VSub_Name timestamp) (",") ) } ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_n child:{(DQ (${ VSub_Name metadata_keys))}) ) terminator: ) ] action: [ (C {(echo)} { (DQ (" ") (EscapedLiteralPart token:) (metadata) (EscapedLiteralPart token: ) (": {") ) } ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:sep) op:Equal rhs:{(DQ )} spids:[909])] spids: [907] ) (ForEach iter_name: env_var iter_words: [{($ VSub_Name "$metadata_keys")}] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_Local pairs: [ (assign_pair lhs: (LhsName name:var_upper) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VOp1_Pound arg_word: {(BUILD_METADATA_)} ) spids: [933 937] ) ) } spids: [931] ) ] spids: [929] ) (C {(echo)} { (DQ (" ") ($ VSub_Name "$sep") (EscapedLiteralPart token: ) (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_DComma arg_word:{(SQ )}) spids: [947 950] ) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token: ) (BracedVarSub token: prefix_op:VSub_Bang spids:[954957]) (EscapedLiteralPart token: ) ) } ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:sep) op: Equal rhs: {(DQ (","))} spids: [962] ) ] spids: [962] ) ] spids: [926 968] ) spids: [922 924] ) (C {(echo)} {(DQ (" },"))}) ] spids: [-1 885] ) ] spids: [-1 978] ) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token:) (jenkins-node) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [990 993] ) (EscapedLiteralPart token:) ) } ) (C {(echo)} {(DQ ("}"))}) ] spids: [791] ) spids: [785 790] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id: BoolUnary_n child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [1017 1020] ) ) } ) ) terminator: ) ] action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:version) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(find_version)})]) left_token: spids: [1030 1032] ) } spids: [1029] ) ] spids: [1029] ) (Pipeline children: [ (C {(cat)} { (CommandSubPart command_list: (CommandList children:[(C {(print_started)})]) left_token: spids: [1037 1039] ) } ) (C {(jq)} {(.)}) ] negated: False ) (C {(exit)}) ] spids: [-1 1026] ) ] spids: [-1 1050] ) (FuncDef name: upload_version body: (BraceGroup children: [ (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:version) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(find_version)})]) left_token: spids: [1067 1069] ) } spids: [1066] ) ] spids: [1062] ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:upload_attempt) op:Equal spids:[1074])] spids: [1072] ) (Sentence child: (C {(echo)} {(-n)} {(SQ <"Run starting at ">)}) terminator: ) (C {(date)} {(-d)} {(DQ ("@") (${ VSub_Name timestamp))}) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_n child:{(DQ (${ VSub_Name version))}) ) terminator: ) ] action: [(C {(echo)} {(DQ ("Found Kubernetes version: ") (${ VSub_Name version))})] spids: [-1 1115] ) ] else_action: [(C {(echo)} {(DQ ("Could not find Kubernetes version"))})] spids: [1128 1138] ) (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:json_file) op: Equal rhs: {(DQ (${ VSub_Name gcs_build_path) (/started.json))} spids: [1146] ) ] spids: [1142] ) (ForEach iter_name: upload_attempt iter_words: [{(Lit_LBrace "{") (1..3) (Lit_RBrace "}")}] do_arg_iter: False body: (DoGroup children: [ (C {(echo)} { (DQ ("Uploading version to: ") (${ VSub_Name json_file) (" (attempt ") (${ VSub_Name upload_attempt) (")") ) } ) (AndOr children: [ (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:application/json"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} { (CommandSubPart command_list: (CommandList children:[(C {(print_started)})]) left_token: spids: [1204 1206] ) } {(DQ (${ VSub_Name json_file))} ) (ControlFlow token:) ] op_id: Op_DPipe ) (ControlFlow token:) ] spids: [1166 1222] ) spids: [1160 1164] ) ] spids: [1059] ) spids: [1053 1058] ) (FuncDef name: update_job_result_cache body: (BraceGroup children: [ (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:build_result) op: Equal rhs: {($ VSub_Number "$1")} spids: [1261] ) ] spids: [1257] ) (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:version) op: Equal rhs: { (CommandSubPart command_list: (CommandList children:[(C {(find_version)})]) left_token: spids: [1270 1272] ) } spids: [1269] ) ] spids: [1265] ) (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:job_results) op: Equal rhs: {(${ VSub_Name gcs_job_path) (/jobResultsCache.json)} spids: [1279] ) ] spids: [1275] ) (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:tmp_results) op: Equal rhs: {(DQ (${ VSub_Name WORKSPACE) (/_tmp/jobResultsCache.tmp))} spids: [1290] ) ] spids: [1286] ) (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [(assign_pair lhs:(LhsName name:cache_size) op:Equal rhs:{(300)} spids:[1319])] spids: [1315] ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:upload_attempt) op:Equal spids:[1325])] spids: [1323] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id:BoolUnary_n child:{(DQ (${ VSub_Name version))}) ) terminator: ) ] action: [(C {(echo)} {(DQ ("Found Kubernetes version: ") (${ VSub_Name version))})] spids: [-1 1344] ) ] else_action: [(C {(echo)} {(DQ ("Could not find Kubernetes version"))})] spids: [1357 1367] ) (C {(mkdir)} {(-p)} { (BracedVarSub token: suffix_op: (StringUnary op_id:VOp1_Percent arg_word:{(Lit_Slash /) ("*")}) spids: [1375 1380] ) } ) (SimpleCommand words: [{(echo)} {(DQ ("["))}] redirects: [ (Redir op_id: Redir_Great fd: -1 arg_word: {(${ VSub_Name tmp_results)} spids: [1394] ) ] ) (ForEach iter_name: upload_attempt iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(seq)} {(3)})]) left_token: spids: [1408 1412] ) } ] do_arg_iter: False body: (DoGroup children: [ (C {(echo)} { (DQ ("Copying ") (${ VSub_Name job_results) (" to ") (${ VSub_Name tmp_results) (" (attempt ") (${ VSub_Name upload_attempt) (")") ) } ) (AndOr children: [ (Pipeline children: [ (SimpleCommand words: [{(gsutil)} {(-q)} {(cat)} {(${ VSub_Name job_results)}] redirects: [ (Redir op_id: Redir_GreatAnd fd: 2 arg_word: {(-)} spids: [1455] ) ] ) (C {(sed)} {(-n)} {(SQ <"s/^\\({\"version\".*}\\),*/\\1,/p">)}) (SimpleCommand words: [{(tail)} {(-) (${ VSub_Name cache_size)}] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(${ VSub_Name tmp_results)} spids: [1479] ) ] ) ] negated: False ) (ControlFlow token:) ] op_id: Op_DPipe ) (ControlFlow token:) ] spids: [1415 1493] ) spids: [1407 1413] ) (SimpleCommand words: [ {(echo)} { (DQ ("{") (EscapedLiteralPart token:) (version) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (${ VSub_Name version) (EscapedLiteralPart token:) (", ") (EscapedLiteralPart token:) (buildnumber) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (${ VSub_Name BUILD_NUMBER) (EscapedLiteralPart token:) (",") ) } { (DQ (EscapedLiteralPart token:) (result) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token:) (${ VSub_Name build_result) (EscapedLiteralPart token:) ("}") ) } ] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(${ VSub_Name tmp_results)} spids: [1538] ) ] ) (SimpleCommand words: [{(echo)} {(DQ ("]"))}] redirects: [ (Redir op_id: Redir_DGreat fd: -1 arg_word: {(${ VSub_Name tmp_results)} spids: [1552] ) ] ) (ForEach iter_name: upload_attempt iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(seq)} {(3)})]) left_token: spids: [1566 1570] ) } ] do_arg_iter: False body: (DoGroup children: [ (C {(echo)} { (DQ ("Copying ") (${ VSub_Name tmp_results) (" to ") (${ VSub_Name job_results) (" (attempt ") (${ VSub_Name upload_attempt) (")") ) } ) (AndOr children: [ (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:application/json"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(${ VSub_Name tmp_results)} {(${ VSub_Name job_results)} ) (ControlFlow token:) ] op_id: Op_DPipe ) (ControlFlow token:) ] spids: [1573 1633] ) spids: [1565 1571] ) (C {(rm)} {(-f)} {(${ VSub_Name tmp_results)}) ] spids: [1254] ) spids: [1248 1253] ) (FuncDef name: upload_artifacts_and_build_result body: (BraceGroup children: [ (Assignment keyword: Assign_Local flags: ["'-r'"] pairs: [ (assign_pair lhs: (LhsName name:build_result) op: Equal rhs: {($ VSub_Number "$1")} spids: [1661] ) ] spids: [1657] ) (Assignment keyword: Assign_Local pairs: [(assign_pair lhs:(LhsName name:upload_attempt) op:Equal spids:[1667])] spids: [1665] ) (Sentence child: (C {(echo)} {(-n)} {(SQ <"Run finished at ">)}) terminator: ) (C {(date)} {(-d)} {(DQ ("@") (${ VSub_Name timestamp))}) (ForEach iter_name: upload_attempt iter_words: [{(Lit_LBrace "{") (1..3) (Lit_RBrace "}")}] do_arg_iter: False body: (DoGroup children: [ (C {(echo)} { (DQ ("Uploading to ") (${ VSub_Name gcs_build_path) (" (attempt ") (${ VSub_Name upload_attempt) (")") ) } ) (C {(echo)} {(DQ ("Uploading build result: ") (${ VSub_Name build_result))}) (AndOr children: [ (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:application/json"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} { (CommandSubPart command_list: (CommandList children: [ (C {(echo)} {(DQ ("{"))}) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token: ) (result) (EscapedLiteralPart token:) (": ") (EscapedLiteralPart token: ) (${ VSub_Name build_result) (EscapedLiteralPart token:) (",") ) } ) (C {(echo)} { (DQ (" ") (EscapedLiteralPart token: ) (timestamp) (EscapedLiteralPart token:) (": ") (${ VSub_Name timestamp) ) } ) (C {(echo)} {(DQ ("}"))}) ] ) left_token: spids: [1752 1800] ) } {(DQ (${ VSub_Name gcs_build_path) (/finished.json))} ) (ControlFlow token:) ] op_id: Op_DPipe ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (LogicalAnd left: (BoolUnary op_id: BoolUnary_d child: {(DQ (${ VSub_Name artifacts_path))} ) right: (BoolUnary op_id: BoolUnary_n child: { (CommandSubPart command_list: (CommandList children: [ (C {(ls)} {(-A)} {(DQ (${ VSub_Name artifacts_path))} ) ] ) left_token: spids: [1830 1840] ) } ) ) ) terminator: ) ] action: [ (C {(echo)} {(DQ ("Uploading artifacts"))}) (AndOr children: [ (C {(gsutil)} {(-m)} {(-q)} {(-o)} {(DQ ("GSUtil:use_magicfile=True"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(-r)} {(-c)} {(-z)} {(log) (Lit_Comma ",") (txt) (Lit_Comma ",") (xml)} {(DQ (${ VSub_Name artifacts_path))} {(DQ (${ VSub_Name gcs_build_path) (/artifacts))} ) (ControlFlow token: ) ] op_id: Op_DPipe ) ] spids: [-1 1845] ) ] spids: [-1 1909] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id: BoolUnary_e child: {(DQ (${ VSub_Name WORKSPACE) (/build-log.txt))} ) ) terminator: ) ] action: [ (C {(echo)} {(DQ ("Uploading build log"))}) (C {(gsutil)} {(-q)} {(cp)} {(-Z)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(DQ (${ VSub_Name WORKSPACE) (/build-log.txt))} {(DQ (${ VSub_Name gcs_build_path))} ) ] spids: [-1 1928] ) ] spids: [-1 1968] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolBinary op_id: BoolBinary_GlobNEqual left: {(DQ (${ VSub_Name gcs_indirect_path))} right: {(DQ )} ) ) terminator: ) ] action: [ (C {(echo)} { (DQ ("Writing ") (${ VSub_Name gcs_build_path) (" to ") (${ VSub_Name gcs_indirect_path) (/) (${ VSub_Name BUILD_NUMBER) (.txt) ) } ) (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name gcs_build_path))}) (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:text/plain"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(-)} { (DQ (${ VSub_Name gcs_indirect_path) (/) (${ VSub_Name BUILD_NUMBER) (.txt) ) } ) ] negated: False ) (ControlFlow token: ) ] op_id: Op_DPipe ) (C {(echo)} { (DQ ("Marking build ") (${ VSub_Name BUILD_NUMBER) (" as the latest completed build for this PR") ) } ) (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name BUILD_NUMBER))}) (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:text/plain"))} {(-h)} {(DQ ("Cache-Control:private, max-age=0, no-transform"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(-)} {(DQ (${ VSub_Name gcs_job_path) (/latest-build.txt))} ) ] negated: False ) (ControlFlow token: ) ] op_id: Op_DPipe ) ] spids: [-1 1998] ) ] spids: [-1 2137] ) (C {(echo)} { (DQ ("Marking build ") (${ VSub_Name BUILD_NUMBER) (" as the latest completed build") ) } ) (AndOr children: [ (Pipeline children: [ (C {(echo)} {(DQ (${ VSub_Name BUILD_NUMBER))}) (C {(gsutil)} {(-q)} {(-h)} {(DQ ("Content-Type:text/plain"))} {(-h)} {(DQ ("Cache-Control:private, max-age=0, no-transform"))} {(cp)} {(-a)} {(DQ (${ VSub_Name gcs_acl))} {(-)} {(DQ (${ VSub_Name gcs_latest_path) (/latest-build.txt))} ) ] negated: False ) (ControlFlow token:) ] op_id: Op_DPipe ) (ControlFlow token:) ] spids: [1704 2216] ) spids: [1698 1702] ) (C {(echo)} {(-e)} { (DQ (EscapedLiteralPart token:) (EscapedLiteralPart token:) (EscapedLiteralPart token:) ("*** View logs and artifacts at ") (${ VSub_Name results_url) (" ***") (EscapedLiteralPart token:) (EscapedLiteralPart token:) ) } ) ] spids: [1654] ) spids: [1648 1653] ) (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id: BoolUnary_z child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [2247 2250] ) ) } ) ) terminator: ) ] action: [ (If arms: [ (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id: BoolUnary_n child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [2266 2269] ) ) } ) ) terminator: ) ] action: [(C {(upload_version)})] spids: [-1 2275] ) (if_arm cond: [ (Sentence child: (DBracket expr: (BoolUnary op_id: BoolUnary_n child: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id:VTest_ColonHyphen arg_word:{(SQ )}) spids: [2288 2291] ) ) } ) ) terminator: ) ] action: [ (C {(upload_artifacts_and_build_result)} {(${ VSub_Name JENKINS_BUILD_FINISHED)}) (C {(update_job_result_cache)} {(${ VSub_Name JENKINS_BUILD_FINISHED)}) ] spids: [2281 2297] ) ] else_action: [ (C {(echo)} { (DQ ( "ERROR: Called without JENKINS_BUILD_STARTED or JENKINS_BUILD_FINISHED set." ) ) } ) (C {(echo)} {(DQ ("ERROR: this should not happen"))}) (C {(exit)} {(1)}) ] spids: [2314 2336] ) ] spids: [-1 2256] ) ] spids: [-1 2338] ) ] )