GitHub Actions और भी बेहतर हो सकता है
(blog.yossarian.net)- GitHub Actions उत्पादकता और फीचर्स के लिहाज से उपयोगी है, लेकिन असली workflows लिखते समय debugging delays, security mistakes, type की कमी, और official actions की कमी बार-बार समय की बर्बादी बनती हैं
- छोटे बदलावों के लिए भी
git add; git commit; git pushऔर browser logs देखना दोहराना पड़ता है, और एक आसान release workflow में भी 4 commits और failed release की जरूरत पड़ी थी ${{... }}expansion,pull_request_target, broadGITHUB_TOKENdefault permissions, और fork के SHA references—ये सभी security के ऐसे points हैं जहां गलती आसानी से हो सकती है; खासकर fork SHA इच्छित repository के commit जैसा दिख सकता है- Action inputs में
type:validation नहीं है, औरworkflow_callवworkflow_dispatchके साथ support scope भी अलग-अलग है, इसलिए array/object inputs की जगह CSV-style strings या flattened inputs खुद handle करने पड़ते हैं - Push के समय validation, runtime security checks, private repositories में default token permissions को घटाना, ज्यादा सख्त type checking, और ज्यादा official/semi-official actions workflow reliability बढ़ा सकते हैं
उपयोगी, लेकिन बार-बार अड़चन पैदा करने वाला GitHub Actions
- GitHub Actions 2019 से professional projects और hobby projects में रोज इस्तेमाल होने लायक productivity और stability में बड़ा योगदान देने वाला tool रहा है
- Feature expansion भी लगातार जारी रहा है
- फिर भी असली development process में यह बड़ी निराशा और समय की बर्बादी का कारण भी बनता है
छोटी गलती के लिए भी debugging बहुत भारी है
- Release workflow सेट करते समय छोटी error पकड़ने के लिए 4 commits और 4 failed releases की जरूरत पड़ने का एक example है
- जहां जरूरत थी वहां
${{ ... }}नहीं लगाया गया needs:relationship छोड़ दिया गया
- जहां जरूरत थी वहां
- मौजूदा debugging cycle में एक साधारण गलती verify करने के लिए भी कई steps हैं
- development environment से browser पर switch करना पड़ता है
- सही tab ढूंढना पड़ता है
- Actions summary और status screen में click करके जाना पड़ता है
- buffered console logs refresh करते हुए अगली error खोजनी पड़ती है
- छोटे change में भी पूरा process 30 seconds से ज्यादा ले सकता है
-
सुधार की दिशा
- interactive debugging shell दिया जाना चाहिए, या कम से कम
git add; git commit; git pushकिए बिना छोटे changes के साथ workflow फिर से run कर पाने की सुविधा होनी चाहिए - repository settings के जरिए साफ तौर पर गलत workflows को push के समय reject किया जा सके
- ऐसी syntax जो चल ही नहीं सकती
- non-existent job या step references
- गलत YAML के कारण workflow का चुपचाप न चलना
- interactive debugging shell दिया जाना चाहिए, या कम से कम
Security mistakes बहुत आसानी से हो जाती हैं
- GitHub Actions में users द्वारा लिखे workflows का अनजाने में vulnerable हो जाना आसान है
- Shell या किसी दूसरे execution context में
${{ ... }}expansion इस्तेमाल करते समय, अगर expanded value user-controlled input है, तो malicious code injection हो सकता है- example में
inputs.frobके जरिए code inject होता है और$MY_IMPORTANT_SECRETleak हो सकता है
- example में
pull_request_targetको किसी non-trivial workflow में safe तरीके से इस्तेमाल करना बहुत मुश्किल है- intended use case शायद fork से आए PR पर label लगाना या comment करना जैसे narrow scope तक सीमित है
- लेकिन असल में यह एक बड़े foot-gun की तरह exposed है
- Workflow और job-level permissions भी आसानी से जरूरत से ज्यादा set हो जाती हैं
- सामान्य
GITHUB_TOKENकी default access permissions बहुत broad हैं - personal account repositories में default token permissions घटाना अक्सर भूल जाते हैं
- जरूरी permission scope ठीक से न पता होने के कारण token permissions जरूरत से ज्यादा दे दी जाती हैं
- सामान्य
- GitHub permission model को
read/write/noneकी single axis में फिट करने से confusion और बढ़ता हैid-token: writeworkflow का OpenID Connect token पढ़ने की अनुमति देता है- कुछ security advisory
GEToperations कोwritepermission चाहिए होती है, जबकि दूसरे operations को सिर्फreadचाहिए
SHA-pinned actions fork commits से confuse हो सकते हैं
actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18eजैसा दिखने वाला reference असल मेंactions/checkoutrepository का commit नहीं भी हो सकता है- वह SHA
actions/checkoutnetwork के अंदर किसी fork में मौजूद commit है, और GitHub के alternates use की वजह से parent repository का हिस्सा जैसा दिख सकता है - Chainguard की related post problem को तीन हिस्सों में बांटती है
- fork का SHA reference और target repository का SHA reference visually अलग नहीं दिखते
- GitHub REST API का
/repos/{user}/{repo}/commits/{ref}{ref}सिर्फ fork में होने पर भी ऐसा JSON response लौटाता है जो केवल{user}/{repo}को reference करता है - fork और non-fork SHA को अलग न पहचान पाने पर GitHub Actions की trusted source restriction bypass हो सकती है
- GitHub की response अब तक documentation में additional wording जोड़ने तक ही रही है
-
सुधार की दिशा
- साफ तौर पर unsafe workflows को push के समय reject करने वाला paranoid workflow security mode चाहिए
- AddressSanitizer जैसी runtime instrumentation की तरह, workflow execution के दौरान security-risky patterns को failure माना जा सके
- जैसे:
pull_request_targetमें target repository के अलावा किसी ref सेactions/checkoutuse करने पर fail
- जैसे:
pull_request_targetको deprecate या remove करने का विकल्प भी विचार किया जा सकता है- personal repositories में भी organization/enterprise की तरह default
GITHUB_TOKENscope को ज्यादा restrictive set कर पाना चाहिए - जिस repository को reference किया गया है उसमें मौजूद न होकर केवल fork में मौजूद SHA-pinned action को default रूप से reject करना चाहिए
Type system में consistency और expressiveness की कमी है
- Custom GitHub Action
inputs:के नीचे inputs define कर सकता है, लेकिन action inputs में type enforcement नहीं है type: numberजैसी declaration action inputs में काम नहीं करती- GitHub Actions के अंदर भी type support कहां उपलब्ध है, यह consistent नहीं है
workflow_call:boolean,number,stringsupportworkflow_dispatch:boolean,choice,number,stringsupport- action inputs: type support नहीं
- Type support वाले inputs भी array या object जैसे complex data structures support नहीं करते
paths: [foo, bar, baz]जैसा array input संभव नहींheaders:के नीचे hierarchical structure वाला object input संभव नहीं
- Action authors को इसकी जगह temporary-format inputs मांगने पड़ते हैं
paths: foo,bar,bazजैसा CSV-style parsing खुद implement करनाheader-foo,header-bazकी तरह natural hierarchy को flatten करना
- यह तरीका maintainability और security दोनों के लिए अच्छा नहीं है
- single flat input namespace खुद manage करना पड़ता है
- complex inputs के लिए arbitrary unspecified language बनानी पड़ती है
-
सुधार की दिशा
- action और workflow authors हर जगह
type:इस्तेमाल कर सकें choiceको भी सिर्फworkflow_dispatchतक सीमित न रखकर हर जगह इस्तेमाल किया जा सके- जहां static रूप से type infer किया जा सकता है, वहां गलत type वाले workflow changes को push के समय reject किया जाना चाहिए
type: objectऔरtype: arrayचाहिए- internal types heterogeneous हो सकते हैं, इसलिए perfect न सही, फिर भी यह मौजूदा स्थिति से बेहतर हो सकता है
- जरूरत पड़ने पर JSON serialized string के रूप में pass किया जा सकता है
- GitHub Actions में पहले से
fromJSON(...)function है
- action और workflow authors हर जगह
Official actions platform trust से सीधे जुड़ी हैं
- GitHub Actions के third-party ecosystem में कई high-quality actions हैं
- उनके नीचे GitHub द्वारा maintained official actions हैं
- core
gitwork:actions/checkout - GitHub work और repository management:
actions/{upload,download}-artifact,actions/cache,actions/stale - essential setup:
actions/setup-python,actions/setup-node
- core
- ऐसे actions की general-purpose nature और importance ज्यादा होती है, इसलिए officially maintained implementation की value बड़ी है
- लेकिन official actions की संख्या कम है, और GitHub features को सीधे जोड़ने वाले tasks भी कभी-कभी official action के रूप में उपलब्ध नहीं होते
- example: pull request को merge queue में programmatically add करने वाला action
- GitHub CLI में
gh pr mergeहै, लेकिन action के रूप में expose नहीं है
-
बंद हो चुके official actions के examples
actions/create-release: March 2021 से unmaintained- users को community-maintained workflow पर जाने की सलाह दी गई
- representative example के तौर पर
softprops/action-gh-releaseका उल्लेख है actions/upload-release-asset:actions/create-releaseके same period में unmaintained markedactions/setup-ruby: February 2021 से unmaintained- users को
ruby/setup-rubyपर जाने की सलाह दी गई - migration अपने-आप में relatively painless था, लेकिन core components छोड़े जा सकते हैं—यह impression platform trust पर खराब असर डालता है
- official high-quality actions की कमी होने पर users GitHub API surface को खुद handle करते हुए security mistakes करते रह सकते हैं
-
Ecosystem सुधार की दिशा
- GitHub infrastructure के अलग-अलग हिस्सों को सीधे जोड़ने वाले, और आज REST API calls या
ghexecution से manually handle करने पड़ने वाले tasks official actions के रूप में दिए जाने लायक हैं - बड़े third-party actions के साथ मिलकर
community-actionsजैसी semi-official organization बनाई जा सकती है- GitHub-reviewed actions
- repository security best practices का पालन
- semantic version updates
- major ecosystem actions के लिए clear trust path
- GitHub infrastructure के अलग-अलग हिस्सों को सीधे जोड़ने वाले, और आज REST API calls या
मौजूदा tools और GitHub roadmap
- कई लोगों ने local GitHub Actions emulation tool
nektos/actrecommend किया- simple workflows को तेजी से iterate और debug करने में useful
- लेकिन images और events कभी-कभी GitHub के real environment जैसे पूरी तरह नहीं होते, इसलिए इसे lossy tool माना जाता है
rhysd/actionlintlocal linting और security linting के लिए इस्तेमाल होता है- limitation यह है कि केवल workflows lint कर सकता है, actions lint नहीं कर सकता
- GitHub Actions extension for VS Code editor के अंदर lint और repository workflow integration देता है
- public JSON schema पर based है
- running workflow display, variable completion आदि देता है
- लेकिन secrets typo या dynamically generated output name typo जैसी problems detect नहीं कर पाता, इसलिए add-commit-push debugging अब भी चाहिए
- GitHub Actions project management lead Julian Dunn ने कुछ ongoing features और priorities share किए
- interactive debugging GitHub Actions के public roadmap में है
- tag/SHA-based workflow pinning से ज्यादा immutable approach की ओर जाने का काम भी public roadmap में है
- GitHub official actions ecosystem की health और quality को priority मानता है, और हर action को पर्याप्त maintenance व attention देने के लिए official actions की संख्या छोटी रखने की strategy अपनाता है
1 टिप्पणियां
Hacker News की राय
GitHub Actions वर्कफ़्लो के दो तरीके हैं। 1) GitHub Actions के साथ “प्रोग्रामिंग” करना, जहाँ ईमेल भेजने जैसी चीज़ों के लिए भी marketplace tools जोड़ दिए जाते हैं, YAML 500–1000 लाइनों तक बढ़ जाता है और conditionals की भरमार से उसे समझना मुश्किल हो जाता है
2) GitHub Actions में सिर्फ़ “configuration” रखना, और लगातार पूछना कि “क्या इस YAML complexity को scripts में धकेला जा सकता है?” ईमेल भेजना भी script में डाल दें तो workflow करीब 50–60 लाइनों में खत्म हो जाता है, और script को local पर debug कर सकते हैं, इसलिए बेवकूफ़ी भरा push-debug-commit loop लगभग गायब हो जाता है। हर नई team में जाने पर मैं कहता हूँ कि 1 पागलपन का रास्ता है और 2 समझदारी है, लेकिन करीब आधे लोग फिर भी 1 चुनते हैं। debugging tools की कमी और vendor lock-in भी 2 चुनने पर कहीं कम समस्या बनते हैं
हालांकि सब कुछ किसी proper programming language में धकेल देना ही कई बार पर्याप्त नहीं होता। GHA के vendor-specific features इस्तेमाल करने पड़ते हैं, या jobs के बीच dependencies दिखानी होती हैं, या किसी ऐसे REST API को call करना होता है जो पहले से action के रूप में अच्छी तरह abstract हो चुका है। अपनी पसंद की language में फिर से implement किया जा सकता है, लेकिन इससे vendor dependency खत्म नहीं होती और वह फिर भी fragile रहता है। आखिरकार GHA का vendor lock-in वाला value proposition बहुत मजबूत है, इसलिए लोगों को नंबर 2 के लिए मनाने के लिए और भी मजबूत फायदे चाहिए
यह बात सिर्फ़ GHA नहीं, सभी build servers पर लागू होती है। build server को history, artifacts management, permissions/audit जोड़ने वाला script runner होना चाहिए, और असली build process को target repository पर छोड़ देना चाहिए
संदर्भ के लिए, GHA behavior को local पर reproduce करने की कोशिश करने वाला nektos/act है: https://github.com/nektos/act
build/test/sign/deploy वगैरह को जितना हो सके portable scripts के रूप में लिखना चाहिए, और ये scripts हमेशा local पर काम करनी चाहिए। GitHub को मैं सिर्फ़ उस environment को अपने-आप तैयार करने और सच में उन scripts को चलाने वाली चीज़ मानता हूँ
git commit, push, wait loop एक भयानक user experience है। users को ऐसी portable pipeline मिलनी चाहिए जो local machine समेत कहीं भी चले। Act इस समस्या को कुछ हद तक हल करता है, लेकिन आम तौर पर असली environment को हूबहू represent नहीं कर पाता
production जैसी कई pipelines local पर नहीं चलाई जा सकतीं, लेकिन कम महत्वपूर्ण development stages में ऐसे workflows को capture करके local पर चलाने से रोकने की कोई वजह नहीं है। Garden portable pipelines देता है और पूरे dependency graph पर caching जोड़ता है। कुछ customers का execution time 80% से ज़्यादा घटा है, और developers git पर पहले push किए बिना ही तुरंत देख लेते हैं कि tests pass हुए या fail। यह open source है: https://github.com/nektos/act, https://docs.garden.io
make releaseजैसे एक ही target/command इस्तेमाल करने चाहिएGH Actions के रन को debug करने की पीड़ा से पूरी तरह सहमत हूं। हाथ में जो tool है, वह बस debug चालू करके फिर से run करने की सुविधा है। pipeline को ठीक करने या debug करने के लिए बनाए गए कचरा commits बहुत ज्यादा हैं, और ज्यादातर बस यह देखने के लिए अंधाधुंध आज़माने जैसे होते हैं कि चलेगा या नहीं
reusable logic जैसी बहुत बुनियादी चीजें भी बेवजह जटिल हैं या उनकी documentation खराब है। पता चलने के बाद तो काफी आसान था, लेकिन GitHub docs बहुत खराब थे। ऐसा लगता था कि reusability पाने के लिए action को public करना होगा या किसी दूसरे repository में रखना होगा, लेकिन असल में reusable logic वाला नया YAML file बनाया जा सकता है। बस उसे workflows folder के root में रखना पड़ता है, तभी काम करता है। GH Actions के साथ काम करना सच में तकलीफदेह है, लेकिन एक बार चलने लगे तो बहुत सुविधाजनक है। commit और push करने से पहले actions test करने के लिए कोई local runner जैसा हो तो अच्छा होगा
यह सिर्फ GitHub की समस्या भी नहीं है। दूसरे बड़े CI platforms भी workflow और integration के मामले में खास बेहतर नहीं हैं। अब जितना हो सके सब कुछ script करता हूं
GitHub Actions एक घटिया CI/CD system है। एक ही VM पर steps parallel में run नहीं कर सकते, और container-based jobs को second-class citizen जैसा treat किया जाता है
पहली समस्या की वजह से local credentials या environment dependency setup को parallelize नहीं कर सकते।
google-github-actions/setup-gcloudको 1 minute से ज्यादा लगते देखकर गुस्सा आता है। दूसरी समस्या की वजह से repository के अंदर Dockerfile से CI environment setup को express करना, image content बदलने पर CI से image को दोबारा build करवाकर उस image पर depend करने वाले workflows को wait कराना, और content न बदला हो तो दोबारा build किए बिना पहले से installed dependencies के साथ तुरंत run करना—ऐसी configuration बहुत मुश्किल है। GitHub Actions में हर बार cache को फिर से भरने की कोशिश करनी पड़ती है। cache की 5GB limit है, पैसे देकर भी बढ़ा नहीं सकते, और FIFO से बाहर धकेल दिया जाता है, इसलिए 5GB पार होने पर वह लगभग न होने जैसा है। Concourse की सच में बहुत याद आती है। parallel jobs, custom pipeline triggers, CI environment में SSH करके debugging, pipeline के बिना one-off jobs run करना, artifacts बनाए बिना jobs के बीच directory contents pass करना—ये सब संभव था। GitHub Actions.github/workflowsमें एक file डालते ही इस्तेमाल शुरू करने की आसान entry की वजह से popular हुआ खिलौना CI/CD जैसा है। onboarding के लिए अच्छा है, लेकिन शुरुआती features से आगे बढ़ने पर इसे “best” कहने लायक पर्याप्त powerful नहीं हैSSH debugging और one-off jobs सच में सपने जैसे थे
GitHub fork और non-fork SHA references में फर्क नहीं कर पाता, इसलिए fork GitHub Actions की security settings को bypass कर सकता है—यह अब तक कैसे solve नहीं हुआ, समझ नहीं आता
अगर security control को आसानी से bypass किया जा सकता है, तो यह गंभीर security issue है। किसी को मेरा SHA इस्तेमाल करने के लिए राजी करना पड़ेगा, लेकिन social engineering आमतौर पर आसान ही होती है
ईमानदारी से कहूं तो यह कितना खराब है, इस पर शर्म आने लायक है। unrelated build failure का notification संयोग से सिर्फ उस latest maintainer को जाना जिसने आखिरी merge किया, यह भी अजीब है। नया जोड़ा गया maintainer Matrix पर बताने तक मुझे यह पता भी नहीं चल सकता कि मेरा update/build एक हफ्ते से fail हो रहा है
cache action आंखों से देखने पर ही साफ टूटा हुआ है, लेकिन लगता है कोई maintainer नहीं है। UI टूट जाए या tab unload हो जाए तो step के build log को tail भी नहीं कर सकते। workflows को worker nodes के बीच portable बनाने के लिए abstraction भी लगभग नहीं है। default images तो लगभग आपदा हैं। शुरू में बस लगा कि वे बहुत bloated हैं और चिढ़ हुई, लेकिन जितना अंदर गया, उतना लगा कि “इसे किसी ऐसे Microsoft व्यक्ति ने संभाला है जिसे Linux नहीं पता।” Nix या Docker इस्तेमाल करने वालों के लिए हल्की images देने की भी कोई कोशिश नहीं है। मैं GitHub से दूर जा रहा हूं, और मुख्य वजह यह है कि Actions ने आंखें खोल दीं। YAML में programming न करने की वजह यह है कि मैं YAML को उस ecosystem की बदनामी मानता हूं, जो आधुनिक और सच में उपयोगी technology नहीं जानता और जिस पर VC money बरसाकर बनाया गया है
https://pre-commit.ci की मैं ज़ोरदार सिफारिश करता हूँ। मैं इससे जुड़ा हुआ व्यक्ति नहीं, बस एक संतुष्ट यूज़र हूँ
आइडिया यह है कि commit से पहले कोड जाँचने और संभव हो तो ठीक करने वाले hooks लिखें या मौजूदा hooks इस्तेमाल करें, और push के बाद CI फिर से जाँच करे और ज़रूरत पड़े तो अपने-आप fix commit भी कर दे। इसकी automatic caching अच्छी है, इसलिए यह यकीन न होने लायक तेज़ है, और local development machine और CI में वही config इस्तेमाल होता है, इसलिए debugging की समस्याएँ काफी कम हो जाती हैं। open source के लिए यह मुफ़्त है। यह automatic release जैसी चीज़ें नहीं करता, केवल जाँच करता है, लेकिन वह जाँच बहुत अच्छे से करता है
source code को ही जाँचना हो तो
skip_install = Trueके साथ static checks भी चला सकते हैं। इसे ऐसे container में चलाएँ जिसमें global tool के रूप में tox install हो और सभी ज़रूरी Python versions मौजूद हों। उदाहरण के लिए https://github.com/georgek/docker-python-multiversion जैसी image है। maintain नहीं होती, लेकिन update करना आसान है।[tox] envlist = py{310,311},[testenv],[testenv:check]मेंpre-commit run --all-files --show-diff-on-failureरखने जैसा boilerplate काफ़ी हैgit commit; git push; repeatloop से बहुत ज़्यादा गुजरने के बाद मुझे https://github.com/mxschmitt/action-tmate मिला। यह steps के बीच shell access खोल देता है, इसलिए सभी समस्याएँ हल नहीं करता, लेकिन कभी-कभी दर्द ज़रूर कम कर देता हैनिजी तौर पर, अच्छा होगा अगर अभी
actions/upload-artifactजैसी चीज़ इस्तेमाल किए बिना action run में HTML report attach की जा सकेखासकर test builds में output HTML report जल्दी देखना अक्सर ज़रूरी होता है। अभी मुझे जो तरीके पता हैं वे upload-artifact या GH Pages हैं, लेकिन GH Pages तब अच्छा नहीं है जब उसी repository में कई report outputs हों या आप latest नहीं बल्कि पुराने reports जल्दी देखना चाहें। अगर job summary में HTML report link जोड़ने वाला एक साधारण
attach-reportaction हो, और click करने पर HTML render हो जाए, तो अच्छा होगा। दूसरे automation CI/CD systems HTML reports capture और view करने के लिए default रूप से कहीं ज़्यादा समृद्ध support देते हैं$GITHUB_STEP_SUMMARYमें Markdown output सीधे जोड़ सकते हैंमुझे लगता है कि GH Actions असल में Microsoft के “Azure Pipelines” rebranding के काफ़ी करीब है। TFS/VSTS/AzDO build और release pipelines के पुराने सभी रूप इस्तेमाल कर चुका हूँ, और मेरे हिसाब से यह team इस काम में अच्छी नहीं है
Azure Pipelines किसी हद तक इस्तेमाल लायक भी इसलिए हुआ क्योंकि उससे पहले आज़माए गए सारे approaches सचमुच fail हो गए थे। एक project ऐसा भी था जो commit किए बिना private environment में edit-run-debug loop चलाने के लिए pipelines को locally run करने देता, लेकिन जाहिर है उसे cancel कर दिया गया: https://github.com/microsoft/azure-pipelines-agent/pull/2687/files#diff-570b52bcb927a5365c22d17a21e8e19e1ba3427c7f3ec16ea64b7b3d14e4ee20। फिर भी quality of life बढ़ाने वाले tools हैं। उदाहरण के लिए syntax समझने वाला VS Code extension: https://marketplace.visualstudio.com/items?itemName=ms-azure-devops.azure-pipelines। थोड़ा विवादास्पद ढंग से कहूँ तो अगर YAML की जगह XML इस्तेमाल किया गया होता, तो top पर मौजूद xmlns declaration भर से ज़्यादातर अच्छे code editors में अलग user intervention के बिना validation मिल सकती थी। XML भयानक है, लेकिन जब हमने उसे पूरी तरह छोड़ दिया तो उसके साथ कई उपयोगी features भी खो दिए