You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
blog/posts/2020/2020-02-16-rust-ci.md

78 lines
4.5 KiB
Markdown

5 years ago
<!-- title: Intégration continue d'un projet Rust -->
<!-- category: Développement -->
Mon projet d'apprentissage de Rust avance doucement et c'est volontaire. Je prends le temps d'améliorer ma centaine de lignes de code, d'écrire des tests unitaires et je continue à lire sur Rust : la newsletter hebdomadaire et des liens sur [Reddit](https://www.reddit.com/r/rust/). <!-- more --> Suite à la découverte de [Clippy](https://github.com/rust-lang/rust-clippy), l'utilitaire de détection d'erreurs de programmation, j'ai revu un code qui fonctionnait mais avait des failles potentielles et abusait du type *String* alors que des littéraux faisaient l'affaire. J'avais peu à peu mis des String partout pour ~~simplifier~~ contourner le borrowing (un classique du débutant en Rust semble-t-il) et par manque de vision sur la manière dont ma fonction serait utilisée.
Finalement, j'ai un petit bout de mon projet (un seul module) avec ses tests unitaires, suffisamment complet pour mettre en place une intégration continue. Késako ? Il s'agit de s'assurer de la qualité du code au fur et à mesure de son écriture pour garantir une bonne qualité en fin de développement en incitant le développeur à améliorer son code tout au long du cycle. On peut aller plus ou moins loin dans les attentes d'une intégration continue :
1. vérifier que le code compile,
2. vérifier que les tests unitaires s'exécutent sans erreur,
3. mesurer la couverture de code des tests,
4. vérifier la conformité par rapport à des règles : formatage, commentaires ou autre,
5. déployer le résultat pour le mettre à disposition mais on empiète sur la CD (Continuous Delivery).
5 years ago
A une autre époque, j'aurais mis en place un Gitlab et une chaîne d'intégration de A à Z, j'aurais tâté du système, fait du scripting, déployé des containers, appris plein de trucs... Aujourd'hui je dois faire rapide et efficace donc j'ai tablé sur les fournisseurs de CI en ligne (Cloud CI providers pour les anglos) qui peuvent s'interfacer avec mon projet sur GitHub. J'ai testé Circle CI et Travis CI et c'est ce dernier qui m'a semblé [le mieux gérer les projets Rust](https://docs.travis-ci.com/user/languages/rust/).
Techniquement, c'est très simple : on ajoute un fichier de configuration *.travis.yml* à son projet GitHub qui définit le pipeline d'intégration, on se connecte à Travis avec son identifiant GitHub et on configure son projet, et hop. A chaque commit Git, Travis déroule pipeline d'intégration.
5 years ago
Ma configuration pour Rust a quelques particularités :
- on peut construire le projet avec la version stable, beta et nightly de Rust afin de prévoir les problèmes de compatiblité avec les prochaines versions. Je me suis limité à stable et beta
- Je ne m'arrête pas à la compilation et au déroulement des tests sans erreurs. La détection de *mauvais code* par Clippy est fatale et casse le build. Je suis là pour apprendre à écrire du bon code Rust, autant compliquer les choses.
- la couverture de code est réalisée à partir du binaire avec un outil non spécifique à Rust qui à partir des informations de déboguage d'un binaire calcule le taux de couverture du code par des tests. Cet outil s'appelle kcov.
Mon fichier de configuration *.travis.yml* :
```yaml
language: rust
sudo: required
rust:
- stable
- beta
before_script:
- rustup component add clippy
script:
- cargo clippy
- cargo test
jobs:
fast_finish: true
cache: cargo
addons:
apt:
packages:
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- cmake
- gcc
- binutils-dev
- libiberty-dev
after_success: |
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz &&
cd kcov-master &&
mkdir build &&
cd build &&
cmake .. &&
make &&
make install DESTDIR=../../kcov-build &&
cd ../.. &&
rm -rf kcov-master &&
for file in target/debug/stacorust-*; do [ -x "${file}" ] || continue; mkdir -p "target/cov/$(basename $file)"; ./kcov-build/usr/local/bin/kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
bash <(curl -s https://codecov.io/bash) &&
echo "Uploaded code coverage"
```
Les résultats de build avec moult détails son publiés sur le site de Travis CI : https://travis-ci.org/kianby/stacorust
et ceux de la couverture de code sur le site CodeCov : https://codecov.io/gh/kianby/stacorust
![badges](/images/2020/ci-badges.png)
> Cerise sur le gateau, on peut intégrer les badges sur la page README du projet pour avoir une vue synthétique de l'intégration continue.