- หนึ่งในวิธีที่มีประโยชน์ที่ทีมพัฒนาใช้ในการรวบรวมและเก็บรักษาความรู้ขององค์กร คือการเพิ่มชุด snippet, script หรือ workflow ที่มีประโยชน์ให้มากขึ้น
- นั่นจึงเป็นเหตุผลที่หลายรีโพซิทอรีมีสิ่งอย่าง Makefile หรือ bash script ถูกสร้างขึ้นมา
- แล้วสิ่งอย่างการติดตั้งเครื่องมือที่มีประโยชน์ทั่วทั้งองค์กร, การสร้าง boilerplate code หรือการรันคำสั่ง AWS ที่ซับซ้อนซึ่งไม่มีใครจำได้ ควรทำอย่างไร?
- บางบริษัท เช่น Slack หรือ Shopify มี CLI ภายในของตัวเอง
- เทอร์มินัลสมัยใหม่อย่าง Warp มีความสามารถในการจัดทำเอกสารและแชร์ workflow ได้
- CLI สำหรับใช้งานภายในองค์กรสามารถสร้างได้ง่าย ตัวอย่างนี้จะลองสร้าง CLI สำหรับบริษัทชื่อ acme
ข้อกำหนดในการออกแบบ CLI
- มีจุดเข้าใช้งานร่วมที่สามารถรันคำสั่งจากที่ไหนก็ได้ด้วย
acme <command>
- นักพัฒนาทุกคนสามารถสั่ง
acme <command> จากที่ใดก็ได้เพื่อทริกเกอร์คำสั่ง โดยไม่ต้องย้ายไปยังรีโพซิทอรีใดรีโพซิทอรีหนึ่งก่อน
- เปิดให้นักพัฒนาร่วมเพิ่มคำสั่งใหม่ได้ง่าย
- ทำให้สามารถปล่อยเวอร์ชันใหม่ได้ง่ายด้วย
acme update
- รองรับข้ามแพลตฟอร์ม (เช่น ถ้าสั่ง
acme download something บน Linux ให้ใช้ curl แต่บน Windows ให้ใช้ Invoke-WebRequest)
- ให้
acme list แสดงรายการคำสั่งที่ใช้งานได้พร้อมคำอธิบายสั้น ๆ
เริ่มโปรเจ็กต์ด้วย just
- just เป็นเครื่องมือคล้าย
make แต่เน้นการรันคำสั่งโดยเฉพาะ
- รองรับข้ามแพลตฟอร์ม และยังสามารถรันคำสั่งเฉพาะแพลตฟอร์มได้ด้วย
- ตัวเลือกอื่นมีเช่น
magic-cli ของ Slack (เหมาะมากถ้าคุณถนัด Ruby) หรือ make
การตั้งค่าโปรเจ็กต์
- ติดตั้ง
just โดยทำตามคำแนะนำ ที่นี่
- สร้างโฟลเดอร์
~/acme/cli แล้วเพิ่ม justfile ต่อไปนี้ไว้ที่ root:
default:
just --list
# Show arch and os name
os-info:
echo "Arch: {{arch()}}"
echo "OS: {{os()}}"
- ในเอกสารของ
just คำสั่งถูกเรียกว่า "recipes"
- ถ้ารัน
just โดยไม่ระบุ recipe ระบบจะรัน recipe แรกใน justfile โดยปกติรูปแบบที่นิยมคือกำหนดชื่อ recipe แรกว่า "default"
$ just
just --list
Available recipes:
default
os-info # Show arch and os name
- recipe
default จะรัน just list เพื่อแสดงรายการ recipe ทั้งหมดพร้อมคอมเมนต์
- ควรซ่อน recipe
default ไว้
- เมื่อรัน recipe แต่ละคำสั่งจะถูกพิมพ์ออกมาก่อนการทำงาน สามารถใช้ prefix
@ เพื่อปิดการแสดงผลนี้ได้ คล้ายกับ Makefile
[private]
@default:
just --list
# Show arch and os name
@os-info:
echo "Arch: {{arch()}}"
echo "OS: {{os()}}"
สร้าง alias acme
การเขียน recipe ใหม่
recipe แบบง่าย
recipe เฉพาะแพลตฟอร์ม
- snippet ที่มีเครื่องมืออย่าง
systemd จะถูกเปิดให้เห็นเฉพาะเมื่อนักพัฒนาใช้เครื่อง Linux เท่านั้น
- ใช้แอตทริบิวต์
[linux] เพื่อให้ recipe แสดงเฉพาะบน Linux
[linux]
@list-systemd-services:
systemctl list-units --type=service
recipe แบบข้ามแพลตฟอร์ม
recipe แบบสคริปต์
- สามารถฝังสคริปต์ทั้งชุดลงใน recipe ได้
- recipe ที่เริ่มด้วย shebang (
#!) จะถูกบันทึกเป็นไฟล์แยกแล้วจึงนำไปรัน
- มีประโยชน์เมื่อ workflow ต้องการตรรกะที่ซับซ้อนขึ้นเล็กน้อย เช่น control flow (if-else, loop), การเก็บและจัดการตัวแปร เป็นต้น
# Say hello world in sh
hello-world-sh:
#!/usr/bin/env sh
hello='Yo'
echo "$hello from a shell script!"
- นี่หมายถึงสามารถใช้ภาษาโปรแกรมที่มีความสามารถด้าน scripting ที่ทรงพลังได้ งานบางอย่างทำใน Python ได้ง่ายกว่า 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")
- ไม่ใช่นักพัฒนาทุกคนจะติดตั้ง Python ไว้ในเครื่อง และถึงติดตั้งแล้วก็อาจไม่มี pillow ดังนั้นจึงสามารถใช้
nix เพื่อรันสคริปต์พร้อม dependency ได้:
# 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
...
การแจกจ่าย recipe
- ใช้
git แทนการเขียนกลไก deploy เอง
- สร้างรีโพซิทอรีบน GitHub แล้ว push สิ่งที่ทำมาจนถึงตอนนี้ขึ้นไป
$ 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 เพื่อร่วมส่งการเปลี่ยนแปลงเข้ามาได้
- ทำ
git pull อัตโนมัติด้วย recipe acme update
# Update the Acme CLI
@update:
git fetch
git checkout main
เอกสารประกอบ
- ความสำเร็จของเครื่องมือภายในขึ้นอยู่กับการยอมรับใช้งานอย่างมาก ดังนั้นคู่มือการใช้งานที่ดีซึ่งช่วยให้ผู้ใช้ใหม่ติดตั้งและสำรวจเครื่องมือได้จึงสำคัญมาก
- แนะนำวิธีติดตั้งและใช้งานใน
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 ภายในบริษัทเพื่อชวนให้ทุกคนลองใช้ และแต่ละคนก็สามารถส่ง snippet ของตัวเองเข้ามาได้
ฟีเจอร์เพิ่มเติม
- ฟังก์ชัน Completion คือกลไกที่ช่วยเติมคำสั่งย่อย, path ของไฟล์, option ฯลฯ อัตโนมัติเมื่อกดปุ่ม TAB
- shell ส่วนใหญ่มีความสามารถนี้ และ CLI tool หลัก ๆ ส่วนใหญ่ก็มักมีวิธีติดตั้ง completion ให้ด้วย
- CLI framework หลักส่วนมาก เช่น Click ของ Python, Cobra ของ Golang, clap ของ Rust สามารถสร้าง completion ได้อัตโนมัติ
Just สามารถสร้าง Completion ได้ด้วยการรัน just --completion <shell>.
1 ความคิดเห็น
ดูเหมือนว่าการออกแบบ DX ภายในบริษัทจะเป็นหัวข้อสำคัญสำหรับทีมแพลตฟอร์มเอนจิเนียริงมาโดยตลอด