- Homebrew là trình quản lý gói trên macOS giúp cài đặt và quản lý công cụ CLI dễ dàng, cho phép nhà phát triển cấu hình môi trường hệ thống hiệu quả bằng các công cụ họ thường dùng
- Hướng dẫn này giải thích quy trình phân phối các script CLI cá nhân bằng Homebrew, đồng thời chỉ ra cách đơn giản hóa việc bảo trì thông qua tích hợp GitHub và quy trình tự động hóa
- Quy trình phân phối diễn ra theo chuỗi tạo CLI → phát hành GitHub Release → tạo Tap → viết và cập nhật Formula, và cuối cùng có thể cài đặt chỉ với các lệnh
brew tap và brew install
- Nếu hiểu hệ thống thuật ngữ và best practice của Homebrew, bạn có thể triển khai phân phối ổn định với khả năng tái lập cao hơn và bảo mật chuỗi cung ứng tốt hơn
- Có thể tự động hóa bằng workflow GitHub Actions, và một khi đã thiết lập xong thì việc phát hành các CLI khác về sau sẽ rất đơn giản
Bối cảnh và động lực
- Homebrew là trình quản lý gói được ưa chuộng khi cài đặt công cụ CLI và được nhiều nhà phát triển sử dụng
- Tuy nhiên, khi phân phối CLI do chính mình tạo ra, nhiều người thường chọn npm hoặc RubyGem, còn cách phân phối qua Homebrew có thể tạo cảm giác xa lạ về mặt quy trình
- Kho
core chính thức của Homebrew có chủ trương không mặn mà với việc đưa các công cụ tự tạo vào, nên nhà phát triển thông thường sẽ phân phối qua tap và formula riêng
- Hướng dẫn này được giải thích dựa trên kinh nghiệm phân phối một CLI đơn giản viết bằng Ruby
Giải thích thuật ngữ
- Homebrew dùng bộ thuật ngữ đặc trưng theo chủ đề nấu bia, nên nếu hiểu chúng thì sẽ dễ nắm cấu trúc hệ thống hơn
- Formula là tệp định nghĩa gói, chứa hướng dẫn cài đặt mã nguồn hoặc binary
- Tap là kho Git chứa các Formula, dùng để quản lý các gói tùy chỉnh theo người dùng hoặc tổ chức
- Cask là manifest cài đặt cho ứng dụng GUI hoặc binary lớn; tương tự Formula nhưng xử lý các tệp đã build sẵn
- Bottle là dạng gói binary build sẵn được sao chép thay vì build từ mã nguồn, giúp tăng tốc cài đặt
- Cellar là thư mục nơi các Formula đã cài được đặt vào, ví dụ đường dẫn
/opt/homebrew/Cellar
- Keg là thư mục instance cài đặt của một Formula cụ thể, được bố trí theo từng phiên bản bên trong Cellar
Tổng quan
- Kho Homebrew core không nhận nội dung ngách hoặc do cá nhân gửi lên, vì vậy người dùng phải tạo kho tap riêng để phân phối CLI
- 1. Tạo CLI, đưa lên GitHub và phát hành theo tag
- 2. Tạo Tap bằng
brew tap-new rồi push lên GitHub
- 3. Viết Formula bằng
brew create (gồm URL tarball và SHA256)
- 4. Mỗi khi phát hành phiên bản mới thì cập nhật Formula để người dùng có thể dễ dàng cài bằng lệnh
brew install
- Sau khi phân phối xong, người dùng có thể cài CLI chỉ với hai lệnh:
brew tap your_github_handle/tap và brew install your_cool_cli
- Hướng dẫn này bỏ qua phần phát triển CLI và tập trung vào việc tạo tap, tạo Formula và quy trình cập nhật
- Ví dụ sử dụng CLI
imsg, công cụ tạo web archive tương tác từ cơ sở dữ liệu iMessage
Tạo tap
- Làm theo hướng dẫn tạo tap của Homebrew, thay thế bằng tên người dùng GitHub hoặc tên tổ chức của bạn
- Để gom tất cả công cụ CLI sau này vào một tap, tác giả khuyến nghị đặt tên
homebrew-tap; tiền tố homebrew được CLI xử lý đặc biệt và hậu tố tap là thông lệ phổ biến
- Chạy lệnh tạo tap:
brew tap-new searlsco/homebrew-tap
- Lệnh này tạo scaffold tại
/opt/homebrew/Library/Taps/searlsco/homebrew-tap
- Tạo kho tương ứng trên GitHub rồi push nội dung vừa sinh ra:
cd /opt/homebrew/Library/Taps/searlsco/homebrew-tap, git remote add origin git@github.com:searlsco/homebrew-tap.git, git push -u origin main
- Sau khi sở hữu tap, người dùng khác có thể clone kho này bằng lệnh
brew tap searlsco/tap để đặt vào /opt/homebrew/Library/Taps
- Ban đầu chưa có nội dung hữu ích, nhưng có thể dùng để xác nhận hành vi cơ bản
Tạo Formula
- Homebrew có thể tham chiếu trực tiếp kho GitHub, nhưng khuyến nghị dùng tarball theo phiên bản và checksum để tăng khả năng tái lập và bảo mật chuỗi cung ứng mã nguồn mở
- Lệnh tạo Formula:
brew create https://github.com/searlsco/imsg/archive/refs/tags/v0.0.5.tar.gz --tap searlsco/homebrew-tap --set-name imsg --ruby
- Cờ
--tap chỉ định tap tùy chỉnh và đặt Formula vào /opt/homebrew/Library/Taps/searlsco/homebrew-tap/Formula
--set-name imsg đặt tên Formula một cách tường minh; nên chọn tên đủ độc nhất để tránh trùng (ví dụ lưu ý xung đột với các CLI như TLDR hay standard đã có)
--ruby là preset template cho Ruby CLI, một trong nhiều tùy chọn giúp đơn giản hóa việc tùy biến
- Formula tạo ra lúc đầu có thể chưa chạy được, nên có thể dùng LLM để chỉnh sửa: chạy
brew install --verbose imsg, đưa lỗi vào ChatGPT rồi lặp lại việc cập nhật Formula
- Tệp cuối cùng Formula/imsg.rb có thể được sao chép làm điểm khởi đầu cho việc phân phối Ruby CLI
- Khi phân phối qua Homebrew thay vì trình quản lý gói đặc thù ngôn ngữ, người dùng vẫn có thể nâng cấp mượt mà ngay cả khi bạn thay đổi ngôn ngữ triển khai
Những điểm nổi bật chính của Formula
- Mọi Formula đều được viết bằng Ruby, vì trước thời JavaScript hay AI thì nhiều công cụ phát triển phổ biến được xây trên Ruby
- Có thể chỉ định kho Git bằng phương thức
head, nhưng hiệu quả thực tế của nó không rõ ràng
- Việc thêm
livecheck rất đáng giá vì giúp cập nhật phiên bản Formula dễ hơn
- Bài kiểm tra chạy binary có thể được triển khai đơn giản bằng cách kiểm tra đầu ra trợ giúp; đừng bị các comment được sinh ra làm nản lòng
- Dùng lệnh
brew style searlsco/tap để kiểm tra lỗi style
- Mặc định
uses_from_macos "ruby" trong template --ruby dùng phiên bản 2.6.10 (phát hành từ trước COVID, đã EOL 3 năm), nên tác giả khuyến nghị phụ thuộc vào Formula ruby mới hơn bằng depends_on "ruby@3"
- Khi đã hài lòng với Formula, chỉ cần
git push để phát hành live; người dùng có thể cài bằng brew tap searlsco/tap và brew install imsg
Cập nhật Formula cho từng bản phát hành CLI
- Việc phải cập nhật thủ công
url và hash sha256 ở đầu Formula sau mỗi lần phát hành khá phiền; tác giả còn cho rằng ngay cả thao tác push tag hay tạo GitHub Release cũng đã mệt mỏi
- Có thể tạo PR bằng lệnh
bump-formula-pr của Homebrew hoặc bằng GitHub Actions, nhưng quy trình fork và PR lại phức tạp một cách không cần thiết
- Nếu bạn là chủ sở hữu tap, cách đơn giản hơn là commit trực tiếp vào nhánh
main
- Để tránh điều này, tác giả khuyến nghị thêm workflow GitHub vào kho Formula để tự động cập nhật tap khi có release
- Có thể sao chép và dùng ví dụ workflow
- Cần cấu hình: tạo GitHub Personal Access Token (PAT), cấp quyền
Content → Write cho kho homebrew-tap, rồi lưu vào Secrets của kho Formula dưới tên HOMEBREW_TAP_TOKEN
- Chỉ định tap và Formula bằng biến môi trường (ví dụ dòng 13-15)
- Nên dùng cấu hình tài khoản bot GitHub để cập nhật:
GH_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com, GH_NAME: github-actions[bot]
- Sau khi tạo release rồi chạy
git push --tags, bản cập nhật sẽ được áp dụng tự động chỉ trong vài giây; người dùng có thể nâng cấp bằng brew update và brew upgrade imsg
Điểm hay nhất
- Quy trình này tuy phức tạp, nhưng sau khi đã thiết lập tap và hoàn thành một ví dụ Formula thì việc phân phối thêm CLI gần như trở nên rất nhỏ nhặt
- Có thể xuất bản Formula mới chỉ trong vài phút nên khá tiện lợi
- Quy trình chính thức của Homebrew có phần rườm rà, nhưng tự động hóa sẽ giúp mọi thứ dễ chịu hơn
- Nó giảm bớt sự phiền hà giữa mỗi lần release và phân phối công cụ, đồng thời có thể mở rộng để hỗ trợ CLI viết bằng nhiều ngôn ngữ khác nhau
- Tác giả không chắc mình có thực sự đăng thêm Formula nào nữa hay không, nhưng cảm thấy hài lòng vì khả năng đó giờ đã rộng mở
Chưa có bình luận nào.