NPM et la mise en production

Choisissons la solution !

a marqué ce sujet comme résolu.

NPM est jeune, n'est pas super fiable lors de l'installation des paquets et a des logs peu bavards. Il est donc à éviter en production, surtout quand la personne qui fait la MEP ne connaît pas cet outil. De plus, on pourrait raccourcir le temps ou le site est en maintenance.

Je vois plusieurs solutions qui pourraient être mise en place :

  • Le build se fait avant l'arrêt du serveur Django, dans un dossier à part qui est copié lors de la MEP.
    On aurait donc quelque chose comme :
1
2
3
4
5
6
7
Build du front dans /dist
Vérification du build
-| Arrêt du serveur Django / Mise en maintenance
Opérations diverses
Copie du /dist dans le /static (actuellement je crois que /static n'est qu'un raccourci vers /dist)
Opérations diverses
|-> Redémarrage du serveur Django / Arrêt de la maintenance
  • Le build se fait en-dehors du serveur de production et est archivé (il faut simplement lancer la commande npm run gulp -- build et faire une archive du dist/). Puis cette archive est importé lors de la MEP puis décompressée.
  • Le build est versionné dans notre dépôt Git donc le serveur n'a rien à faire.
  • Les paquets requis pour le build sont versionnés dans notre dépôt Git donc le serveur n'a pas de problème avec l'installation des paquets.

Il y a sûrement d'autres façons de faire, n'hésitez pas à en proposer !

Situphen :)

+0 -0

J'avais déjà bossé là dessus lorsque j'avais travaillé sur le versionning des fichiers statiques. À l'époque je n'avais pas la solution mais j'ai enfin trouvé comment faire ça proprement (ça traine dans une des mes nombreuses branches mais je ne sais plus laquelle).

@artagis : le wget c'est pas propre du tout. Ce qu'il faut c'est prendre tout le statique de ZDS et le mettre dans un dossier A puis lancer un python manage.py collectstatic qui vers les envoyer mais également ceux de l'admin et des app externes vers un dossier B (ce qui n'est pas fait aujourd'hui).

+1 -0

Je pense que c'est un non-sens que de pusher des versions buildées sur le repo.

Par contre, le fait de builder "ailleurs" - via un collectstatic + un wget (ou équivalent), … - ça par contre, ça peut être efficace.

+0 -0

On parlait de ce sujet pendant le dernier Zest'Meeting, je profite donc pour vous faire part de mon enquête.

Nous avons plus ou moins conclu que ce n'était pas une bonne idée de builder le front lors de la MEP, mais de faire ce travail en amont. La MEP (du front) derait être un wget/paste des fichiers déjà buildés ailleurs.

Sandh0se à proposé quelque chose que je trouve assez sympa, qui consiste à utiliser les releases github pour mettre à disposition le zip du dossier front. Ainsi, le déploiement de la partie front se résumerait à télécharger le fichier et à le décompresser. En normalisant la nomenclature de ces fichiers, on pourrait donc adapter le script de déploiement. ça reviendrait à télécharger le lien suivant : https://github.com/zestedesavoir/zds-site/archive/front-<tag>.zip lors de la MEP.

Comment builder ailleurs ?

En m’intéressant à la question, je suis tombé sur le service gratuit drone.io, qui fonctionne a peu près comme travis et cie. Sa particularité est qu'à la fin du build, il met a disposition un lien de téléchargement du résultat du build. On pourrait lui demander, pour chaque mise à jour sur la branche de prod de builder le front, ainsi on récupère le lien de téléchargement qu'on envoi sur la release github.

Après un essai rapide, le build du front sur drone.io se fait en 5 min et le .zip fait 600Ko.

Voilà le résultat de mon enquête.

Sandh0se à proposé quelque chose que je trouve assez sympa, qui consiste à utiliser les releases github pour mettre à disposition le zip du dossier front. Ainsi, le déploiement de la partie front se résumerait à télécharger le fichier et à le décompresser.

Attention à ne pas reporter tout le taff sur celui qui fait la release hein. Si aujourd'hui la plupart des releases ne sont pas dans Github (ou sont faites en retard), c'est peut-être qu'il y a une raison, par exemple…

On pourrait lui demander, pour chaque mise à jour sur la branche de prod de builder le front

Ce critère n'est pas bon, puisque du coup on ne pourrait pas mettre en pré-production avec le même moyen qu'en prod (quand on met en pré-production, on est pas forcément sur la branche de prod - c'est même rarement le cas).

Bref, y'a de l'idée, mais pour moi il faut encore creuser pour bien prendre en compte toutes les contraintes.

Attention à ne pas reporter tout le taff sur celui qui fait la release hein. Si aujourd'hui la plupart des releases ne sont pas dans Github (ou sont faites en retard), c'est peut-être qu'il y a une raison, par exemple…

En effet. Après le temps perdu à faire la release ainsi sera aussi le temps gagné au déploiement, et l'assurance que l'on a un build qui marche.

Ce critère n'est pas bon, puisque du coup on ne pourrait pas mettre en pré-production avec le même moyen qu'en prod (quand on met en pré-production, on est pas forcément sur la branche de prod - c'est même rarement le cas).

SpaceFox

Tout à fait. La preprod est déployée a partir de la branche de release, et la prod à partir de la branche de prod (ou du tag je sais jamais). On pourrait donc changer le critère en buildant le front uniquement pour les branches de release et pour celles qui hotfixeront la prod ?

Pour le problème de la release, c'est surtout un problème d'automatisation. S'il me faut 20 minutes de manips bordéliques pour tout bien avoir avec le package bien propre, non seulement c'est un gros risque d'erreurs dans les manips manuelles, mais en plus ça va me démotiver à faire des MEP. Il faut bien comprendre qu'aujourd'hui, une MEP qui ne pète rien, c'est moins de 5 minutes à passer grâce à l'automatisation.

Bon bah je pense avoir réglé le problème de l'automatisation :p

Puisque Travis build le front, pourquoi ne pas lui faire push ? J'ai testé ça ce soir, et ça a l'air de plutôt bien marcher !

En gros, quand c'est pas une PR, que c'est bien une branche release-XX, et qu'on est bien dans les tests front, si tout s'est bien passé lors du build, il balance le dossier dist/ sur GitHub.

Y'a plus qu'a créer un utilisateur sur GitHub (genre zds-buildbot), de l'ajouter aux contributeurs du répo, et de mettre son mot de passe encrypté dans le .travis.yml (voir http://docs.travis-ci.com/user/encryption-keys/ )

+4 -0

@Sandhose : le problème avec cette méthode c'est que du coup, étant donné que du coup on ne peut pas remerger la release dans dev sans remettre le dossier dist dans dev. 'fin c'est possible, mais faudrait du coup faire plusieurs cherry pick, ce qui rend le processus de release un peu complexe, surtout si on a eu beaucoup de hotfix lors de la release.

Bah, pourquoi on pousserait pas le dossier dist/ sur dev, puisque ça permettrait d'avoir une version relativement a jour du front pour les contributers occasionnels qui n'ont pas forcément la patience d'installer le stack front ?

+0 -0

En plus d'alourdir le dépôt…

Je suis pas sûr qu'une mise à jour du sprite, du CSS et du JS (représente environ 1 Mo) une fois tous les mois aie un réel impacte comparé à la taille du répo actuellement. De plus, si vraiment la taille compte pour quelqu'un qui n'a pas forcément une bonne connexion, les 1.7Mo du dossier dist/ représentent pas grand chose comparé aux 122Mo du projet (en dehors des dépendances) si l'on clone en --depth=0

…on risquerait d'avoir un dist qui n'est plus à jour avec les scss.

C'est pour ça que je parlais de contributeurs occasionnels: un contributeur régulier aura forcément le stack front à jour. Quelqu'un qui vient, qui clone le répo, et installe les dépendances pip pourra faire tourner le site "à peu près", suffisamment pour qu'il puisse faire une modification côté back.


Au passage, ce genre de solutions est déjà en place sur pas mal de projets open-source importants, comme bootstrap, materialize.css three.js ou encore moment.js… Je ne dis pas que tout le monde le fait/doit le faire, mais je vois pas en quoi c'est une mauvaise solution…

+0 -0

Je ne dis pas que tout le monde le fait/doit le faire, mais je vois pas en quoi c'est une mauvaise solution…

Je ne dis pas que la solution est mauvaise, mais ce n'est jamais une bonne idée de conserver des fichiers qui ne sont pas forcément au même niveau de mise à jour sur le dépôt. Et (je n'ai pas trop fouillé) mais je ne sais pas si ça tiendra niveau gestion de conflit si on se retrouve avec des cas un peu tordus (déjà arrivé) comme un hotfix en prod pendant une release par exemple.

En cas de hotfix, il faudra donc push le front compilé avec (donc git add --force ...). Une autre solution sinon serait d'inclure dans le message de commit (qui doit être dispo en variable d'environnement sur Travis, à tester…) un tag genre [front build] dès que l'on release, ou que l'on fait un hotfix (plutôt que de dépendre du nom de la branche)

EDIT: Le message de commit est pas exposé, mais il peut être récupéré via git rev-list --format=%B --max-count=1 $TRAVIS_COMMIT

+0 -0

Bon en y réfléchissant et après discussion, la solution reste d'une propreté douteuse (on balance des trucs "compilés" dans le dépôt) mais il ne semble pas y en avoir de meilleure.

Donc :

  • Tout commit de release provoque le build et le commit du front dans le dépôt (pour que les releases soient correctement buildées sans que ça soit oublié)
  • et tout commit contenant [build front] provoque le build et le commit du front dans le dépôt (pour pouvoir gérer les cas spéciaux)
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte