CI/CD: build et distributions des sites web via GitLab Pages

Salut !

Il y a actuellement plusieurs sites qui sont gérés depuis la forge git.duniter.org et qui ont besoin d’être compilé à chaque changement :

Je ne sais pas pour moneda-libre.org. Je ne sais plus pour la doc de silkaj. Ni pour les autres sites…
Mais on a plein de besoins avec d’autres sites à venir !

Ça concerne aussi bien les sites statiques (SSG) comme le site de la monnaie libre que les single page application (SPA) comme wotwizard. ping @Paidge

Le problème, c’est que le workflow n’est pas super optimisé je trouve.

Voici l’état actuel du fonctionnement :

Les sites sont sur le serveur de @poka, et un webhook est configuré sur gitlab pour chaque site pour envoyer à api.monnaie-libre.fr le fait qu’un changement a eu lieu dans le dépôt.
Ensuite, api.monnaie-libre.fr tire les changements et rebuild le site en question sur le serveur en faisant quelque chose comme :

cd /home/axiom/apps/monnaie-libre-fr
git fetch --all
git checkout --force origin/master
unset NODE_ENV
yarn install
yarn generate --color

Et le serveur nginx sert les fichiers compilés du dossier dist.

Ne pourrait-on pas builder le site dans la CI ?

Au lieu de faire le build sur le serveur, ce serait plus pratique de le faire dans la CI avec un fichier .gitlab-ci.yml que l’on pourrait configurer comme l’on veut. On aurait le résultat de la CI avec gitlab qui serait conservé et dispo avec graphql. Car actuellement, je ne sais même pas si le build a planté ou pas sur le serveur.

Ensuite, il n’y aurait plus qu’à synchroniser le dossier dist entre la CI et le serveur.
Comment la CI peut mettre à jour un site sur un autre serveur ?
Je suis nul en CI/CD. Ça doit bien être possible de faire ça ?

Aussi, sur github, certain dépôt on buildé le site pour chaque pull request et on peut “visiter” le site en l’état sur une url dédié. On peut faire ça avec gitlab actuellement ?

ping @1000i100 @Moul

Avec des outils monorepo, il y a des trucs à faire aussi.
Cet article de turborepo explique comment ils simplifient la CI : Remote Caching – Turborepo

1 Like

Est-ce que ces sites utilisent la même technologie ?
Ça permettrait d’avoir une image Docker de base pour tous les construire.
Une fois construits ils sont distribués via GitLab Pages.
Les fichiers plats des sites seraient disponibles sur le serveur Doppler.

Il est peut-être possible d’avoir pages sur un autre serveur, à creuser.
Puis distribués via Nginx, configuration qu’on peut adapter.

Je ne connais pas le fonctionnement de GH. Tu veux dire que tu peux consulter le site dans différents états ? À chaque commit, par PR ? C’est pas possible à ma connaissance avec GitLab.

Ils ont node.js en commun, ensuite différente config.

Les “fichiers plats”, c’est ce que j’appel les fichiers compilés ?
C’est quoi le serveur Doppler ?

Oui, c’est ça ! Pour chaque pull request ça créé un “deploy preview” qui se met à jour quand on ajoute des commits à la branche. C’est plutôt Netlify qui fait ça, mais il y en a d’autres comme Vercel…

1 Like

Est-ce différentes stacks Node.js ? VuePress pour le site de Silkaj. Y’en-a-t-il d’autres ?

Oui, SSG

Le serveur qui héberge GitLab et les sites web duniter.org duniter.fr entres-autres via cette technique.

Avec ce nouveau fonctionnement, est-ce que api.monnaie-libre.fr fait encore sens ?

Ok, j’ai regardé un peu en détails ces trois dépôts, ils partagent tous en commun le framework nuxt v2.
Nuxt.js pourrait être installé dessus une image Node.js, afin de ne pas le re-télécharger et réinstaller à chaque build.

Est-ce que cette solution GitLab Pages t’irais ?

Ça semble pas spécialement intéressant d’avoir Nuxt v2 pré-installé.
Partir sur une image Node.js devrait fait l’affaire.


@ManUtopiK, j’ai réussi à installer les dépendances et générer le site web pour les sites ML et carte.
Ils nécessitent Node v16, ça ne fonctionne pas encore avec v18.

Pour ML et carte, ça va publier à chaque commit sur la branche principale master.


@Paidge, j’ai également réussi à construire WW II qui nécessite npm install, npm run build et yarn generate.

Pour WW, est-ce que tu préfères que ça publie à chaque commit sur la branche principale master ou lorsqu’il y a un tag et/ou + action manuelle ?


Je vous propose dès que possible une configuration GitLab-CI pour ces trois dépôts/projets.
Puis, j’adapterais la configuration Ansible pour notre infra, pour que les sites soient servis sur le serveur Doppler.

Ça vous va ?

1 Like

J’avoue que le tag me paraît plus pertinent puisque j’ai tendance à commiter un peu à l’arrache :stuck_out_tongue: Mais comme je crée des tags pour les moments vraiment importants dans le développement alors oui ça me paraît parfaitement coïncider à mon mode de fonctionnement :slight_smile:

1 Like

Merci @Moul de regarder tout ça !

Oui, il vaut mieux partir sur une image node.js que un nuxt v2 pré-installé. Surtout que je suis en train de migrer plein de chose sur nuxt v3…

Pour l’instant, que ça publie à chaque commit sur la branche principale master c’est super. On pourra affiner par la suite…

C’est là où je ne comprends plus comment tout ça marche.
Le serveur Doppler, c’est là où travail la CI, ou c’est là que la CI dépose les fichiers et c’est Ansible qui pointent vers ces fichiers ? Et gitlab pages dans tout ça ?

Avec ta solution, il faudrait faire pointer les domaines vers le serveur Doppler du coup ?

On y est presque !
Le truc génial si on arrivait à faire ça ce serait :

  • un nouveau commit ou tag sur la branche master : la CI dépose les fichiers plats sur le serveur de @poka.
  • une nouvelle branche : la CI build cette branche et la dépose et sert avec Doppler sur une url dédiée par branche. Elle se met à jour à chaque nouveau commit sur cette branche.

Avec ce fonctionnement, on pourrait développer des nouvelles fonctionnalités facilement en ligne, et être sûr du contenu en prod.

Pour déposer sur le serveur de @poka, il m’a dit que le CI pouvait faire un rsync. Il m’a sorti ça avec chatGPT, il faut adapter :

voici une fonction bash pour envoyer en rsync (avec lien vers ma clé
privé ssh) le build du site monnaie-libre.fr à la fin de la CI de notre
gitlab (git.duniter.fr):

#!/bin/bash

# Envoie du build du site monnaie-libre.fr avec rsync

# Récupération des informations nécessaires

REMOTE_HOST="git.duniter.fr"
REMOTE_USER="gitlab-runner"
REMOTE_PATH="/var/www/monnaie-libre.fr"
LOCAL_PATH="/home/gitlab-runner/build_site"
SSH_KEY="/home/gitlab-runner/.ssh/gitlab-runner_ssh_key"

# Envoi du build avec rsync

rsync -avz -e "ssh -i $SSH_KEY" ${LOCAL_PATH}/
${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}

voici le ficher yaml pour la CI gitlab du dépot du site web
monnaie-libre.fr (nuxtjs):

image: node:14.5.0

variables:
  CI_DEBUG_MODE: "true"

cache:
  paths:
    - node_modules/

before_script:
  - npm install

pages:
  script:
    - npm run build
  artifacts:
    paths:
      - build/

deploy:
  stage: deploy
  script:
    # Envoie du build du site monnaie-libre.fr avec rsync
    - ./deploy-site.sh
  only:
    - master
  except:
    - branches

Voici le contenu du fichier deploy-site.sh:

#!/bin/bash

# Envoie du build du site monnaie-libre.fr avec rsync

# Récupération des informations nécessaires

REMOTE_HOST="git.duniter.fr"
REMOTE_USER="gitlab-runner"
REMOTE_PATH="/var/www/monnaie-libre.fr"
LOCAL_PATH="/home/gitlab-runner/build_site"
SSH_KEY="/home/gitlab-runner/.ssh/gitlab-runner_ssh_key"

# Envoi du build avec rsync

rsync -avz -e "ssh -i $SSH_KEY" ${LOCAL_PATH}/
${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}
1 Like

J’ai trouvé cette explication où il se connecte en ssh au serveur distant et fait un curl pour récupérer les fichiers plats.
Le problème c’est de savoir où sont les fichiers plats ?

Sinon, il y a scp aussi, mais la solution rsync de poka me semble mieux…

Cette autre page fait ça en se connectant en ssh et en faisant un git pull (ce que je fais finalement via api.monnaie-libre.fr, sauf que là c’est la CI qui le fait). Mais cette solution a le problème que je mentionne : ce n’est pas la CI qui build le site.

C’est le serveur où il y a GitLab. Les jobs tournent sur les runners qui sont sur d’autres serveurs. Les artefacts/Pages sont rappatriés sur Doppler. Actuellement, les fichiers statiques des sites web servis sont servis par le serveur Doppler.

Ansible gère entre-autres notre configuration Nginx pour faire pointer le nom de domaine vers le dossier des fichiers statiques. GitLab Pages est la fonctionnalité de GitLab qui gère le déploiement des artefacts générés pour être publiés.

Oui, est-ce que ça irait ? Est-ce préféré de les avoir sur l’infra de poka/axiom ?
Il est possible qu’ils soient distribués sur un autre serveur avec cette solution. Mais, si je comprends bien cette solution, c’est que tous les Pages seraient distribués par un autre serveur. Ça ne semble pas granulaire.
Ça aurait été bien, car Doppler commence à servir beaucoup de sites.

Sinon, pour ne pas devoir mettre en place une authentification ssh pour rsync, il est possible de télécharger les artefacts générés via l’interface de GitLab et son API. Je ne sais pas à quel point c’est possible de mettre en pratique.

Par exemple, sur la droite le bouton “Download”, pour télécharger l’artefact du site web de Silkaj.

1 Like

Merci pour toutes tes explications. Je pense comprendre un peu mieux l’infra !

Non, je pense qu’on va rester sur l’infra axiom. Surtout si Doppler sert beaucoup de sites.
Je viens de voir ta branche avec le .gitlab-ci.yml, génial, merci !
Je vais essayer de me dépatouiller avec ça…

Ok.

@Paidge, souhaites-tu que WotWizard soit distribué via Pages?
Je vois que wotwizard.duniter.org redirige vers wot-wizard.duniter.org et que ce dernier affiche l’interface de WW backend.

Propositions :

Je ne sais pas. Qu’est-ce que cela implique ? Déjà que je ne suis pas très doué en administration serveur alors depuis que je fais du Nuxt avec NodeJS, je suis complètement largué. Et, de plus, je n’ai jamais vraiment compris le fonctionnement de la CI/CD avec Gitlab :confused: Même si j’ai essayé d’instalelr le runner sur on de mes serveurs une fois.

Surtout, ce que j’aimerais, c’est qu’il y ait un nouveau build pour chaque nouveau tag. Ensuite, pour le serveur d’hébergement et le nom de domaine, j’ai envie dire peu importe. Si on doit changer d’URL, ce n’est pas forcément gênant si on met en place une redirection 301