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  }