Open BenoitAverty opened 7 years ago
Allez je me lance. Je commence par un projet tout con pour me concentrer sur la base : Une appli java Spring, un front en react. L'appli a besoin d'une base postgre pour fonctionner. Il y a un fichier docker-compose.yaml à la racine du projet qui démarre l'appli (3 conteneurs : front, back, base) et un dossier integration-tests qui contient des tests e2e avec selenium. Pas de continuous delivery.
Du coup si je pars sur l'hypothèse du yaml:
# oscip.yml
environment:
docker: '^1.13' #1.13 and above
docker-compose: '^1.11'
java: 8
maven: '^3.3'
node: 8
build:
- stage: 'build'
parallel: true
steps:
- name: front
folder: ./client
scripts:
- npm install
- npm test
- npm run build
- name: back
folder: ./server
scripts:
- gradle build
- stage: integration-tests
steps:
- name: docker-deploy
scripts:
- docker-compose up -d
- name: tests
scripts:
- npm install
- npm test
- stage: release
parallel: true
condition: manual-trigger # Déclenchement de la release à la main via l'ihm, en cliquant sur l'étape par exemple. On pourrait aussi imaginer des conditions sur le nom de branche, sur un tag, sur une PR...
steps:
- name: release-client
scripts:
- npm run release
- name: release-server
scripts:
- gradle release
Je vous laisse imaginer le pipeline que ca pourrait donner. On 3 stages, le premier a deux étapes qui s'exécutent en parallèle, le second deux étapes séquentielles et le dernier deux étapes parallèles également.
Mon avis : c'est pas terrible. La partie "build" est trop complexe pour du yaml. C'est de l'impératif comme dit Jérémie, décrit avec un langage déclaratif. Ca peut sans doute être simplifié mais on voit déjà des limitations : le parallel: true
, pas mal de verbosité parce que j'ai voulu 3 niveaux dans la modélisation du pipeline (stage, step, script). On suppose également que chaque script s'occupe lui même d'archiver ou publier ce qui doit l'être (code coverage, résultats de tests, packages...), mais ça c'est pas forcément un mal (sauf si on veut les voir direct dans l'outil !).
Une solution serait de tout faire des des scripts sur le repo, mais c'est dommage de le faire pour un cas si simple je trouve, ca disperse l'info du process de build.
Du coup j'ai décrit le même build avec un DSL groovy, fait à l'arrache sans rien vérifier donc il y a peut-être des choses invalides.
def javaEnv = [ java: '8', maven: '^3.3' ]
def nodeEnv = [ node: '8' ]
def dockerEnv = [ docker: '^1.13', 'docker-compose': '^1.11' ]
stage 'build', parallel: true {
step 'front', folder: './client', env: nodeEnv {
npm install
npm test
npm run build
}
step 'back', folder: './server', env: javaEnv {
gradle build
}
}
stage 'integration-tests', parallel: true {
// plus besoin de mettre deux steps juste pour changer de directory. Du coup, dans ce cas précis, on pourrait dire que les "steps" sont exécutées en parallèle par défaut...
withEnv dockerEnv + nodeEnv { // Addition d'environnements ! Juste pour montrer ce qu'un DSL peut permettre. Mais est-ce une bonne idée ?
docker-compose up -d
dir './integration-tests' {
npm run test
}
}
}
stage 'release', parallel: true, condition: 'manual-trigger' {
// Pas besoin d'utiliser "step" car chacune ne contiendrait qu'un seul script. On peut voir ca comme des steps "anonymes". Le parallel s'applique alors aux deux scripts, alors que plus haut il s'appliquait aux deux steps.
npm run release
gradle release
}
J'ai une petite préférence pour le groovy, même si je pense que j'y ai mis plein de mauvaises idées. Et bien sûr, j'admet que c'est probablement plus difficile à appréhender au début pour des gens qui sont habitué à du travis ou circleci.
Je pense que je suis trop parti dans mon délire, non ? Qu'en pensez-vous ?
Les 2 premiers c'est des projet bateaux, le comportement par défaut s'applique. Le dernier te permet de faire des tests d'intégration entre les deux composants
En effet c'est un projet relativement simple mais pas basique.
Je suis pas hyper fan de séparer le fichier de build en 3. Comme un script de build dans le dépot, ca découpe l'information en plusieurs endroits. Par contre tu as raison : il faudrait proposer des comportements "par défaut", qui pourrient être activés par un paramètre en yaml ou une fonction groovy.
Travis permet de faire ça tout seul mais il ne fait pas vraiment des "pipelines". Juste un enchainement de script.
Oui, séparer le build en 3 c'est pas cool. Petite subtilité cachée derrière mon idée...
1 projet dans git == 1 fichier dans le repo == 1 projet dans l'outil de CI (qui se décline en plusieurs vues : 1 par branche, merge requests, etc)
L'idée c'est de laisser la possibilité de faire :
1 projet dans git == x fichiers dans le repo == X projets dans l'outil de CI.
On en parlera en "vrai" ça sera plus simple :) mais je suis pas sur que ce soit une bonne idée non plus...
J'aime bien la version 2 ! J'aime le mélange de la structure déclarative et d'une liste de command shell. Je craignais vraiment de partir sur une solution qui réinvente ant/maven/grunt etc..
(au risque de paraphraser @jeremiehuchet )
Pour moi un repo git ne devrait contenir qu'une seule "facette" (module ou composante ou techno...) du projet (front ou back ou autre).
Pourrait-on imaginer avoir un fichier de build placé dans un sous rep ?
je proposais de les mettre tous à la racine car ça me semblait pas tres optimal d'aller à la recherche de tous les fichiers trucs.yml dans tout le repo (recherche à faire à chaque build).
Quoique... git ls-tree -r --name-only $branch
est assez efficace.
Personellement je ne suis pas fan de mettre plusieurs fichiers dans un seul repo, que ca soit pour faire un ou plusieurs projets dans l'outil de CI.
Si on veut rester simple, je pense qu'il est important de rester sur l'équation «1 Projet <=> 1 Dépot <=> 1 projet dans l'outil de ci». La difficulté étant bien sur de savoir ce que c'est que «1 projet»
Ma réponse personelle à ca, c'est que deux composants qui ont exactement le même cicle de vie forment un seul projet. Quand tu es dans un environnement microservices, chaque composant est indépendant des autres (c'est même ca l'intérêt principal). Par contre, un front et un back pour moi forment un seul projet. Le back n'est consommé que par son front, et le front ne peux pas fonctionner sans le back. 99% du temps, une nouvelle feature va impacter les deux, les numéros de versionsont les mêmes, tu as besoin des deux pour faire des tests, etc. Bref, ils sont fortement couplés. Donc je les met dans le même repo et j'ai envie de les builder dans une seule pipeline.
Ca ne serait pas le cas pour un front qui fonctionne tout seul par exemple (type PWA) et qui consomme plusieurs API, chacune de ces API étant potentiellement consommées par plusieurs consommateurs : ex tweetdeck et l'api twitter.
@mmouterde : Pour moi c'est même indépendant de la techno. Si tu as un front angular et un back node par exemple, tu peux avoir un seul package.json et du coup ca fait un seul projet qui se build en deux lignes de commandes. Par contre, si tu utilises quelque chose comme create-react-app, tu deviens obligé de séparer le front et le back dans deux projets npm, et on revient presque au cas que j'ai proposé plus haut (en remplace gradle build
par npm run build
)
Toutes vos propositions ont de bonnes idées, mais comment on fait ensuite pour ordonnancer tout ça ? Ca cause des dépendances entre plusieurs projets / fichiers et je trouve que ca disperse l'info sur le process de build.
Enfin, mon dernier argument (qui est très personnel pour le coup), c'est que l'intérêt que je vois à un pipeline par rapport à un simple build "enchainement de scripts" (type travis ou circle), c'est que justement tu peux ordonnancer et visualiser différentes étapes pour construire un projet complexe qui fait intervenir plusieurs composants. Tu vois direct au même endroit ce qui a planté, le front, le back, ou est-ce que tu en est, etc...
de manière générale : ok !
Histoire de répéter ta question différement :
comment on fait ensuite pour ordonnancer tout ça ?
Comment voyez vous (ou pas) la possibilité de faire un pipeline "cross-project" ?
Tu es à fond dans les microservices, tu as plein de projets, plein de micro builds. Un truc cool ça serait de pouvoir tester les services entre eux : récupérer les artefacts produits par les micro builds et faire des tests d'intégration automatiques.
@BenoitAverty je comprend bien. Mon actuel projet Orange en ce moment est un peu complexifié par un découpage en plusieurs repo git (lifecycle identique, pb de synchro..). Il est découpé car deux équipes bossent sur le projet (API / front). On aurait sans doute gagné du temps à n'avoir qu'un repo.
Pour la question des projets complexes, du cross project etc.. je remets sur le tapis la question du périmètre #4 Il me semble délicat d'intégrer les tests end to end dans une PIC, la topologie réseau, VM, authent, proxy etc me parait difficilement envisageable dans un fichier de config sympa, c'est un coup à se retrouver avec des IP et des mots de passe dans la config, non ?
Tu fais référence à
Éviter autant que possible les dépendances vers le serveur d'intégration (dans l'idéal, uniquement pour les étapes optionnelles)
?
faut pas prendre le conseil à la lettre à mon avis ^^
bin j'aimerais éviter de provoquer ça : https://github.com/search?p=99&q=extension%3Akey+BEGIN+RSA+PRIVATE+KEY&ref=searchresults&type=Code
Haha, pas mal 😁
Je fais pareil, mais je chiffre la clé ^^ et sur ce point y'a des features à proposer. Si tu coupes tout moyen de communication avec une machine extérieure je ne peux pas utiliser cet outil !
Le jeu. 9 mars 2017 15:11, Martin Mouterde notifications@github.com a écrit :
bin j'aimerais éviter de provoquer ça : https://github.com/search?p=99&q=extension%3Akey+BEGIN+RSA+PRIVATE+KEY&ref=searchresults&type=Code
— You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub https://github.com/mmouterde/OSCIP/issues/7#issuecomment-285361095, or mute the thread https://github.com/notifications/unsubscribe-auth/AA4W9IQGCduGyE-XOdpMyHdjMAmunJtxks5rkAiYgaJpZM4MTx0d .
Je pense également que tout test automatisé doit faire partie du pipeline d'un projet, en particulier quand tu veux aller vers du continuous deployment jusqu'a la pré-prod voire la prod. Effectivement, ce genre de test est plus dur à automatiser, mais dans un premier temps je pense qu'il faut
J'ajoute que les clés dans des dépots publics, c'est déjà un problème et il est indépendant de l'outil de ci je pense. Il est vrai que déployer un environnement fonctionnel automatiquement n'est pas simple !
Hello,
Suite au petit échange de mail, je pense qu'il est utile de définir un peu les étapes qu'il faudra valider dans un ordre pas forcément défini
Et la démarche proposée par Jérémie que je trouve intéressante : Imaginer des projets du simple au complexe, et répondre à quelques unes de ces questions dans le cadre de ces projets. On peut en discuter ci-dessous.