xref: /aosp_15_r20/external/tink/python/tools/distribution/create_release.sh (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang#!/bin/bash
2*e7b1675dSTing-Kang Chang# Copyright 2020 Google LLC
3*e7b1675dSTing-Kang Chang#
4*e7b1675dSTing-Kang Chang# Licensed under the Apache License, Version 2.0 (the "License");
5*e7b1675dSTing-Kang Chang# you may not use this file except in compliance with the License.
6*e7b1675dSTing-Kang Chang# You may obtain a copy of the License at
7*e7b1675dSTing-Kang Chang#
8*e7b1675dSTing-Kang Chang#      http://www.apache.org/licenses/LICENSE-2.0
9*e7b1675dSTing-Kang Chang#
10*e7b1675dSTing-Kang Chang# Unless required by applicable law or agreed to in writing, software
11*e7b1675dSTing-Kang Chang# distributed under the License is distributed on an "AS IS" BASIS,
12*e7b1675dSTing-Kang Chang# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7b1675dSTing-Kang Chang# See the License for the specific language governing permissions and
14*e7b1675dSTing-Kang Chang# limitations under the License.
15*e7b1675dSTing-Kang Chang################################################################################
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang# This script creates the release artifacts of Tink Python which includes a
18*e7b1675dSTing-Kang Chang# source distribution and binary wheels for Linux and macOS.  All Python tests
19*e7b1675dSTing-Kang Chang# are exectued for each binary wheel and the source distribution.
20*e7b1675dSTing-Kang Chang
21*e7b1675dSTing-Kang Changset -euox pipefail
22*e7b1675dSTing-Kang Chang
23*e7b1675dSTing-Kang Changdeclare -a PYTHON_VERSIONS=
24*e7b1675dSTing-Kang ChangPYTHON_VERSIONS+=("3.7")
25*e7b1675dSTing-Kang ChangPYTHON_VERSIONS+=("3.8")
26*e7b1675dSTing-Kang ChangPYTHON_VERSIONS+=("3.9")
27*e7b1675dSTing-Kang ChangPYTHON_VERSIONS+=("3.10")
28*e7b1675dSTing-Kang Changreadonly PYTHON_VERSIONS
29*e7b1675dSTing-Kang Chang
30*e7b1675dSTing-Kang Changreadonly PLATFORM="$(uname | tr '[:upper:]' '[:lower:]')"
31*e7b1675dSTing-Kang Chang
32*e7b1675dSTing-Kang Changexport TINK_PYTHON_ROOT_PATH="${PWD}"
33*e7b1675dSTing-Kang Changreadonly TINK_VERSION="$(grep ^TINK "${TINK_PYTHON_ROOT_PATH}/VERSION" \
34*e7b1675dSTing-Kang Chang  | awk '{gsub(/"/, "", $3); print $3}')"
35*e7b1675dSTing-Kang Chang
36*e7b1675dSTing-Kang Changreadonly IMAGE_NAME="quay.io/pypa/manylinux2014_x86_64"
37*e7b1675dSTing-Kang Changreadonly IMAGE_DIGEST="sha256:31d7d1cbbb8ea93ac64c3113bceaa0e9e13d65198229a25eee16dc70e8bf9cf7"
38*e7b1675dSTing-Kang Changreadonly IMAGE="${IMAGE_NAME}@${IMAGE_DIGEST}"
39*e7b1675dSTing-Kang Chang
40*e7b1675dSTing-Kang Chang#######################################
41*e7b1675dSTing-Kang Chang# Builds Tink Python built distribution (Wheel) [1].
42*e7b1675dSTing-Kang Chang#
43*e7b1675dSTing-Kang Chang# This function must be called from within the Tink Python's root folder.
44*e7b1675dSTing-Kang Chang#
45*e7b1675dSTing-Kang Chang# [1] https://packaging.python.org/en/latest/glossary/#term-Built-Distribution
46*e7b1675dSTing-Kang Chang# Globals:
47*e7b1675dSTing-Kang Chang#   None
48*e7b1675dSTing-Kang Chang# Arguments:
49*e7b1675dSTing-Kang Chang#   None
50*e7b1675dSTing-Kang Chang#######################################
51*e7b1675dSTing-Kang Chang__create_and_test_wheels_for_linux() {
52*e7b1675dSTing-Kang Chang  echo "### Building and testing Linux binary wheels ###"
53*e7b1675dSTing-Kang Chang  # Use signatures for getting images from registry (see
54*e7b1675dSTing-Kang Chang  # https://docs.docker.com/engine/security/trust/content_trust/).
55*e7b1675dSTing-Kang Chang  export DOCKER_CONTENT_TRUST=1
56*e7b1675dSTing-Kang Chang
57*e7b1675dSTing-Kang Chang  # We use setup.py to build wheels; setup.py makes changes to the WORKSPACE
58*e7b1675dSTing-Kang Chang  # file so we save a copy for backup.
59*e7b1675dSTing-Kang Chang  cp WORKSPACE WORKSPACE.bak
60*e7b1675dSTing-Kang Chang
61*e7b1675dSTing-Kang Chang  local -r tink_base_dir="/tmp/tink"
62*e7b1675dSTing-Kang Chang  local -r tink_py_relative_path="${PWD##*/}"
63*e7b1675dSTing-Kang Chang  local -r workdir="${tink_base_dir}/${tink_py_relative_path}"
64*e7b1675dSTing-Kang Chang  # Build binary wheels.
65*e7b1675dSTing-Kang Chang  docker run \
66*e7b1675dSTing-Kang Chang    --volume "${TINK_PYTHON_ROOT_PATH}/..:${tink_base_dir}" \
67*e7b1675dSTing-Kang Chang    --workdir "${workdir}" \
68*e7b1675dSTing-Kang Chang    -e TINK_PYTHON_SETUPTOOLS_OVERRIDE_BASE_PATH="${tink_base_dir}" \
69*e7b1675dSTing-Kang Chang    "${IMAGE}" \
70*e7b1675dSTing-Kang Chang    "${workdir}/tools/distribution/build_linux_binary_wheels.sh"
71*e7b1675dSTing-Kang Chang
72*e7b1675dSTing-Kang Chang  ## Test binary wheels.
73*e7b1675dSTing-Kang Chang  docker run \
74*e7b1675dSTing-Kang Chang    --volume "${TINK_PYTHON_ROOT_PATH}/..:${tink_base_dir}" \
75*e7b1675dSTing-Kang Chang    --workdir "${workdir}" \
76*e7b1675dSTing-Kang Chang    "${IMAGE}" \
77*e7b1675dSTing-Kang Chang    "${workdir}/tools/distribution/test_linux_binary_wheels.sh"
78*e7b1675dSTing-Kang Chang
79*e7b1675dSTing-Kang Chang  # Docker runs as root so we transfer ownership to the non-root user.
80*e7b1675dSTing-Kang Chang  sudo chown -R "$(id -un):$(id -gn)" "${TINK_PYTHON_ROOT_PATH}"
81*e7b1675dSTing-Kang Chang  # Restore the original WORKSPACE.
82*e7b1675dSTing-Kang Chang  mv WORKSPACE.bak WORKSPACE
83*e7b1675dSTing-Kang Chang}
84*e7b1675dSTing-Kang Chang
85*e7b1675dSTing-Kang Chang#######################################
86*e7b1675dSTing-Kang Chang# Builds Tink Python source distribution [1].
87*e7b1675dSTing-Kang Chang#
88*e7b1675dSTing-Kang Chang# This function must be called from within the Tink Python's root folder.
89*e7b1675dSTing-Kang Chang#
90*e7b1675dSTing-Kang Chang# [1] https://packaging.python.org/en/latest/glossary/#term-Source-Distribution-or-sdist
91*e7b1675dSTing-Kang Chang# Globals:
92*e7b1675dSTing-Kang Chang#   PYTHON_VERSIONS
93*e7b1675dSTing-Kang Chang# Arguments:
94*e7b1675dSTing-Kang Chang#   None
95*e7b1675dSTing-Kang Chang#######################################
96*e7b1675dSTing-Kang Chang__create_and_test_sdist_for_linux() {
97*e7b1675dSTing-Kang Chang  echo "### Building and testing Linux source distribution ###"
98*e7b1675dSTing-Kang Chang  local sorted=( $( echo "${PYTHON_VERSIONS[@]}" \
99*e7b1675dSTing-Kang Chang    | xargs -n1 | sort -V | xargs ) )
100*e7b1675dSTing-Kang Chang  local latest="${sorted[${#sorted[@]}-1]}"
101*e7b1675dSTing-Kang Chang  enable_py_version "${latest}"
102*e7b1675dSTing-Kang Chang
103*e7b1675dSTing-Kang Chang  # Patch the workspace to use http_archive rules which specify the release tag.
104*e7b1675dSTing-Kang Chang  #
105*e7b1675dSTing-Kang Chang  # This is done so that an already patched version of WORKSPACE is present in
106*e7b1675dSTing-Kang Chang  # the sdist. Then, when building from the sdist, the default patching logic
107*e7b1675dSTing-Kang Chang  # in performed by setup.py will be a no-op.
108*e7b1675dSTing-Kang Chang  #
109*e7b1675dSTing-Kang Chang  # TODO(b/281635529): Use a container for a more hermetic testing environment.
110*e7b1675dSTing-Kang Chang  cp WORKSPACE WORKSPACE.bak
111*e7b1675dSTing-Kang Chang
112*e7b1675dSTing-Kang Chang  # Build source distribution.
113*e7b1675dSTing-Kang Chang  TINK_PYTHON_SETUPTOOLS_TAGGED_VERSION="${TINK_VERSION}" \
114*e7b1675dSTing-Kang Chang    python3 setup.py sdist --owner=root --group=root
115*e7b1675dSTing-Kang Chang  local sdist_filename="tink-${TINK_VERSION}.tar.gz"
116*e7b1675dSTing-Kang Chang  cp "dist/${sdist_filename}" release/
117*e7b1675dSTing-Kang Chang
118*e7b1675dSTing-Kang Chang  # Restore the original WORKSPACE.
119*e7b1675dSTing-Kang Chang  mv WORKSPACE.bak WORKSPACE
120*e7b1675dSTing-Kang Chang
121*e7b1675dSTing-Kang Chang  # Test install from source distribution.
122*e7b1675dSTing-Kang Chang  python3 --version
123*e7b1675dSTing-Kang Chang  python3 -m pip list
124*e7b1675dSTing-Kang Chang  # Install Tink dependencies.
125*e7b1675dSTing-Kang Chang  python3 -m pip install --require-hashes -r requirements.txt
126*e7b1675dSTing-Kang Chang  python3 -m pip install --no-deps --no-index -v "release/${sdist_filename}"
127*e7b1675dSTing-Kang Chang  python3 -m pip list
128*e7b1675dSTing-Kang Chang  find tink/ -not -path "*cc/pybind*" -type f -name "*_test.py" -print0 \
129*e7b1675dSTing-Kang Chang    | xargs -0 -n1 python3
130*e7b1675dSTing-Kang Chang}
131*e7b1675dSTing-Kang Chang
132*e7b1675dSTing-Kang Chang#######################################
133*e7b1675dSTing-Kang Chang# Creates a Tink Python distribution for Linux.
134*e7b1675dSTing-Kang Chang#
135*e7b1675dSTing-Kang Chang# This function must be called from within the Tink Python's root folder.
136*e7b1675dSTing-Kang Chang#
137*e7b1675dSTing-Kang Chang# Globals:
138*e7b1675dSTing-Kang Chang#   None
139*e7b1675dSTing-Kang Chang# Arguments:
140*e7b1675dSTing-Kang Chang#   None
141*e7b1675dSTing-Kang Chang#######################################
142*e7b1675dSTing-Kang Changcreate_distribution_for_linux() {
143*e7b1675dSTing-Kang Chang  __create_and_test_wheels_for_linux
144*e7b1675dSTing-Kang Chang  __create_and_test_sdist_for_linux
145*e7b1675dSTing-Kang Chang}
146*e7b1675dSTing-Kang Chang
147*e7b1675dSTing-Kang Chang#######################################
148*e7b1675dSTing-Kang Chang# Creates a Tink Python distribution for MacOS.
149*e7b1675dSTing-Kang Chang#
150*e7b1675dSTing-Kang Chang# This function must be called from within the Tink Python's root folder.
151*e7b1675dSTing-Kang Chang#
152*e7b1675dSTing-Kang Chang# Globals:
153*e7b1675dSTing-Kang Chang#   PYTHON_VERSIONS
154*e7b1675dSTing-Kang Chang# Arguments:
155*e7b1675dSTing-Kang Chang#   None
156*e7b1675dSTing-Kang Chang#######################################
157*e7b1675dSTing-Kang Changcreate_distribution_for_macos() {
158*e7b1675dSTing-Kang Chang  echo "### Building macOS binary wheels ###"
159*e7b1675dSTing-Kang Chang
160*e7b1675dSTing-Kang Chang  for v in "${PYTHON_VERSIONS[@]}"; do
161*e7b1675dSTing-Kang Chang    enable_py_version "${v}"
162*e7b1675dSTing-Kang Chang
163*e7b1675dSTing-Kang Chang    # Build binary wheel.
164*e7b1675dSTing-Kang Chang    python3 -m pip wheel -w release .
165*e7b1675dSTing-Kang Chang
166*e7b1675dSTing-Kang Chang    # Test binary wheel.
167*e7b1675dSTing-Kang Chang    # TODO(ckl): Implement test.
168*e7b1675dSTing-Kang Chang  done
169*e7b1675dSTing-Kang Chang}
170*e7b1675dSTing-Kang Chang
171*e7b1675dSTing-Kang Changenable_py_version() {
172*e7b1675dSTing-Kang Chang  # A partial version number (e.g. "3.9").
173*e7b1675dSTing-Kang Chang  local partial_version="$1"
174*e7b1675dSTing-Kang Chang
175*e7b1675dSTing-Kang Chang  # The latest installed Python version that matches the partial version number
176*e7b1675dSTing-Kang Chang  # (e.g. "3.9.5").
177*e7b1675dSTing-Kang Chang  local version="$(pyenv versions --bare | grep "${partial_version}" | tail -1)"
178*e7b1675dSTing-Kang Chang
179*e7b1675dSTing-Kang Chang  # Set current Python version via environment variable.
180*e7b1675dSTing-Kang Chang  pyenv shell "${version}"
181*e7b1675dSTing-Kang Chang
182*e7b1675dSTing-Kang Chang  # Update environment.
183*e7b1675dSTing-Kang Chang  python3 -m pip install --require-hashes -r \
184*e7b1675dSTing-Kang Chang    "${TINK_PYTHON_ROOT_PATH}/tools/distribution/requirements.txt"
185*e7b1675dSTing-Kang Chang}
186*e7b1675dSTing-Kang Chang
187*e7b1675dSTing-Kang Changmain() {
188*e7b1675dSTing-Kang Chang  eval "$(pyenv init -)"
189*e7b1675dSTing-Kang Chang  mkdir -p release
190*e7b1675dSTing-Kang Chang
191*e7b1675dSTing-Kang Chang  if [[ "${PLATFORM}" == 'linux' ]]; then
192*e7b1675dSTing-Kang Chang    create_distribution_for_linux
193*e7b1675dSTing-Kang Chang  elif [[ "${PLATFORM}" == 'darwin' ]]; then
194*e7b1675dSTing-Kang Chang    create_distribution_for_macos
195*e7b1675dSTing-Kang Chang  else
196*e7b1675dSTing-Kang Chang    echo "${PLATFORM} is not a supported platform."
197*e7b1675dSTing-Kang Chang    exit 1
198*e7b1675dSTing-Kang Chang  fi
199*e7b1675dSTing-Kang Chang}
200*e7b1675dSTing-Kang Chang
201*e7b1675dSTing-Kang Changmain "$@"
202