Comment publier Django¶
Ce document explique comment est réalisée une publication de Django.
Veuillez s’il-vous-plaît garder ces instructions à jour si vous procédez à des modifications ! La clé ici est d’être descriptif et non pas normatif, sentez-vous donc libre de simplifier ou de faire d’autres changements dans la procédure, mais alors mettez à jour ce document en fonction !
Aperçu¶
Il peut être nécessaire d’effectuer trois différents types de publications :
Publications de sécurité : annonce et résolution d’une vulnérabilité. Cela implique généralement deux ou trois publications simultanées – par ex. 3.2.x, 4.0.x et selon le timing, peut-être une 4.1.x.
Publications de version normale : soit une publication finale (par ex. 4.1) ou une mise à jour corrective (par ex. 4.1.1).
Prépublications : par ex. 4.2 alpha, bêta ou rc.
La version courte des étapes à suivre est :
S’il s’agit d’une publication de sécurité, prénotifier la liste de distribution de sécurité une semaine avant la publication effective.
Relire les notes de publication, particulièrement en ce qui concerne leur organisation et leur formulation. Écrire un brouillon d’article de blog et de courriel d’annonce.
Changer les numéros de version and créer les artefacts de version.
Créer la nouvelle
Release
dans l’admin dedjangoproject.com
.Définir la date prévue mais assurez-vous que le champ
is_active
est désactivé.Upload the artifacts (tarball, wheel, and checksums).
Vérifier les signatures du ou des paquets, contrôler s’ils peuvent être installés et s’assurer de leur fonctionnement minimal.
Envoyer la ou les nouvelles versions au serveur PyPI.
Enable the
is_active
flag for each release in the admin ondjangoproject.com
.Publier l’article de blog et envoyer le courriel d’annonce.
Update version numbers post-release in stable branch(es).
Add stub release notes for the next patch release in
main
and backport.
Il y a beaucoup de détails, accrochez-vous !
Prérequis¶
Certains prérequis sont nécessaires avant de commencer. S’il s’agit de votre première publication, vous devriez vous coordonner avec un autre publicateur afin de régler ces différentes exigences et écrire à la liste de diffusion des opérateurs pour demander l’accès et les permissions requises.
Un environnement Unix avec les outils suivants installés (par ordre alphabétique) :
bash
git
GPG
make
man
des outils de hachage (typiquement
md5sum
,sha1sum
etsha256sum
sur Linux, oumd5
etshasum
sur macOS)python
Une paire de clé GPG. Assurez-vous de garder confidentielle la partie privée de la clé, dans un endroit sécurisé. La partie publique doit être envoyée sur votre compte GitHub ainsi que sur le serveur Jenkins exécutant la tâche «confirm release».
Plus d’une clé GPG
Si la clé que vous souhaitez utiliser n’est pas votre clé de signature par défaut, vous devrez ajouter
-u vous@example.com
à chaque commande de signature GPG affichée ci-dessous, oùvous@example.com
est l’adresse de courriel associée à la clé que vous allez utiliser.A clean Python virtual environment (Python 3.9+) to build artifacts, with these required Python packages installed:
$ python -m pip install build twine
Un accès au projet Django sur PyPI pour envoyer les fichiers binaires, idéalement avec la permission d’annulation de publication <https://pypi.org/help/#yanked>`_ au cas où cela serait nécessaire. Créez un jeton de portée de projet en suivant la documentation officielle et configurez votre fichier
$HOME/.pypirc
comme ceci :~/.pypirc
¶[distutils] index-servers = pypi django [pypi] username = __token__ password = # User-scoped or project-scoped token, to set as the default. [django] repository = https://upload.pypi.org/legacy/ username = __token__ password = # A project token.
Un accès au projet Django sur Transifex, avec rôle de gestionnaire. Générez un jeton d’API dans la section des réglages d’utilisation et configurez votre fichier
$HOME/.transifexrc
comme ceci :~/.transifexrc
¶[https://www.transifex.com] rest_hostname = https://rest.api.transifex.com token = # API token
Un accès à l’interface d’administration Django de
djangoproject.com
comme « mainteneur de site ».Access to create a post in the Django Forum - Announcements category and to send emails to the django-announce mailing list.
Un accès au dépôt
django-security
sur GitHub. Parmi d’autres choses, cela donne accès à la liste de distribution de prénotification (nécessaire pour les tâches de préparation des publications de sécurité).Access to the Django project on Read the Docs.
Tâches de pré-publication¶
Il faut s’occuper de quelques tâches avant même de commencer le processus de publication en tant que tel. Celles-ci commencent environ une semaine avant la publication ; la plupart peuvent être réalisées à n’importe quel moment précédant la publication réelle.
10 jours (ou plus) avant une publication de sécurité¶
Faites la demande d’un ID CVE pour la correction du problème de sécurité qui sera publiée. Un identifiant par problème, demandé avec
Vendor: djangoproject
etProduct: django
.Produisez le ou les correctifs appropriés (et privés) en utilisant
git format-patch
, un pour la branchemain
et un pour chaque branche stable soumise à cette correction.
Une semaine avant une publication de sécurité¶
Envoyez une notification préalable exactement une semaine avant la publication de sécurité. Le modèle de ce message ainsi qu’une liste de destinataires se trouvent dans le wiki GitHub privé
django-security
. Placer les destinataires en copie cachée en prenant soin d’y inclure les identifiants CVE adéquats. Joignez tous les correctifs des vulnérabilités corrigées (concernant les branchesmain
et stables) et signez le texte du courriel avec la clé qui sera utilisée pour la publication, avec une commande telle que :$ gpg --clearsign --digest-algo SHA256 prenotification-email.txt
Notifiez django-announce au sujet de la mise à jour de sécurité à venir avec un message général du genre :
Notice of upcoming Django security releases (3.2.24, 4.2.10 and 5.0.2) Django versions 5.0.2, 4.2.10, and 3.2.24 will be released on Tuesday, February 6th, 2024 around 1500 UTC. They will fix one security defect with severity "moderate". For details of severity levels, see: https://docs.djangoproject.com/en/dev/internals/security/#how-django-discloses-security-issues
Quelques jours avant toute publication¶
À l’approche de la publication, surveillez Trac pour vous assurer qu’aucun ticket bloquant ne reste pour la prochaine publication. Dans des circonstances exceptionnelles, comme par exemple le respect d’une date de publication de sécurité prédéterminée, une publication peut tout de même avoir lieu avec des tickets bloquants ouverts. Le publicateur est responsable de la décision de publier même si des tickets bloquants sont encore ouverts ou de différer la date de publication si nécessaire, quand celle-ci n’est pas liée à la sécurité.
Se coordonner avec les autres fusionneurs pour être sûr qu’ils n’ont pas de commits en attente pour cette publication.
Relire les notes de publication, y compris la version en ligne pour détecter tout lien cassé ou erreur reST, et s’assurer que les notes de publication contiennent la bonne date.
Revérifier que les notes de publication mentionnent la planification d’obsolescence pour toute API signalée comme obsolète et qu’elles mentionnent tout changement dans la prise en charge des versions de Python.
Revérifier que le sommaire des notes de publication contienne un lien vers les notes de la nouvelle publication ; le fichier concerné est
docs/releases/index.txt
.S’il s’agit d’une publication principale, s’assurer que les traductions en provenance de Transifex ont été intégrées. Cette opération est parfois réalisée par un gestionnaire des traductions autre que le publicateur, mais voici les étapes à suivre. Ce processus est un peu long donc assurez-vous d’avoir 4-10 heures à y consacrer et idéalement planifiez cette tâche un ou deux jours avant le jour de la publication.
En plus de posséder un compte Transifex configuré, la commande tx CLI doit être disponible dans votre chemin
PATH
. Vous pouvez alors récupérer toutes les traductions en lançant :$ python scripts/manage_translations.py fetch
Cette commande prend du temps à s’exécuter. Lorsqu’elle a terminé, inspectez soigneusement le résultat au cas où des erreurs ou avertissements y figureraient. S’il y en a, vous devrez explorer pour résoudre ces problèmes au cas par cas.
Les traductions récemment récupérées ont besoin d’ajustement manuel. Tout d’abord, les valeurs
PO-Revision-Date
doivent être manuellement mises à jour pour être postérieures àPOT-Creation-Date
. Vous pouvez utiliser une commande telle que celle-ci pour mettre à jour en lot tous les fichiers.po
(comparez le diff avec la branche stable concernée) :$ git diff --name-only stable/5.0.x | grep "\.po" | xargs sed -ri "s/PO-Revision-Date: [0-9\-]+ /PO-Revision-Date: $(date -I) /g"
All the new
.po
files should be manually and carefully inspected to avoid committing a change in a file without any new translations. Also, there shouldn’t be any changes in the « plural forms »: if there are any (usually Spanish and French report changes for this) those will need reverting.Lastly, commit the changed/added files (both
.po
and.mo
) and create a new PR targeting the stable branch of the corresponding release (example PR updating translations for 4.2).Mettez à jour la page de manuel de django-admin:
$ cd docs $ make man $ man _build/man/django-admin.1 # do a quick sanity check $ cp _build/man/django-admin.1 man/django-admin.1
puis faites le commit de la page de manuel modifiée.
S’il s’agit de la publication « .0 » d’une nouvelle série, créez une nouvelle branche à partir de la branche stable actuelle dans le dépôt django-docs-translations. Par exemple, lors de la publication de Django 4.2 :
$ git checkout -b stable/4.2.x origin/stable/4.1.x $ git push origin stable/4.2.x:stable/4.2.x
Écrivez l’article de blog d’annonce de la publication. Vous pouvez l’écrire dans le site d’administration tout en le marquant comme inactif. Voici quelque exemples : exemple d’annonce de publication de sécurité, exemple d’annonce de publication normale, exemple d’annonce de pré-publication.
A few days before a feature freeze¶
In preparation for the alpha release, the directory
/home/www/www/media/releases/A.B
must be created on the djangoproject
server.
Before the feature freeze, a branch targeting main
must be created to
prepare for the next feature release. It should be reviewed and approved a few
days before the freeze, allowing it to be merged after the stable branch is
cut. The following items should be addressed in this branch:
Update the
VERSION
tuple indjango/__init__.py
, incrementing to the next expected release (example commit).Create a stub release note for the next feature release. Use the stub from the previous feature release or copy the contents from the current version and delete most of the contents leaving only the headings (example commit).
Remove
.. versionadded::
and.. versionchanged::
annotations in the documentation from two releases ago, as well as any remaining older annotations. For example, in Django 5.1, notes for 4.2 will be removed (example commit).Remove features that have reached the end of their deprecation cycle, including their docs and the
.. deprecated::
annotation. Each removal should be done in a separate commit for clarity. In the commit message, add aRefs #XXXXX --
prefix linking to the original ticket where the deprecation began if possible. Make sure this gets noted in the removed features section in the release notes (example commit).Increase the default PBKDF2 iterations in
django.contrib.auth.hashers.PBKDF2PasswordHasher
by about 20% (pick a round number). Run the tests, and update the 3 failing hasher tests with the new values. Make sure this gets noted in the release notes (example commit).
Concrete examples for past feature release bootstrap branches: 5.2 bootstrap, 5.1 bootstrap, 5.0 bootstrap.
Feature freeze tasks¶
Remove empty sections from the release notes (example commit).
Build the release notes locally and read them. Make any necessary change to improve flow or fix grammar (example commit).
Create a new stable branch from
main
. For example, when feature freezing Django 5.2:$ git checkout -b stable/5.2.x upstream/main $ git push upstream -u stable/5.2.x:stable/5.2.x
At the same time, update the
django_next_version
variable indocs/conf.py
on the stable release branch to point to the new development version. For example, when creatingstable/5.2.x
, setdjango_next_version
to'6.0'
on the new stable branch (example commit).Go to the Add release page in the admin, create a
Release
object for the final release, ensuring that the Release date field is blank, thus marking it as unreleased. For example, when creatingstable/5.2.x
, create5.2
with the Release date field blank. If the release is part of an LTS branch, mark it so.Go to the Add document release page in the admin, create a new
DocumentRelease
object for the English language for the newly createdRelease
object. Do not mark this as default.Ajoutez la nouvelle branche sur Read the Docs. Comme les noms de versions automatiquement générés («stable-A.B.x») diffèrent des noms de versions utilisés dans Read the Docs («A.B.x»), créez un ticket demandant la nouvelle version.
Request the new classifier on PyPI. For example
Framework :: Django :: 5.2
.Create a roadmap page for the next release on Trac. To create a new page on the Wiki, navigate to the URL of where you wish to create the page and a « Create this page » button will be available.
Mettez à jour la version de développement active à la branche actuelle et ajoutez la branche de pré-publication dans le processus de publication de Django sur Trac.
Update the
docs/fixtures/doc_releases.json
JSON fixture for djangoproject.com, so people without access to the production DB can still run an up-to-date copy of the docs site (example PR). This will be merged after the final release.
Production réelle de la nouvelle version¶
Voilà, il s’agit maintenant de la partie sympa où nous allons effectivement produire la publication ! Si vous produisez plusieurs publications, répétez ces étapes pour chaque publication.
Vérifiez que Jenkins est vert pour la ou les versions que vous allez produire. Vous ne devriez probablement pas produire de version tant que ce n’est pas vert, et vous devez vous assurer que la dernière exécution en vert inclue les modifications que vous allez publier.
Nettoyez les notes de cette publication. Faites les modifications dans
main
et rétroportez-les dans toutes les branches où les notes de publication de cette version apparaissent.Pour une publication majeure, enlevez l’en-tête
UNDER DEVELOPMENT
au sommet des notes de publication, enlevez le préfixeExpected
et mettez à jour la date de publication si nécessaire (commit d’exemple).Pour une publication corrective, enlevez le préfixe
Expected
et mettez à jour la date de publication de toutes les publications, si nécessaire (commit d’exemple).
Une nouvelle version se base toujours sur une branche de publication, vous devriez donc vérifier que vous vous trouvez sur une branche stable et à jour. De plus, vous devriez avoir sous la main un environnement virtuel dédié pour chaque version à publier. Par exemple :
$ git checkout stable/4.1.x $ git pull
S’il s’agit d’une mise à jour de sécurité, fusionnez les correctifs appropriés à partir de
django-security
. Rebasez ces correctifs si nécessaire pour que chacun d’entre eux soit un commit simple sur la branche de publication plutôt qu’un commit de fusion. Pour s’assurer de cela, fusionnez-les avec le drapeau--ff-only
; par exemple :$ git checkout stable/4.1.x $ git merge --ff-only security/4.1.x
(Cela suppose que
security/4.1.x
est une branche du dépôtdjango-security
contenant les correctifs de sécurité nécessaires pour la prochaine publication de la série 4.1).Si Git refuse de fusionner avec
--ff-only
, revenez dans la branche des correctifs de sécurité et rebasez-la sur la branche dans laquelle vous allez effectuer la fusion (git checkout security/4.1.x; git rebase stable/4.1.x
), puis retournez dans la branche initiale et effectuez la fusion. Vérifiez que le message de commit de chaque correction de sécurité explique qu’il s’agit bien d’un correctif de sécurité et qu’une annonce va suivre (exemple de commit de sécurité).Mettez à jour le numéro de version dans
django/__init__.py
pour la publication. Veuillez lire les notes sur la définition du tuple VERSION ci-dessous pour plus de détails sur le format deVERSION
(commit d’exemple).If this is a pre-release package also update the « Development Status » trove classifier in
pyproject.toml
to reflect this. Anrc
pre-release should not change the trove classifier (example commit for alpha release, example commit for beta release).Sinon, assurez-vous que le classificateur est défini à
Development Status :: 5 - Production/Stable
.
Building the artifacts¶
Optionally use helper scripts
You can streamline some of the steps below using helper scripts from the Wiki:
Placez une étiquette sur la publication avec
git tag
. Par exemple :$ git tag --sign --message="Tag 4.1.1" 4.1.1
Vous pouvez contrôler votre travail en exécutant
git tag --verify <tag>
.Assurez-vous d’avoir une arborescence parfaitement propre en exécutant
git clean -dfx
.Run
python -m build
to generate the release packages. This will create the release artifacts (tarball and wheel) in adist/
directory. For Django 5.0 or older, you need to runmake -f extras/Makefile
instead.Générez les empreintes des paquets à publier :
$ cd dist $ md5sum * $ sha1sum * $ sha256sum *
Créez un fichier « checksums », Django-<<VERSION>>.checksum.txt` contenant les empreintes et les informations de publication. Commencez avec ce modèle et insérez la version correcte, la date, l’identifiant de clé GPG (provenant de
gpg --list-keys --keyid-format LONG
), le nom d’utilisateur de responsable de version GitHub, l’URL de publication et les sommes de contrôle :This file contains MD5, SHA1, and SHA256 checksums for the source-code tarball and wheel files of Django <<VERSION>>, released <<DATE>>. To use this file, you will need a working install of PGP or other compatible public-key encryption software. You will also need to have the Django release manager's public key in your keyring. This key has the ID ``XXXXXXXXXXXXXXXX`` and can be imported from the MIT keyserver, for example, if using the open-source GNU Privacy Guard implementation of PGP: gpg --keyserver pgp.mit.edu --recv-key XXXXXXXXXXXXXXXX or via the GitHub API: curl https://github.com/<<RELEASE MANAGER GITHUB USERNAME>>.gpg | gpg --import - Once the key is imported, verify this file: gpg --verify <<THIS FILENAME>> Once you have verified this file, you can use normal MD5, SHA1, or SHA256 checksumming applications to generate the checksums of the Django package and compare them to the checksums listed below. Release packages ================ https://www.djangoproject.com/download/<<VERSION>>/tarball/ https://www.djangoproject.com/download/<<VERSION>>/wheel/ MD5 checksums ============= <<MD5SUM>> <<RELEASE TAR.GZ FILENAME>> <<MD5SUM>> <<RELEASE WHL FILENAME>> SHA1 checksums ============== <<SHA1SUM>> <<RELEASE TAR.GZ FILENAME>> <<SHA1SUM>> <<RELEASE WHL FILENAME>> SHA256 checksums ================ <<SHA256SUM>> <<RELEASE TAR.GZ FILENAME>> <<SHA256SUM>> <<RELEASE WHL FILENAME>>
Signez le fichier de sommes de contrôle (
gpg --clearsign --digest-algo SHA256 Django-<version>.checksum.txt
). Cela produit un document signé,Django-<version>.checksum.txt.asc
que vous pouvez ensuite vérifier avecgpg --verify Django-<version>.checksum.txt.asc
.
Rendre la ou les publications publique(s)¶
Vous êtes maintenant prêt à publier les nouveaux paquets. Pour cela :
Create a new
Release
entry in the djangoproject.com’s admin. If this is a security release, this should be done 15 minutes before the announced release time, no sooner:- Version
Must match the version number as defined in the tarball (
django-<version>.tar.gz
). For example: « 5.2 », « 4.1.1 », or « 4.2rc1 ».- Is active
Set to False until the release is fully published (last step).
- LTS
Enable if the release is part of an LTS branch.
- Dates
Set the release date to today. This release will not be published until
is_active
is enabled.- Artifacts
Upload the tarball (
django-<version>.tar.gz
), wheel (django-<version>-py3-none-any.whl
), and checksum (django-<version>.checksum.txt.asc
) files created earlier.
Test that the release packages install correctly using
pip
. Here’s one simple method (this just tests that the binaries are available, that they install correctly, and that migrations and the development server start, but it’ll catch silly mistakes): https://code.djangoproject.com/wiki/ReleaseTestNewVersion.Lancez la construction confirm-release sur Jenkins pour vérifier les fichiers de sommes de contrôle (par ex. utilisez
4.2rc1
pour https://media.djangoproject.com/pgp/Django-4.2rc1.checksum.txt).Envoyez les paquets à publier vers PyPI (pour les prépublications, n’envoyez que le fichier wheel) :
$ twine upload --repository django dist/*
Update the newly created
Release
in the admin indjangoproject.com
and enable theis_active
flag.Poussez votre travail et la nouvelle étiquette :
$ git push $ git push --tags
Écrivez l’article de blog annonçant que la publication est en ligne.
Pour une publication majeure (par ex. 4.1, 4.2), mettez à jour la version stable par défaut de la documentation en activant le drapeau
is_default
sur l’objetDocumentRelease
approprié de la base de donnéesdocs.djangoproject.com
(cela va automatiquement mettre àFalse
ce drapeau pour toutes les autres instances) ; vous pouvez faire cela par le moyen du site d’administration.Créez des objets
DocumentRelease
pour chaque langue ayant déjà un tel objet pour une version précédente. Mettez à jour le fichier robots.docs.txt de djangoproject.com en copiant le résultat obtenu en lançant la commandemanage_translations.py robots_txt
de la branche stable actuelle dans le dépôt django-docs-translations. Par exemple, lors de la publication de Django 4.2 :$ git checkout stable/4.2.x $ git pull $ python manage_translations.py robots_txt
Publiez l’annonce de publication sur la liste de diffusion django-announce ainsi que sur le forum Django. Cette annonce doit contenir un lien vers l’article de blog de l’annonce.
S’il s’agit d’une mise à jour de sécurité, envoyez un message séparé à oss-security@lists.openwall.com. Indiquez un sujet descriptif tel que par exemple « Django » suivi du titre du problème provenant des notes de publication (y compris l’ID CVE). Le corps du message doit inclure les détails de la vulnérabilité, par exemple le texte de l’article de blog de l’annonce. Incluez un lien vers cet article de blog d’annonce.
Après la publication¶
Vous êtes presque au bout ! Tout ce qui reste à faire est :
If this is not a pre-release, update the
VERSION
tuple indjango/__init__.py
again, incrementing to whatever the next expected release will be. For example, after releasing 4.1.1, updateVERSION
toVERSION = (4, 1, 2, 'alpha', 0)
(example commit).Ajoutez la version dans la liste des versions de Trac si nécessaire (et, s’il s’agit d’une version finale, mettez-la comme version par défaut en modifiant le réglage
default_version
dans le fichier trac.ini de code.djangoproject.com). La nouvelle version X.Y doit être ajoutée après la publication alpha et la version par défaut doit être mise à jour après la publication.0
.S’il s’agit d’une nouvelle version majeure :
Mettez à jour la branche stable actuelle et enlevez les branches de pré-publication dans le processus de publication de Django sur Trac.
Mettez à jour la page de téléchargement de djangoproject.com (PR d’exemple).
S’il s’est agi d’une publication de sécurité, mettez à jour Archive des issues de sécurité avec les détails sur les problèmes corrigés.
S’il s’agit d’une prépublication, les catalogues de traduction doivent être mis à jour :
Make a new branch from the recently released stable branch:
git checkout stable/A.B.x git checkout -b update-translations-catalog-A.B.x
Ensure that the release’s dedicated virtual environment is enabled and run the following:
$ cd django $ django-admin makemessages -l en --domain=djangojs --domain=django processing locale en
Review the diff before pushing and avoid committing changes to the
.po
files without any new translations (example commit).Make a pull request against the corresponding stable branch and merge once approved.
Forward port the updated source translations to the
main
branch (example commit).
If this was an
rc
pre-release, call for translations for the upcoming release in the Django Forum - Internationalization category.
Notes sur la définition du tuple VERSION¶
La version de Django est contrôlée par le tuple VERSION
dans django/__init__.py
. C’est un tuple à cinq éléments, contenant :
La version majeure.
La version mineure.
La version micro.
Le statut, qui peut-être « alpha », « beta », « rc » ou « final ».
Le numéro de série, dans le cas des versions alpha/beta/RC qui se font suite (autorisant, par exemple, « beta 1 », « beta 2 », etc.).
Pour une version finale, le statut est toujours « final » et le numéro de série 0. Un numéro de série à 0 avec le statut « alpha » est signalé comme une « pre-alpha ».
Quelques exemples :
(4, 1, 1, "final", 0)
→ « 4.1.1 »(4, 2, 0, "alpha", 0)
→ « 4.2 pre-alpha »(4, 2, 0, "beta", 1)
→ « 4.2 beta 1 »