50 điểm bởi xguru 2024-09-03 | 1 bình luận | Chia sẻ qua WhatsApp
  • Một trong những cách hữu ích để đội ngũ phát triển thu thập và lưu giữ tri thức của tổ chức là liên tục mở rộng bộ sưu tập các snippet, script hoặc workflow hữu ích
  • Vì vậy nhiều repository thường có những thứ như Makefile, script bash, v.v.
  • Nhưng còn những việc như cài đặt công cụ hữu ích trên toàn tổ chức, tạo boilerplate code, hay chạy các lệnh AWS phức tạp mà chẳng ai nhớ nổi thì sao?
    • Một số công ty như Slack hay Shopify có CLI nội bộ riêng
    • Terminal hiện đại Warp có tính năng giúp tài liệu hóa và chia sẻ workflow
  • CLI dùng nội bộ cho tổ chức có thể được tạo khá dễ dàng. Ví dụ, hãy thử làm một CLI cho công ty tên là acme

Yêu cầu thiết kế CLI

  • Có một điểm vào chung để chạy lệnh ở bất kỳ đâu với acme <command>
    • Mọi lập trình viên đều có thể chạy acme <command> ở bất kỳ đâu để kích hoạt lệnh mà không cần phải chuyển vào một repository cụ thể trước
  • Giúp các lập trình viên dễ dàng đóng góp lệnh mới
  • Giúp việc phát hành phiên bản mới trở nên dễ dàng với acme update
  • Hỗ trợ đa nền tảng (ví dụ: khi chạy acme download something, trên Linux dùng curl, còn trên Windows dùng Invoke-WebRequest)
  • Cho phép xem danh sách các lệnh khả dụng cùng mô tả ngắn bằng acme list

Bắt đầu dự án với just

  • just là công cụ tương tự make, nhưng chuyên cho việc thực thi lệnh
  • Hỗ trợ đa nền tảng và cũng có thể chạy các lệnh đặc thù theo nền tảng
  • Các lựa chọn khác gồm magic-cli của Slack (rất phù hợp để bắt đầu nếu bạn rành Ruby) hoặc make

Thiết lập dự án

  • Cài đặt just. Làm theo hướng dẫn tại đây
  • Tạo thư mục ~/acme/cli và thêm justfile sau vào thư mục gốc:
default:  
  just --list  
  
# Show arch and os name  
os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  
  • Trong tài liệu của just, các lệnh được gọi là “recipes”
  • Khi chạy just mà không chỉ định recipe nào, recipe đầu tiên trong justfile sẽ được chạy. Thông thường, recipe đầu tiên hay được đặt tên là default
$ just  
just --list  
Available recipes:  
    default  
    os-info # Show arch and os name  
  • Recipe default sẽ chạy just list. Nó hiển thị danh sách tất cả recipe cùng với chú thích
  • Nên ẩn recipe default
  • Khi chạy recipe, mỗi lệnh sẽ được in ra trước khi thực thi. Có thể dùng tiền tố @ để tắt phần in này. Tương tự Makefile
[private]  
@default:  
  just --list  
  
# Show arch and os name  
@os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  

Tạo alias acme

  • Để chạy theo dạng acme <command>, thêm alias vào .bashrc
    alias acme='just --justfile ~/acme/cli/justfile'  
    
  • Tải alias mới bằng source ~/.bashrc hoặc exec bash

Viết recipe mới

Recipe đơn giản

  • Lấy thông tin người dùng/vai trò AWS IAM
    @aws-id:  
      aws sts get-caller-identity  
    
    • Đơn giản hóa những lệnh chẳng ai nhớ nổi có lẽ là trường hợp sử dụng chính của CLI nội bộ
    • Giả sử awscli là đa nền tảng, recipe này sẽ hoạt động bất kể được gọi từ đâu

Recipe đặc thù nền tảng

  • Những snippet có dùng công cụ như systemd sẽ chỉ được hiển thị khi lập trình viên đang dùng máy Linux
  • Dùng thuộc tính [linux] để recipe chỉ hiển thị trên Linux
[linux]  
@list-systemd-services:  
  systemctl list-units --type=service  

Recipe đa nền tảng

  • Cài đặt riêng cho Windows và Linux để lấy kích thước thư mục
    [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 dạng script

  • Có thể nhúng cả script đầy đủ vào recipe
  • Recipe bắt đầu bằng shebang (#!) sẽ được lưu thành tệp riêng rồi thực thi
  • Hữu ích khi workflow cần logic phức tạp hơn một chút như điều khiển luồng (if-else, vòng lặp), lưu và xử lý biến, v.v.
# Say hello world in sh  
hello-world-sh:  
  #!/usr/bin/env sh  
  hello='Yo'  
  echo "$hello from a shell script!"  
  • Điều này có nghĩa là có thể tận dụng các ngôn ngữ lập trình có khả năng scripting mạnh. Có những việc làm bằng Python dễ hơn 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")  
  • Không phải lập trình viên nào cũng cài Python trên máy, và dù có thì cũng chưa chắc đã có pillow. Có thể dùng nix để chạy script kèm theo dependencies:
# 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  
  ...  

Phân phối recipe

  • Thay vì tự xây cơ chế triển khai riêng, hãy dùng git
  • Tạo repository trên GitHub và push những gì đã làm tới thời điểm này
$ 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  
  • Giờ thì bất kỳ ai có quyền truy cập repository này đều có thể tạo PR để đóng góp thay đổi
  • Tự động hóa git pull bằng recipe acme update
# Update the Acme CLI  
@update:  
  git fetch  
  git checkout main  

Tài liệu hóa

  • Với công cụ nội bộ, mức độ được chấp nhận sử dụng là cực kỳ quan trọng, nên nhất định phải có hướng dẫn sử dụng tốt để người dùng mới biết cách cài đặt và khám phá công cụ
  • Hướng dẫn cài đặt và cách dùng trong 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:  
...  
  • Giờ đây tất cả lập trình viên của Acme Corp đều có thể dùng nó!
  • Hãy đăng một tin nhắn trên Slack nội bộ để khuyến khích mọi người thử dùng, và mỗi người có thể đóng góp snippet của riêng mình

Tính năng bổ sung

  • Completion là cơ chế tự động hoàn thành subcommand, đường dẫn tệp, tùy chọn, v.v. khi nhấn phím TAB
  • Hầu hết shell đều hỗ trợ tính năng này, và đa số công cụ CLI lớn đều cung cấp cách cài đặt completion
    • Hầu hết framework CLI phổ biến như Click của Python, Cobra của Golang, hay clap của Rust đều có thể tự động sinh completion
  • Just có thể sinh completion bằng cách chạy just --completion <shell>.

1 bình luận

 
bus710 2024-09-03

Từ trước đến nay, có vẻ như việc thiết kế DX nội bộ trong công ty là một chủ đề quan trọng đối với platform engineering.