blob: fe71458fc0c942d8c2a8fc97d22c0062383d9341 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2019 The TensorFlow Authors. All Rights Reserved.
#
# 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.
# ==============================================================================
# External `common.sh`
# Keep in sync with tensorflow_estimator and configure.py.
# LINT.IfChange
LATEST_BAZEL_VERSION=3.1.0
# LINT.ThenChange(
# //tensorflow/opensource_only/configure.py,
# //tensorflow_estimator/google/kokoro/common.sh,
# //tensorflow/tools/ci_build/install/install_bazel.sh,
# //tensorflow/tools/ci_build/install/install_bazel_from_source.sh)
# Run flaky functions with retries.
# run_with_retry cmd
function run_with_retry {
eval "$1"
# If the command fails retry again in 60 seconds.
if [[ $? -ne 0 ]]; then
sleep 60
eval "$1"
fi
}
function die() {
echo "$@" 1>&2 ; exit 1;
}
# A small utility to run the command and only print logs if the command fails.
# On success, all logs are hidden.
function readable_run {
# Disable debug mode to avoid printing of variables here.
set +x
result=$("$@" 2>&1) || die "$result"
echo "$@"
echo "Command completed successfully at $(date)"
set -x
}
# LINT.IfChange
# Redirect bazel output dir b/73748835
function set_bazel_outdir {
mkdir -p /tmpfs/bazel_output
export TEST_TMPDIR=/tmpfs/bazel_output
}
# Downloads bazelisk to ~/bin as `bazel`.
function install_bazelisk {
date
case "$(uname -s)" in
Darwin) local name=bazelisk-darwin-amd64 ;;
Linux) local name=bazelisk-linux-amd64 ;;
*) die "Unknown OS: $(uname -s)" ;;
esac
mkdir -p "$HOME/bin"
wget --no-verbose -O "$HOME/bin/bazel" \
"https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/$name"
chmod u+x "$HOME/bin/bazel"
if [[ ! ":$PATH:" =~ :"$HOME"/bin/?: ]]; then
PATH="$HOME/bin:$PATH"
fi
set_bazel_outdir
which bazel
bazel version
date
}
# Install the given bazel version on linux
function update_bazel_linux {
if [[ -z "$1" ]]; then
BAZEL_VERSION=${LATEST_BAZEL_VERSION}
else
BAZEL_VERSION=$1
fi
rm -rf ~/bazel
mkdir ~/bazel
pushd ~/bazel
readable_run wget https://github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh
chmod +x bazel-*.sh
./bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh --user
rm bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh
popd
PATH="/home/kbuilder/bin:$PATH"
set_bazel_outdir
which bazel
bazel version
}
# LINT.ThenChange(
# //tensorflow_estimator/google/kokoro/common.sh)
function install_ubuntu_16_pip_deps {
PIP_CMD="pip"
while true; do
if [[ -z "${1}" ]]; then
break
fi
if [[ "$1" == "pip"* ]]; then
PIP_CMD="$1"
fi
shift
done
# LINT.IfChange(linux_pip_installations)
# To have reproducible builds, these dependencies should be pinned always.
# Prefer pinning to the same version as in setup.py
# First, upgrade pypi wheels
"${PIP_CMD}" install --user --upgrade setuptools pip wheel
# Now, install the deps, as listed in setup.py
"${PIP_CMD}" install --user 'absl-py ~= 0.10'
"${PIP_CMD}" install --user 'astunparse ~= 1.6.3'
"${PIP_CMD}" install --user 'flatbuffers ~= 1.12.0'
"${PIP_CMD}" install --user 'google_pasta ~= 0.2'
"${PIP_CMD}" install --user 'h5py ~= 3.1.0'
"${PIP_CMD}" install --user 'keras_preprocessing ~= 1.1.2'
"${PIP_CMD}" install --user 'numpy ~= 1.19.2'
"${PIP_CMD}" install --user 'opt_einsum ~= 3.3.0'
"${PIP_CMD}" install --user 'protobuf >= 3.9.2'
"${PIP_CMD}" install --user 'six ~= 1.15.0'
"${PIP_CMD}" install --user 'termcolor ~= 1.1.0'
"${PIP_CMD}" install --user 'typing_extensions ~= 3.7.4'
"${PIP_CMD}" install --user 'wheel ~= 0.35'
"${PIP_CMD}" install --user 'wrapt ~= 1.12.1'
# We need to pin gast dependency exactly
"${PIP_CMD}" install --user 'gast == 0.3.3'
# Finally, install tensorboard and estimator
# Note that here we want the latest version that matches (b/156523241)
"${PIP_CMD}" install --user --upgrade --force-reinstall 'tb-nightly ~= 2.4.0.a'
"${PIP_CMD}" install --user --upgrade --force-reinstall 'tensorflow_estimator ~= 2.3.0'
# Test dependencies
"${PIP_CMD}" install --user 'grpcio ~= 1.32.0'
"${PIP_CMD}" install --user 'portpicker ~= 1.3.1'
"${PIP_CMD}" install --user 'scipy ~= 1.5.2'
# LINT.ThenChange(:mac_pip_installations)
# Need to be addressed later. Unblocking 2.4 branchcut
"${PIP_CMD}" install --user 'PyYAML ~= 5.3.1'
}
# TODO(amitpatankar): Move this function logic into install_macos_pip_deps.
function install_macos_pip_deps_virtualenv {
PIP_CMD="pip"
${PIP_CMD} install --upgrade setuptools pip wheel
# Now, install the deps, as listed in setup.py
${PIP_CMD} install 'absl-py ~= 0.10'
${PIP_CMD} install 'astunparse ~= 1.6.3'
${PIP_CMD} install 'flatbuffers ~= 1.12.0'
${PIP_CMD} install 'google_pasta ~= 0.2'
${PIP_CMD} install 'h5py ~= 3.1.0'
${PIP_CMD} install 'keras_preprocessing ~= 1.1.2'
${PIP_CMD} install 'numpy ~= 1.19.2'
${PIP_CMD} install 'opt_einsum ~= 3.3.0'
${PIP_CMD} install 'protobuf >= 3.9.2'
${PIP_CMD} install 'six ~= 1.15.0'
${PIP_CMD} install 'termcolor ~= 1.1.0'
${PIP_CMD} install 'typing_extensions ~= 3.7.4'
${PIP_CMD} install 'wheel ~= 0.35'
${PIP_CMD} install 'wrapt ~= 1.12.1'
# We need to pin gast dependency exactly
${PIP_CMD} install 'gast == 0.3.3'
# Finally, install tensorboard and estimator
# Note that here we want the latest version that matches (b/156523241)
${PIP_CMD} install --upgrade --force-reinstall 'tb-nightly ~= 2.4.0.a'
${PIP_CMD} install --upgrade --force-reinstall 'tensorflow_estimator ~= 2.3.0'
# Test dependencies
${PIP_CMD} install 'grpcio ~= 1.32.0'
${PIP_CMD} install 'portpicker ~= 1.3.1'
${PIP_CMD} install 'scipy ~= 1.5.2'
${PIP_CMD} install 'twine ~= 3.2.0'
}
function install_macos_pip_deps {
# TODO(mihaimaruseac): Remove need for sudo, then this can be merged with
# above (probably needs to convert to venv too).
SUDO_CMD=""
PIP_CMD="pip"
while true; do
if [[ -z "${1}" ]]; then
break
fi
if [[ "$1" == "sudo" ]]; then
SUDO_CMD="sudo "
elif [[ "$1" == "pip3.7" ]]; then
PIP_CMD="python3.7 -m pip"
SUDO_CMD="sudo -H "
elif [[ "$1" == "pip"* ]]; then
PIP_CMD="$1"
fi
shift
done
# LINT.IfChange(mac_pip_installations)
# To have reproducible builds, these dependencies should be pinned always.
# Prefer pinning to the same version as in setup.py
# First, upgrade pypi wheels
${PIP_CMD} install --user --upgrade setuptools pip wheel
# Now, install the deps, as listed in setup.py
${PIP_CMD} install --user 'absl-py ~= 0.10'
${PIP_CMD} install --user 'astunparse ~= 1.6.3'
${PIP_CMD} install --user 'flatbuffers ~= 1.12.0'
${PIP_CMD} install --user 'google_pasta ~= 0.2'
${PIP_CMD} install --user 'h5py ~= 3.1.0'
${PIP_CMD} install --user 'keras_preprocessing ~= 1.1.2'
${PIP_CMD} install --user 'numpy ~= 1.19.2'
${PIP_CMD} install --user 'opt_einsum ~= 3.3.0'
${PIP_CMD} install --user 'protobuf >= 3.9.2'
${PIP_CMD} install --user 'six ~= 1.15.0'
${PIP_CMD} install --user 'termcolor ~= 1.1.0'
${PIP_CMD} install --user 'typing_extensions ~= 3.7.4'
${PIP_CMD} install --user 'wheel ~= 0.35'
${PIP_CMD} install --user 'wrapt ~= 1.12.1'
# We need to pin gast dependency exactly
${PIP_CMD} install --user 'gast == 0.3.3'
# Finally, install tensorboard and estimator
# Note that here we want the latest version that matches (b/156523241)
${PIP_CMD} install --user --upgrade --force-reinstall 'tb-nightly ~= 2.4.0.a'
${PIP_CMD} install --user --upgrade --force-reinstall 'tensorflow_estimator ~= 2.3.0'
# Test dependencies
${PIP_CMD} install --user 'grpcio ~= 1.32.0'
${PIP_CMD} install --user 'portpicker ~= 1.3.1'
${PIP_CMD} install --user 'scipy ~= 1.5.2'
${PIP_CMD} install --user 'twine ~= 3.2.0'
# LINT.ThenChange(:linux_pip_installations)
}
function maybe_skip_v1 {
# If we are building with v2 by default, skip tests with v1only tag.
if grep -q "build --config=v2" ".bazelrc"; then
echo ",-v1only"
else
echo ""
fi
}
# Copy and rename a wheel to a new project name.
# Usage: copy_to_new_project_name <whl_path> <new_project_name>, for example
# copy_to_new_project_name test_dir/tf_nightly-1.15.0.dev20190813-cp35-cp35m-manylinux2010_x86_64.whl tf_nightly_cpu
# will create a wheel with the same tags, but new project name under the same
# directory at
# test_dir/tf_nightly_cpu-1.15.0.dev20190813-cp35-cp35m-manylinux2010_x86_64.whl
function copy_to_new_project_name {
WHL_PATH="$1"
NEW_PROJECT_NAME="$2"
PYTHON_CMD="$3"
ORIGINAL_WHL_NAME=$(basename "${WHL_PATH}")
ORIGINAL_WHL_DIR=$(realpath "$(dirname "${WHL_PATH}")")
ORIGINAL_PROJECT_NAME="$(echo "${ORIGINAL_WHL_NAME}" | cut -d '-' -f 1)"
FULL_TAG="$(echo "${ORIGINAL_WHL_NAME}" | cut -d '-' -f 2-)"
NEW_WHL_NAME="${NEW_PROJECT_NAME}-${FULL_TAG}"
VERSION="$(echo "${FULL_TAG}" | cut -d '-' -f 1)"
ORIGINAL_WHL_DIR_PREFIX="${ORIGINAL_PROJECT_NAME}-${VERSION}"
NEW_WHL_DIR_PREFIX="${NEW_PROJECT_NAME}-${VERSION}"
TMP_DIR="$(mktemp -d)"
${PYTHON_CMD} -m wheel unpack "${WHL_PATH}"
mv "${ORIGINAL_WHL_DIR_PREFIX}" "${TMP_DIR}"
pushd "${TMP_DIR}/${ORIGINAL_WHL_DIR_PREFIX}"
mv "${ORIGINAL_WHL_DIR_PREFIX}.dist-info" "${NEW_WHL_DIR_PREFIX}.dist-info"
if [[ -d "${ORIGINAL_WHL_DIR_PREFIX}.data" ]]; then
mv "${ORIGINAL_WHL_DIR_PREFIX}.data" "${NEW_WHL_DIR_PREFIX}.data"
fi
ORIGINAL_PROJECT_NAME_DASH="${ORIGINAL_PROJECT_NAME//_/-}"
NEW_PROJECT_NAME_DASH="${NEW_PROJECT_NAME//_/-}"
# We need to change the name in the METADATA file, but we need to ensure that
# all other occurences of the name stay the same, otherwise things such as
# URLs and depedencies might be broken (for example, replacing without care
# might transform a `tensorflow_estimator` dependency into
# `tensorflow_gpu_estimator`, which of course does not exist -- except by
# manual upload of a manually altered `tensorflow_estimator` package)
sed -i.bak "s/Name: ${ORIGINAL_PROJECT_NAME_DASH}/Name: ${NEW_PROJECT_NAME_DASH}/g" "${NEW_WHL_DIR_PREFIX}.dist-info/METADATA"
${PYTHON_CMD} -m wheel pack .
mv *.whl "${ORIGINAL_WHL_DIR}"
popd
rm -rf "${TMP_DIR}"
}
# Create minimalist test XML for web view. It includes the pass/fail status
# of each target, without including errors or stacktraces.
# Remember to "set +e" before calling bazel or we'll only generate the XML for
# passing runs.
function test_xml_summary {
set +x
set +e
mkdir -p "${KOKORO_ARTIFACTS_DIR}/${KOKORO_JOB_NAME}/summary"
# First build the repeated inner XML blocks, since the header block needs to
# report the number of test cases / failures / errors.
# TODO(rsopher): handle build breakages
# TODO(rsopher): extract per-test times as well
TESTCASE_XML="$(sed -n '/INFO:\ Build\ completed/,/INFO:\ Build\ completed/p' \
/tmpfs/kokoro_build.log \
| grep -E '(PASSED|FAILED|TIMEOUT)\ in' \
| while read -r line; \
do echo '<testcase name="'"$(echo "${line}" | tr -s ' ' | cut -d ' ' -f 1)"\
'" status="run" classname="" time="0">'"$( \
case "$(echo "${line}" | tr -s ' ' | cut -d ' ' -f 2)" in \
FAILED) echo '<failure message="" type=""/>' ;; \
TIMEOUT) echo '<failure message="timeout" type=""/>' ;; \
esac; \
)"'</testcase>'; done; \
)"
NUMBER_OF_TESTS="$(echo "${TESTCASE_XML}" | wc -l)"
NUMBER_OF_FAILURES="$(echo "${TESTCASE_XML}" | grep -c '<failure')"
echo '<?xml version="1.0" encoding="UTF-8"?>'\
'<testsuites name="1" tests="1" failures="0" errors="0" time="0">'\
'<testsuite name="Kokoro Summary" tests="'"${NUMBER_OF_TESTS}"\
'" failures="'"${NUMBER_OF_FAILURES}"'" errors="0" time="0">'\
"${TESTCASE_XML}"'</testsuite></testsuites>'\
> "${KOKORO_ARTIFACTS_DIR}/${KOKORO_JOB_NAME}/summary/sponge_log.xml"
}
# Create minimalist test XML for web view, then exit.
# Ends script with value of previous command, meant to be called immediately
# after bazel as the last call in the build script.
function test_xml_summary_exit {
RETVAL=$?
test_xml_summary
exit "${RETVAL}"
}