เวลาเราจะ develop อะไรสักอย่าง มักจะมี environment variable ที่ต้อง maintain เข้ามาใน program เช่น urls,  port, database ถ้าเราจะต้องมาประกาศตัวแปรทุกรอบที่เปิด IDE มันก็คงยุ่งยาก ยิ่งถ้ามีหลาย environment อีกล่ะ

ทีนี้ ใน blog นี้ เราจะมารู้จัก 3 tool ที่จะช่วยเราจัดการ environments ได้ฮะ

  1. direnv ทำให้ folder พร้อมใช้งานได้กับ environment variable ที่เตรียมไว้
  2. devbox ทำให้ folder แยกเป็นเอกเทศ แบบ container ฮะ มี package ติดตั้งแยกไปเลย
  3. 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

  1. ก่อนอื่นก็ต้องติดตั้ง direnv ตรงนี้ ผมใช้ homebrew ฮะ
  2. พอติดตั้งเสร็จ ก็ให้ 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 ให้เราเอง แบบนี้ฮะ

  1. สร้าง venv ขั้นมาก่อน
    venv
  2. สร้าง .envrc โดยเขียนให้ activate venv และจบด้วย layout python
  1. ให้เราอยู่ใน folder นั้น และพิมพ์ direnv allow เพื่อสั่ง execute .envrc
    allow
  2. ลองออกจาก folder ก็จะเห็นว่า direnv มัน deactivate ให้เอง
    leave

โดยทั่วไป เราสามารถ 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 folder
  • gum choose ให้สร้าง prompt เพื่อเลือก file จาก ls
  • --env-file เพื่อ input file ที่เราเลือกจาก gum prompt

แล้วเราก็สั่ง direnv allow อีกทีก็เรียบร้อยแล้วฮะ ทีนีเราก็สามารถเลือก env file ของเราได้เองแล้ว ทำงานง่ายขึ้นมากๆ


Repo

GitHub - bluebirz/sample-env: Demo direnv, devbox, and gum for isolated environments management
Demo direnv, devbox, and gum for isolated environments management - bluebirz/sample-env

References