50 points par xguru 2024-09-03 | 1 commentaires | Partager sur WhatsApp
  • 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

  • Pour l’exécuter sous la forme acme <command>, ajouter un alias dans .bashrc
    alias acme='just --justfile ~/acme/cli/justfile'  
    
  • Recharger le nouvel alias avec source ~/.bashrc ou exec bash

Écrire de nouvelles recipes

Recipe simple

  • Récupérer les informations d’utilisateur/rôle AWS IAM
    @aws-id:  
      aws sts get-caller-identity  
    
    • Simplifier des commandes dont personne ne se souvient est probablement le principal cas d’usage d’une CLI interne
    • En supposant que awscli soit multiplateforme, cette recipe fonctionne quel que soit l’endroit d’où elle est appelée

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

  • Implémenter séparément le calcul de la taille d’un dossier sous Windows et sous Linux
    [windows]  
    [no-cd]  
    get-folder-size path:  
      (Get-ChildItem "{{path}}" -Recurse -Force | Measure-Object -Property Length -Sum).Sum / 1MB  
    
    [linux]  
    [no-cd]  
    get-folder-size path:  
      du -sh {{path}}  
    

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

 
bus710 2024-09-03

Il me semble que la conception de la DX en interne est depuis longtemps un sujet important pour le platform engineering.