Comment savoir quelle version de notre code se trouve dans chaque environnement?

14

Mon équipe utilise actuellement un processus de branchement / déploiement assez simple qui ressemble à ceci:

                ┌────────┐ ┌────┐ ┌──────┐
 Environments:  │  DEV   │ │ QA │ │ PROD │
                └────────┘ └────┘ └──────┘

                     ▲       ▲       ▲
                     │       │       │

                ┌────────┐ ┌────┐ ┌──────┐
 Builds:        │  DEV   │ │ QA │ │ PROD │
                └────────┘ └────┘ └──────┘

                     ▲       ▲       ▲
                     │       │       │

                ┌────────┐ ┌────┐ ┌──────┐
 Branches:      │ master │ │ qa │ │ prod │
                └────────┘ └────┘ └──────┘

Chaque environnement a sa propre branche (nous utilisons git ) et sa propre build qui utilise cette branche. Lorsque nous voulons passer d'un environnement à un autre, par exemple, de DEV à QA, nous fusionnons la masterbranche dans qaet lançons une nouvelle version de QA (qui est ensuite automatiquement déployée dans l'environnement QA).

Nous envisageons de passer à un nouveau processus qui éliminerait la création d'une branche dédiée et la construction pour chaque environnement. Au lieu de cela, une version unique créerait un «package de déploiement» qui pourrait ensuite être déployé dans n'importe quel environnement. Nous imaginons qu'un workflow typique ressemblerait à ceci:

                ┌────────┐     ┌────┐     ┌──────┐
 Environments:  │  DEV   │ ──► │ QA │ ──► │ PROD │
                └────────┘     └────┘     └──────┘

                      ▲ 
                       \ 

                        ┌───────────────┐
 Builds:                │ release build │
                        └───────────────┘

                                ▲
                                │

                ┌────────┐ ┌─────────┐
 Branches:      │ master │ │ release │
                └────────┘ └─────────┘

La promotion d'un environnement à un autre ne serait plus gérée dans le contrôle de code source; au lieu de cela, nous prendrions simplement les binaires déjà construits (le "package de déploiement") et les déposerions dans le nouvel environnement.

Ce nouveau système nous permettrait de déployer n'importe quelle build dans n'importe quel environnement, ce qui présente plusieurs avantages. Par exemple, il est trivial de tester les correctifs de bogues PROD dans DEV et QA. Notre système actuel ne fournit pas un moyen facile de le faire sans faire reculer une branche, ce que nous aimerions évidemment éviter.

Le plus gros inconvénient de ce nouveau système est que nous n'avons plus de moyen automatique de suivre le code dans quel environnement. Si nous devons apporter une correction dans PROD, nous n'avons plus de branche dédiée synchronisée avec la base de code de production actuelle. Il en va de même pour l'AQ - si nous voulons pousser un changement rapide vers l'AQ sans accélérer les travaux en cours master, nous n'avons plus de branche qui reflète l'état actuel de l'environnement d'AQ.

Comment pouvons-nous garder une trace du code dans chaque environnement?

Quelques options que nous envisageons:

  • utiliser des balises git pour garder une trace de quel commit est dans quel environnement
  • incorporer le commit git utilisé par la build dans chaque package de déploiement
Nathan Friend
la source
Avez-vous un système CI tel que Hudson ou Jenkins? Est-il capable de repousser les balises de ce qu'il a construit vers git? (Je sais qu'il existe des plugins pour Hudson et Jenkins qui peuvent ... - pas aussi sûrs des autres).
@MichaelT Nous utilisons MSBuild pour nos builds et Octopus Deploy pour nos déploiements. Je suis assez confiant que nous pourrions faire Octopus manipuler notre référentiel git avec un script de déploiement Powershell personnalisé.
Nathan Friend

Réponses:

14

Les balises Git sont ce que vous voulez vraiment utiliser pour désigner les versions. La raison en est qu'ils ont un sens pour vous et peuvent être utilisés pour reconnaître rapidement le lien entre le code déployé par l'état et toute information que le serveur de build peut avoir (comme le numéro de build).

Bien que ce soit la réponse que vous recherchez, elle ne résout que la moitié du problème. L'autre est "hé, voici le déployé .[wje]arsur le serveur, de quelle version est-il venu?" Nous savons que vous ne déploierez jamais différentes versions de l'application sur dev et qa ou prod. Droite?

La solution à cette partie de la question consiste à demander au serveur de génération de mettre les informations dans le manifeste. Venant d'un exemple maven et svn que j'ai devant moi:

<manifestEntries>
    <Specification-Title>${project.name}</Specification-Title>
    <Specification-Version>${project.version}</Specification-Version>
    <Build-Number>${build.number}</Build-Number>
    <Build-Id>${build.id}</Build-Id>
    <Svn-Revison>${svn.revision}</Svn-Revison>
</manifestEntries>

C'est dans la configuration d'archive maven-war-plugin. Mais vous pouvez également le trouver dans d'autres plugins. Ensuite, à Hudson, une partie de l'invocation de build maven est:

-Dbuild.number=${BUILD_NUMBER}
-Dsvn.revision=${SVN_REVISION}
-Dbuild.id=${BUILD_ID}

qui définit ces définitions que maven reprend ensuite. Et puis, il suffit de regarder dans le fichier MANIFEST.MF qui a été déployé sur le serveur pour voir de quelle version il s'agit.

Il existe un plugin git , qui offre un ensemble similaire de variables d'environnement, notamment:

  • GIT_COMMIT - SHA du courant
  • GIT_BRANCH - Nom du référentiel distant (par défaut à l'origine), suivi du nom de la branche actuellement utilisée, par exemple "origine / maître" ou "origine / foo"

La combinaison de ces deux pratiques vous permet d'identifier facilement la build (car les numéros de build vont de l'avant et ont un sens, contrairement aux sommes de contrôle sha) et le git commit spécifique à partir duquel il est construit.


la source
3

Une approche complètement différente consisterait à rejeter versionscomplètement l'idée de . Vous n'avez qu'une "version unique" qui a un comportement configurable différent. La seule différence serait que vous avez une base de code commune - même en production, vous déploieriez le travail en cours : mais pas activé.

La différence se résume uniquement à l'activation de différents ensembles de fonctionnalités dans votre produit.

La désactivation / activation se fait via des bascules de fonction .

Avantage: l'ensemble du processus de publication est simplifié: vous fournissez toujours une version intégrée de votre logiciel. Chaque fonctionnalité est toujours disponible en master. Aucune branche supplémentaire n'est nécessaire.

Il n'y a aucune douleur à fusionner des fonctionnalités ensemble, car: aucune branche n'a besoin de fusionner. Il n'y a pas de confusion sur la fonctionnalité de quelle branche et peut-être dépendre ou en conflit avec les fonctionnalités d'autres branches. Chaque partie pouvait être activée à volonté. Même un retour en arrière n'est plus nécessaire: ce n'est qu'une action sur un interrupteur .

Je ne sais pas, si cela fonctionne pour votre base de code: les conditions préalables en termes de qualité de code et de discipline de développeur sont assez élevées - vous devez faire face au "nettoyage" après qu'une fonctionnalité est devenue une fonctionnalité de base et vous devez gérer un tas de bascules empêcher un plus grand désordre .

Peut-être que cela fonctionne pour vous.

Thomas Junk
la source
Mais qu'en est-il du déploiement de différents états de référentiel sur différents serveurs? Le code qui s'exécute sur la boîte QA est-il le même que celui qui s'exécute en production pour pouvoir reproduire un bogue? Le code que les développeurs ont poussé vers leur boîte de développeur est-il le même que celui contre lequel QA s'exécute?
1
La question doit être posée différemment: le bug avec une configuration spéciale est-il reproductible "maintenant" si oui, vous pouvez le corriger. Si non - le bug est-il important? Vous poussez toujours le travail (et le code intégré).
Thomas Junk
-1

Nous utilisons maven pour mettre la version dans le fichier manifeste. Demandez ensuite à l'application d'afficher la version s'il s'agit d'une application Web, ou disposez d'un point de terminaison / version pour les services Web.

Josh Chappelle
la source