पाइपलाइन फ़ेलियर की डिबगिंग

Pipeline failure को डिबग करने का मतलब है "build लाल है" को एक समझे हुए failure में बदलना: कौन-सा job, step और test fail हुआ, पहली error क्या थी, क्या उसी commit पर यह फिर होता है, और किस change ने इसे पैदा किया। Automation reporting और debugging वाले lesson ने ISTQB का debugging cycle, यानी failure को reproduce करना, उसके cause का diagnosis करना और उसे ठीक करना, एक fail हुए test पर लागू किया था; pipeline के स्तर पर commit, runner और run history भी सबूत का हिस्सा बन जाते हैं। Tester अक्सर reproduction और शुरुआती diagnosis की अगुवाई करता है, फिर developer को सबूत सौंपता है।

उदाहरण: एक nightly end-to-end run चार shards में से एक में fail होता है। Log test का नाम बताता है, trace दिखाता है कि page को कौन-सा data मिला, आपके laptop पर test तब fail होता है जब browser runner का time zone इस्तेमाल करता है, और bisect उस commit का नाम बताता है जिसने date format बिगाड़ा।

यह क्यों ज़रूरी है

लाल pipeline अपने पीछे हर merge और हर release रोक देती है, और ग़लत classification धीमी debugging से भी महँगी है। Product defect को "flaky" कहना उसे users तक पहुँचने देता है; environment की समस्या को product bug कहना developers को ऐसा defect खोजने भेजता है जो code में है ही नहीं। हरा होने तक re-run करना दोनों काम करता है: सबूत छिपाता है और टीम को सिखाता है कि लाल का कोई मतलब नहीं।

Tester का भरोसा यहीं बनता है। जो report failing test, पहली error, artifacts, reproduction command और पहला bad commit बताती है, वह जल्दी ठीक होती है; "pipeline लाल है, कोई देख सकता है?" वाली नहीं।

Log और artifacts से शुरू करें

Automation reporting और debugging वाले lesson की तरह पहली error और उसके सबूत से शुरू करें; pipeline में इसका मतलब है पहले पहला failed job और उसके अंदर पहला failed step ढूँढना। Scroll करने की बजाय log में test का नाम या error marker (GitHub Actions के raw log में ##[error]) search करें, और याद रखें कि runner के timestamps आम तौर पर UTC में होते हैं।

फिर retention period ख़त्म होने से पहले job के artifacts डाउनलोड करें, जैसे JUnit XML report, Playwright trace और application logs, और उन्हें उसी lesson की तरह पढ़ें। इन्हें job के आख़िरी green run से मिलाएँ: नई runner image, बदली हुई dependency या कम tests का चलना, code पढ़ने से पहले ही मिलने वाले सुराग हैं।

# GitHub CLI: logs of the failed steps only, then the artifacts of one job
gh run view 9876543 --log-failed
gh run download 9876543 -n e2e-results-3

# open the trace recorded for the failing test
npx playwright show-trace test-results/invoice-order-date/trace.zip

आज़माएँ: XML फ़ॉर्मेटर आज़माएँ: टेक्स्ट डिफ़

Failure को locally reproduce करें

जो failure आप अपनी machine पर reproduce कर सकते हैं, उसे debugger, extra logging और जितने चाहें उतने runs से जाँचा जा सकता है। Reproduction parity का मामला है: हर उस चीज़ में CI job से मेल बिठाएँ जो result बदल सकती है, फिर एक बार में एक ही चीज़ बदलें। अगर test locally फिर भी pass हो, तो बचा हुआ फ़र्क़ ही आपका सबसे अच्छा सुराग है।

  • Commit: job log में लिखा exact SHA। GitHub Actions पर pull-request run target branch में एक temporary merge को टेस्ट करता है, आपकी branch के head को नहीं; यह commit किसी branch पर नहीं होता, इसलिए उसे git fetch origin pull/<number>/merge से fetch करें और जाँचें कि SHA log से मेल खाता है।
  • Image और versions: अगर हो तो job की container image, lockfile से dependencies (npm ci, npm install नहीं) और वे browser builds जो आपका Playwright version pin करता है।
  • Environment variables: job की non-secret values, CI=true समेत, जिसे कई test configurations पढ़ते हैं; अपने test credentials, production secrets कभी नहीं।
  • Time zone, locale और seed: runners अक्सर UTC और English locale में चलते हैं, और random data बनाने वाले tests को अपना seed log करना चाहिए ताकि वही data दोबारा चल सके।
  • Subset और order: वही shard और workers की वही संख्या, फिर failing test अकेले और बार-बार, ताकि "अकेले fail होता है" और "सिर्फ़ दूसरे tests के साथ fail होता है" में फ़र्क़ हो सके।
git checkout 9f8e7d6                     # the SHA the job tested
npm ci && npx playwright install --with-deps chromium
export CI=true TEST_SEED=48151           # non-secret values copied from the job
npx playwright test --shard=3/4 --workers=2
npx playwright test invoice.spec.ts --repeat-each=10

Timeouts, fail-fast और re-runs

Timeout का मतलब है कि जिस चीज़ का test इंतज़ार कर रहा था वह हुई ही नहीं: कोई element, कोई response, कोई service। Limit बढ़ाने से यह शायद ही ठीक होता है; call log या trace बताता है कि इंतज़ार किसका था। Limits को परतों में रखें: test timeout (Playwright में default 30 seconds) एक नामित test को fail करता है और report फिर भी लिखी जाती है, जबकि job timeout (GitHub Actions में timeout-minutes, set न हो तो 360 minutes) पूरा job cancel कर देता है और हो सकता है कोई report न छोड़े। Test timeouts को job timeout से काफ़ी नीचे रखें।

Fail-fast पहले failure पर रुक जाता है (Playwright में -x, जो --max-failures=1 का छोटा रूप है); run-all हर failure इकट्ठा करता है। Linting और unit tests जैसे सस्ते शुरुआती stages में fail-fast रखें। महँगे stages और nightly runs में सब कुछ चलाएँ: एक failing test और चालीस failing tests अलग कहानी कहते हैं, और चालीस आम तौर पर environment जैसे किसी साझा cause की ओर इशारा करते हैं। GitHub Actions का matrix एक job fail होने पर बाक़ी jobs cancel कर देता है, जब तक आप fail-fast: false set न करें।

जितना हो सके उतना सीमित re-run करें: सिर्फ़ failed jobs (gh run rerun <run-id> --failed, जहाँ run ID run के URL वाला लंबा नंबर है, उसका # नंबर नहीं) या सिर्फ़ failing test। GitHub Actions का re-run वही commit इस्तेमाल करता है, इसलिए pass होना non-determinism साबित करता है, fix नहीं; इसे सबूत के रूप में दर्ज करें।

Retries और quarantine, संक्षेप में: automatic retry तब run को हरा कर देता है जब कोई flaky test बाद की attempt में pass हो जाए, और quarantine किसी known-flaky test को non-blocking job में ले जाता है जहाँ वह चलता रहता है। दोनों containment हैं, इलाज नहीं: ज़्यादा से ज़्यादा एक retry रखें, "retry पर pass" को flaky रिपोर्ट करें, और हर quarantined test को owner, ticket और deadline दें। Flaky tests guide यह policy समझाती है, और CI/CD testing guide का triage flow दिखाता है कि re-run कहाँ फ़िट होता है।

jobs:
  e2e:
    runs-on: ubuntu-latest
    timeout-minutes: 30      # job limit: cuts off a hang
    strategy:
      fail-fast: false       # one failing shard does not cancel the others
      matrix:
        shard: [1, 2, 3, 4]
    steps:
      # checkout and install steps omitted
      - run: npx playwright test --shard=${{ matrix.shard }}/4

आज़माएँ: YAML फ़ॉर्मेटर

कई pipeline runs में फैले regression का bisect

जब main का कोई scheduled run कई merges के बाद लाल हो जाता है, तो pipeline history आख़िरी green run और पहला red run देती है, दोनों अपने commit के साथ। पहले CI test reports में test की history देखें: जो test हफ़्तों से कभी-कभार fail हो रहा है वह flaky होने का उम्मीदवार है, नया regression नहीं। अगर वह किसी एक run से हर बार fail होता है, तो binary search change ढूँढ लेती है: बीच वाला commit टेस्ट करें, वह आधा रखें जिसमें pass, fail में बदलता है, और दोहराएँ। सोलह candidate commits के लिए ज़्यादा से ज़्यादा चार test runs चाहिए।

git bisect run यह search automate करता है: इसे दी गई command good commit के लिए 0, test न हो सकने वाले commit को skip करने के लिए 125, और bad commit के लिए 1 से 127 तक का कोई दूसरा code देकर exit करती है। Result पर तभी भरोसा करें जब bad commit पर test हर बार fail हो, इसलिए हर step पर उसे दोहराएँ, और जब environment स्थिर रहे। अगर आख़िरी green commit अब भी fail होता है, तो cause code के बाहर है, जैसे runner image, कोई external service या expired test data।

# last green nightly: a1b2c3d     first red nightly: 9f8e7d6
git bisect start 9f8e7d6 a1b2c3d
# TZ=UTC gives the browser the runner's time zone (Linux and macOS)
git bisect run sh -c 'npm ci || exit 125
  TZ=UTC npx playwright test -g "order date" --repeat-each=3'
# git prints "<sha> is the first bad commit"
git bisect reset

Worked example: एक लाल nightly run

Main पर nightly run 412 लाल है; run 411 green था, और बीच में नौ commits हैं। Fail-fast बंद है, इसलिए चारों shards पूरे हुए, और shard 3 में invoice.spec.ts के test "invoice shows the order date" में एक failure है: expected 1 Oct 2026, received 30 Sep 2026। वह पहली attempt और retry दोनों में fail हुआ, इसलिए report उसे flaky नहीं, failed दिखाती है। Trace दिखाता है कि API ने createdAt के रूप में 2026-09-30T22:40:00Z लौटाया, यानी Riyadh में 1 October को 01:40, जो store का time zone है: data सही है और display ग़लत।

Riyadh में tester के laptop पर test pass होता है। Job जैसा ही commit, lockfile, browser build और seed रखने पर एक फ़र्क़ बचता है: runner का browser UTC इस्तेमाल करता है। Playwright का timezoneId UTC पर set करने पर test 10 में से 10 बार fail होता है। Bisect command में TZ=UTC जोड़ने पर, ताकि हर commit runner के time zone में चले, git bisect run से c41d9a0 का नाम आता है, "Format dates with Intl.DateTimeFormat", जिसने store का time zone हटा दिया था। Tester run link, test, trace, reproduction setting और पहले bad commit के साथ product defect दर्ज करता है, और test configuration में timezoneId pin करने का सुझाव देता है ताकि local runs CI जैसा व्यवहार करें।

Nightly run 412, shard 3, invoice-date test के दो local runs के साथ: सिर्फ़ browser का time zone अलग था, और उसे UTC पर set करते ही test locally भी वैसे ही fail हुआ जैसे CI में।
SettingCI: nightly run 412, shard 3Laptop: पहला runLaptop: time zone मिलाने के बाद
टेस्ट हुआ commit9f8e7d69f8e7d69f8e7d6
Dependencieslockfile, npm cilockfile, npm cilockfile, npm ci
Browser buildPlaywright का pinned ChromiumPlaywright का pinned ChromiumPlaywright का pinned Chromium
Test data seed481514815148151
Browser time zoneUTCAsia/Riyadh (UTC+3)UTCtimezoneId से set
Invoice-date test30 Sep 2026 दिखाता हैफ़ेल1 Oct 2026 दिखाता हैपास10 में से 10 runs में 30 Sep 2026 दिखाता हैफ़ेल
  • CI job से अलग: यही सुराग है

आज़माएँ: Timezone कन्वर्टर

आम गलतियाँ

  • Job के artifacts को डाउनलोड करने से पहले expire हो जाने देना, जिससे ऐसे failure का trace और reports खो जाते हैं जिसे आप reproduce नहीं कर पाए।
  • सिर्फ़ failed jobs की जगह पूरा workflow re-run करना, जिससे runner का समय ख़र्च होता है और पहले से pass हुए jobs दोबारा चलते हैं।
  • अलग commit पर reproduce करना, जैसे CI ने जो merge commit टेस्ट किया उसकी जगह अपनी branch का head, या lockfile की जगह npm install से।
  • Run के URL वाले run ID की जगह gh run rerun को उसका # नंबर देना, जिससे command आपके चुने हुए run को re-run नहीं करती।
  • महँगे matrix में fail-fast चालू छोड़ देना, जिससे एक failure उन shards को cancel कर देता है जिनके results triage के लिए चाहिए थे।
  • Flaky test या बदले हुए environment का bisect करना: तब search किसी बेक़सूर commit की ओर इशारा करती है।

QA का नज़रिया

टीम के साथ तय करें कि लाल pipeline को कौन और कितनी जल्दी देखेगा; कुछ टीमें यह भूमिका बारी-बारी से निभाती हैं, कभी tester और developer साथ मिलकर। Run link से शुरू करें और जो मिले उसे साथ-साथ लिखते जाएँ: job, step, पहली error, artifacts, reproduction command, re-run का result और classification।

वह माँगें जो अगले failure को सस्ता बनाए: tests fail होने पर भी artifacts upload हों, seeds और versions log में छपें, और test timeouts job timeout से नीचे हों। CI/CD testing guide जिस failure log की सलाह देती है उसे रखें; कुछ हफ़्तों में यह दिखा देता है कि product defects, flaky tests या environments में से किसका दबदबा है, और यही वह सबूत है जिससे pipeline ठीक करवाई जा सकती है।

अभ्यास

Timeout हुए job का triage करें

आपका काम

एक pull request की pipeline लाल है। नीचे दिया run summary और log पढ़ें, फिर failure को classify करें, ग़ायब सबूत बताएँ, reproduction की योजना बनाएँ और लिखें कि pipeline में क्या बदलेंगे ताकि अगला failure बेहतर सबूत छोड़े।

सामग्री
Pull request #214, workflow "ci", run #7731 (run ID 11407731 in its URL)
Commit 5be20d7 (merge of feature/refunds into main)

unit-tests    passed     3m 10s
api-tests     failed    20m 00s
e2e (1/2)     skipped    needs: api-tests
e2e (2/2)     skipped    needs: api-tests

api-tests log, last lines (UTC):
12:04:31  PASS  orders.create > returns 201 for a valid order (0.8s)
12:04:32  RUN   refunds.create > refunds a captured payment
12:23:58  ##[error]The job running on runner ci-runner-07 has exceeded the
          maximum execution time of 20 minutes.
12:23:58  ##[error]The operation was canceled.

Artifacts: unit-reports (api-reports missing)
api-tests on main, last two runs: passed, passed
चरण
  1. Failed job, step और शुरू हुआ आख़िरी test पहचानें।
  2. सबूत जितनी इजाज़त दे उतना failure classify करें, और बताएँ कि skipped jobs आपको क्या बताते हैं।
  3. समझाएँ कि API tests की report क्यों नहीं है और अगली बार वह कैसे मिलेगी।
  4. लिखें कि आप failure कैसे reproduce करेंगे और कैसे re-run करेंगे।
मॉडल उत्तर दिखाएँ
मॉडल उत्तर

api-tests का test step hang हुआ: refunds.create > refunds a captured payment 12:04:32 पर शुरू हुआ और कोई result नहीं दिया; लगभग 19 minutes बाद 20 minutes के job timeout ने job cancel कर दिया। यह assertion failure नहीं, hang है। E2e jobs इसलिए skip हुए क्योंकि उन्हें api-tests चाहिए, इसलिए वे product के बारे में कुछ नहीं बताते।

Classification अभी खुली है: product defect (refund call कभी लौटती ही नहीं), environment की समस्या (payment stub, database lock) या flaky hang। Main पर यह job green है और pull request refunds बदलता है, इसलिए यह change पहला संदिग्ध है, पर फ़ैसला सिर्फ़ reproduction करेगा।

Test runner के report लिखने से पहले job cancel हो गया। Job timeout से काफ़ी नीचे per-test timeout set करें (जैसे 60 seconds) और tests के HTTP calls पर client timeouts लगाएँ, ताकि hang एक नामित test को report के साथ fail करे; reports ऐसे step में upload करें जो tests fail होने पर भी चले; और request ids और timestamps log करें ताकि server logs से उनका मिलान हो सके।

सिर्फ़ failed job को एक बार re-run करें (gh run rerun 11407731 --failed, run ID के साथ, #7731 के साथ नहीं): pass होने से वह flaky का उम्मीदवार बनता है, पर change सुरक्षित साबित नहीं होता। Locally merge commit fetch करें (git fetch origin pull/214/merge), 5be20d7 checkout करें, npm ci चलाएँ, job की services शुरू करें, refunds.create को छोटे timeout के साथ अकेले चलाएँ और hang के दौरान application और stub के logs पढ़ें। Bisect की ज़रूरत नहीं: इकलौता candidate change यही pull request है।

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

क्या जाँच से पहले failed job को re-run करूँ?

पहले पहली error पढ़ें और artifacts डाउनलोड करें, फिर उसी commit पर एक बार re-run करें। Re-run बताता है कि failure deterministic है या नहीं; यह triage का सबूत है, fix नहीं, और उसमें pass होना यह साबित नहीं करता कि change सुरक्षित है।

अगर failure locally reproduce न हो तो क्या करूँ?

बचे हुए फ़र्क़ एक-एक करके ख़त्म करें: container image, browser build, environment variables, time zone, seed, shard और workers की संख्या। अगर test फिर भी pass हो, तो CI में ही ज़्यादा सबूत जुटाएँ: हर attempt पर traces, ज़्यादा logging, debug logging के साथ re-run, और वहीं test को दोहराकर नापें कि वह कितनी बार fail होता है।

Bisect कब करना फ़ायदेमंद है?

जब failure deterministic हो और आख़िरी green और पहले red run के बीच कई commits हों, जो main branch के scheduled runs में आम है। एक pull request में change ख़ुद ही संदिग्ध है, और flaky test या बदले हुए environment पर bisect ग़लत commit की ओर इशारा करता है।

संदर्भ

  • ISTQB Certified Tester Foundation Level (CTFL) v4.0ISTQB · 2023सॉफ़्टवेयर टेस्टिंग का फ़ाउंडेशन पाठ्यक्रम: टेस्ट स्तर और प्रकार, टेस्ट डिज़ाइन तकनीकें, टेस्ट प्रबंधन और टूल।
  • GitHub Actions documentationGitHubGitHub Actions में workflows, jobs, runners और artifacts कैसे परिभाषित होते हैं — जहाँ हर push या pull request पर ऑटोमेटेड टेस्ट चलते हैं।
  • Reference — GitGit projectहर Git command और उसके options का आधिकारिक reference, काम के अनुसार समूहित — setup, branching, sharing, patching, inspection और debugging।
  • Playwright DocumentationMicrosoft (Playwright)Playwright का आधिकारिक दस्तावेज़ — Chromium, WebKit और Firefox चलाने वाला end-to-end टेस्ट फ़्रेमवर्क।

Mutqan tools से अभ्यास करें

दो टेक्स्ट की लाइन-दर-लाइन या शब्द-दर-शब्द तुलना करें और अंतर हाइलाइट करें।

फ़ॉर्मेटिंग

XML को मनचाहे इंडेंटेशन के साथ प्रिटी-प्रिंट करें और वापस मिनिफ़ाई भी करें।

फ़ॉर्मेटिंग

तारीख़ और समय को अलग-अलग timezone के बीच बदलें (रियाद, अम्मान, दिल्ली, UTC, न्यूयॉर्क, लंदन…)।

यूटिलिटीज़

YAML को एकसमान इंडेंटेशन और quoting के साथ फ़ॉर्मेट और वैलिडेट करें।

फ़ॉर्मेटिंग

और गहराई से

इस topic में आपकी प्रगति

QA रोडमैप का हिस्सा