1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
#!/bin/bash -xe
# Release packages to PyPI
if [ "$RELEASE_DIR" = "" ]; then
echo Please run this script through the tools/release.sh wrapper script or set the environment
echo variable RELEASE_DIR to the directory where the release should be built.
exit 1
fi
ExitWarning() {
exit_status="$?"
if [ "$exit_status" != 0 ]; then
# Don't print each command before executing it because it will disrupt
# the desired output.
set +x
echo '******************************'
echo '* *'
echo '* THE RELEASE SCRIPT FAILED! *'
echo '* *'
echo '******************************'
set -x
fi
exit "$exit_status"
}
trap ExitWarning EXIT
version="$1"
echo Releasing production version "$version"...
nextversion="$2"
RELEASE_BRANCH="candidate-$version"
# If RELEASE_GPG_KEY isn't set, determine the key to use.
if [ "$RELEASE_GPG_KEY" = "" ]; then
TRUSTED_KEYS="
BF6BCFC89E90747B9A680FD7B6029E8500F7DB16
86379B4F0AF371B50CD9E5FF3402831161D1D280
20F201346BF8F3F455A73F9A780CC99432A28621
F2871B4152AE13C49519111F447BF683AA3B26C3
"
for key in $TRUSTED_KEYS; do
if gpg --with-colons --card-status | grep -q "$key"; then
RELEASE_GPG_KEY="$key"
break
fi
done
if [ "$RELEASE_GPG_KEY" = "" ]; then
echo A trusted PGP key was not found on your PGP card.
exit 1
fi
fi
# Needed to fix problems with git signatures and pinentry
export GPG_TTY=$(tty)
# port for a local Python Package Index (used in testing)
PORT=${PORT:-1234}
# subpackages to be released (the way the script thinks about them)
SUBPKGS_NO_CERTBOT="acme certbot-apache certbot-nginx certbot-dns-cloudflare \
certbot-dns-digitalocean certbot-dns-dnsimple certbot-dns-dnsmadeeasy \
certbot-dns-gehirn certbot-dns-google certbot-dns-linode certbot-dns-luadns \
certbot-dns-nsone certbot-dns-ovh certbot-dns-rfc2136 certbot-dns-route53 \
certbot-dns-sakuracloud"
SUBPKGS="certbot $SUBPKGS_NO_CERTBOT"
# certbot_compatibility_test is not packaged because:
# - it is not meant to be used by anyone else than Certbot devs
# - it causes problems when running pytest - the latter tries to
# run everything that matches test*, while there are no unittests
# there
tag="v$version"
built_package_dir="packages"
if [ -d "$built_package_dir" ]; then
echo "there shouldn't already be a $built_package_dir directory!"
echo "if it's not important, maybe delete it and try running the script again?"
exit 1
fi
git tag --delete "$tag" || true
tmpvenv=$(mktemp -d)
python3 -m venv "$tmpvenv"
. $tmpvenv/bin/activate
# update packaging tools to their pinned versions
tools/pip_install.py build towncrier uv virtualenv
root_without_le="$version.$$"
root="$RELEASE_DIR/le.$root_without_le"
echo "Cloning into fresh copy at $root" # clean repo = no artifacts
git clone . $root
git rev-parse HEAD
cd $root
if [ "$RELEASE_BRANCH" != "candidate-$version" ] ; then
git branch -f "$RELEASE_BRANCH"
fi
git checkout "$RELEASE_BRANCH"
# Update changelog. `--yes` automatically clears out older newsfragments,
# and all of towncrier's changes are staged for commit when it's done
towncrier build --version "$version" --yes
git commit -m "Update changelog for $version release"
SetVersion() {
ver="$1"
# bumping Certbot's version number is done differently
for pkg_dir in $SUBPKGS_NO_CERTBOT certbot-compatibility-test certbot-ci letstest
do
setup_file="$pkg_dir/setup.py"
if [ $(grep -c '^version' "$setup_file") != 1 ]; then
echo "Unexpected count of version variables in $setup_file"
exit 1
fi
sed -i "s/^version.*/version = '$ver'/" $pkg_dir/setup.py
done
init_file="certbot/src/certbot/__init__.py"
if [ $(grep -c '^__version' "$init_file") != 1 ]; then
echo "Unexpected count of __version variables in $init_file"
exit 1
fi
sed -i "s/^__version.*/__version__ = '$ver'/" "$init_file"
git add $SUBPKGS certbot-compatibility-test certbot-ci letstest
}
SetVersion "$version"
# Unset CERTBOT_OLDEST to prevent wheels from being built improperly due to
# conditionals like the one found in certbot-dns-dnsimple's setup.py file.
unset CERTBOT_OLDEST
echo "Preparing sdists and wheels"
for pkg_dir in $SUBPKGS
do
cd $pkg_dir
rm -rf build dist
# It's not strictly necessary, but using uv to install build dependencies speeds things up a
# little bit.
python -m build --installer uv
cd -
done
mkdir "$built_package_dir"
for pkg_dir in $SUBPKGS
do
mv "$pkg_dir"/dist/* "$built_package_dir"
done
cd "$built_package_dir"
echo "Generating checksum file and signing it"
sha256sum *.tar.gz > SHA256SUMS
gpg -u "$RELEASE_GPG_KEY" --detach-sign --armor --sign --digest-algo sha256 SHA256SUMS
git add *.tar.gz SHA256SUMS*
echo "Installing packages to generate documentation"
# cd .. is NOT done on purpose: we make sure that all subpackages are
# installed from local archives rather than current directory (repo root)
VIRTUALENV_NO_DOWNLOAD=1 virtualenv ../venv
. ../venv/bin/activate
pip install -U setuptools
pip install -U pip
# This creates a string like "acme==a.b.c certbot==a.b.c ..." which can be used
# with pip to ensure the correct versions of our packages installed.
subpkgs_with_version=""
for pkg in $SUBPKGS; do
subpkgs_with_version="$subpkgs_with_version $pkg==$version"
done
# Now, use our local archives. Disable cache so we get the correct packages even if
# we (or our dependencies) have conditional dependencies implemented with if
# statements in setup.py and we have cached wheels lying around that would cause
# those ifs to not be evaluated.
python ../tools/pip_install.py \
--no-cache-dir \
--find-links . \
$subpkgs_with_version
cd ~-
# get a snapshot of the CLI help for the docs
# We set CERTBOT_DOCS to use dummy values in example user-agent string.
CERTBOT_DOCS=1 certbot --help all > certbot/docs/cli-help.txt
jws --help > acme/docs/jws-help.txt
deactivate
git add certbot/docs/cli-help.txt
while ! git commit --gpg-sign="$RELEASE_GPG_KEY" -m "Release $version"; do
echo "Unable to sign the release commit using git."
echo "You may have to configure git to use gpg by running:"
echo 'git config --global gpg.program $(command -v gpg)'
read -p "Press enter to try signing again."
done
git tag --local-user "$RELEASE_GPG_KEY" --sign --message "Release $version" "$tag"
git rm --cached -r "$built_package_dir"
git commit -m "Remove built packages from git"
if [ "$RELEASE_BRANCH" = candidate-"$version" ] ; then
SetVersion "$nextversion".dev0
git commit -m "Bump version to $nextversion"
fi
|