J'ai une application Web où nous déployons en production chaque fois qu'une fonctionnalité est prête, parfois plusieurs fois par jour, parfois plusieurs semaines.
Actuellement, nous n'augmentons pas les numéros de version de notre projet, et tout est en place depuis la version 0.0.1-SNAPSHOT
depuis plus d'un an .. Je me demande quelle est la façon la plus simple de proposer la livraison continue d'une application Web. Il semble exagéré de surpasser le numéro de version sur chaque commit, et ne jamais écraser le numéro de version comme nous le faisons actuellement semble également erroné.
Quelle est la meilleure pratique recommandée pour ce type d'utilisation de Maven?
Le problème est en réalité un double:
pom.xml
individuel (et il peut y en avoir beaucoup).Je recommande la présentation suivante qui traite des réalités pratiques de la livraison continue avec Maven:
La clé à retenir est que chaque version est une version potentielle, évitez donc d'utiliser des instantanés.
Ceci est mon résumé basé sur la vidéo liée par la réponse de Mark O'Connor.
1.0-SNAPSHOT
sont transformées en versions réelles telles que 1.0.buildNumber
où buildNumber
est le numéro du travail Jenkins. Étapes de l'algorithme:
1.0-SNAPSHOT
1.0.JENKINS-JOB-NUMBER
afin que la version de l'instantané soit transformée en une version réelle 1.0.124
1.0-SNAPSHOT
à 1.0.JENKINS-JOB-NUMBER
mvn install
mvn install
est un succès, Jenkins validera la branche 1.0.JENKINS-JOB-NUMBER
et une version réelle non instantanée sera créée avec une balise appropriée dans git pour une reproduction ultérieure. Si le mvn install
échoue, Jenkins supprimera simplement la branche nouvellement créée et échouera à la construction.Je recommande fortement la vidéo liée à la réponse de Mark.
À partir de Maven 3.2.1, les versions respectueuses de la livraison continue sont prises en charge immédiatement: https://issues.Apache.org/jira/browse/MNG-5576 Vous pouvez utiliser 3 variables prédéfinies dans la version:
${changelist}
${revision}
${sha1}
Donc, ce que vous faites fondamentalement est:
1.0.0-${revision}
. (Vous pouvez utiliser mvn versions:set
pour le faire rapidement et correctement dans un projet multi-module.)<revision>SNAPSHOT</revision>
pour le développement local.mvn clean install -Drevision=${BUILD_NUMBER}
ou quelque chose comme ceci ou même mvn clean verify -Drevision=${BUILD_NUMBER}
.Vous pouvez par exemple utiliser https://wiki.jenkins-ci.org/display/JENKINS/Version+Number+Plugin pour générer des numéros de construction intéressants.
Une fois que vous avez découvert que la construction est stable (par exemple, réussir les tests d’acceptation), vous pouvez transmettre la version à Nexus ou à un autre référentiel. Toutes les constructions instables vont juste à la poubelle.
Il existe d'excellentes discussions et propositions sur la manière de traiter le numéro de version Maven et la distribution continue (CD) (je les ajouterai après ma partie de la réponse).
Alors d’abord mon avis sur les versions SNAPSHOT. En maven, un SNAPSHOT indique qu’elle est en cours de développement pour la version spécifique avant le suffixe SNAPSHOT. Pour cette raison, des outils tels que Nexus ou le plug-in maven-release-plug ont un traitement spécial pour SNAPSHOTS. Pour Nexus, ils sont stockés dans un référentiel séparé et il est autorisé à mettre à jour plusieurs artefacts avec la même version de SNAPSHOT. Donc, un instantané peut changer sans que vous le sachiez (parce que vous n'incrémentez jamais un nombre dans votre pom). Pour cette raison, je ne recommande pas d'utiliser les dépendances SNAPSHOT dans un projet, en particulier dans un monde CD, car la construction n'est plus fiable.
SNAPSHOT en tant que version du projet poserait un problème lorsque votre projet est utilisé par d'autres projets, pour les raisons susmentionnées.
Un autre problème de SNAPSHOT pour moi est qu’il n’est plus vraiment traçable ni reproductible. Lorsque je vois une version 0.0.1-SNAPSHOT en production, je dois effectuer quelques recherches pour savoir quand elle a été construite à partir de quelle révision elle a été construite. Lorsque je trouve une version de ce logiciel sur un système de fichiers, je dois consulter le fichier pom.properties ou MANIFEST pour savoir s’il s’agit d’une vieille saleté ou de la dernière et meilleure version.
Pour éviter le changement manuel du numéro de version (en particulier lorsque vous créez plusieurs versions par jour), laissez le serveur de construction le modifier à votre place. Donc, pour le développement, j'irais avec un
<major>.<minor>-SNAPSHOT
version, mais lors de la création d’une nouvelle version, le serveur de compilation pourrait remplacer le SNAPSHOT par quelque chose de plus unique et traçable.
Par exemple un de ceci:
<major>.<minor>-b<buildNumber>
<major>.<minor>-r<scmNumber>
Ainsi, les nombres majeur et mineur peuvent être utilisés pour des problèmes de marketing ou simplement pour montrer qu'un nouveau grand jalon est atteint et peuvent être modifiés manuellement lorsque vous le souhaitez. Et le buildNumber (numéro de votre serveur d'intégration continue) ou le scmNumber (Révision de Subversion ou GIT) rendent chaque version unique et traçable. Lors de l'utilisation de la révision buildNumber ou Subversion, les versions du projet sont même triables (pas avec les numéros GIT). Avec le buildNumber ou le scmNumber, il est également un peu facile de voir quels changements ont été apportés dans cette version.
Un autre exemple est le contrôle de version de stackoverflow qui utilise
<year>.<month>.<day>.<buildNumber>
Et voici les liens manquants:
NE FAITES PAS CELA!
<Major>.<minor>-<build>
vous mordra dans le dos parce que Maven traite n'importe quoi après un trait d'union comme LEXIQUE. Cela signifie que la version 1 sera lexicalement supérieure à 10.
C'est mauvais, car si vous demandez la dernière version de quelque chose dans maven, alors le point ci-dessus gagne.
La solution consiste à utiliser un point décimal au lieu d'un trait d'union précédant le numéro de build.
FAIRE CECI!
<Major>.<minor>.<build>
Il est correct d’avoir les versions SNAPSHOT localement, mais dans le cadre d’une construction, il est préférable d’utiliser
mvn versions:set -DnewVersion=${major}.${minor}.${build.number}
Il existe des moyens de dériver la version majeure/mineure du pom, par exemple en utilisant help: evaluer et diriger vers une variable d'environnement avant d'appeler les versions: set. C'est sale, mais je me suis vraiment égratigné la tête (et les autres membres de mon équipe) pour simplifier les choses, et (à l'époque), Maven n'était pas assez mûr pour gérer cela. Je pense que Maven 2.3.1 pourrait avoir quelque chose qui aiderait cela, alors cette information pourrait ne plus être pertinente.
Il est normal qu'un groupe de développeurs publie la même version majeure.minor - mais il est toujours bon de garder à l'esprit que les modifications mineures sont ininterrompues et que les modifications de version majeures entraînent des modifications de dernière minute de l'API ou la dépréciation de fonctionnalités/comportements.
Du point de vue de la livraison continue, chaque build est potentiellement libérable. Par conséquent, chaque enregistrement doit créer un build.
Comme point de départ, vous pouvez jeter un oeil à Maven: la référence complète. Versions du projet.
Ensuite, il y a un bon post sur la stratégie de versioning.
Dans mon travail pour les applications Web, nous utilisons actuellement ce modèle de versioning:
<jenkins build num>-<git-short-hash>
Exemple: 247-262e37b9.
C'est bien parce que cela vous donne une version toujours unique et traçable jusqu'à la version de build et git de jenkins qui l'a produite.
Dans Maven 3.2.1+, ils ont finalement éliminé les avertissements concernant l'utilisation d'une $ {propriété} en tant que version, ce qui facilite grandement leur construction. Changez simplement tous vos poms pour utiliser <version>${revision}</version>
et construisez avec -Drevision=whatever
. Le seul problème avec cela est que, dans vos poms publiés, la version restera à ${revision}
dans le fichier pom réel, ce qui peut causer toutes sortes de problèmes étranges. Pour résoudre ce problème, j'ai écrit un simple plugin maven ( https://github.com/jeffskj/cd-versions-maven-plugin ) qui effectue le remplacement de la variable dans le fichier.