- L’une des méthodes utiles pour une équipe de développement pour collecter et préserver les connaissances de l’organisation consiste à enrichir progressivement une collection de snippets, de scripts ou de workflows utiles
- C’est pourquoi de nombreux dépôts finissent par contenir des éléments comme des
Makefile ou des scripts bash
- Mais comment gérer, à l’échelle de toute l’organisation, des tâches comme l’installation d’outils utiles, la génération de code boilerplate ou l’exécution de commandes AWS complexes dont personne ne se souvient ?
- Certaines entreprises, comme Slack ou Shopify, disposent de leur propre CLI interne
- Le terminal moderne Warp propose aussi des fonctions pour documenter et partager des workflows
- Il est facile de créer une CLI à usage interne. Voici par exemple la création d’une CLI pour une entreprise appelée acme
Exigences de conception de la CLI
- Disposer d’un point d’entrée commun permettant d’exécuter des commandes partout avec
acme <command>
- Tous les développeurs peuvent lancer
acme <command> de n’importe où pour déclencher une commande, sans avoir à se déplacer d’abord dans un dépôt précis
- Permettre aux développeurs de contribuer facilement de nouvelles commandes
- Permettre de déployer facilement une nouvelle version avec
acme update
- Prendre en charge le multiplateforme (par ex.
acme download something utilise curl sous Linux et Invoke-WebRequest sous Windows)
- Permettre d’afficher avec
acme list la liste des commandes disponibles et une courte description
Démarrer le projet avec just
- just est un outil similaire à
make, mais spécialisé dans l’exécution de commandes
- Il prend en charge le multiplateforme et peut aussi exécuter des commandes spécifiques à une plateforme
- Parmi les autres options, on trouve
magic-cli de Slack (excellent pour démarrer si vous maîtrisez bien Ruby) ou make
Mise en place du projet
- Installer
just. Suivre les instructions ici
- Créer le dossier
~/acme/cli et ajouter à la racine le justfile suivant :
default:
just --list
# Show arch and os name
os-info:
echo "Arch: {{arch()}}"
echo "OS: {{os()}}"
- Dans la documentation de
just, les commandes sont appelées des « recipes »
- Si l’on exécute
just sans recipe, la première recipe du justfile est lancée. Il est courant de nommer cette première recipe default
$ just
just --list
Available recipes:
default
os-info # Show arch and os name
- La recipe
default exécute just list. Elle affiche la liste de toutes les recipes et leurs commentaires
- Il est préférable de masquer la recipe
default
- Lorsqu’on exécute une recipe, chaque commande s’affiche avant son exécution. Il est possible de supprimer cet affichage avec le préfixe
@, comme dans un Makefile
[private]
@default:
just --list
# Show arch and os name
@os-info:
echo "Arch: {{arch()}}"
echo "OS: {{os()}}"
Créer l’alias acme
Écrire de nouvelles recipes
Recipe simple
Recipe spécifique à une plateforme
- Un snippet utilisant un outil comme
systemd ne doit être exposé que si le développeur utilise une machine Linux
- Utiliser l’attribut
[linux] pour n’exposer la recipe que sous Linux
[linux]
@list-systemd-services:
systemctl list-units --type=service
Recipe multiplateforme
Recipe script
- Il est possible d’intégrer un script complet dans une recipe
- Une recipe qui commence par un shebang (
#!) est enregistrée dans un fichier séparé puis exécutée
- C’est utile lorsqu’un workflow a besoin d’une logique un peu plus complexe, comme du contrôle de flux (if-else, boucles), du stockage et de la manipulation de variables, etc.
# Say hello world in sh
hello-world-sh:
#!/usr/bin/env sh
hello='Yo'
echo "$hello from a shell script!"
- Cela signifie qu’on peut s’appuyer sur des langages de programmation offrant de puissantes capacités de scripting. Certaines tâches sont plus simples en Python qu’en Bash
# scale jpg image by 50%
[no-cd]
scale-jpg path:
#!/usr/bin/env python3
import PIL.Image
image = PIL.Image.open("{{path}}")
factor = 0.5
image = image.resize((round(image.width * factor), round(image.height * factor)))
image.save("{{path}}.s50.jpg")
- Tous les développeurs n’ont pas forcément Python installé sur leur machine et, même si c’est le cas, pillow n’est pas nécessairement présent. Il est possible d’utiliser
nix pour exécuter un script avec ses dépendances incluses :
# scale jpg image by 50%
[no-cd]
scale-jpg path:
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3Packages.pillow
import PIL.Image
...
Déployer les recipes
- Au lieu de créer son propre mécanisme de déploiement, utiliser
git
- Créer un dépôt sur GitHub et y pousser ce qui a été fait jusqu’ici
$ git init
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin git@github.com:acme/cli.git
$ git push -u origin main
- Désormais, toute personne ayant accès à ce dépôt peut créer une PR et contribuer des changements
- Automatiser
git pull avec une recipe acme update
# Update the Acme CLI
@update:
git fetch
git checkout main
Documentation
- Pour qu’un outil interne réussisse, son adoption est cruciale, et il faut absolument un bon guide d’utilisation pour aider les nouveaux utilisateurs à l’installer et à l’explorer
- Guider l’installation et l’utilisation dans le
README
# Acme CLI
## Prerequisites
`just`: Install just [here](https://github.com/casey/just/blob/master/README.md#installation)
## Installation
Clone this repo:
...
Set up the `acme` alias:
...
## Usage
List all available recipes:
...
- Désormais, tous les développeurs d’Acme Corp peuvent l’utiliser !
- Publier un message sur le Slack interne pour encourager tout le monde à l’essayer, et chacun peut aussi proposer ses propres snippets
Fonctionnalités supplémentaires
- La complétion est un mécanisme qui permet de compléter automatiquement des sous-commandes, chemins de fichiers, options, etc. en appuyant sur la touche TAB
- La plupart des shells proposent cette fonctionnalité, et la majorité des grands outils CLI expliquent comment installer leur système de complétion
- La plupart des grands frameworks CLI, comme Click pour Python, Cobra pour Golang ou clap pour Rust, peuvent générer automatiquement la complétion
Just peut générer la complétion en exécutant just --completion <shell>.
1 commentaires
Il me semble que la conception de la DX en interne est depuis longtemps un sujet important pour le platform engineering.