50 puntos por xguru 2024-09-03 | 1 comentarios | Compartir por WhatsApp
  • Una forma útil para que el equipo de desarrollo recopile y preserve el conocimiento de la organización es ir ampliando una colección de snippets, scripts o flujos de trabajo útiles
  • Por eso en muchos repositorios se terminan creando cosas como Makefile y scripts de bash
  • Pero, ¿qué pasa con tareas como instalar herramientas útiles para toda la organización, generar código boilerplate o ejecutar comandos complejos de AWS que nadie recuerda?
    • Algunas empresas como Slack o Shopify tienen su propia CLI interna
    • Warp, una terminal moderna, tiene funciones para documentar y compartir flujos de trabajo
  • Es fácil crear una CLI para uso interno de la organización. Como ejemplo, se construye una CLI para una empresa llamada acme

Requisitos de diseño de la CLI

  • Tener un punto de entrada común para poder ejecutar comandos desde cualquier lugar con acme <command>
    • Todos los desarrolladores pueden ejecutar acme <command> desde cualquier sitio para disparar comandos, sin necesidad de moverse primero a un repositorio específico
  • Permitir que los desarrolladores contribuyan nuevos comandos fácilmente
  • Permitir desplegar nuevas versiones fácilmente con acme update
  • Soporte multiplataforma (por ejemplo, si ejecutas acme download something, en Linux usar curl y en Windows Invoke-WebRequest)
  • Permitir ver la lista de comandos disponibles y una breve descripción con acme list

Empezar el proyecto con just

  • just es una herramienta similar a make, pero especializada en la ejecución de comandos
  • Soporta multiplataforma y también puede ejecutar comandos específicos de cada plataforma
  • Otras opciones son magic-cli de Slack (excelente para empezar si conoces bien Ruby) o make

Configurar el proyecto

  • Instala just. Sigue las instrucciones aquí
  • Crea la carpeta ~/acme/cli y agrega el siguiente justfile en la raíz:
default:  
  just --list  
  
# Show arch and os name  
os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  
  • En la documentación de just, a los comandos se les llama "recipes"
  • Si ejecutas just sin indicar una recipe, se ejecuta la primera recipe del justfile. Un patrón común es nombrar la primera recipe como default
$ just  
just --list  
Available recipes:  
    default  
    os-info # Show arch and os name  
  • La recipe default ejecuta just list. Muestra todas las recipes y sus comentarios
  • Conviene ocultar la recipe default
  • Cuando se ejecuta una recipe, cada comando se imprime antes de ejecutarse. Puedes quitar esa salida con el prefijo @. Es similar a Makefile
[private]  
@default:  
  just --list  
  
# Show arch and os name  
@os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  

Crear el alias acme

  • Para ejecutarlo con la forma acme <command>, agrega este alias a tu .bashrc
    alias acme='just --justfile ~/acme/cli/justfile'  
    
  • Carga el nuevo alias con source ~/.bashrc o exec bash

Escribir nuevas recipes

Recipe simple

  • Obtener información del usuario/rol de AWS IAM
    @aws-id:  
      aws sts get-caller-identity  
    
    • Simplificar comandos que nadie recuerda es probablemente uno de los principales casos de uso de una CLI interna
    • Se asume que awscli es multiplataforma, así que esta recipe funcionará sin importar desde dónde se invoque

Recipe específica por plataforma

  • Los snippets que incluyen herramientas como systemd solo se exponen si el desarrollador usa una máquina Linux
  • Usa el atributo [linux] para que la recipe solo se muestre en Linux
[linux]  
@list-systemd-services:  
  systemctl list-units --type=service  

Recipe multiplataforma

  • Implementar el cálculo del tamaño de una carpeta tanto en Windows como en 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}}  
    

Recipes con script

  • Puedes incrustar un script completo dentro de una recipe
  • Las recipes que empiezan con Shebang(#!) se guardan en un archivo aparte y luego se ejecutan
  • Esto resulta útil cuando un flujo de trabajo necesita lógica un poco más compleja, como control de flujo (if-else, loops), guardar variables o manipularlas
# Say hello world in sh  
hello-world-sh:  
  #!/usr/bin/env sh  
  hello='Yo'  
  echo "$hello from a shell script!"  
  • Esto significa que puedes aprovechar lenguajes de programación con capacidades de scripting potentes. Algunas tareas son más fáciles de hacer en Python que 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")  
  • No todos los desarrolladores tienen Python instalado en su computadora, y aunque lo tengan, puede que no tengan instalado pillow. Se puede usar nix para ejecutar scripts con dependencias incluidas:
# 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  
  ...  

Desplegar recipes

  • En lugar de crear tu propio mecanismo de despliegue, usa git
  • Crea un repositorio en GitHub y haz push de lo que llevas hasta ahora
$ 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  
  • Ahora cualquiera que tenga acceso a este repositorio puede crear un PR y contribuir cambios
  • Automatiza git pull con una recipe acme update
# Update the Acme CLI  
@update:  
  git fetch  
  git checkout main  

Documentación

  • Para que una herramienta interna tenga éxito, la adopción es muy importante, y hace falta una buena guía de uso para que los nuevos usuarios puedan instalarla y explorarla
  • Incluye en el README instrucciones de instalación y uso
# 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:  
...  
  • ¡Ahora ya puede usarla cualquier desarrollador de Acme Corp!
  • Publica un mensaje en el Slack interno para animar a todos a probarla, y que cada quien pueda aportar sus propios snippets

Funciones adicionales

  • La función de autocompletado (Completion) es un mecanismo que permite completar automáticamente subcomandos, rutas de archivos, opciones, etc., al presionar la tecla TAB
  • La mayoría de los shells ofrecen esta función, y la mayoría de las herramientas CLI importantes explican cómo instalar su autocompletado
    • La mayoría de los principales frameworks de CLI, como Click de Python, Cobra de Golang y clap de Rust, pueden generar autocompletado automáticamente
  • Just puede generar Completion ejecutando just --completion <shell>.

1 comentarios

 
bus710 2024-09-03

Parece que, desde hace tiempo, el diseño de la DX interna de la empresa ha sido un tema importante para platform engineering.