diff options
| author | Natalia <124304+nessita@users.noreply.github.com> | 2026-03-09 10:50:44 -0300 |
|---|---|---|
| committer | Natalia <124304+nessita@users.noreply.github.com> | 2026-03-16 22:09:17 -0300 |
| commit | 3d930a9f57f553228a9bec22e64bc183f802e461 (patch) | |
| tree | 6ada21a1505fd3aa1da3b00aa1204d660aa34512 | |
| parent | b787274edebfd08c52acd0eda1f826b2cad79466 (diff) | |
[6.0.x] Combined scripts confirm_release.sh and test_new_version.sh into verify_release.sh.
This reuses the same download for both artifacts and checks both GPG
signature and minimal correctness in the same script. Docs and script
do_django_release.py were updated.
Backport of 3abf89887993140d28676f26420ee0d46a617f51 from main.
| -rw-r--r-- | docs/internals/howto-release-django.txt | 10 | ||||
| -rwxr-xr-x | scripts/confirm_release.sh | 57 | ||||
| -rwxr-xr-x | scripts/do_django_release.py | 9 | ||||
| -rwxr-xr-x | scripts/test_new_version.sh | 48 | ||||
| -rwxr-xr-x | scripts/verify_release.sh | 95 |
5 files changed, 100 insertions, 119 deletions
diff --git a/docs/internals/howto-release-django.txt b/docs/internals/howto-release-django.txt index 5425f5f43c..90c627a40e 100644 --- a/docs/internals/howto-release-django.txt +++ b/docs/internals/howto-release-django.txt @@ -479,17 +479,11 @@ Building the artifacts $ PGP_KEY_ID=<key-id> PGP_KEY_URL=<key-url> DEST_FOLDER=~/releases scripts/do_django_release.py - * Test new version script: + * Verify the release (after artifacts were uploaded): .. code-block:: shell - $ VERSION=5.2.1 scripts/test_new_version.sh - - * Confirm release signature script: - - .. code-block:: shell - - $ VERSION=5.2.1 scripts/confirm_release.sh + $ VERSION=5.2.1 scripts/verify_release.sh #. Tag the release using ``git tag``. For example: diff --git a/scripts/confirm_release.sh b/scripts/confirm_release.sh deleted file mode 100755 index c3b4d12c5a..0000000000 --- a/scripts/confirm_release.sh +++ /dev/null @@ -1,57 +0,0 @@ -#! /bin/bash - -set -xue - -CHECKSUM_FILE="Django-${VERSION}.checksum.txt" -MEDIA_URL_PREFIX="https://media.djangoproject.com" -RELEASE_URL_PREFIX="https://www.djangoproject.com/m/releases/" -DOWNLOAD_PREFIX="https://www.djangoproject.com/download" - -if [[ ! "${VERSION}" =~ ^[0-9]+\.[0-9]+(\.[0-9]+|a[0-9]+|b[0-9]+|rc[0-9]+)?$ ]] ; then - echo "Not a valid version" -fi - -rm -rf "${VERSION}" -mkdir "${VERSION}" -cd "${VERSION}" - -function cleanup { - cd .. - rm -rf "${VERSION}" -} -trap cleanup EXIT - -echo "Download checksum file ..." -curl --fail --output "$CHECKSUM_FILE" "${MEDIA_URL_PREFIX}/pgp/${CHECKSUM_FILE}" - -echo "Verify checksum file ..." -if [ -n "${GPG_KEY:-}" ] ; then - gpg --recv-keys "${GPG_KEY}" -fi -gpg --verify "${CHECKSUM_FILE}" - -echo "Finding release artifacts ..." -mapfile -t RELEASE_ARTIFACTS < <(grep "${DOWNLOAD_PREFIX}" "${CHECKSUM_FILE}") - -echo "Found these release artifacts: " -for ARTIFACT_URL in "${RELEASE_ARTIFACTS[@]}" ; do - echo "- $ARTIFACT_URL" -done - -echo "Downloading artifacts ..." -for ARTIFACT_URL in "${RELEASE_ARTIFACTS[@]}" ; do - ARTIFACT_ACTUAL_URL=$(curl --head --write-out '%{redirect_url}' --output /dev/null --silent "${ARTIFACT_URL}") - curl --location --fail --output "$(basename "${ARTIFACT_ACTUAL_URL}")" "${ARTIFACT_ACTUAL_URL}" - -done - -echo "Verifying artifact hashes ..." -# The `2> /dev/null` moves notes like "sha256sum: WARNING: 60 lines are improperly formatted" -# to /dev/null. That's fine because the return code of the script is still set on error and a -# wrong checksum will still show up as `FAILED` -echo "- MD5 checksums" -md5sum --check "${CHECKSUM_FILE}" 2> /dev/null -echo "- SHA1 checksums" -sha1sum --check "${CHECKSUM_FILE}" 2> /dev/null -echo "- SHA256 checksums" -sha256sum --check "${CHECKSUM_FILE}" 2> /dev/null diff --git a/scripts/do_django_release.py b/scripts/do_django_release.py index b3cc0248ac..3d5bbb5210 100755 --- a/scripts/do_django_release.py +++ b/scripts/do_django_release.py @@ -206,12 +206,9 @@ print( f"* Signed checksum {checksum_file_path}.asc" ) -# Test the new version and confirm the signature using Jenkins. -print("\n==> ACTION Test the release artifacts:") -print(f"VERSION={django_version} test_new_version.sh") - -print("\n==> ACTION Run confirm-release job:") -print(f"VERSION={django_version} confirm_release.sh") +# Verify the release artifacts (GPG signature, checksums, and smoke test). +print("\n==> ACTION Verify the release artifacts:") +print(f"VERSION={django_version} verify_release.sh") # Upload to PyPI. print("\n==> ACTION Upload to PyPI, ensure your release venv is activated:") diff --git a/scripts/test_new_version.sh b/scripts/test_new_version.sh deleted file mode 100755 index 317ce71ee1..0000000000 --- a/scripts/test_new_version.sh +++ /dev/null @@ -1,48 +0,0 @@ -#! /bin/bash - -# Original author: Tim Graham. - -set -xue - -cd /tmp - -RELEASE_VERSION="${VERSION}" -if [[ -z "$RELEASE_VERSION" ]]; then - echo "Please set VERSION as env var" - exit 1 -fi - -PKG_TAR=$(curl -Ls -o /dev/null -w '%{url_effective}' https://www.djangoproject.com/download/$RELEASE_VERSION/tarball/) -echo $PKG_TAR - -PKG_WHL=$(curl -Ls -o /dev/null -w '%{url_effective}' https://www.djangoproject.com/download/$RELEASE_VERSION/wheel/) -echo $PKG_WHL - -python3 -m venv django-pip -. django-pip/bin/activate -python -m pip install --no-cache-dir $PKG_TAR -django-admin startproject test_one -cd test_one -./manage.py --help # Ensure executable bits -python manage.py migrate -python manage.py runserver 0 - -deactivate -cd .. -rm -rf test_one -rm -rf django-pip - - -python3 -m venv django-pip-wheel -. django-pip-wheel/bin/activate -python -m pip install --no-cache-dir $PKG_WHL -django-admin startproject test_one -cd test_one -./manage.py --help # Ensure executable bits -python manage.py migrate -python manage.py runserver 0 - -deactivate -cd .. -rm -rf test_one -rm -rf django-pip-wheel diff --git a/scripts/verify_release.sh b/scripts/verify_release.sh new file mode 100755 index 0000000000..d808b62cfa --- /dev/null +++ b/scripts/verify_release.sh @@ -0,0 +1,95 @@ +#! /bin/bash + +# Verify a Django release: checks GPG signature, artifact checksums, and +# smoke-tests installation from both the tarball and the wheel. +# +# Usage: VERSION=5.2 bash scripts/verify_release.sh +# +# Set GPG_KEY to a key fingerprint to import it before verifying, e.g.: +# GPG_KEY=<fingerprint> VERSION=5.2 bash scripts/verify_release.sh + +set -xue + +if [[ -z "${VERSION:-}" ]]; then + echo "Please set VERSION as env var" + exit 1 +fi + +if [[ ! "${VERSION}" =~ ^[0-9]+\.[0-9]+(\.[0-9]+|a[0-9]+|b[0-9]+|rc[0-9]+)?$ ]]; then + echo "Not a valid version" + exit 1 +fi + +CHECKSUM_FILE="Django-${VERSION}.checksum.txt" +MEDIA_URL_PREFIX="https://media.djangoproject.com" +DOWNLOAD_PREFIX="https://www.djangoproject.com/download" + +WORKDIR=$(mktemp -d) + +function cleanup { + rm -rf "${WORKDIR}" +} +trap cleanup EXIT + +cd "${WORKDIR}" + +echo "Downloading checksum file ..." +curl --fail --output "${CHECKSUM_FILE}" "${MEDIA_URL_PREFIX}/pgp/${CHECKSUM_FILE}" + +echo "Verifying checksum file signature ..." +if [[ -n "${GPG_KEY:-}" ]]; then + gpg --recv-keys "${GPG_KEY}" +fi +gpg --verify "${CHECKSUM_FILE}" + +echo "Finding release artifacts ..." +mapfile -t RELEASE_ARTIFACTS < <(grep "${DOWNLOAD_PREFIX}" "${CHECKSUM_FILE}") + +echo "Found these release artifacts:" +for ARTIFACT_URL in "${RELEASE_ARTIFACTS[@]}"; do + echo "- ${ARTIFACT_URL}" +done + +echo "Downloading artifacts ..." +for ARTIFACT_URL in "${RELEASE_ARTIFACTS[@]}"; do + ARTIFACT_ACTUAL_URL=$(curl --head --write-out '%{redirect_url}' --output /dev/null --silent "${ARTIFACT_URL}") + curl --location --fail --output "$(basename "${ARTIFACT_ACTUAL_URL}")" "${ARTIFACT_ACTUAL_URL}" +done + +echo "Verifying artifact hashes ..." +# The `2>/dev/null` suppresses notes like "sha256sum: WARNING: 60 lines are +# improperly formatted". Return code is still set on error and a wrong +# checksum will still show up as FAILED. +echo "- MD5 checksums" +md5sum --check "${CHECKSUM_FILE}" 2>/dev/null +echo "- SHA1 checksums" +sha1sum --check "${CHECKSUM_FILE}" 2>/dev/null +echo "- SHA256 checksums" +sha256sum --check "${CHECKSUM_FILE}" 2>/dev/null + +PKG_TAR=$(ls Django-*.tar.gz) +PKG_WHL=$(ls Django-*.whl) + +echo "Testing tarball install ..." +python3 -m venv django-pip +. django-pip/bin/activate +python -m pip install --no-cache-dir "${WORKDIR}/${PKG_TAR}" +django-admin startproject test_one +cd test_one +./manage.py --help # Ensure executable bits +python manage.py migrate +python manage.py runserver 0 +deactivate +cd .. + +echo "Testing wheel install ..." +python3 -m venv django-pip-wheel +. django-pip-wheel/bin/activate +python -m pip install --no-cache-dir "${WORKDIR}/${PKG_WHL}" +django-admin startproject test_one +cd test_one +./manage.py --help # Ensure executable bits +python manage.py migrate +python manage.py runserver 0 +deactivate +cd .. |
