31
Oct 19

Chaîne CI/CD avec SAS Studio


L'approche CI/CD (intégration continue et développement continue en français) se propose d'augmenter la fréquence de livraison et d'améliorer la qualité des livrables en automatisant ces étapes. Nous pouvons grossièrement résumer les étapes de développement ainsi:
- Les développeurs récupèrent d'un repo central le projet,
- Ils développent localement,
- Ils effectuent leurs tests,
- Ils poussent leurs modifications dans le repo central.
L'exécution des tests et le "push" sont automatisés dans l'approche CI/CD.

Si la tâche des développeurs s'arrêtent ici, la chaine CI/CD, elle, continue. Les livrables sont ensuite poussés dans un premier environnement où seront effectués des tests d'intégration et de non régression. Le développeur est informé du résultats des tests. S'ils sont acceptés, les livrables sont déployées dans l'environnement suivant pour y subir encore des batteries de tests (user acceptance, ...) et ainsi de suite. Il s'agit de cycles itératives qui sont répétés jusqu'à l'obtention d'une version satisfaisante appelé release.

S'il est relativement simple de mettre en place cette approche avec des langages comme Java - il suffit d'une jvm, d'un IDE qui supporte Git sur son poste local et qui intègre JUnit directement -, avec SAS cela devient rapidement compliqué pour de multiples raisons. En voici quelques unes:
- Les développeurs disposant d'un moteur SAS sur leur machine desktop développent pour leur propre besoin et n'ont généralement pas vocation à mettre en commun leurs développements.
- Les développeurs travaillant sur un serveur commun ne disposent généralement pas de moteur SAS local. Tous leurs développements doivent donc se faire en partageant les ressources du serveur.
- Le serveur est sur Linux et les machines desktop sur Windows. S'il n'est pas possible de faire de partage Samba entre ces machines, il n'y a pas d'autres possibilités que de travailler sur le serveur. les développeurs travaillent sur la même version du projet.
- Le problème se complexifie encore plus si le projet nécessite une ou des bases de données pour le stockage (des datamarts et/ou des solutions métiers) et d'application Web (Visual Analytics, Web Report Studio, Solutions métiers) pour des raisons de coûts de licence et d'infrastructure.
- Les développeurs SAS ne se contentent pas seulement de créer / modifier des programmes SAS et peuvent être amenés à mettre à jour des ddl, manipuler des fichiers de configurations en Excel, des métadonnées ...

Mise en place de la chaîne CI/CD

De quoi avons nous besoin pour construire une chaîne de développement CI/CD ?
- D'environnement de développements et d'intégration séparés,
- D'un outil de gestion de versions - CVS en anglais - (Git, SVN, ...),
- D'un repo central (GitHub, GitLab, TFS, ...),
- D'un framework de tests (Expresso, JUnit, SASUnit, ...),
- D'un orchestrateur qui s'occupe du workflow en lui même(Jenkins, ...).

Séparation des environnements

La complexité dépend de l'architecture :
- Si le serveur SAS tourne sous Windows, il est possible d'avoir un dossier commun dans lequel les utilisateurs ont leur propre dossier, accessible par le serveur. Dans ce cas le serveur SAS peut être utilisé comme environnement d'intégration.
- Si le serveur SAS tourne sous Linux et qu'il est possible de faire un montage Samba, nous nous retrouvons dans le cas précédent.
- Si les développeurs travaillent directement sur le serveur, il leur faudra un dossier dédié. S'il est possible d'avoir une machine d'intégration, cela diminuerait la complexité.

Le cas le plus complexe est donc lorsqu'il faut partager le serveur entre les développeurs et qu'il héberge l'environnement d'intégration également. Comment peut-on alors ségréger les développeurs et l'environnement d'intégration dans un même environnement mutualisé ? Une tentative de solution consiste à créer une branche dans le repo distant par développeur ainsi que pour l'intégration. Chaque commit validé part dans sa branche distante. Si les tests sont validés, les développements sont poussés dans une nouvelle branche local du dossier local d'intégration où ils subiront d'autres tests:
Une fois les tests d'intégration et de validation effectués, les développements qui sont dans une sous-branche local sont fusionnés dans la branche local d'intégration (git merge) puis sont poussés dans la branche distante d'intégration. S'ils ne sont pas bons, la sous-branche local est supprimé.

Cette architecture présente toutefois quelques difficultés à mettre en place, notamment au niveau de la gestion des droits:
- Les dossiers des utilisateurs devraient être en read/write pour le développeur uniquement,
- Le dossier d'intégration uniquement en read/write pour les utilisateurs du groupe des testeurs,
- Le compte effectue les pull/push devrait avoir des droits étendus (sudo, chmod, chgrp, etc...) pour pouvoir effectuer ses tâches.

Gestion de versions

Depuis la maintenance 6 de la plateforme SAS 9.4, SAS dispose de nouvelles fonctions pour s'intégrer aussi bien avec un repo Git local qu'un repo Git distant. Voici le lien vers la documentation vers ces nouvelles fonctions: Using Git Functions in SAS.

SAS Studio intègre directement dans son interface le support de ces fonctions et permet donc de s'affranchir de coder. La documentation officielle décrit très bien cette intégration: Understanding Git Integration in SAS Studio.

Brièvement, nous pouvons dire que SAS Studio supporte:
- L'intégration avec un dépôt distant (supporte les fonctionnalités pull/push).
- La consultation de l'historique des pull/push.
- La gestion d'un repo Git local(git status, git commit, création de branches, ...).

La documentation détaille également les étapes de configuration.

Deux limitations cependant:
- La version à date ne gère pas les hooks. Il est possible de contourner cette limitation en surchargant le script GitServices.js de manière à ce qu'il exécute le hook,
- L'historique ne fonctionne que si la branche principale s'appelle master. Cette limitation peut être contourner en ajoutant un alias à la branche mère. Par example pour la branche intégration:
git symbolic-ref refs/remotes/origin/master refs/remotes/origin/integration
git symbolic-ref refs/heads/master refs/heads/integration

Notre préférence va donc pour l'utilisation de Git et son équivalent distant.

Framework de tests

SAS ne dispose pas nativement de framework de tests. Cependant Andreas Mangold et Klaus Landwich ont créés un framework de tests 100% écrit en SAS. Ce framework se composent d'une collections de macro SAS qui peuvent être utilisés pour exécuter le code et vérifier les résultats basiquement en comparant les résultats obtenues après l'exécution du code avec les résultats escomptés. SASUnit produit également un rapport HTML contenant les résultats des tests.

Le framework est téléchargeable ici. Le site documente largement son utilisation. L'archive téléchargé contient:
- les macros SAS du framework,
- des programmes de tests exemples,
- des exemples de binaires qui vont exécuter les tests.

Voici l'architecture applicative du Framework:



Fonctionnalité des dossiers:
- example : contient les programmes d'exemples
- bin: les binaires d'exécution des tests
- dat: les données de tests
- doc: les sorties des tests (html, images, log, ...)
- saspgm: les programmes de tests
- resources : contient les ressources utilisées pour générer les rapports (html, css, iamges, scripts javscript...)
- saspgm : contient les macros SAS du framework en lui-même.
- sasunit: les macros SAS
- linux: les macros spécifiques à Linux
- unix_aix: les macros spécifiques à unix_aix
- Windows: les macros spécifiques à Windows
(* Les macros du framework font appellent à des commandes systèmes c'est pour cela qu'il existe des macros spécifiques à un OS en particulier. Il faut s'assurer que le serveur d'exécution utilisé peut exécuter des commandes systèmes)

Les binaires proposés exécutent le programme SAS run_all.sas qui lance l'ensemble des programmes SAS suffixé par _test situé dans le répertoire saspgm.

Les programmes de tests doivent respecter une certaine structure :

Pour automatiser l'exécution de ces tests après un commit, il suffit de créer dans la branche locale du développeur un hook post-commit qui appel le binaire de SASUnit.

L'orchestrateur

L'orchestrateur va organiser le workflow. Il peut être utilisé pour l'exécution des tests unitaires, des livraisons entre les environnements, ...
Jenkins est souvent utilisé pour cette tâche. SASUnit générant des rapports HTML, il faut installer le plug-in HTML Publisher.

Dans notre cas, nous avons besoin d'un build qui:
- pousse dans la branche distante du développeur les développements,
- exécute les tests unitaires du développeur,
- S'ils sont bons, déclenche le buid intégration.
Celui-ci effectue les action suivantes:
- créés une nouvelle branche locale temporaire dans le repo local intégration,
- pull la branche distante du développeur vers la nouvelle branche locale temporaire,
- exécute les test d'intégration et non de régression ,

Les builds Jenkins peuvent être appelés par des commandes curls. Afin de pouvoir déclencher des builds Jenkins à l'aide de commandes curl, quelques étapes sont nécessaires:
- Créer un token pour l'utilisateur. Généralement, l'on définie un compte administrateur de service. Le token se crée dans l'interface Jenkins -> Utilisateur -> Compte technique -> Configurer -> API TOKEN
- Récupérer son crumbIssuer. Pour cela il faut entrer dans le navigateur l'adresse suivante: http[s]://<url du serveur Jenkins>:<Port du serveur Jenkins>/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)

La commande curl pour déclencher le build est de la forme:
curl -I -X POST "http[s]://<login>:<API TOKEN>@<url jenkins>:<port jenkins>/job/<nom du build>/build?token_name=SASAPITOKEN" -H "Jenkins-Crumb:<crumbIssuer>"

CI/CD avec SAS Studio en action

Voici une petite vidéo illustrant un petit cas pratique d'exécution d'une chaîne CI/CD avec SAS Studio.


Merci de votre lecture.