Garbage Collector


The little space of a writer, tinkerer, and a coffee addict

Blog avec Hugo et publication automatisée

Blog avec Hugo et publication automatisée

AprĂšs avoir mis en place mon nouveau blog avec le gĂ©nĂ©rateur Hugo, il m’avait fallu voir comment automatiser la publication. En effet, Hugo gĂ©nĂšre dans un dossier public/ les pages web statiques et celles-ci doivent ĂȘtre dĂ©posĂ©es sur un serveur web pour les prĂ©senter. Voici donc ce que j’ai construit rapidement pour qu’une publication soit aussi simple qu’un git commit; git push.

Les outils

Voici les outils utilisĂ©s, j’avais d’ores et dĂ©jĂ  ceux-ci Ă  disposition.

Initialisation du site

Pour pouvoir Ă©crire tranquillement mes billets depuis mon PC, j’ai le binaire Hugo installĂ© dessus dans /usr/local/bin. J’ai Ă©galement git installĂ© dessus pour pouvoir communiquer avec mon repo.

Les sources de mon blog seront déposées dans /home/seb/blog. Ce dossier est initialisé par Hugo de la façon suivante :

$ hugo new site blog

Ce qui nous donne le retour suivant :

Congratulations! Your new Hugo site is created in /home/seb/blog.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.

La sortie de la commande nous propose d’installer un thĂšme graphique, vous pouvez choisir celui Ă  votre prĂ©fĂ©rence sur leur site. Pour ma part, il s’agit du thĂšme Casper3. Nous l’installons de la maniĂšre suivante :

$ cd /home/seb/blog
$ git init
$ git submodule add https://github.com/jonathanjanssens/hugo-casper3.git themes/hugo-casper3

L’intĂ©rĂȘt de le cloner en submodule est que le repo du thĂšme sera indĂ©pendant du votre tout en se trouvant dans la mĂȘme arborescence du projet. Cela permet de gĂ©rer les dĂ©pendances tierces d’un projet tout en gardant des commits sĂ©parĂ©s.

Nous ajoutons ensuite ce thĂšme Ă  la config du site.

$ echo 'theme = "hugo-casper3"' >> /home/seb/blog/config.toml

On ajoute un premier article.

$ hugo new posts/first_article.md
/home/seb/blog/content/posts/first_article.md created

On ouvre /home/seb/blog/content/posts/first_article.md avec son Ă©diteur de texte favori (pour ma part j’utilise Zettlr pour la rĂ©daction en Markdown). Dedans vous verrez que le dĂ©but est une entĂȘte au format YAML.

---
title: "First_article"
date: 2021-01-04T16:38:47+01:00
draft: true
---

Mettez drat: false, puis ajoutez un peu de contenu et sauvegardez le fichier.

Le minimum est fait, on peut lancer le serveur de test d’Hugo pour voir ce que ça donne.

$ hugo serve

Se connecter Ă  l’URL http://localhost:1313 et voilĂ  le rĂ©sultat :

hugo1.png

Notez que si vous Ă©ditez le fichier de l’article, Hugo le rechargera Ă  chaque sauvegarde sans avoir besoin de redĂ©marrer le serveur.

Voilà, le site de base est construit. Il nous reste donc à le passer en mode versionné via Git.

Créer le repo Git

Chez votre hébergeur favori, créez un nouveau dépÎt Git. Récupérez ensuite son URL pour pouvoir le définir comme remote dans le répertoire de travail précédemment créé.

$ git remote add origin https://url_du_repo.git
# on consulte les remote pour voir
$ git remote -v
origin	https://url_du_repo.git (fetch)
origin	https://url_du_repo.git (push)

L’Ă©tat actuel du repo devrait ĂȘtre le suivant :

$ git status

Sur la branche master

Aucun commit

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)
	nouveau fichier : .gitmodules
	nouveau fichier : themes/hugo-casper3

Fichiers non suivis:
  (utilisez "git add <fichier>..." pour inclure dans ce qui sera validé)
	archetypes/
	config.toml
	content/

Vous noterez que Git ne voit que le dossier content/ dans lequel se trouve notre premier billet. Git ignore les dossiers vites. Si vous souhaitez les envoyer sur le remote, créez dans chacun des dossiers un fichier caché vide. (ex : touch .emptydir)

Envoyons tout ça chez notre hébergeur.

$ git add -A
$ git status
Sur la branche master

Aucun commit

Modifications qui seront validées :
  (utilisez "git rm --cached <fichier>..." pour désindexer)
	nouveau fichier : .gitmodules
	nouveau fichier : archetypes/default.md
	nouveau fichier : config.toml
	nouveau fichier : content/posts/first_article.md
	nouveau fichier : themes/hugo-casper3

$ git commit -m 'first commit'
[master (commit racine) 56f708b] first commit
 5 files changed, 22 insertions(+)
 create mode 100644 .gitmodules
 create mode 100644 archetypes/default.md
 create mode 100644 config.toml
 create mode 100644 content/posts/first_article.md
 create mode 160000 themes/hugo-casper3

$ git branch --set-upstream-to=origin/master master
La branche 'master' est paramétrée pour suivre la branche distante 'master' depuis 'origin'.

$ git push -u origin master
ÉnumĂ©ration des objets: 10, fait.
DĂ©compte des objets: 100% (10/10), fait.
Compression par delta en utilisant jusqu'à 16 fils d'exécution
Compression des objets: 100% (6/6), fait.
Écriture des objets: 100% (10/10), 895 octets | 895.00 Kio/s, fait.
Total 10 (delta 0), réutilisés 0 (delta 0), réutilisés du pack 0
remote: . Processing 1 references
remote: Processed 1 references in total
To https://url_du_repo.git
 + 28f6a11...56f708b master -> master
La branche 'master' est paramétrée pour suivre la branche distante 'master' depuis 'origin'.

Et voilĂ  c’est envoyĂ©.

hugo_gitea.png

Mise en place du Webhook avec Jenkins

Pour pouvoir automatiser la gĂ©nĂ©ration, il faut que Jenkins (mon moteur de CICD) soit informĂ© qu’il doive dĂ©clencher le traitement associĂ© lorsqu’un commit est poussĂ© sur le repo. Pour cela nous utilisons les Webhooks. Attention, cela nĂ©cessite que le serveur Jenkins soit joignable depuis Internet dans le cas oĂč vous hĂ©bergez depuis GitHub ou GitLab par exemple. Chez moi, ils discutent entre deux sur le LAN.

CrĂ©ation d’utilisateurs

Dans mon cas toutes les actions sont liĂ©es Ă  Gitea, mais elles doivent ĂȘtre similaires pour GitHub ou autre. Adaptez selon votre hĂ©bergeur. Chez votre hĂ©bergeur Git, crĂ©ez un token pour l’utilisateur qui sera chargĂ© de faire les dĂ©ploiements Ă  partir de ce repo.

Enregistrez ce token dans les credentials de Jenkins

deploy_token.png

Allez dans le menu Configure => Configure System de Jenkins pour créer un nouveau serveur Gitea. Mettez en Credentials celui créé précédemment.

gitea_jenkins.png

Jenkins ne permettant pas les connexions anonymes par défaut, il est nécessaire de créer un utilisateur pour ce traitement. Une fois créé, connectez-vous avec pour lui générer un token dans le menu Configure de son profil. Sauvegardez bien ce token, vous ne le reverrez plus.

jenkins_gitea_token.png

Retournez chez votre hébergeur Git et créez un nouveau Webhook au niveau du repo Blog. Dans mon cas sur Gitea voici les instructions à renseigner :

gitea_webhook.png

L’URL cible peut ĂȘtre formĂ©e de la maniĂšre suivante :

https://serveur_jenkins/gitea-webhook/post?job=<Job_a_lancer>

Dans le champ “Secret”, renseignez l’utilisateur et le token de la maniĂšre suivante : user:token. Celui-ci sera envoyĂ© dans la requĂȘte POST pour l’authentification auprĂšs de Jenkins.

Testons le rĂ©sultat avec le bouton “Test delivery”. Celui-ci va envoyer un faux commit via le Webhook.

test_delivery.png

En cas d’erreur :

Jenkins et Gitea discutent entre eux, on peut passer à la suite en créant le job !

Création du job Jenkins

En raison de l’organisation de mes serveurs, j’ai crĂ©Ă© deux jobs : un qui build sur la machine Jenkins et envoie les sources sur le serveur Web, un qui place les sources au bon endroit avec les bons droits. Mon serveur web ne peut pas accĂ©der Ă  Gitea, Jenkins ne peut donc pas l’utiliser comme agent pour build le site localement. Si vous n’avez pas ces contraintes, il suffit de les fusionner.

Je n’ai pas fait trĂšs compliquĂ©, il s’agit de deux jobs Freestyle.

Job Hugo_Build

Hugo_Build est paramétré de la façon suivante :

Il s’agit de ce nom de job qu’il faut mettre dans l’URL du webhook : https://serveur_jenkins/gitea-webhook/post?job=Hugo_Build

Enfin, j’exĂ©cute une simple tache shell qui envoie le contenu du dossier public d’Hugo:

/usr/local/bin/hugo && rsync -avz --delete -r public/ cicd_user@mon_serveur_web:/tmp/hugoblog

La commande rsync permet de synchroniser deux dossiers. Ici, elle est paramĂ©trĂ©e pour supprimer ce qui n’est pas prĂ©sent sur la source. Cela permet donc d’effacer sur le serveur web un article que j’aurais supprimĂ© du Git.

Une derniĂšre Ă©tape post build appelle le job Hugo_Publish

Job Hugo_Publish

Hugo_Publish est encore plus simple. Il est configurĂ© pour s’exĂ©cuter sur le serveur web (Restrict where this project can be run) puis se contente de faire le mĂȘme rsync en interne, mais en mettant les bons droits au passage.

sudo rsync -avz --chown apache:apache --delete /tmp/hugoblog/ /srv/hugoblog

Bien Ă©videmment, adaptez l’emplacement des fichiers Ă  l’emplacement attendu par votre serveur Web !

Et voilà, nous avons toute la chaßne technique de créée !

Testons tout ça

Vu que le job a Ă©tĂ© crĂ©Ă© aprĂšs le commit, nous pouvons le lancer directement dans Jenkins. Si tout va bien niveau droits d’accĂšs, votre premier billet devrait avoir Ă©tĂ© publiĂ© sur votre serveur web.

Pour tester tout la chaßne, il vous suffit de créer ou de modifier le post fait au tout début puis de le pousser sur Git. Si tout va bien, le traitement va se déclencher dans Jenkins puis le résultat sera en ligne au bout de quelques secondes.

N’hĂ©sitez-pas Ă  me faire un retour sur cette mĂ©thode, si vous voyez des axes d’amĂ©lioration ou bien d’autres mĂ©thodes !


📑 Table of Contents

📚 Read my latest book

Follow me on Mastodon

đŸ·ïž All Tags 📄 All Posts đŸ—ș Sitemap RSS Feed