go.etcd.io/etcd@v3.3.27+incompatible/scripts/release (about)

     1  #!/usr/bin/env bash
     2  
     3  set -o errexit
     4  set -o nounset
     5  set -o pipefail
     6  
     7  help() {
     8    echo "$(basename $0) [version]"
     9    echo "Release etcd using the same approach as the etcd-release-runbook (https://goo.gl/Gxwysq)"
    10    echo ""
    11    echo "WARNING: This does not perform the 'Add API capabilities', 'Performance testing' "
    12    echo "         or 'Documentation' steps. These steps must be performed manually BEFORE running this tool."
    13    echo ""
    14    echo "WARNING: This script does not sign releases, publish releases to github or sent announcement"
    15    echo "         emails. These steps must be performed manually AFTER running this tool."
    16    echo ""
    17    echo "  args:"
    18    echo "    version: version of etcd to release, e.g. '3.2.18'"
    19    echo "  flags:"
    20    echo "    --no-upload: skip gs://etcd binary artifact uploads."
    21    echo "    --no-docker-push: skip docker image pushes."
    22    echo ""
    23  }
    24  
    25  main() {
    26    VERSION=$1
    27    if [[ ! "${VERSION}" =~ [0-9]+.[0-9]+.[0-9]+ ]]; then
    28      echo "Expected 'version' param of the form '<major-version>.<minor-version>.<patch-version>' but got '${VERSION}'"
    29      exit 1
    30    fi
    31    RELEASE_VERSION="v${VERSION}"
    32    MINOR_VERSION=$(echo "${VERSION}" | cut -d. -f 1-2)
    33    BRANCH="release-${MINOR_VERSION}"
    34  
    35    if ! command -v docker >/dev/null; then
    36      echo "cannot find docker"
    37      exit 1
    38    fi
    39  
    40    # Expected umask for etcd release artifacts
    41    umask 022
    42  
    43    # Set up release directory.
    44    local reldir="/tmp/etcd-release-${VERSION}"
    45    if [ ! -d "${reldir}/etcd" ]; then
    46      mkdir -p "${reldir}"
    47      cd "${reldir}"
    48      git clone https://github.com/etcd-io/etcd.git --branch "${BRANCH}"
    49    fi
    50    cd "${reldir}/etcd"
    51  
    52    # If a release version tag already exists, use it.
    53    local remote_tag_exists=$(git ls-remote origin "refs/tags/${RELEASE_VERSION}" | grep -c "${RELEASE_VERSION}")
    54    if [ ${remote_tag_exists} -gt 0 ]; then
    55      echo "Release version tag exists on remote. Checking out refs/tags/${RELEASE_VERSION}"
    56      git checkout -q "tags/${RELEASE_VERSION}"
    57    fi
    58  
    59    # Check go version.
    60    # download "yq" from https://github.com/mikefarah/yq
    61    local go_version="go$(yq read .travis.yml "go[0]")"
    62    local current_go_version=$(go version | awk '{ print $3 }')
    63    if [[ "${current_go_version}" != "${go_version}" ]]; then
    64      echo "Current go version is ${current_go_version}, but etcd ${RELEASE_VERSION} requires ${go_version} (see .travis.yml)."
    65      exit 1
    66    fi
    67  
    68    # If the release tag does not already exist remotely, create it.
    69    if [ ${remote_tag_exists} -eq 0 ]; then
    70      # Bump version/version.go to release version.
    71      local source_version=$(egrep "\s+Version\s*=" version/version.go | sed -e "s/.*\"\(.*\)\".*/\1/g")
    72      if [[ "${source_version}" != "${VERSION}" ]]; then
    73        source_minor_version=$(echo "${source_version}" | cut -d. -f 1-2)
    74        if [[ "${source_minor_version}" != "${MINOR_VERSION}" ]]; then
    75          echo "Wrong etcd minor version in version/version.go. Expected ${MINOR_VERSION} but got ${source_minor_version}. Aborting."
    76          exit 1
    77        fi
    78        echo "Updating version from ${source_version} to ${VERSION} in version/version.go"
    79        sed -i "s/${source_version}/${VERSION}/g" version/version.go
    80      fi
    81  
    82      echo "Building etcd and checking --version output"
    83      ./build
    84      local etcd_version=$(bin/etcd --version | grep "etcd Version" | awk '{ print $3 }')
    85      if [[ "${etcd_version}" != "${VERSION}" ]]; then
    86        echo "Wrong etcd version in version/version.go. Expected ${etcd_version} but got ${VERSION}. Aborting."
    87        exit 1
    88      fi
    89      echo "bin/etcd --version:"
    90      bin/etcd --version
    91      sleep 3
    92  
    93      if [[ ! -z $(git status -s) ]]; then
    94        echo "Committing version/version.go update."
    95        git add version/version.go
    96        git commit -m "version: bump up to ${VERSION}"
    97        git diff --staged
    98      fi
    99  
   100      # Push the version change if it's not already been pushed.
   101      if [ $(git rev-list --count "origin/${BRANCH}..${BRANCH}") -gt 0 ]; then
   102        read -p "Push version bump up to ${VERSION} to github.com/etcd-io/etcd [y/N]? " confirm
   103        [[ "${confirm,,}" == "y" ]] || exit 1
   104        git push
   105      fi
   106  
   107      # Tag release.
   108      if [ $(git tag --list | grep -c "${RELEASE_VERSION}") -gt 0 ]; then
   109        echo "Skipping tag step. git tag ${RELEASE_VERSION} already exists."
   110      else
   111        echo "Tagging release..."
   112        KEYID=$(gpg --list-keys --with-colons| awk -F: '/^pub:/ { print $5 }')
   113        if [[ -z "${KEYID}" ]]; then
   114          echo "Failed to load gpg key. Is gpg set up correctly for etcd releases?"
   115          exit 1
   116        fi
   117        git tag --local-user "${KEYID}" --sign "${RELEASE_VERSION}" --message "${RELEASE_VERSION}"
   118      fi
   119  
   120      # Verify the latest commit has the version tag
   121      local tag="$(git describe --exact-match HEAD)"
   122      if [ "${tag}" != "${RELEASE_VERSION}" ]; then
   123        echo "Error: Expected HEAD to be tagged with ${RELEASE_VERSION}, but 'git describe --exact-match HEAD' reported: ${tag}"
   124        exit 1
   125      fi
   126  
   127      # Verify the version tag is on the right branch
   128      local branch=$(git branch --contains "${RELEASE_VERSION}")
   129      if [ "${branch}" != "release-${MINOR_VERSION}" ]; then
   130        echo "Error: Git tag ${RELEASE_VERSION} should be on branch release-${MINOR_VERSION} but is on ${branch}"
   131        exit 1
   132      fi
   133  
   134      # Push the tag change if it's not already been pushed.
   135      read -p "Push etcd ${RELEASE_VERSION} tag [y/N]? " confirm
   136      [[ "${confirm,,}" == "y" ]] || exit 1
   137      git push origin "tags/${RELEASE_VERSION}"
   138    fi
   139  
   140    # Build release.
   141    # TODO: check the release directory for all required build artifacts.
   142    if [ -d release ]; then
   143      echo "Skpping release build step. /release directory already exists."
   144    else
   145      echo "Building release..."
   146      # Check for old and new names of the release build script.
   147      # TODO: Move the release script into this on as a function?
   148      if [ -f ./scripts/release.sh ]; then
   149        ./scripts/release.sh "${RELEASE_VERSION}"
   150      else
   151        ./scripts/build-release.sh "${RELEASE_VERSION}"
   152      fi
   153    fi
   154  
   155    # Sanity checks.
   156    ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version | grep -q "etcd Version: ${VERSION}" || true
   157    ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcdctl version | grep -q "etcdctl version: ${VERSION}" || true
   158    echo "./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version:"
   159    ./release/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd --version
   160    sleep 3
   161  
   162    # Upload artifacts.
   163    if [ "${NO_UPLOAD}" == 1 ]; then
   164      echo "Skipping artifact upload to gs://etcd. --no-upload flat is set."
   165    else
   166      read -p "Upload etcd ${RELEASE_VERSION} release artifacts to gs://etcd [y/N]? " confirm
   167      [[ "${confirm,,}" == "y" ]] || exit 1
   168      gsutil -m cp ./release/*.zip gs://etcd/${RELEASE_VERSION}/
   169      gsutil -m cp ./release/*.tar.gz gs://etcd/${RELEASE_VERSION}/
   170      gsutil -m acl ch -u allUsers:R -r gs://etcd/${RELEASE_VERSION}/
   171    fi
   172  
   173      # Push images.
   174    if [ "${NO_DOCKER_PUSH}" == 1 ]; then
   175      echo "Skipping docker push. --no-docker-push flat is set."
   176    else
   177      read -p "Publish etcd ${RELEASE_VERSION} docker images to quay.io [y/N]? " confirm
   178      [[ "${confirm,,}" == "y" ]] || exit 1
   179      for i in {1..5}; do
   180        docker login quay.io && break
   181        echo "login failed, retrying"
   182      done
   183      gcloud docker -- login -u _json_key -p "$(cat /etc/gcp-key-etcd-development.json)" https://gcr.io
   184  
   185      echo "Pushing container images to quay.io" ${RELEASE_VERSION}
   186      docker push quay.io/coreos/etcd:${RELEASE_VERSION}
   187  
   188      echo "Pushing container images to gcr.io" ${RELEASE_VERSION}
   189      gcloud docker -- push gcr.io/etcd-development/etcd:${RELEASE_VERSION}
   190  
   191      for TARGET_ARCH in "-arm64" "-ppc64le"; do
   192        echo "Pushing container images to quay.io" ${RELEASE_VERSION}${TARGET_ARCH}
   193        docker push quay.io/coreos/etcd:${RELEASE_VERSION}${TARGET_ARCH}
   194  
   195        echo "Pushing container images to gcr.io" ${RELEASE_VERSION}${TARGET_ARCH}
   196        gcloud docker -- push gcr.io/etcd-development/etcd:${RELEASE_VERSION}${TARGET_ARCH}
   197      done
   198  
   199      echo "Setting permissions using gsutil..."
   200      gsutil -m acl ch -u allUsers:R -r gs://artifacts.etcd-development.appspot.com
   201    fi
   202  
   203    ### Release validation
   204    mkdir -p downloads
   205  
   206    # Check image versions
   207    for IMAGE in "quay.io/coreos/etcd:${RELEASE_VERSION}" "gcr.io/etcd-development/etcd:${RELEASE_VERSION}"; do
   208      local image_version=$(docker run --rm "${IMAGE}" etcd --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]')
   209      if [ "${image_version}" != "${VERSION}" ]; then
   210        echo "Check failed: etcd --version output for ${IMAGE} is incorrect: ${image_version}"
   211        exit 1
   212      fi
   213    done
   214  
   215    # Check gsutil binary versions
   216    local BINARY_TGZ="etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64.tar.gz"
   217    gsutil cp "gs://etcd/${RELEASE_VERSION}/${BINARY_TGZ}" downloads
   218    tar -zx -C downloads -f "downloads/${BINARY_TGZ}"
   219    local binary_version=$("./downloads/etcd-${RELEASE_VERSION}-$(go env GOOS)-amd64/etcd" --version | grep "etcd Version" | awk -F: '{print $2}' | tr -d '[:space:]')
   220    if [ "${binary_version}" != "${VERSION}" ]; then
   221      echo "Check failed: etcd --version output for ${BINARY_TGZ} from gs://etcd/${RELEASE_VERSION} is incorrect: ${binary_version}"
   222      exit 1
   223    fi
   224  
   225    # TODO: signing process
   226    echo ""
   227    echo "WARNING: The release has not been signed and published to github. This must be done manually."
   228    echo ""
   229    echo "Success."
   230    exit 0
   231  }
   232  
   233  POSITIONAL=()
   234  NO_UPLOAD=0
   235  NO_DOCKER_PUSH=0
   236  
   237  while test $# -gt 0; do
   238          case "$1" in
   239            -h|--help)
   240              shift
   241              help
   242              exit 0
   243              ;;
   244            --no-upload)
   245              NO_UPLOAD=1
   246              shift
   247              ;;
   248            --no-docker-push)
   249              NO_DOCKER_PUSH=1
   250              shift
   251              ;;
   252            *)
   253              POSITIONAL+=("$1") # save it in an array for later
   254              shift # past argument
   255              ;;
   256          esac
   257  done
   258  set -- "${POSITIONAL[@]}" # restore positional parameters
   259  
   260  if [[ ! $# -eq 1 ]]; then
   261    help
   262    exit 1
   263  fi
   264  
   265  main $1