Après avoir divisé notre code en bits réutilisables, comment pouvons-nous tester et déployer?

9

Nous avons commencé avec un développeur et un repo svn contenant tout notre code:

^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1

(à l'époque, c'était une grande amélioration). Après que cela ait eu la chance de se développer un peu, nous avons commencé à avoir des problèmes avec les dépendances circulaires, les suites de tests lentes et les difficultés générales à réutiliser le code (car par exemple, l'ensemble des fonctionnalités de website1 s'était glissé dans le module-a autrement générique).

Voulant modulariser la base de code, et nous attendons à ce que nous passions à git sous peu (et ayant lu quelque part que git n'aime pas svn mega-repos), nous sommes passés à une structure beaucoup plus granulaire:

^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)

C'était génial conceptuellement. Plus d'un code modulaire, beaucoup plus rapide test-suites, plus facile à documents, etc. Nous open source certains de nos composants plus génériques, et fait tous les modules pip installable ( en utilisant pip install -e .pour les installer dans le developmentvirtualenv).

Nous avons créé un ^/srv/trunkréférentiel contenant la structure des dossiers de l'environnement d'exécution, c'est-à-dire. ^/srv/trunk/libpour les modules, /srv/trunk/srcpour les restes de ^/foo/trunk, ^/srv/trunk/wwwpour les sites Web etc.

Et enfin (en prenant une idée de perforce, avec laquelle j'ai travaillé il y a très longtemps [ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html] ), nous avons créé un "vcs- fetch "fichier texte qui répertorie tous les dépôts pertinents et où ils doivent être récupérés dans l'environnement de développement, et une commande correspondante pour le faire. Par exemple, une ligne vcs-fetc:

svn srv/lib/module-a ^/module-a/trunk

causerait soit (première fois)

cd /srv/lib && svn co ^/module-a/trunk module-a

ou (après)

cd /srv/lib/module-a && svn up

et de même pour les dépôts github (à la fois nos propres packages de fournisseurs et ceux modifiés / non modifiés).

Nous avons utilisé le même processus vcs-fetch pour créer l'environnement de production, mais nous découvrons rapidement que nous n'avons aucun moyen de savoir quelle version était utilisée dans prod après avoir effectué vcs-fetch.

Avec le méga-repo, nous pouvions simplement noter le numéro de révision avant de mettre à jour la prod à partir du tronc, et revenir en arrière était simple svn -r nnn up .. Avec du code à la fois dans svn et git (et un module dans hg) - et ~ 120 repos, il n'est pas évident de le faire.

J'ai lu http://12factor.net/ aujourd'hui, et le premier facteur est "une base de code" donc je me demande aussi si je suis loin du bon chemin ici?

Une idée que j'avais était de créer un script de déploiement qui créerait des roues de «déploiement» installables par pip et les regrouperait dans un requirements.txtfichier. Un déploiement impliquerait alors la création d'un nouveau virtualenv, l'installation par pip du fichier requirements.txt répertoriant les roues de déploiement et la commutation du virtualenv actif. Revenir au précédent impliquerait simplement de basculer le virtualenv en arrière (mais à moins que nous voulions garder les virtualenvs pour toujours, cela ne nous permettrait pas de revenir à un moment donné - selon mon expérience, cela n'a jamais été nécessaire cependant).

À ce stade, je me demande si je marche dans la mauvaise direction, ou si je ne viens pas assez loin sur le bon chemin ..? (tout ce que je lis continue de parler de "votre application", et je ne sais pas comment cela se traduit par l'exécution de 14 sites Web à partir de la même base de code ...)

thebjorn
la source
Puis-je supposer que les composants individuels sont désormais développés par différentes équipes avec des cycles de développement divergents? Si tel est le cas, la séparation du référentiel est inévitable dans les deux cas. Même si avec git, vous placeriez ensuite des balises de version synchronisées pour les configurations principales et stables. Jetez un œil à l'outil de mise en pension de Google. Tenter de faire correspondre les versions de développement par des métadonnées intégrées est à peu près inutile. Lier l'application ensemble via pip est également parfaitement légitime.
Ext3h
Si vous incluez des estimations KLOC (1000 lignes de code) et des mesures d'octets du code, nous pouvons facilement avoir une idée de la taille, par exemple "2000 lignes de code. Code source de 50 kilo-octets". ou "40 KLOC, 2 Go XML". . Il semble que vous ayez juste besoin de migrer vers git et git a des fonctions d'importation. Vous pouvez commencer par lire le git book .
Niklas
1
@ Programmer400 la base de code est: .py 670 kloc, .js: 135kloc, .less: 25kloc, .html: 130kloc. Si gros, mais pas énorme. D'après ce que j'ai lu, git n'aime pas vraiment les repos de cette taille, donc j'imagine que nous devrons nous diviser en plus petits repos avant de passer à git ..?
thebjorn

Réponses:

2

On dirait qu'il vous manque des branches (ou plutôt des branches 'tags' ou 'release').

Au lieu d'utiliser votre revnum SVN comme référence pour déterminer la version que vous installez, vous devez créer une branche à cette révision publiée. Vous déployez ensuite ce nom de branche.

Cela facilite la branche même s'il n'y a pas de changements, donc chaque module conserve le même numéro de version, mais vos packages OSS peuvent ne pas aimer être branchés sans changement, donc la meilleure chose à faire est de garder un script de dépendances - donc version 5 de votre produit nécessite le module OSS X v2 et ainsi de suite.

Vous changeriez votre script pour arrêter de faire référence aux versions et travailler à la place avec les noms de branche (bien qu'ils puissent être n'importe quoi, il est préférable de décider d'une convention de dénomination fixe, par exemple Release_1_2_3)

Une autre astuce consiste à maintenir un fichier avec chaque module décrivant la version actuelle, vous pouvez les générer automatiquement si nécessaire, et peut-être également inclure un journal des modifications complet, mais cela signifie que n'importe qui peut voir quelle version est déployée en regardant simplement.

gbjbaanb
la source
1

Je pense que vous avez déjà beaucoup de bonnes idées, j'en ai utilisé la plupart sur divers projets au fil des ans, et votre principale préoccupation semble être l'incapacité de dire quelle version de tous les modules est incluse dans un package donné si vous vous séparez les.

Je suis tout à fait d'accord pour les diviser, à un certain niveau de granularité, surtout si vous avez plusieurs équipes et différents cycles de publication, comme le mentionne @ Ext3h.

Étant donné que je ne sais pas à quel point vos modules sont isolés ou à quel point vous souhaitez que votre version soit détaillée, je suggère quelques options.


Utilisez des sous-modules git. Avec les sous-modules, vous pouvez stocker chaque module dans un référentiel git séparé, similaire à votre configuration svn, et aussi à ce que vous pensez. Vous liez ensuite ces modules au projet racine qui contiendra une référence à la validation appropriée de chaque sous-module, pour chacune de ses propres validations.

IMO, c'est une configuration théoriquement agréable et assez simple. Les principaux inconvénients sont que le flux de travail pour les sous-modules est un peu gênant, mais vous semblez avoir résolu de telles choses avec des scripts auparavant, donc ce n'est peut-être pas un vrai problème.

L'autre mise en garde est que les références de validation de sous-module seront simplement un SHA1, il n'y a jamais de détails lisibles par l'homme sur la branche que vous êtes, et vous pourriez finir par devoir extraire manuellement la bonne branche lorsque vous souhaitez travailler directement dans le sous-module.

Cependant, je n'ai pas beaucoup utilisé ce modèle, donc je ne sais pas quel problème cela pourrait poser pour un grand projet tel que le vôtre.


Une autre alternative consiste à utiliser une sorte de gestionnaire de dépendances. Cela nécessite que chaque module ou ensemble de modules puisse être versionné, empaqueté et publié individuellement, et que vous ayez un système qui puisse rassembler ces packages comme vous le souhaitez quand vous le souhaitez.

Vous suggérez déjà pip, et ce qui semble manquer dans votre suggestion est de stocker le fichier requirements.txt résultant avec la build, ou dans le référentiel du projet racine, afin que vous puissiez recréer le virtualenv plus tard plutôt que d'avoir à enregistrer sur le disque.

Il existe également d'autres systèmes; J'ai mis en place un projet assez important en utilisant une version légèrement personnalisée d'Apache Ivy comme outil pour empaqueter et publier chaque module, ainsi que pour les rassembler pour le projet final. Ivy stocke également un manifeste répertoriant toutes les versions de tous les modules auxquels vous faites référence, si vous devez recréer la configuration ultérieurement.

axl
la source