GitHub Actions धीरे-धीरे engineering teams को खत्म कर रहा है
(iankduncan.com)- Repo में डिफ़ॉल्ट रूप से शामिल CI होने की वजह से इसका व्यापक उपयोग होता है, लेकिन संरचनात्मक अक्षम्यता और अस्थिर user experience डेवलपर productivity को घटाते हैं
- Log viewer का धीमा loading और browser crash, जटिल YAML syntax और expression errors बार-बार debugging को जन्म देते हैं
- Compute resources पर मालिकाना नियंत्रण न होने वाली संरचना के कारण performance, scalability और environment control के मामले में इसकी सीमाएँ सामने आती हैं
- इन समस्याओं को दरकिनार करने की कोशिश में बार-बार जटिल YAML या विशाल Bash scripts के जरिए CI को फिर से बनाने की स्थिति पैदा होती है
- इसके मुकाबले Buildkite सरल YAML संरचना, self-hosting योग्य agents और व्यावहारिक log experience के जरिए लंबे समय तक maintain किए जा सकने वाला CI विकल्प प्रस्तुत करता है
GitHub Actions की समस्याएँ
- GitHub Actions का log viewer अक्षम है: साधारण error जाँचने के लिए भी कई चरणों में क्लिक और page loading की ज़रूरत पड़ती है
- Build fail होने पर checks summary page → workflow run page → job page → collapsed step पर क्लिक तक पहुँचने के लिए 3~4 चरणों के page transition की ज़रूरत होती है, और हर चरण में अलग loading होती है
- बड़े build logs में browser बार-बार crash हो जाता है, और search feature इस्तेमाल करते समय Chrome के freeze होने की समस्या पुन: उत्पन्न की जा सकती है
- लंबे logs में scrolling ही काम नहीं करती, जिससे आखिरकार raw log artifact डाउनलोड करके text editor में खोलना पड़ता है
- Back button मूल PR page पर लौटाने के बजाय अप्रत्याशित GitHub Actions UI pages पर ले जाता है, और browser history Actions URLs से भर जाती है
- Debugging process की non-productive nature
- Environment variables देखने के लिए
run: envstep जोड़कर फिर से push करने पर 20 मिनट का feedback loop बनता है, और एक लाइन के बदलाव के लिए यह प्रक्रिया दर्जनों बार दोहरानी पड़ती है - 20 मिनट वाले feedback loops बार-बार दोहरने से पूरे दिन का काम CI के इंतज़ार में निकल जाता है
- Environment variables देखने के लिए
- YAML की संरचनात्मक सीमाएँ
- GitHub Actions YAML, अपनी expression language, context object model और string interpolation rules से मिलकर बना एक विशेष रूप है
${{ }}expression में एक quote गलत हो जाए तो runner spin up होने तक 4 मिनट इंतज़ार करने के बाद ही पता चलता है कि string गायब हो गई- Expression syntax configuration के लिए बहुत जटिल है, और औपचारिक programming language के रूप में इस्तेमाल करने के लिए बहुत सीमित — यह एक liminal space में मौजूद है
- इसकी syntax documentation से नहीं, बल्कि failures के अनुभव से सीखनी पड़ती है
- Marketplace के security risks
uses:syntax से external actions लाते समय, repository, secrets और build environment तक access unverified third parties को दे दिया जाता है- SHA pinning संभव है, लेकिन व्यवहार में बहुत कम लोग ऐसा करते हैं, और pinning के बाद भी बिना पढ़े गए opaque code को
GITHUB_TOKENaccess के साथ चलाया जाता है - Marketplace में अलग-अलग quality वाले community-maintained actions मिले-जुले रूप में मौजूद हैं, और ज़्यादातर shell scripts और Dockerfile पर आधारित हैं
- Dependency management अपारदर्शी है और unsafe code execution की संभावना बनी रहती है
- Compute environment की पाबंदियाँ
- GitHub Actions के default runners Microsoft के स्वामित्व वाले shared runners हैं, जो धीमे, resource-limited और meaningful customization से लगभग रहित हैं
- बड़े runners की लागत इतनी होती है कि finance team की ओर से "हमें इस पर बात करनी चाहिए" जैसा meeting request आ सकता है, और तब भी environment control नहीं मिलता
- Namespace, Blacksmith, Actuated, Runs-on, BuildJet जैसी कम-से-कम 6 startups सिर्फ GitHub Actions runners की धीमी गति दूर करने पर केंद्रित हैं, जो खुद default computing environment की कमज़ोरी का प्रमाण है
- Self-hosted runner सेट करने पर compute की समस्या हल हो सकती है, लेकिन YAML expressions, permission model, Marketplace, log viewer जैसी बाकी समस्याएँ जस की तस रहती हैं
छोटे लेकिन जमा होते जाने वाले मुद्दे
actions/cache: cache keys उलझाऊ हैं, cache miss चुपचाप होते हैं, और cache eviction अपारदर्शी है, इसलिए caching debugging में बचने वाले समय से ज़्यादा समय खर्च हो जाता है- Reusable workflows: एक तय गहराई से अधिक nesting संभव नहीं, calling workflow के context तक साफ़ access नहीं, और isolated testing भी संभव नहीं
GITHUB_TOKENpermission model:permissions: write-allबहुत व्यापक है, और granular permissions में repository, workflow और job-level settings के बीच की interaction भूलभुलैया जैसी जटिल हो जाती है- Concurrency control: उसी branch पर चल रही execution को cancel करना एक लाइन में संभव है, लेकिन उससे आगे की सूक्ष्म control capability उपलब्ध नहीं है
- Secrets को
ifcondition में इस्तेमाल न कर पाना:if: secrets.DEPLOY_KEY != ''जैसी conditional execution संभव नहीं, जो security की दृष्टि से तर्कसंगत है, लेकिन ऐसे workflows लिखने में जो fork और main repo दोनों पर काम करें workaround की ज़रूरत पड़ती है
"बस Bash script लिख लो" का जाल
- CI YAML से थके engineers के लिए सब कुछ
run:bash scripts से बदल देने का प्रलोभन रहता है, लेकिन समय के साथ उसमें conditionals, functions, argument parsing और parallel processing जुड़ते जाते हैं - 3 महीने बाद स्थिति यह हो सकती है कि 800 लाइन की bash
waitऔर PID files के साथ job parallelization को फिर से implement कर रही हो, और अपनी retry logic तथा output parsing logic भी रखती हो - नतीजा यह होता है कि CI system से बाहर निकलने के बजाय बिना test framework वाला और ऐसा उससे भी खराब CI system bash में खुद बना लिया जाता है जिसे कोई ठीक से समझ न सके
- Bash glue के रूप में ठीक है, लेकिन build system या test harness के रूप में इस्तेमाल करने पर यह complexity को guardrails वाली जगह से बिना guardrails वाली जगह पर ले जाता है
Buildkite का वैकल्पिक दृष्टिकोण
-
स्थिर log viewer
- Buildkite का log viewer browser crash किए बिना logs को सही ढंग से दिखाता है, और ANSI colors तथा test framework formatting वैसे के वैसे render होते हैं
- Annotation feature के जरिए build steps test failure summary, coverage report, deployment links आदि को सीधे build page पर Markdown में output कर सकते हैं
- क्योंकि agents अपनी infrastructure पर चलते हैं, इसलिए SSH के जरिए build machine में लॉग इन करके सीधे debugging की जा सकती है
-
सरल YAML संरचना
- Buildkite का YAML pipeline को वर्णित करने वाली शुद्ध data structure है, जिसमें सिर्फ steps, commands और plugins घोषित किए जाते हैं
- अगर वास्तविक logic चाहिए, तो ऐसी वास्तविक programming language में scripts लिखी जाती हैं जिन्हें local पर चलाया जा सके
- यह "orchestration configuration में, logic code में" जैसी सीमा को स्पष्ट बनाए रखता है — वही सीमा जिसे GitHub Actions धुंधला कर देता है
-
Compute environment पर पूरा नियंत्रण
- Buildkite agent एक single binary है, जिसे अपने cloud, on-premises या custom hardware कहीं भी चलाया जा सकता है
- Instance type, caching, local storage और network पर पूरी तरह नियंत्रण संभव है, और NVMe drives व 20GB Docker layer cache वाले बड़े EC2 instances से लेकर Raspberry Pi तक समर्थित हैं
- "Buildkite, लेकिन और तेज़" जैसी कोई third-party industry मौजूद नहीं है; बस और बड़ी machine चला दीजिए
- छोटे open source libraries संभालने वाले individual maintainers के लिए GitHub Actions का public repo free tier अब भी मूल्यवान है
- इस लेख का मुख्य लक्ष्य वे teams हैं जो production systems चलाती हैं, जहाँ CI time को प्रति सप्ताह engineering time loss के रूप में मापा जाता है, और 45 मिनट की builds compute cost और labor cost दोनों पैदा करती हैं
- ऐसे environments में Buildkite agents चलाने का overhead बहुत जल्दी अपनी लागत वसूल कर लेता है
-
Dynamic pipelines का समर्थन
- Buildkite में pipeline steps data होते हैं, और scripts runtime पर dynamically अतिरिक्त steps generate करके upload कर सकती हैं
- Monorepo में बदली गई files के आधार पर केवल ज़रूरी build और test steps को सटीक रूप से generate किया जा सकता है, जिससे hardcoded matrix या
if: contains(...)spaghetti की ज़रूरत नहीं रहती - GitHub Actions का
matrix,ifconditions और reusable workflows इसे approximate करने की कोशिश करते हैं, लेकिन अंत में कम अभिव्यक्तिशील declarative language में Rube Goldberg machine बन जाती है
-
Plugin structure की सरलता
- संरचनात्मक रूप से यह GitHub Actions Marketplace की तरह third-party repos से code लाने का तरीका है
- अंतर यह है कि Buildkite plugins आम तौर पर Docker images के बजाय thin shell hooks होते हैं, इसलिए उनका surface area छोटा होता है और उन्हें कुछ ही मिनटों में पूरा पढ़ा जा सकता है
- चूँकि यह अपनी infrastructure पर चलता है, इसलिए blast radius पर user का नियंत्रण रहता है
-
User experience पर केंद्रित छोटे features
- Buildkite custom emoji (
:parrot:,:docker:आदि) को pipeline steps के साथ दिखा सकता है; यह भले छोटा feature लगे, लेकिन product use experience के प्रति सूक्ष्म ध्यान दिखाता है - GitHub Actions ऐसा लगता है मानो उसने कभी यह सवाल ही नहीं पूछा: "क्या यह इस्तेमाल करने में आनंददायक है?" — जैसे किसी committee-design का उत्पाद हो
- Buildkite custom emoji (
निष्कर्ष: CI system चुनने के मानदंड
- GitHub Actions ने default होने के लाभ से बाज़ार पर कब्ज़ा किया है: public repos के लिए free, उसी platform में built-in जिसे सभी पहले से इस्तेमाल करते हैं, और "Good Enough" स्तर का
- यह CI का Internet Explorer जैसा है; switching cost वास्तविक है और समय सीमित है, इसलिए इसका उपयोग जारी रहता है
- Buildkite लगातार उपयोगिता और developer experience के मामले में बेहतर है
- साधारण open source projects के लिए GitHub Actions पर्याप्त है, लेकिन बड़े production environments के लिए Buildkite अधिक उपयुक्त है
- CI systems के इतिहास में market share अक्सर सबसे श्रेष्ठ system नहीं, बल्कि वह system लेता है जिससे शुरुआत करना सबसे आसान हो
- GitHub Actions वह CI है जिससे शुरू करना सबसे आसान है, जबकि Buildkite वह CI है जिसे लंबे समय तक इस्तेमाल करना सबसे अच्छा है — और लंबी अवधि में यही ज़्यादा महत्वपूर्ण है
- अगर CI tool की संरचना डेवलपर का समय खाती है, तो समस्या डेवलपर नहीं, tool खुद है
अभी कोई टिप्पणी नहीं है.