isolated development ด้วย direnv & devbox (& gum)
เวลาเราจะ develop อะไรสักอย่าง มักจะมี environment variable ที่ต้อง maintain เข้ามาใน program เช่น urls, port, database ถ้าเราจะต้องมาประกาศตัวแปรทุกรอบที่เปิด IDE มันก็คงยุ่งยาก ยิ่งถ้ามีหลาย environment อีกล่ะ
ทีนี้ ใน blog นี้ เราจะมารู้จัก 3 tool ที่จะช่วยเราจัดการ environments ได้ฮะ
direnv
ทำให้ folder พร้อมใช้งานได้กับ environment variable ที่เตรียมไว้devbox
ทำให้ folder แยกเป็นเอกเทศ แบบ container ฮะ มี package ติดตั้งแยกไปเลยgum
เพื่อ switch environment ถ้าเรามีหลาย environment
ที่สำคัญ คือ ทั้งสามตัวเป็น file-based config ทำให้เราสามารถ push ขึ้น repo เพื่อให้ทีมทำงานได้สะดวกมากๆ (แต่แน่นอน ระวังเรื่อง security management ด้วยนะฮะ เช่น credentials อะไรงี้)
direnv
สำหรับ env
tool ตัวแรก direnv
สามารถ setup environment ให้เราอัตโนมัติแค่เข้าถึง folder ที่กำหนดฮะ อย่างเช่น ถ้าเราเข้า folder ของ Python มันก็จะ activate venv
ให้เลย
direnv
setup
- ก่อนอื่นก็ต้องติดตั้ง
direnv
ตรงนี้ ผมใช้ homebrew ฮะ - พอติดตั้งเสร็จ ก็ให้ add hook เข้าไปใน shell file ของเรา อย่างของผมใช้ zsh ผมก็ไปใส่ที่
~/.zshrc
eval "$(direnv hook zsh)"
And that's it. We are ready to initial my folder.
direnv
ใช้งานจริง
auto-scripts
สมมติว่าเราอยากจะ develop Python มาสักตัวนึง ปกติแล้ว เราก็ต้องสร้าง venv
แล้วสั่ง activate
ถูกมั้ยฮะ พอจะออกก็สั่ง deactivate
ทีนี้ พอเราใช้ direnv
เราไม่ต้องสั่งทุกครั้งที่เข้า folder แล้วฮะ เพราะมันจะทำหน้าที่ activate
กับ deactivate
ให้เราเอง แบบนี้ฮะ
- สร้าง
venv
ขั้นมาก่อน
- สร้าง
.envrc
โดยเขียนให้ activatevenv
และจบด้วยlayout python
- ให้เราอยู่ใน folder นั้น และพิมพ์
direnv allow
เพื่อสั่ง execute.envrc
- ลองออกจาก folder ก็จะเห็นว่า
direnv
มัน deactivate ให้เอง
โดยทั่วไป เราสามารถ check Python venv
ด้วยคำสั่ง which pip
แต่ที่เห็นว่า prompt ของผมมัน show venv
ก็มาจาก Oh-my-posh นะฮะ อยากรู้เพิ่มเติมก็ดูได้ที่ dotfiles ของผม หรือ https://ohmyposh.dev นะฮะ
กำหนด env vars
ทีนี้ นอกจาก auto-script แล้ว ความสามารถจริงจังของมันอีกอย่างคือ การ embed variable เข้าไปใน environment ได้ฮะ
สมมติว่าเราอยากจะ embed variable env
เข้าไป เราก็แก้ไข .envrc
เป็นแบบนี้
แล้วเราก็สั่ง direnv allow
อีกทีนึง แล้วเข้าไปอยู่ใน folder นั้น เราก็จะดึงค่า variable env
ออกมาได้ แล้วพอเราออกจาก folder ค่า env
ก็จะหายไป
ด้วยความสามารถนี้ เราก็สามารถ maintain variable เอาไว้ได้ โดยไม่ต้องห่วงว่า เอ๊ะ เรา embed รึยังนะ
ชีวิตง่ายขึ้นไปอีกหนึ่ง step
devbox
สำหรับ packages
ย้ายมาอีกตัวกันบ้าง devbox
ทำหน้าที่ ติดตั้ง package ให้ โดยกำหนดเป็นแต่ละ folder ได้เลย
devbox
setup
curl -fsSL https://get.jetify.com/devbox | bash
ถ้าเจอ error Error: Unable to find nix startup file
ให้ลองติดตั้ง Nix package manager
sh <(curl -L https://nixos.org/nix/install) # for macos
devbox
ใช้งานจริง
ก่อนอื่นก็ต้อง init
devbox init
มันจะมี file "devbox.json" ขึ้นมาฮะ
ทีนี เราอยากจะติดตั้งอะไรก็devbox search
สักทีนึง
devbox search package
devbox search package@version
โอเค เราอยากจะได้ Python 3.10 ก็สั่งไปว่า
devbox add [email protected]
ถ้าเป็นครั้งแรกนะฮะ devbox
จะพยายามติดตั้ง nix package manager ถ้ายังไม่มี
ครั้งถัดไป เราจะเห็น package ถูกติดตั้งปรื้ดๆ ให้ทันทีฮะ
ทีน้ี เรามาดู "devbox.json" อีกที จะเห็นว่ามันมี update
บรรทัดที่ 4 เราจะเห็นว่ามันมี "[email protected]" ข้างใน packages
ฮะ
ได้ฤกษ์ใช้จริง ก็ต้องสั่งเริ่ม
devbox shell # start shell
เราจะเห็นว่ามี python environment เรียบร้อย ซึ่ง default เราจะได้venv
folder มีชื่อว่า ".venv"
แล้วออกจาก shell ด้วยคำสั่ง exit
exit # exit shell
ด้วยว่า env เป็นชื่อ .venv
เราสามารถเปลี่ยนโดยเพิ่มชื่อที่env
(บรรทัด 17-19) แล้วเพิ่ม init_hook
(บรรทัด 9) แบบนี้ฮะ
รวมร่าง direnv & devbox
devbox
ช่วยสร้าง venv
ให้เรา แต่เราก็ต้อง run shell และ activate เอง ทีนี้ เราก็รวม devbox
กับ direnv
เข้าด้วยกัน ให้มัน run shell อัตโนมัติ โดยใช้คำสั่ง
devbox generate direnv
เราจะได้ .envrc
หน้าตาแบบนี้ฮะ
คราวนี้ เราก็สามารถ control package กับ activate environment ได้สะดวกมากขึ้นล่ะฮะ
gum
สำหรับหลาย env
ถึงตรงนี้ เราสามารถสร้าง isolated workspace จะติดตั้ง package อะไร มากแค่ไหน ให้มี environment variable อะไรบ้าง ทุกอย่างเสร็จหมดแล้ว ใช้สะดวกมากแค่เข้า folder ทีเดียวจบ
แล้วถ้าเรามี environment หลายตัวล่ะ เช่น dev
กับ prod
?
แน่นอนว่า เราจะต้องมี file สำหรับแต่ละ environment อยู่แล้วแหละ แต่จะทำยังไงให้เราเลือกได้ว่า วันนี้จะใช้ environment ไหน
มาทำความรู้จักกับน้องหมากฝรั่ง gum
กันฮะ
gum
เป็น tool เล็กๆ ตัวนี้ ให้เราออกแบบ prompt สำหรับงานเฉพาะได้ มันจะเจ๋งมากๆ ถ้าเราใช้ใน operation ที่เป็น shell script ซึ่งครั้งนี้เราจะได้เห็นว่า เราจะใช้ gum
ยังไงให้มาช่วยเรื่อง environment ที่มีหลายตัวของเราฮะ
gum
setup
ผมติดตั้งผ่าน homebrew นะ
brew install gum
หรือใครสะดวกวิธีอื่นก็ดูที่ references ข้างล่างได้เลยฮะ
gum
ใช้งานจริง
คือ gum
ให้เราเขียน shell prompt ง่ายๆ แบบนี้ฮะ
แล้วเราสามารถ adapt กับ setup ของเราไม่ยาก
เริ่มต้นว่าเรามี 2 environments คือ dev
กับ prod
นะฮะ เราก็เขียน 2 env
file
วาง structure แบบนี้
ทีนี้ devbox
มี flag ตัวนึงที่ใช้กับ direnv
ได้ มันคือ --env-file
ให้เรากำหนดได้เองว่าจะใช้ env filepath ไหน ทีนี้เราจะเขียนแบบนี้ลงใน .envrc
นะฮะ
ls .envs
ให้ list all file ที่มีใน.envs
foldergum choose
ให้สร้าง prompt เพื่อเลือก file จากls
--env-file
เพื่อ input file ที่เราเลือกจากgum
prompt
แล้วเราก็สั่ง direnv allow
อีกทีก็เรียบร้อยแล้วฮะ ทีนีเราก็สามารถเลือก env
file ของเราได้เองแล้ว ทำงานง่ายขึ้นมากๆ
Repo
References
direnv
https://direnv.netdirenv
wiki https://github.com/direnv/direnv/wikihomebrew
https://www.bluebirz.net/en/homebrew-one-place-for-all/devbox
by jetify https://www.jetify.com/devbox/- Nix package manager https://nixos.org/download/
gum
https://github.com/charmbracelet/gum