आपका GitHub Actions CI धीमा क्यों है (और इसे कैसे तेज़ करें)

आपका GitHub Actions CI धीमा क्यों है (और इसे कैसे तेज़ करें)

आपके वर्कफ़्लो में छिपे प्रदर्शन अवरोधों के आसान समाधान

वह समस्या जिस पर किसी का ध्यान नहीं जाता

वर्कफ़्लो विफल होने पर GitHub आपको ईमेल भेजेगा। लेकिन जब आपकी CI को जितना समय लगना चाहिए उससे दोगुना समय लगता है? तब आपको चुप्पी मिलती है। हर pull request और हर commit पर चलने वाली एक धीमी बिल्ड, जो बार-बार उन्हीं डिपेंडेंसीज़ को कंपाइल करती है—यह एक ऐसा नुकसान है जो साफ सामने होते हुए भी छिपा रहता है।

30 जून, 2026 तक, CI प्रदर्शन पहले से कहीं अधिक महत्वपूर्ण हो गया है। डेवलपमेंट टीमें बड़ी हैं, डिप्लॉयमेंट तेजी से होते हैं, और धीमे फीडबैक लूप्स की लागत पूरी टीम पर भारी पड़ती है। यदि आपकी CI को 5 मिनट के बजाय 15 मिनट लगते हैं, और आपकी टीम प्रति सप्ताह 40 PR खोलती है, तो आप सामूहिक रूप से मशीनों का इंतज़ार करते हुए प्रति सप्ताह 8 घंटे बर्बाद कर रहे हैं। यह एक पूरे व्यक्ति के खाली समय के बराबर है। फिर भी अधिकांश टीमों को इस समस्या के प्रति सचेत करने वाला डैशबोर्ड कभी नहीं दिखता।

यह क्यों होता है

GitHub Actions को सेट अप करना आसान है, जो कि इनके हर जगह फैलने का एक कारण है। लेकिन उस सादगी का मतलब है कि समझदारी भरे डिफ़ॉल्ट अक्सर प्रदर्शन की बड़ी गिरावटों को छिपा देते हैं। आप एक वर्कफ़्लो बनाएंगे, यह काम करेगा, और जब तक कुछ बुरी तरह से टूट न जाए, आप इसके बारे में सोचना बंद कर देते हैं। इस बीच, वर्कफ़्लो अनावश्यक काम कर सकता है: हर रन में पैकेज री-इंस्टॉल करना, विशाल कैश आर्टिफैक्ट्स अपलोड करना, वर्कफ़्लो मैट्रिक्स में टाइपो के कारण परीक्षणों को दो बार चलाना, या बूट होने में बहुत अधिक समय लेने वाली पुरानी इमेजेस का उपयोग करना।

आम कारणों को खोजना और ठीक करना आसान है। आइए उन्हें विस्तार से समझें।

सामान्य कारण

हर बार डिपेंडेंसीज़ को फिर से बनाना (Rebuilding)

सबसे आसान गलतियों में से एक अपनी डिपेंडेंसीज़ को कैश न करना है। यदि आपका वर्कफ़्लो हर रन पर वही npm पैकेज, Go मॉड्यूल, या Python लाइब्रेरीज़ इंस्टॉल करता है, तो आप बिल्कुल उन्हीं फ़ाइलों के लिए दिन में कई बार इंटरनेट, अनपैकिंग और सत्यापन की कीमत चुका रहे हैं।

अधिकांश भाषाओं में एक बिल्ट-इन कैशिंग रणनीति होती है। Node.js के लिए, GitHub Actions एक कैश एक्शन प्रदान करता है जो स्टोर करता है node_modules या रनों के बीच आपकी लॉक फ़ाइल। Python के लिए, आप pip व्हील्स को कैश कर सकते हैं। Java में Maven और Gradle कैश हैं। यदि आप इनका उपयोग नहीं कर रहे हैं, तो आपकी CI अनावश्यक काम कर रही है।

धीमी या बहुत भारी (bloated) इमेजेस

GitHub Actions वर्कफ़्लो कंटेनरों में चलते हैं। आपके द्वारा चुनी गई इमेज एक आधार तय करती है कि हर रन को बूट होने में कितना समय लगेगा। पुरानी या अत्यधिक बड़ी बेस इमेज (जैसे आपकी ज़रूरत न होने वाले बिल्ड टूल्स के साथ एक पूर्ण Ubuntu) का उपयोग करने से आपको हर एक रन पर कई मिनटों का नुकसान होता है।

जब हो सके मिनिमल इमेजेस पर स्विच करें। यदि आपको विशिष्ट टूल्स की आवश्यकता है, तो एक बार एक कस्टम Docker इमेज बनाएं, इसे GitHub Container Registry जैसी रजिस्ट्री में पुश करें, और इसका पुनः उपयोग करें। पहली रन को इमेज बनाने में अधिक समय लगता है, लेकिन बाद की रन इसे तुरंत पुल (pull) कर लेती हैं।

गलती से जॉब्स को दो बार चलाना

वर्कफ़्लो मैट्रिक्स शक्तिशाली होते हैं लेकिन इन्हें गलत कॉन्फ़िगर करना आसान होता है। एक आम गलती विभिन्न Node संस्करणों या ऑपरेटिंग सिस्टम के लिए एक मैट्रिक्स सेट अप करना है, फिर यह महसूस करना कि आपका इरादा असल में इसे केवल एक बार चलाने का था। प्रत्येक डुप्लिकेट रन CPU, स्टोरेज और समय की खपत करता है।

अपने वर्कफ़्लो YAML की समीक्षा करें। यदि आपको कोई ऐसा मैट्रिक्स दिखता है जो अनावश्यक रूप से काम को दोहरा रहा है, तो इसे समतल (flatten) करें या केवल कुछ ब्रॉन्चेस पर चलने के लिए एक शर्त जोड़ें।

बड़े या अनावश्यक आर्टिफैक्ट्स

यदि आपका वर्कफ़्लो हर रन के बाद बड़े बिल्ड आर्टिफैक्ट्स या लॉग अपलोड करता है, तो GitHub उन्हें स्टोर करने और कंप्रेस करने में समय बिताएगा। यदि आप वास्तव में उन आर्टिफैक्ट्स का उपयोग आगे नहीं कर रहे हैं, तो वे पूरी तरह से व्यर्थ हैं।

आप क्या अपलोड करते हैं इसके बारे में स्पष्ट रहें। क्या आपको पूरे बिल्ड डायरेक्टरी की आवश्यकता है, या केवल अंतिम बाइनरी की? क्या आपको सफल रनों के लॉग की आवश्यकता है, या केवल विफलता पर? एक रिटेंशन नीति (retention policy) सेट करें ताकि पुराने आर्टिफैक्ट्स जमा न हों।

क्रमिक (Serial) कदम जो समानांतर (parallel) चल सकते हैं

यदि आपका वर्कफ़्लो एक के बाद एक क्रम में lint, फिर परीक्षण (tests), फिर build चलाता है, तो आप समय के एक हिस्से के लिए केवल एक CPU कोर का उपयोग कर रहे हैं। GitHub Actions डिफ़ॉल्ट रूप से समानांतर में कई जॉब्स चला सकता है। यदि आपके पास स्वतंत्र कदम हैं, तो उन्हें अलग जॉब्स में विभाजित करें।

एक सरल उदाहरण: linting तेज़ है और इसे पूरे बिल्ड की आवश्यकता नहीं है। इसे इसकी अपनी जॉब के रूप में चलाएं। यदि यह विफल रहता है, तो आप परीक्षणों का इंतज़ार किए बिना तुरंत जान जाते हैं। यदि यह पास हो जाता है, तो परीक्षण और बिल्ड एक ही समय में चलते हैं।

धीमेपन को कैसे मापें

अनुकूलन (optimize) करने से पहले, आपको एक बेसलाइन की आवश्यकता होती है। GitHub Actions टैब में एक वर्कफ़्लो टाइमलाइन प्रदान करता है। एक हालिया रन खोलें, और प्रत्येक जॉब और कदम की अवधि देखें। आपको लगभग हमेशा कम से कम एक ऐसा कदम मिलेगा जो जितना होना चाहिए उससे बहुत धीमा है।

संख्याओं को लिखें। बदलाव करने के बाद, वापस आएं और तुलना करें। "CI 12 मिनट से घटकर 5 मिनट हो गया" देखना संतोषजनक है और यह साबित करता है कि सुधार ने काम किया।

चरण-दर-चरण अनुकूलन (optimization) चेकलिस्ट

चरण 1: डिपेंडेंसी कैशिंग सक्षम करें

अपनी भाषा के लिए एक कैशिंग चरण जोड़ें। Node.js के लिए, इसे अपने वर्कफ़्लो में जोड़ें:

- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

यह cache: 'npm' लाइन GitHub को आपकी node_modules को रनों के बीच स्वचालित रूप से सहेजने और पुनर्स्थापित करने के लिए कहती है। अन्य भाषाओं में समान विकल्प हैं—अपनी भाषा के लिए आधिकारिक एक्शन देखें।

चरण 2: अपनी बेस इमेज का ऑडिट करें

यदि आपका वर्कफ़्लो उपयोग करता है runs-on: ubuntu-latest, तो जांचें कि उस इमेज में क्या शामिल है। यदि आपको केवल Node.js की आवश्यकता है, तो आधिकारिक Node इमेज (docker://node:20) या GitHub के लाइटवेट संस्करण पर स्विच करने पर विचार करें। यदि आपको एक कस्टम सेटअप की आवश्यकता है, तो एक बार एक मिनिमल इमेज बनाएं और पुश करें।

चरण 3: धीमी जॉब्स को समानांतर (parallel) जॉब्स में विभाजित करें

अपने वर्कफ़्लो YAML की समीक्षा करें। यदि आपके पास क्रमिक (sequential) जॉब्स हैं जो एक-दूसरे पर निर्भर नहीं हैं, तो उन्हें विभाजित करें। उदाहरण के लिए:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run lint

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test

अब lint और test, lint-के-बाद-test की बजाय एक ही समय में चलते हैं।

चरण 4: अनावश्यक (redundant) आर्टिफैक्ट्स हटाएं

अपने वर्कफ़्लो में जांचें actions/upload-artifact। यदि आर्टिफैक्ट का उपयोग किसी अन्य जॉब द्वारा नहीं किया जाता है या मैन्युअल रूप से डाउनलोड नहीं किया जाता है, तो इसे हटा दें। यदि आप डिबगिंग के लिए आर्टिफैक्ट्स रखते हैं, तो एक छोटी रिटेंशन अवधि निर्धारित करें:

- uses: actions/upload-artifact@v4
  if: failure()
  with:
    name: logs-on-failure
    retention-days: 7

यह केवल विफलता पर लॉग अपलोड करता है और एक सप्ताह के बाद उन्हें हटा देता है।

चरण 5: मैट्रिक्स दोहराव (matrix duplication) की जांच करें

अपने वर्कफ़्लो में खोजें matrix: और प्रत्येक की समीक्षा करें। यदि मैट्रिक्स वास्तव में आपके वांछित व्यवहार को नहीं बदल रहा है, तो इसे हटा दें। एक मैट्रिक्स जो हर बिल्ड को दो बार चलाता है वह बेकार का बोझ है।

चरण 6: चरणों के क्रम की समीक्षा करें

एक जॉब के भीतर, प्रत्येक चरण क्रमिक रूप से चलता है। सुनिश्चित करें कि क्रम समझ में आने योग्य है। यदि कोई चरण धीमा है लेकिन उसका परिणाम बहुत बाद में उपयोग किया जाता है, तो उसे उस स्थान के करीब ले जाने पर विचार करें जहाँ इसका उपयोग किया जाता है। यदि कोई चरण तेज़ और स्वतंत्र है, तो उसे आगे बढ़ाएं ताकि यह जल्दी विफल हो सके।

समय के साथ निगरानी (Monitoring)

एक बार जब आप अनुकूलन कर लें, तो इसे न भूलें। CI वर्कफ़्लो बदलते रहते हैं—डिपेंडेंसीज़ बड़ी हो जाती हैं, नए चरण जुड़ जाते हैं, इमेजेस बदल जाती हैं। अपने सबसे धीमे वर्कफ़्लो की स्पॉट-जांच करने के लिए एक मासिक रिमाइंडर सेट करें। यदि यह धीमा होता दिख रहा है, तो संकट बनने से पहले इसकी जांच करें।

कुछ टीमें GitHub Actions मीट्रिक्स को एक मॉनिटरिंग डैशबोर्ड पर एक्सपोर्ट करती हैं। यह उन्नत है, लेकिन यदि आपके पास कई वर्कफ़्लो हैं, तो यह बदलावों को स्वचालित रूप से सामने लाकर अपना लाभ देता है।

निष्कर्ष

धीमी CI आपकी टीम की गति (velocity) पर एक ऐसा कर (tax) है जो कभी बिल पर दिखाई नहीं देता। यह प्रति सप्ताह सैकड़ों रनों में चुपचाप बढ़ता जाता है। समाधान कठिन नहीं हैं—कैशिंग, समानांतर जॉब्स, अपव्यय को हटाना—लेकिन उनके लिए पहले समस्या को देखना आवश्यक है। इस सप्ताह अपने वर्कफ़्लो की समीक्षा करने में एक घंटा बिताएं। संभावना है कि आपको प्रति रन 5-10 मिनट का बर्बाद समय मिलेगा। यह आपके भविष्य के लिए एक उपहार है।

लाभ

  • तेज़ फीडबैक लूप्स डेवलपर्स को बिना रुकावट के प्रवाह में बनाए रखते हैं।
  • रनों के जल्दी पूरा होने से क्लाउड कंप्यूट लागत कम होती है।
  • समस्याओं का शीघ्र पता चलना (उदा. विभाजित जॉब्स पहले ही विफल हो जाती हैं)।
  • बेहतर डेवलपर अनुभव; 15 मिनट के बजाय 3 मिनट इंतज़ार करने पर लोग अधिक खुश होते हैं।
  • छोटे बदलाव प्रति सप्ताह दर्जनों रनों में मिलकर महत्वपूर्ण समय की बचत करते हैं।
  • मापना आसान है; डैशबोर्ड डेटा पहले से ही GitHub में उपलब्ध है।

हानियाँ

  • ऑडिट और रखरखाव की आवश्यकता होती है; समीक्षा के बिना वर्कफ़्लो अनुकूलित नहीं रहते।
  • अत्यधिक आक्रामक (over-aggressive) कैशिंग प्रोडक्शन तक डिपेंडेंसी बग्स को छिपा सकती है।
  • जॉब्स को बहुत अधिक विभाजित करने से जटिलता उत्पन्न होती है; अधिक जॉब्स का अर्थ है डिबग करने के लिए अधिक चीज़ें।
  • मिनिमल इमेजेस में कभी-कभी उन टूल्स की कमी होती है जिनकी आपको बाद में आवश्यकता होती है, जिससे दोबारा काम करना पड़ता है।
  • आर्टिफैक्ट सफाई नीतियों (cleanup policies) से डिबगिंग के लिए आवश्यक लॉग खोने का जोखिम होता है।
  • समानांतरीकरण (Parallelization) तभी मदद करता है जब आपके पास पर्याप्त कॉनकरेंसी कोटा (concurrency quota) हो; GitHub का मुफ़्त टियर सीमित है।

सावधानी

इस लेख में सभी नाम, कॉन्फ़िगरेशन मान और प्लेसहोल्डर (उदा., node:20, ubuntu-latest, app.example.com) केवल उदाहरण के उद्देश्यों के लिए हैं। किसी भी वर्कफ़्लो को प्रोडक्शन में डिप्लॉय करने से पहले, स्टेगिंग शाखा पर इसका अच्छी तरह से परीक्षण करें। आपका विशिष्ट सेटअप, भाषा संस्करण और इंफ्रास्ट्रक्चर भिन्न हो सकते हैं। एक प्रोजेक्ट के लिए अच्छी तरह से काम करने वाली कैशिंग रणनीतियाँ दूसरे के लिए उपयुक्त नहीं हो सकती हैं। हमेशा अपने वास्तविक वातावरण में प्रदर्शन सुधारों की पुष्टि करें, और साइड इफेक्ट्स की निगरानी करें (उदा., पुराना कैश जिसके कारण पुरानी डिपेंडेंसीज़ आती हैं)। अपने जोखिम पर आगे बढ़ें।

अक्सर पूछे जाने वाले प्रश्न

  • GitHub Actions पर प्रति रिपॉजिटरी अधिकतम कैश आकार क्या है?
  • मुझे कैसे पता चलेगा कि मेरे वर्कफ़्लो में GitHub Actions कैशिंग वास्तव में उपयोग की जा रही है?
  • क्या मैं अपनी CI को तेज़ करने के लिए कस्टम Docker इमेज का उपयोग कर सकता हूँ?
  • कैश बनाने के बाद मेरी पहली रन में कम समय लगने के बजाय अधिक समय क्यों लगता है?
  • कॉनकरेंसी कोटा उपयोग बढ़ाए बिना GitHub Actions में जॉब्स को समानांतर (parallelize) कैसे करें?
  • क्या node_modules को कैश करना बेहतर है या सिर्फ लॉक फ़ाइल को?
  • क्या धीमी CI रन GitHub को स्वचालित रूप से मेरे वर्कफ़्लो को रद्द करने का कारण बन सकती हैं?
  • मुझे अपने GitHub Actions वर्कफ़्लो की समीक्षा और अपडेट कितनी बार करना चाहिए?

टैग्स

#github #actions #ci #cicd #devops #performance #optimization #workflows #automation #testing

Free field guide

Prompt-Injection Defense Checklist

The controls that actually reduce the blast radius when your app feeds untrusted text to an LLM. Enter your email — you'll get the PDF instantly, plus new posts on AI, security & Linux.