- 개발팀에서 조직의 지식을 수집하고 보존하는 유용한 방법 중 하나는 유용한 스니펫, 스크립트 또는 워크플로우 모음을 늘리는 것
- 그래서 많은 리포지토리에 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
를 사용해 프로젝트 시작하기
-
just는
make
와 유사하지만 명령어 실행에 특화된 도구임
- 크로스 플랫폼을 지원하고 플랫폼 특화 명령어도 실행 가능함
- 다른 옵션으로는 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 만들기
새 레시피 작성하기
간단한 레시피
플랫폼 특화 레시피
-
systemd
와 같은 도구가 포함된 스니펫은 개발자가 Linux 머신을 사용하는 경우에만 노출
-
[linux]
속성을 사용해 Linux에서만 레시피 노출되게 함
[linux]
@list-systemd-services:
systemctl list-units --type=service
크로스 플랫폼 레시피
스크립트 레시피
- 레시피에 전체 스크립트를 삽입할 수 있음
- 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 프레임워크는 자동으로 완성 기능을 생성할 수 있음
-
Just
는 just --completion <shell>.
를 실행하여 Completion을 생성할 수 있음