Jeden mikro-balíček pro node rozpoutal internetové peklo. Kde děláme chyby a jak se z nich poučit?

Dobře si prohlédněte následující řádky. Jsou jen tři a velmi jednoduché:

while (str.length < length) {
  str = ' ' + str;
}

Co tenhle kód dělá? Odsadí text str zleva o tolik mezer, aby dostáhl celkové délky length. Nejspíš byste takový vymysleli i na základní škole, po proflámované noci, před první ranní kávou.

A právě takový kousek kódu sehrál v předchozích hodinách velkou roli v node.js světě.

Onen script, jen v maličko složitější podobě (na 17 řádek) existoval od března 2014 v podobě balíčku left-pad, dostupný přes NPM registry a postupně nabíral na popularitě.

Statistika stažení

(Statistiky stažení balíčků poskytuje npm-stat.com)

Kik ve vedlejší roli

Autor onoho balíčku left-pad, @Azer, je poměrně ‘plodný’ a publikoval přes 250 npm balíků. Jedním z nich je i kik. Název poněkud kolidující s chatovací aplikací kik. A právě proto se na @Azera obrátil patentový právník a domáhal se odstranení balíčku, protože název porušuje jejich registrovanou známku. @Azer odmítl a právník tedy si nakonec vydupal u NPM změnu vlastníka balíčku (a možnost odstranění) sám.

Gotta unpublish ‘em all!

Taková reakce NPM zanechala v @Azerovi pocit, že NPM není vhodné místo pro svobodný software. A odpublikoval z něj (npm unpublish) všechny své balíky. Mezi nimi i populární left-pad.

A pak se rozpoutalo peklo

Na balíčku left-pad totiž závisí balíček line-numbers. A na line-numbers závisí Babel. Takže v okamžiku, kdy byl odpublikován left-pad, přestaly fungovat buildy projektů závisejících na Babelu. A že jich je!

Křik uživatelů donutil NPM k reakci:

Mezitím i autoři mezilehlých balíků pracovali na opravách. Celá věc se tak poměrně rychle stabilizovala a buildy začaly opět fungovat.

Zcela odkázáni na milost?

Celá tahle anabáze nádherně ukazuje, jak zranitelný systém je. Stačí rozhodnutí jednoho autora nebo křik jednoho právníka a na druhém konci světa začnou selhávat buildy projektů.

Jsme vydáni na milost balíčkovacímu systému, nad nímž nemáme žádnou kontrolu. A balíčky z něj mohou kdykoliv nenávratně zmizet. Jak z toho ven?

Commitujeme závislosti do repozitáře

Můžete všechny instalované závislosti verzovat spolu se svým kódem. Pak si ale zanášíte cizí kód k sobě a je nutné rebuildovat (npm rebuild) binární rozšíření. Máte ale věc ve svých rukou (tedy repozitáři).

Odkazujeme mimo NPM

Věděli jste, že můžete jako závislost uvést i git nebo Github repozitář? Dokonce i konkrétní commit, branch nebo tag? Zůstáváte tak sice stále závislí na někom jiném, ale nejde už o tak silnou centralizaci jako v případě NPM.

Máme vlastní mirror / proxy

Můžete si vytvořit vlastní proxy, která bude řešit jak vaše privátní balíčky, tak cachovat ty veřejné. Podívejte se třeba na Kappa od PayPalu nebo na npm_lazy.

Nejsme závislí

Někdy je nejsnazším řešením žádnou závislost nevytvářet. Podívejte se, kam nás dovedla závislost na takové třířádkové blbosti, jako je odsazení zleva. Nedávno jsem psal o ne-závislosti na balíku request. Někdy je možná snazší a bezpečnější něco opravdu naprogramovat, ne jen slepovat dokola cizí knihovny.

Mimochodem, balíček left-pad má jako nejnovější číslo verze 0.0.3 a line-numbers 0.2.0. Semver říká, že

Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.

Krom toho, samotná “knihovna” line-numbers je jen 32 řádků dlouhá. Nekupíme tak na sebe knihovny, ale cizí primitivní funkce o pár řádcích. Stojí nám to za ty problémy?

Jak řešíte problémy se závislostmi vy? Máte osvědčené metody? Commitujete závislosti zároveň se zdrojáky? Podělte se prosím v komentářích.