Tüm Yazılar
KategoriDevOps
Okuma Süresi
9 dk
Yayın Tarihi
2026-10-15
Kelime Sayısı
1.036kelime

Kahveni hazırla - bu içerikli bir makale!

Bir npm CLI'yi release tarball'ı ile Homebrew'a taşımak

Özet

muhittincamdali/homebrew-tap, podexit ve sdkbump'ı her GitHub release'ine eklenen npm tarball'ından kuruyor; brew test-bot'un yakaladıkları.

  • podexit ve sdkbump, TypeScript ile yazılmış ve npm'de @mcamdali/podexit ve @mcamdali/sdkbump adlarıyla yayımlanmış komut satırı araçları.
  • İlk iki gündeki üç değişiklik gerçek sorunlardan çıktı; ikisini test-bot buldu.
  • sh brew tap muhittincamdali/tap brew install podexit ya da tek adımda: sh brew install muhittincamdali/tap/podexit Aynısı sdkbump ve sizeledger için de geçerli.
  • Kaynak kod: [github.com/muhittincamdali/homebrew-tap](https://github.com/muhittincamdali/homebrew-tap)
Bir npm CLI'yi release tarball'ı ile Homebrew'a taşımak

İçindekiler


Problem

podexit ve sdkbump, TypeScript ile yazılmış ve npm'de @mcamdali/podexit ve @mcamdali/sdkbump

adlarıyla yayımlanmış komut satırı araçları. Bir Node.js geliştiricisi için

npx @mcamdali/podexit yeterli. İki araç da iOS projeleri için; bu yüzden genellikle bir Mac'te

çalışıyorlar ve Mac'te komut satırı araçlarını kurmanın yaygın yolu Homebrew. Bir formül ayrıca

brew upgrade ve brew uninstall'u ek iş gerektirmeden sağlıyor.

Bunu sunmanın en hafif yolu bir tap. Tap, homebrew-<ad> adlı bir git reposu;

brew tap muhittincamdali/tap, muhittincamdali/homebrew-tap reposunu klonluyor ve Formula/

dizinindeki formüller kurulabilir hâle geliyor. Tap 14 Ekim 2026'da podexit formülüyle açıldı. Ertesi

sabah üç formül vardı: podexit, sdkbump ve sizeledger.

Bu tap'in cevaplaması gereken soru dar: asıl evi npm kayıt defteri olan bir araç için formül tam olarak

neyi indirmeli?

Tasarım kararları ve alternatifler

Tek tarball, bir kez üretiliyor. İki aracın da release workflow'u lint, tip kontrolü, testler ve

build'i çalıştırıyor, paketlenmiş tarball'ı bir smoke test'te kurup deniyor ve ancak ondan sonra

npm pack çalıştırıyor. Aynı adım bir checksum dosyası da yazıyor:

sh
1npm pack --ignore-scripts --pack-destination "$RUNNER_TEMP/release"
2cp "$RUNNER_TEMP/notes.md" "$RUNNER_TEMP/release/notes.md"
3(cd "$RUNNER_TEMP/release" && sha256sum ./*.tgz > SHA256SUMS)

Bu tarball SHA256SUMS ile birlikte GitHub release'ine ekleniyor ve aynı dosya

npm publish --provenance'a veriliyor. Hiçbir şey iki kez paketlenmediği için GitHub'daki kopya ile

npm'deki kopya bayt bayt aynı. 15 Ekim 2026'da podexit 0.1.2 (2a0655c9…) ve sdkbump 0.1.3

(2f5e8df0…) için release indirmesi ile kayıt defteri indirmesinin SHA-256'sı aynıydı.

Formül neden yalnızca kayıt defterini değil release'i gösteriyor. podexit 0.1.0 formülü, podexit

henüz npm'de yokken yazıldı; formülü ekleyen commit bunu ve paket yayına girince release workflow'unun

formülü kayıt defteri tarball'ına taşıyacağını söylüyor. GitHub release URL'i tag yayımlandığı anda

var oluyor, yayımlanmış bir checksum ile geliyor ve npm publish adımının başarısına bağlı değil. İki

üretici script de bunu yansıtıyor: sdkbump'ın scripts/homebrew-formula.ts dosyası release URL'ini,

podexit'inki kayıt defteri URL'ini yazıyor. Baytlar aynı olduğundan aynı sha256 ile iki URL de

doğru.

Kurulumu Homebrew'un npm yardımcıları yapıyor. Formülün kendisi kısa. Tap'teki

Formula/podexit.rb şöyle:

ruby
1class Podexit < Formula
2 desc "Show which CocoaPods stop getting updates when trunk goes read-only"
3 homepage "https://github.com/muhittincamdali/podexit"
4 url "https://github.com/muhittincamdali/podexit/releases/download/v0.1.2/mcamdali-podexit-0.1.2.tgz"
5 sha256 "2a0655c9751e8b849016d10e91fdf6a408999f1adb4ac7f1ec232b3e3783a0f7"
6 license "MIT"
7 
8 depends_on "node"
9 
10 def install
11 system "npm", "install", *std_npm_args
12 bin.install_symlink libexec.glob("bin/*")
13 end

std_npm_args paketi bağımlılıklarıyla birlikte formülün libexec dizinine kuruyor; symlink de

podexit komutunu PATH'e koyuyor. depends_on "node" Homebrew'un kendi Node.js'ini kullanıyor;

böylece araç, kullanıcının kurduğu Node.js sürümüne bağlı kalmıyor.

Gerçek aracı çalıştıran bir test bloğu. Homebrew kurulumdan sonra test do bloğunu çalıştırıyor.

Yalnızca --version'a bakan bir test, paketlenen dosyalar eksik olsa bile geçerdi. Bu yüzden

podexit'in testi tek bir yerel pod içeren küçük bir Podfile.lock yazıp üzerinde çevrimdışı rapor

alıyor:

ruby
1 output = shell_output("#{bin}/podexit --offline --all --cache-dir #{testpath}/cache")
2 assert_match "not affected", output

sdkbump'ın testi komutu boş bir dizinde çalıştırıp No iOS project found mesajıyla 2 çıkış kodu

bekliyor. sizeledger'ın testi bir Demo.app içine 5.000 baytlık bir dosya yazıp JSON çıktısında

"bytes" : 5000 bekliyor. Testlerin hiçbiri ağa ihtiyaç duymuyor.

Derlenmiş araçlar için alternatif. sizeledger Swift ile yazılmış ve hazır derlenmiş binary'lerle

geliyor; bu yüzden formülünde depends_on yok. Arşivi OS.mac? ve Hardware::CPU.intel?

kontrolleriyle seçiyor (macOS universal, Linux x86_64 ya da Linux aarch64), çünkü Homebrew'un stil

kuralları on_macos ya da on_linux blokları içinde url'e izin vermiyor; formüldeki bir yorum bunu

açıklıyor.

İlk iki günde değişenler

Tap'in workflow'u her push ve pull request'te brew test-bot çalıştırıyor: stil ve

brew audit --strict --online için --only-tap-syntax, pull request'lerde ise değişen formülleri

kaynaktan build edip testlerini çalıştıran --only-formulae. İlk iki gündeki üç değişiklik gerçek

sorunlardan çıktı; ikisini test-bot buldu.

Linux node'u çözemedi. Workflow'un ilk sürümü Linux job'ını sade Ubuntu runner'ında

çalıştırıyordu. Orada brew test-bot --only-formulae, node'a bağımlı her formülde "Failed to

determine dependencies" hatasıyla duruyordu. Homebrew'un kendi tap şablonu, yani brew tap-new'in

yazdığı dosya, Linux'u ghcr.io/homebrew/brew container'ı içinde çalıştırıyor. c391558 commit'i

bu düzene geçti:

yaml
1strategy:
2 matrix:
3 os: [macos-26]
4 include:
5 - os: ubuntu-latest
6 container:
7 image: ghcr.io/homebrew/brew:main
8 options: --privileged
9runs-on: ${{ matrix.os }}
10container: ${{ fromJSON(toJSON(matrix.container)) }} # zizmor: ignore[unpinned-images]

Aynı commit Homebrew/actions/setup-homebrew'u @main yerine bir commit SHA'sına sabitledi.

Dosyanın geri kalanı artık brew tap-new'in ürettiği düzeni izliyor: her çalıştırmada

--only-cleanup-before, --only-setup ve --only-tap-syntax, pull request'lerde

--only-formulae. Her adım bash -xeuo pipefail altında çalışıyor; başarısız bir komut job'ı

durduruyor ve log her komutu gösteriyor. Workflow en üst seviyede hiçbir izin vermiyor

(permissions: {}), job'a ise yalnızca actions, checks, contents ve pull request'ler için okuma

izni tanıyor.

Scope'lu paket dosya adını değiştirdi. podexit 0.1.2, @mcamdali scope'u altında yayımlanan ilk

sürüm oldu. npm pack scope'lu bir paketi <scope>-<ad>-<sürüm>.tgz olarak adlandırıyor; release

dosyası mcamdali-podexit-0.1.2.tgz oldu ve formül URL'inin de değişmesi gerekti. sdkbump'ın

release workflow'u ise tarball'ı yeniden sdkbump-<sürüm>.tgz olarak adlandırıyor ve aynı dosya

olduğunu bir yorumla belirtiyor; böylece URL'leri eski biçimini koruyor.

Gereksiz bir version satırı. sizeledger'ın ilk formülü version "0.1.0" tanımlıyordu. Pull

request çalıştırması brew audit'te başarısız oldu: "version 0.1.0 is redundant with version scanned

from URL". Her arşiv adı zaten sizeledger-0.1.0-<platform>.tar.gz ile bitiyor ve Homebrew sürümü

oradan okuyor. 4876203 commit'i satırı kaldırdı; test bloğu --version'ı hâlâ version.to_s ile

karşılaştırıyor.

Yeni sürüm tap'e nasıl ulaşıyor

Her aracın release workflow'unda bir homebrew job'ı var. Tarball'ı bekliyor, SHA-256'yı

hesaplıyor, formülü aracın scripts/homebrew-formula.ts dosyasıyla yazıyor ve homebrew-formula

adlı bir artifact olarak yüklüyor. Repoda HOMEBREW_TAP_TOKEN secret'ı varsa job tap'i klonlayıp

formülü bir branch'e commit'liyor ve pull request açıyor; test-bot bunu diğer her değişiklik gibi

kontrol ediyor. Secret yoksa job bir bildirimle duruyor ve formül artifact'te kalıyor.

Bu yedek yol sizeledger için kullanıldı: reposunda HOMEBREW_TAP_TOKEN yok, bu yüzden release

workflow'unun yazdığı formül, commit mesajında da yazdığı gibi, elle açılan bir pull request ile tap'e

eklendi.

Kullanım

sh
1brew tap muhittincamdali/tap
2brew install podexit

ya da tek adımda:

sh
1brew install muhittincamdali/tap/podexit

Aynısı sdkbump ve sizeledger için de geçerli.

Sınırlar

  • Bu kişisel bir tap, Homebrew core değil. Formülleri yalnızca bu reponun CI'ı inceliyor.
  • podexit ve sdkbump Homebrew'un node paketine ihtiyaç duyuyor; eksikse bağımlılık olarak kuruluyor.
  • Tap'teki podexit formülü hâlâ GitHub release URL'ini kullanıyor, podexit'in üretici script'i ise

kayıt defteri URL'ini yazıyor. İkisi de aynı dosyayı sunduğu için podexit'in release workflow'unun

yazacağı bir güncelleme URL'i değiştirir, checksum'u değiştirmez.

  • Tap'in kendine ait tag'i ya da release'i yok; geçmişi formül commit'lerinden oluşuyor.
  • test-bot macOS'ta yalnızca macos-26 imajında (Apple silicon) çalışıyor.

Kaynak kod: github.com/muhittincamdali/homebrew-tap

Etiketler

#homebrew#npm#cli#github-actions#release-engineering
Muhittin Çamdalı

Muhittin Çamdalı

Senior Mobile Engineer

12+ yıllık deneyime sahip Senior Mobile Engineer. iOS, Flutter ve React Native ile mobil ürünler geliştiriyorum; full-stack ve AI-native çalışıyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Onay e-postasındaki bağlantıyı açıp “Aboneliğimi onayla” düğmesine bastığında aboneliğin başlar. Bültende açılma/tıklama istatistikleri tutulur; dilediğin an tek tıkla ayrılabilirsin. Gizlilik

Paylaş

İlgili İçerik