Debugging a failing pipeline is the systematic process of finding why a CI run failed — distinguishing a real code failure from an environment, configuration, dependency, flakiness or infrastructure problem — using logs, artifacts, and reproduction, rather than blindly re-running.
CI failures fall into a few categories, and diagnosing efficiently means identifying the category first. Real failures: the code genuinely broke a test — the log/report points at the assertion. Environment/config: missing dependency, wrong env var, missing secret, or a difference between CI and local. Flakiness: passes on re-run with no code change (timing, shared state). Infrastructure: runner outage, network timeout, rate limit, expired token. Dependency drift: a transitive dependency changed. The method: read the actual error (not just 'job failed'), reproduce locally where possible (ideally in the same container image), inspect uploaded artifacts (traces, screenshots, logs) for the exact state at failure, check whether it's specific to one job/browser/OS in a matrix (narrows the cause), and use re-run only to confirm a flakiness hypothesis, not as a fix. Reflexive re-running without diagnosis is the anti-pattern that lets real bugs and flakiness fester.
A job fails with 'connection refused' to an external API. Instead of re-running, the engineer checks the log timestamp against the provider's status page, sees an outage window, confirms it's infrastructure (not the code), and adds a retry-with-backoff around that external call so transient outages stop failing unrelated tests.
# Techniques for debugging a failing GitHub Actions run:
# 1) Re-run with debug logging enabled
# Set repo secrets: ACTIONS_STEP_DEBUG=true, ACTIONS_RUNNER_DEBUG=true
# 2) Reproduce the exact CI environment locally with the same container
docker run -it -v "$PWD":/app -w /app \
mcr.microsoft.com/playwright:v1.50.0-jammy bash
# > npm ci && npx playwright test # same env as CI
# 3) Inspect the uploaded failure artifacts
npx playwright show-trace trace.zip
# 4) Add temporary diagnostics to a step
# - run: node -v && npm ls --depth=0 && printenv | grep -i base_urlScenario: A CI job fails. A developer's instinct is to click 're-run' repeatedly; it eventually passes, so they move on. Two days later the same failure returns. Walk through a proper debugging methodology and explain why re-running was the wrong first move.