github.com/shashidharatd/test-infra@v0.0.0-20171006011030-71304e1ca560/mungegithub/mungers/publish_scripts/util.sh (about) 1 #!/bin/bash 2 3 # Copyright 2017 The Kubernetes Authors. 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of the License at 8 # 9 # http://www.apache.org/licenses/LICENSE-2.0 10 # 11 # Unless required by applicable law or agreed to in writing, software 12 # distributed under the License is distributed on an "AS IS" BASIS, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 # This file includes functions shared by the each repository's publish scripts. 18 19 set -o errexit 20 set -o nounset 21 set -o pipefail 22 23 # sync_repo() cherry picks the latest changes in k8s.io/kubernetes/${filter} to the 24 # local copy of the repository to be published. 25 # 26 # prerequisites 27 # 1. we are in the root of the repository to be published 28 # 2. we are on the branch to be published (let's call it "target-branch") 29 # overall flow 30 # 1. fetch the current level of k8s.io/kubernetes 31 # 2. check out the $src_branch of k8s.io/kubernetes as branch kube-sync 32 # 3. rewrite the history of branch kube-sync to *only* include code in $subdirectory 33 # 4. locate all commits between the last time we sync'ed and now 34 # 5. switch back to the "target-branch" 35 # 6. for each commit, cherry-pick it (which will keep authorship) into "target-branch" 36 # 7. update metadata files indicating which commits we've sync'ed to 37 sync_repo() { 38 # subdirectory in k8s.io/kubernetes, e.g., staging/src/k8s.io/apimachinery 39 local subdirectory="${1}" 40 local src_branch="${2}" 41 local kubernetes_remote="${3:-https://github.com/kubernetes/kubernetes.git}" 42 readonly filter src_branch 43 44 local currBranch=$(git rev-parse --abbrev-ref HEAD) 45 local previousKubeSHA=$(cat kubernetes-sha) 46 local new_repo="false" 47 if [[ "${previousKubeSHA}" == "" ]]; then 48 new_repo="true" 49 echo "sync_repo() is processing a repo that doesn't have kubernetes-sha, treat it as a new repo" 50 fi 51 52 git remote add upstream-kube "${kubernetes_remote}" || true 53 git fetch upstream-kube 54 git branch -D kube-sync || true 55 git checkout upstream-kube/"${src_branch}" -b kube-sync 56 git reset --hard upstream-kube/"${src_branch}" 57 58 # this command rewrites git history to *only* include $subdirectory 59 git filter-branch -f --msg-filter 'awk 1 && echo && echo "Kubernetes-commit: ${GIT_COMMIT}"' \ 60 --subdirectory-filter "${subdirectory}" HEAD 61 62 local newKubeSHA=$(git log kube-sync -1 | tail -n 1 | sed "s/Kubernetes-commit: //g") 63 64 local previousBranchSHA=$(git log --grep "Kubernetes-commit: ${previousKubeSHA}" --format='%H') 65 local commits=$(git log --no-merges --format='%H' --reverse ${previousBranchSHA}..HEAD) 66 if [ "${new_repo}" = "true" ]; then 67 commits=$(git log --no-merges --format='%H' --reverse HEAD) 68 fi 69 70 # check if any commit of commits change Godeps/Godeps.json 71 local commits_change_godeps=$(git log --format='%H' --follow Godeps/Godeps.json) 72 local cherrypicks_change_godeps="false" 73 while read commit; do 74 if [[ -z "${commit}" ]]; then 75 continue 76 fi 77 if echo ${commits_change_godeps} | grep -q ${commit} > /dev/null; then 78 echo "branch commit ${commit} changes Godeps.json" 79 cherrypicks_change_godeps="true" 80 break 81 fi 82 done <<< "${commits}" 83 84 git checkout ${currBranch} 85 86 # we must reset Godeps.json to what it looked like in the kube-sync branch 87 # before the first commit that's to be cherry-picked so that any new 88 # Godep.json changes from k8s.io/kubernetes will apply cleanly. Note that 89 # entries for k8s.io/* will be updated later in the process. 90 if [ "${cherrypicks_change_godeps}" = "true" ] && [ "${new_repo}" = "false" ]; then 91 local cleanGodepJsonCommit=${previousBranchSHA} 92 git checkout ${cleanGodepJsonCommit} Godeps/Godeps.json 93 if git diff --cached --exit-code &>/dev/null; then 94 echo "no need to reset Godeps.json!" 95 else 96 git -c user.name="Kubernetes Publisher" -c user.email="k8s-publish-robot@users.noreply.github.com" commit -m "sync: reset Godeps.json" -- Godeps/Godeps.json 97 fi 98 fi 99 100 echo "commits to be cherry-picked:" 101 echo "${commits}" 102 echo "" 103 104 while read commitSHA; do 105 if [[ -z "${commitSHA}" ]]; then 106 continue 107 fi 108 echo "working ${commitSHA}" 109 git -c user.name="Kubernetes Publisher" -c user.email="k8s-publish-robot@users.noreply.github.com" cherry-pick --keep-redundant-commits ${commitSHA} 110 done <<< "${commits}" 111 112 # track the k8s.io/kubernetes commit SHA so we can always determine which level of kube this repo matches 113 # track the filtered branch commit SHA so that we can determine which commits need to be picked 114 echo ${newKubeSHA} > kubernetes-sha 115 if git diff --exit-code &>/dev/null; then 116 echo "SHAs haven't changed!" 117 return 118 fi 119 git -c user.name="Kubernetes Publisher" -c user.email="k8s-publish-robot@users.noreply.github.com" commit -m "sync(k8s.io/kubernetes) ${newKubeSHA}" -- kubernetes-sha 120 } 121 122 # This function updates the vendor/ folder, and removes k8s.io/* and glog from 123 # the vendor/ if the repo being published is a library. This is to avoid issues 124 # like https://github.com/kubernetes/client-go/issues/83 and 125 # https://github.com/kubernetes/client-go/issues/19. 126 # 127 # "deps" lists the dependent k8s.io/* repos and branches. For example, if the 128 # function is handling the release-1.6 branch of k8s.io/apiserver, deps is 129 # expected to be "apimachinery:release-1.6,client-go:release-3.0". Dependencies 130 # are expected to be separated by ",", and the name of the dependent repo and 131 # the branch name are expected to be separated by ":". 132 # 133 # "is_library" indicates if the repo being published is a library. 134 # 135 # This function should be run after the Godeps.json are updated with the latest 136 # revisions of k8s.io/* dependencies. 137 # 138 # To avoid repeated godep restore, repositories should share the GOPATH. 139 # 140 # This function assumes to be called at the root of the repository that's going to be published. 141 # This function assumes the branch that need update is checked out. 142 # This function assumes it's the last step in the publishing process that's going to generate commits. 143 restore_vendor() { 144 local deps="${1:-""}" 145 IFS=',' read -a deps <<< "${DEPS}" 146 dep_count=${#deps[@]} 147 # The Godeps.json of apiserver, kube-aggregator, sample-apiserver in staging 148 # don't contain entries for k8s.io/* repos, so we need to explicitly check 149 # out a revision of deps. 150 for (( i=0; i<${dep_count}; i++ )); do 151 pushd ../"${deps[i]%%:*}" 152 git checkout "${deps[i]##*:}" 153 popd 154 done 155 156 local is_library="${2}" 157 # At this step, currently only client-go's Godeps.json contains entries for 158 # k8s.io repos, with commit hash of the first commit in the master branch. 159 godep restore 160 # need to remove the Godeps folder, otherwise godep won't save source code to vendor/ 161 rm -rf ./Godeps 162 # otherwise `godep save` might fail, see https://github.com/kubernetes/test-infra/issues/2684 163 rm -rf ./vendor 164 godep save ./... 165 if [ "${is_library}" = "true" ]; then 166 echo "remove k8s.io/*, gofuzz, and glog from vendor/" 167 # glog uses global variables, it panics when multiple copies are compiled. 168 rm -rf ./vendor/github.com/golang/glog 169 # this ensures users who get the repository via `go get` won't end up with 170 # multiple copies of k8s.io/ repos. The only copy will be the one in the 171 # GOPATH. 172 # Godeps.json has a complete, up-to-date list of dependencies, so 173 # Godeps.json will be the ground truth for users using godep/glide/dep. 174 rm -rf ./vendor/k8s.io 175 # see https://github.com/kubernetes/kubernetes/issues/45693 176 rm -rf ./vendor/github.com/google/gofuzz 177 fi 178 git add --all 179 # check if there are new contents 180 if git diff --cached --exit-code &>/dev/null; then 181 echo "vendor hasn't changed!" 182 return 183 fi 184 git -c user.name="Kubernetes Publisher" -c user.email="k8s-publish-robot@users.noreply.github.com" commit -m "sync: resync vendor folder" 185 } 186 187 # set up github token in ~/.netrc 188 set_github_token() { 189 mv ~/.netrc ~/.netrc.bak || true 190 echo "machine github.com login ${1}" > ~/.netrc 191 } 192 193 cleanup_github_token() { 194 rm -rf ~/.netrc 195 mv ~/.netrc.bak ~/.netrc || true 196 } 197 198 # Godeps.json copied from the staging area might contain invalid commit hashes 199 # in entries for k8s.io/*. This function updates entry for k8s.io/${1} to track 200 # the latest commit created by the publishing robot. 201 # Currently this function is only useful for client-go. Entries for k8s.io/* are 202 # removed from the Godeps.json in the staging area of other repos. 203 update_godeps_json() { 204 local repo=${1%%:*} 205 local branch=${1##*:} 206 local godeps_json="./Godeps/Godeps.json" 207 local old_revs="" 208 # TODO: pass in the new_rev if we want to depend on a specific revision. 209 local new_rev=$(cd ../${repo}; git rev-parse ${branch}) 210 211 # TODO: simplify the following lines 212 while read path rev; do 213 if [[ "${path}" == "k8s.io/${repo}"* ]]; then 214 old_revs+="${rev}"$'\n' 215 fi 216 done < <(jq '.Deps|.[]|.ImportPath + " " + .Rev' -r < "${godeps_json}") 217 old_revs=$(echo "${old_revs%%$'\n'}" | sort | uniq) 218 while read old_rev; do 219 if [[ -z "${old_rev}" ]]; then 220 continue 221 fi 222 sed -i "s|${old_rev}|${new_rev}|g" "${godeps_json}" 223 done <<< "${old_revs}" 224 }