49P by xguru 16일전 | favorite | 댓글 1개
  • 개발팀에서 조직의 지식을 수집하고 보존하는 유용한 방법 중 하나는 유용한 스니펫, 스크립트 또는 워크플로우 모음을 늘리는 것
  • 그래서 많은 리포지토리에 Makefile, bash 스크립트 같은 것들이 만들어짐
  • 조직 전반에 걸쳐서 유용한 도구 설치, 상용구 코드 생성, 아무도 기억하지 못하는 복잡한 AWS 명령 실행 같은 것은 어떻게 해야 할까?
    • Slack이나 Shopify와 같은 일부 회사에는 자체 내부 CLI가 있음
    • 최신 터미널인 Warp에는 워크플로를 문서화하고 공유할 수 있는 기능이 있음
  • 조직 내부용 CLI는 쉽게 만들수 있음. 예로 acme란 회사용 CLI를 제작해 봄

CLI 설계 요구사항

  • acme <command>로 어디서든 명령어를 실행할 수 있는 공통 진입점을 가짐
    • 모든 개발자는 특정 리포지토리로 먼저 이동할 필요 없이 어디서나 acme <command>를 실행하여 명령을 트리거할 수 있음
  • 개발자들이 새 명령어를 쉽게 기여할 수 있도록 함
  • acme update로 새 버전을 쉽게 배포할 수 있게 함
  • 크로스 플랫폼 지원(예: acme download something을 하면 Linux에서는 curl, Windows에서는 Invoke-WebRequest 사용)
  • acme list로 사용 가능한 명령어 목록과 간단한 설명을 볼 수 있게 함

just를 사용해 프로젝트 시작하기

  • justmake와 유사하지만 명령어 실행에 특화된 도구임
  • 크로스 플랫폼을 지원하고 플랫폼 특화 명령어도 실행 가능함
  • 다른 옵션으로는 Slack의 magic-cli(Ruby를 잘 안다면 시작하기에 훌륭함)나 make가 있음

프로젝트 세팅하기

  • just 설치. 여기 지침 따르기
  • ~/acme/cli 폴더 만들고 루트에 다음 justfile 추가:
default:  
  just --list  
  
# arch와 os 이름 표시   
os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  
  • just 문서에선 명령어를 "recipes"라고 부름.
  • 레시피 없이 just를 실행하면 justfile의 첫번째 레시피 실행. 보통 첫번째 레시피의 이름을 "default"로 지정하는게 일반적인 패턴
$ just  
just --list  
Available recipes:  
    default  
    os-info # Show arch and os name  
  • default 레시피는 just list 실행. 모든 레시피 목록과 주석을 보여줌
  • default 레시피는 숨기는 게 좋음
  • 레시피 실행하면 각 명령어가 실행되기 전 출력됨. @ 접두사로 이 출력 제거 가능. Makefile과 유사
[private]  
@default:  
  just --list  
  
# arch와 os 이름 표시  
@os-info:  
  echo "Arch: {{arch()}}"  
  echo "OS: {{os()}}"  

acme alias 만들기

  • acme <command> 형태로 실행하기 위해 .bashrc에 alias 추가
    alias acme='just --justfile ~/acme/cli/justfile'  
    
  • source ~/.bashrcexec bash로 새 별칭 로드

새 레시피 작성하기

간단한 레시피

  • AWS IAM 사용자/역할 정보 가져오기
    @aws-id:  
      aws sts get-caller-identity  
    
    • 아무도 기억하지 못하는 명령을 단순화하는 것이 아마도 내부 CLI의 주요 사용 사례
    • awscli는 크로스 플랫폼이라고 가정하고 있으므로 이 레시피는 호출 위치에 관계없이 작동

플랫폼 특화 레시피

  • systemd와 같은 도구가 포함된 스니펫은 개발자가 Linux 머신을 사용하는 경우에만 노출
  • [linux] 속성을 사용해 Linux에서만 레시피 노출되게 함
[linux]  
@list-systemd-services:  
  systemctl list-units --type=service  

크로스 플랫폼 레시피

  • 폴더 크기 구하기를 Windows와 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}}  
    

스크립트 레시피

  • 레시피에 전체 스크립트를 삽입할 수 있음
  • Shebang(#!)으로 시작하는 레시피는 별도 파일로 저장되어 실행됨
  • 제어 흐름(if-else, 루프) 사용, 변수 저장 및 조작 등과 같이 워크플로에 약간 더 복잡한 로직이 필요한 경우에 유용
# Say hello world in sh  
hello-world-sh:  
  #!/usr/bin/env sh  
  hello='Yo'  
  echo "$hello from a shell script!"  
  • 강력한 스크립팅 기능을 갖춘 프로그래밍 언어를 활용할 수 있다는 의미. 어떤 작업은 Bash보다 Python에서 더 쉽게 수행할 수 있음
# 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")  
  • 모든 개발자가 컴퓨터에 파이썬을 설치하는 것은 아니며, 설치되어 있더라도 pillow가 설치되어 있지 않을 수도 있음. nix를 사용하여 종속성이 포함된 스크립트를 실행 가능:
# 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  
  ...  

레시피 배포하기

  • 자체 배포 메커니즘을 롤링하는 대신 git을 사용
  • GitHub에 저장소 만들고 현재까지 만든 것을 푸시
$ 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  
  • 이제 이 리포지토리에 액세스할 수 있는 사람은 누구나 PR을 만들어 변경 사항을 기여할 수 있음
  • acme update 레시피로 git pull 자동화
# Update the Acme CLI  
@update:  
  git fetch  
  git checkout main  

문서화

  • 내부 도구의 성공에는 채택(Adoption) 매우 중요하며, 신규 사용자가 도구를 설치하고 탐색할 수 있도록 안내하는 좋은 사용 설명서가 꼭 필요함
  • 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:  
...  
  • 이제 모든 Acme Corp 개발자가 사용할 수 있게 되었음!
  • 사내에 Slack 메시지를 게시하여 모든 사람이 사용해 보도록 독려하고, 각자가 자신만의 스니펫을 제공할 수 있음

추가 기능

  • 자동 완성(Completion) 기능은 TAB 키를 누르면 하위 명령, 파일 경로, 옵션 등을 자동 완성할 수 있는 메커니즘
  • 대부분의 셸은 이 기능을 제공하며, 대부분의 주요 CLI 도구는 완성 기능을 설치하는 방법을 제공
    • Python의 Click, Golang의 Cobra, Rust의 clap 등 대부분의 주요 CLI 프레임워크는 자동으로 완성 기능을 생성할 수 있음
  • Justjust --completion <shell>.를 실행하여 Completion을 생성할 수 있음

예전부터 사내 dx 설계가 플랫폼 엔지니어링에게 중요한 주제인 것 같습니다.