Automatiser la vérification des liens morts avec linkchecker, docker et gitlab
Divulgâchage : Laisser des liens morts, c’est mal. Les vérifier, c’est bien, mais si c’est manuel, on oubliera et ça sera mal. Alors pourquoi pas l’automatiser à chaque déploiement ?
Lorsqu’on s’occupe d’un site web, il n’est jamais bon de laisser traîner des liens morts. Au delà de l’impression que ça donne aux internautes, c’est pour moi une histoire de respect. Bon d’accord, c’est aussi une histoire de SEO.
Pour les vérifier, il y a bien sûr plein d’outils, mais quid de l’automatisation ? Soyons honnêtes, c’est comme pour tous les tests ; si on doit les lancer à la main, c’est contraignant, on oublie et comme chaque fois qu’on ne teste pas, il y a des erreurs.
Alors aujourd’hui, pour votre plus grand bonheur, nous allons vous montrer comment nous avons automatisé cette vérification sur le site des arsouyes.
Linkchecker
Linkchecker est un outil python en ligne de commande qui permet de parcourir un site en suivant les liens. Il a le bon goût de fournir un résumé (nombre de warning, nombre d’erreur) et d’être configurable pour correspondre à nos besoins.
Le projet principal n’as plus eu de commit depuis trois ans mais un fork existe avec des correctifs.
Plutôt qu’utiliser les dépôts, qui pointent vers l’ancienne version, nous allons donc suivre la documentation du nouveau projet et utiliser pip.
pip install git+https://github.com/linkchecker/linkchecker.git
L’utilisation de base n’est pas compliquée, dans notre cas, nous avons ajouté deux options :
linkchecker https://www.arsouyes.org/ \
--check-extern \
--ignore-url=https://mafreebox.free.fr
- Nous activons la vérification des liens externes, pour s’assurer que les pages existent toujours et pouvoir adapter notre contenu en conséquent.
- Nous écartons les liens de configuration de la freebox, puisqu’ils seront bloqué par son contrôle d’accès.
Docker
On pourrait installer une machine dédiée, mais comme le but est de tester différentes versions du site… éventuellement dans des branches, voir en parallèle, lorsqu’on écrit comme des possédés, il est bien plus pratique d’utiliser un conteneur docker qui contiendra les deux outils :
- apache2 pour servir le site, comme en prod ;
- linkchecker pour tester le site local.
On pourrait utiliser deux conteneur, apache2 étant configuré comme service. Mais ça pose le problème de copier les fichiers du conteneur de test vers celui du service, ce qui n’est pas documenté et s’annonce bien plus compliqué à faire que de tout mettre dans une seule machine.
On commence donc par le système de base. Arbitrairement Ubuntu mais techniquement, ça pourrait marcher avec n’importe quel autre dérivé de Debian (ou n’importe quelle autre distribution en adaptant la récupération des paquets).
FROM ubuntu:latest
Par contre, comme ce conteneur sera utilisé par gitlab pour lancer des scripts de tests, il y a quelques subtilités à prendre en compte par rapport aux conteneurs dockers habituels.
Serveur web apache
L’utilisation d’apache n’est fondamentalement pas compliquée. Il suffit d’installer le paquet, d’activer des modules et de copier les fichiers de configuration. Comme la prod utilise HTTPS, nous l’activons aussi, avec une PKI créée pour l’occasion.
RUN apt-get update && apt-get install -y \
apache2
RUN a2enmod rewrite
RUN a2enmod ssl
ADD fake_www.pem /etc/ssl/private/
ADD fake_www.crt /etc/ssl/certs/
ADD fake_root.crt /etc/ssl/certs/
ADD apache.conf /etc/apache2/sites-enabled/000-default.conf
C’est ici qu’intervient la différence avec un conteneur apache2 classique. Comme apache2 ne sera lancé que si on le demande, et que docker n’aime pas s’il tourne en fond, il est d’usage d’utiliser le point d’entrée suivant :
CMD /usr/sbin/apache2ctl -D FOREGROUND
Pour nous, c’est inutile de le mentionner car Gitlab remplacera le point d’entrée du conteneur par ses propres scripts. Par contre, il ne faudra pas oublier de lancer apache2 lors des tests.
Linkchecker
En lui-même, il n’est pas compliqué à installer, on ajoute python, pip et git, puis on lance l’installation comme déjà mentionné :
RUN apt-get update && apt-get install -y \
python \
python-pip \
git
RUN pip install git+https://github.com/linkchecker/linkchecker.git
Si on lance linkchecker sur localhost
maintenant, outre
le manque de fichier à servir, on obtiendra des erreurs de connexion TLS
puisque notre PKI n’est pas installée. On va donc forcer l’ajout de
notre CA aux autorités déjà dans le système :
ADD fake_root.crt /usr/local/share/ca-certificates/
RUN update-ca-certificates
La petite blague est que ces commande vont générer un avertissement
car notre CA est détectée en double (l’autre copie étant dans
/etc/ssl/certs/
, pour apache) mais lors de nos tests, nous
avions des erreurs tant que nous n’avions pas copié la CA…
Giglab
Le reste se passe donc dans la configuration de l’intégration
continue, le fichier .gitlab-ci.yml
.
Phase de préparation
La première phase de la construction du site est, chez nous, la construction des conteneurs. Nous pourrions le faire dans un projet à part mais nous avons trouvé plus pratique de regrouper tout dans un seul projet.
La configuration en elle-même n’est pas compliquée et suit la documentation officielle :
- Nous utilisons une machine spécifique avec une exécution
shell pour construire les conteneurs, on configure donc un
tag
pour restreindre ce job à ce type de machine ; - Comme le conteneur construit sera utilisé par la suite, on doit donc se connecter au registre (première tâche) et à la fin, lui pousser la machine construite (dernière tâche) ;
- Comme on reconstruit à chaque fois, mais qu’on ne modifie que rarement le conteneur, on récupère l’ancien (deuxième tâche) qu’on utilise en cache lors de la construction (troisième tâche) et gagner beaucoup de temps.
Docker utilisant ce cache pour éviter de lancer les commandes (i.e.
apt-get update
), le conteneur n’est donc pas à jours. Sur certains projets, ça peut être génant mais pour notre cas d’usage, c’est acceptable.
variables:
IMG_CHECK : docker.arsouyes.org/$CI_PROJECT_PATH/check:$CI_COMMIT_REF_NAME
prepare:deploy:
stage: prepare
tag:
- docker-build
script:
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN docker.arsouyes.org
- docker pull $IMG_CHECK || true
- docker build --cache-from $IMG_CHECK --tag $IMG_CHECK docker/check
- docker push $IMG_CHECK
Phase de test
C’est ici que toutes les briques sont mises ensemble, les derniers ajustements fait avant de lancer le parcours du site.
Résolution DNS
Comme nous voulons tester comme en prod, nous avons produit
le site avec les références de prod
(i.e. www.arsouyes.org
plutôt qu’un sous-domaine
spécifique). Au risque de parcourir la prod, il est donc nécessaire de
rediriger ce domaine vers la machine locale.
echo "127.0.0.1 www.arsouyes.org" >> /etc/hosts
On pourrait vouloir mettre cette ligne dans la configuration du
conteneur docker (et c’est ce que nous avions fait). Après tout, c’est
une configuration d’environnement non ? Le problème, c’est que ce
fichier sera écrasé lors du chargement du conteneur par gitlab et la
redirection sera donc oubliée. On doit donc garder cette étape lors du
test, dans le yaml
.
Configuration apache
Comme promis, c’est maintenant que nous allons lancer apache2.
/usr/sbin/apache2ctl start
Il faut aussi déployer le site. Plutôt que de faire une copie, vu que nous sommes sur la même machine, nous allons faire un lien symbolique. Si vous n’êtes pas sous ubuntu, vous devrez peut être adapter le répertoire.
rm -rf /var/www/html
ln -s $(pwd)/public /var/www/html
Job complet
La tâche complète consiste donc à enchaîner ces étapes pour finir par le parcours du site à la recherche des liens morts.
check:links:
stage: check
image: $IMG_CHECK
script:
- echo "127.0.0.1 www.arsouyes.org" >> /etc/hosts
- rm -rf /var/www/html
- ln -s $(pwd)/public /var/www/html
- /usr/sbin/apache2ctl start
- linkchecker https://www.arsouyes.org/ --check-extern --ignore-url=https://mafreebox.free.fr
Conclusion
Grâce à cette étape, on peut maintenant vérifier le site avant même qu’il parte en production et éviter les liens morts, par construction.
Effet secondaire, cette vérification se fait également dans n’importe quelle branche et évite donc les mauvaises surprises après les merges.
Et après ?
- Site statique
- 27 Septembre 2017 - tbowan. Après avoir expérimenté le PHP, nous revenons aux sources avec une génération statique du site des arsouyes. Pour les curieux, voici comment nous nous y sommes pris.
- Déployer un site web via sftp et Gitlab
-
10 juin 2019 Avec notre nouvel hébergement, nous avons
du revoir nos scripts de déploiement continu. Remplacer
rsync
parlftp
n’est pas compliqué mais nécessite de fournir les données d’authentifications à l’environnement de déploiement. Heureusement, gitlab fournit une méthode sécurisée pour protéger ces informations sensibles.