Build Pipeline Analyzer Skill
This skill helps diagnose GitHub Actions workflow failures for FanHub's frontend and backend CI/CD pipelines.
FanHub CI/CD Pipeline Structure
Frontend Workflow
name: Frontend CI steps: 1. Checkout code 2. Setup Node.js 18 3. npm ci (install dependencies) 4. npm run lint (ESLint) 5. npm test -- --coverage (Jest tests, 80% minimum) 6. npm run build (production build)
Backend Workflow
name: Backend CI steps: 1. Checkout code 2. Setup Node.js 18 3. Setup PostgreSQL service 4. npm ci (install dependencies) 5. npm run lint (ESLint) 6. npm test -- --coverage (Jest + integration tests) 7. Docker build (multi-stage Dockerfile)
Environment: ubuntu-latest runners, Node 18 LTS
Common CI/CD Failure Patterns
1. Test Failures
1A. Test Timeout
Symptom:
FAIL src/components/CharacterCard.test.js
● CharacterCard › renders character name
Timeout - Async callback was not invoked within the 5000ms timeout
specified by jest.setTimeout.
npm ERR! Test failed. See above for more details.
Root Causes:
- •Unmocked API call (waiting for real network request)
- •Database connection not established (in integration tests)
- •Infinite loop or unresolved Promise
- •CI runner slower than local machine
Diagnostic Questions:
- •Does test pass locally? (flaky vs. broken)
- •Is there an API call without a mock?
- •Is there an async operation without await?
- •Is there a database dependency?
Fixes:
- •
Increase timeout (if genuinely slow operation):
javascriptjest.setTimeout(10000); // 10 seconds
- •
Add missing mocks:
javascriptjest.mock('../api/characters', () => ({ getCharacter: jest.fn().mockResolvedValue({ name: 'Test' }) })); - •
Ensure async completion:
javascriptawait waitFor(() => { expect(screen.getByText('Character Name')).toBeInTheDocument(); }); - •
Fix database setup (backend tests):
javascriptbeforeEach(async () => { await db.reset(); // Ensure DB is ready });
1B. Assertion Failure
Symptom:
FAIL src/api/characters.test.js
● GET /api/characters/:id › returns character with related data
Expected: 200
Received: 500
Database connection timeout
Root Causes:
- •Test database not properly configured in CI
- •Missing environment variables
- •Race condition (test runs before setup completes)
- •Test isolation issue (previous test left dirty state)
Diagnostic Questions:
- •Does test pass when run alone? (
npm test -- CharacterCard) - •Are environment variables set in GitHub Actions?
- •Is the database service running? (check workflow YAML)
- •Is test cleanup happening? (afterEach hooks)
Fixes:
- •
Check GitHub Actions secrets/env vars:
yamlenv: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/testdb NODE_ENV: test
- •
Add test isolation:
javascriptafterEach(async () => { await db.query('TRUNCATE TABLE characters, quotes CASCADE'); }); - •
Wait for services to be ready:
yaml- name: Wait for PostgreSQL run: | until pg_isready -h localhost -p 5432; do sleep 1 done
2. Build Failures
2A. Dependency Install Failure
Symptom:
Run npm ci npm ERR! cipm can only install packages when your package.json and package-lock.json are in sync.
Root Cause: package-lock.json is out of sync with package.json
Fixes:
- •
Locally regenerate lock file:
bashrm package-lock.json npm install git add package-lock.json git commit -m "fix: regenerate package-lock.json"
- •
Or use
npm installin CI (slower but more forgiving):yaml- run: npm install # Instead of npm ci
2B. Build Step Failure
Symptom:
Run npm run build > react-scripts build Failed to compile. Module not found: Can't resolve './CharacterCard' in '/src/pages'
Root Causes:
- •Import path wrong (case-sensitive on Linux, not on Mac/Windows)
- •File not committed to git
- •Build-time environment variable missing
CI vs Local Differences:
- •CI runs on Linux (case-sensitive filesystem)
- •CI clones from git (doesn't see untracked files)
- •CI has different environment variables
Diagnostic Questions:
- •Is the file name exactly right? (
CharacterCard.jsvs.characterCard.js) - •Is the file committed? (
git ls-files | grep CharacterCard) - •Does the build need env vars? (check for
process.env.REACT_APP_*)
Fixes:
- •
Fix import case:
javascript// If file is CharacterCard.js: import CharacterCard from './CharacterCard'; // ✅ Correct import CharacterCard from './characterCard'; // ❌ Works on Mac, fails on Linux
- •
Commit missing files:
bashgit add src/components/CharacterCard.js git commit -m "fix: add missing component file"
- •
Add build-time env vars:
yaml- name: Build env: REACT_APP_API_URL: ${{ secrets.API_URL }} run: npm run build
3. Linting Failures
Symptom:
Run npm run lint /home/runner/work/fanhub/src/components/CharacterCard.js 12:7 error 'character' is assigned a value but never used no-unused-vars ✖ 1 problem (1 error, 0 warnings)
Root Cause: Code passes locally because lint warnings were ignored
Why CI Catches It:
- •Local:
npm run lintmay just warn - •CI: Often configured to fail on errors (
--max-warnings 0)
Fixes:
- •
Fix the lint error (preferred):
javascript// Remove unused variable const { character } = props; // ❌ Unused const { name } = props; // ✅ Used - •
Run lint with auto-fix locally:
bashnpm run lint -- --fix
- •
Add lint-staged to prevent this:
json// package.json { "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "*.js": "eslint --fix" } }
4. Docker Build Failures in CI
4A. COPY Path Issues
Symptom:
Step 4/7 : COPY package*.json ./ COPY failed: file not found in build context or excluded by .dockerignore: stat package.json: file does not exist
Root Cause: Docker build context is wrong in GitHub Actions
CI vs Local Difference:
- •Local: You run
docker buildfrom the right directory - •CI: Workflow might run from repo root
Diagnostic Questions:
- •What's the
docker buildcommand in the workflow? - •Where is the Dockerfile? (
backend/Dockerfile) - •Where is package.json relative to the Dockerfile?
Fixes:
- •
Check workflow docker build command:
yaml# ❌ Wrong context - name: Build Docker image run: docker build -f backend/Dockerfile . # ✅ Correct context - name: Build Docker image run: docker build -f backend/Dockerfile ./backend
- •
Or adjust Dockerfile COPY paths:
dockerfile# If context is repo root and Dockerfile is in backend/: COPY backend/package*.json ./
5. Flaky Tests
Symptom: Test passes sometimes, fails other times (~30% failure rate)
Example:
Run npm test
FAIL src/api/characters.test.js (Run 1/1)
● GET /api/characters/:id › returns character with related data
Expected: 200
Received: 500
But re-running the workflow... it passes.
Root Causes:
- •Race condition (async operations not properly awaited)
- •Shared state between tests (one test affects another)
- •External dependency (database, network)
- •Timing-dependent assertion
Diagnostic Questions:
- •Does it fail consistently or intermittently?
- •Does it pass when run alone?
- •Is there shared state (global variables, database)?
- •Are async operations properly awaited?
Fixes:
- •
Improve test isolation:
javascriptbeforeEach(async () => { await db.resetAllTables(); // Clean slate for each test }); - •
Add retry logic for known-flaky tests:
javascriptjest.retryTimes(2); // Retry failed tests twice
- •
Use proper async patterns:
javascript// ❌ Race condition render(<CharacterCard id={1} />); expect(screen.getByText('Name')).toBeInTheDocument(); // ✅ Wait for async data render(<CharacterCard id={1} />); await waitFor(() => { expect(screen.getByText('Name')).toBeInTheDocument(); }); - •
Increase timeout for slow CI runners:
javascriptjest.setTimeout(10000); // CI may be slower than local
Diagnostic Workflow
When a GitHub Actions build fails:
- •
Identify which step failed
- •Click on the failed workflow run
- •Expand the failed step
- •Look for the red ✖ icon
- •
Extract the actual error message
- •Don't stop at "exit code 1"
- •Scroll up to find the actual error (npm ERR!, FAIL, ERROR)
- •Copy the error message
- •
Determine the failure type
Error Contains Failure Type FAIL,TimeoutTest failure npm ERR!,ERESOLVEDependency issue Module not foundBuild error error+eslintLint failure COPY failedDocker build issue - •
Check if it's a regression
- •Did this pass on the previous commit?
- •Check the commit diff—what changed?
- •Look at previous successful runs for comparison
- •
Distinguish CI-specific vs. universal issues
Issue CI-Specific? Test timeout Maybe (CI slower) Import case mismatch Yes (Linux vs Mac) Missing mocks No (universal) Docker context path Yes (workflow-specific) Lint error No (should fail locally too) - •
Apply the appropriate fix
- •See specific sections above for each failure type
Quick Triage Guide
Build Failed
└─ Which step?
├─ npm ci
│ └─ "out of sync" → Regenerate package-lock.json
├─ npm run lint
│ └─ ESLint error → Fix or run --fix locally
├─ npm test
│ ├─ "Timeout" → Check mocks, increase timeout
│ ├─ Assertion failed → Check DB setup, env vars
│ └─ "Flaky" → Improve test isolation, add retries
├─ npm run build
│ ├─ "Module not found" → Check import case, file committed
│ └─ Build error → Check for missing env vars
└─ docker build
└─ "COPY failed" → Check context path in workflow
Cross-Skill Integration
This skill works well with:
Docker Build Debugger Skill:
- •When Docker build fails in CI
- •Validates Dockerfile patterns
- •Checks COPY order, layer caching
Dependency Conflict Resolver Skill:
- •When npm ci fails with ERESOLVE
- •Diagnoses peer dependency conflicts
- •Suggests upgrade paths
Example question that uses both:
"The CI pipeline fails during Docker build. The error is 'ENOENT package.json'. What should I check?"
Copilot might:
- •Use Build Pipeline Analyzer: Check CI workflow docker build context
- •Use Docker Build Debugger: Validate Dockerfile COPY order
When to Use This Skill
Ask Copilot with this skill when:
- •GitHub Actions workflow fails
- •Need to understand what step failed and why
- •Want to diagnose test failures in CI
- •Dealing with flaky tests
- •Docker build works locally but fails in CI
- •Teaching someone about CI/CD debugging
Example prompts:
- •"The GitHub Actions build failed with test timeout. How do I debug it?"
- •"Why does my Docker build work locally but fail in CI?"
- •"This test is flaky—passes sometimes, fails others. What should I check?"
- •"The workflow failed at the lint step. How do I fix ESLint errors?"
Prevention Strategies
1. Run CI Checks Locally
# Run the same commands CI runs npm ci # Exact install (like CI) npm run lint # Catch lint errors npm test -- --coverage # Run with coverage (like CI) npm run build # Test production build
2. Use Act to Test Workflows Locally
# Install act: https://github.com/nektos/act act # Runs GitHub Actions locally with Docker
3. Add Lint-Staged (Pre-commit Hooks)
Catch issues before they reach CI:
{
"lint-staged": {
"*.js": ["eslint --fix", "git add"]
}
}
4. Monitor Flaky Tests
Track which tests fail intermittently:
# Run tests multiple times to find flakes
for i in {1..10}; do npm test; done
Links to Future Modules
This skill connects to:
Module 6 (MCP Servers):
- •Use GitHub MCP to query Actions logs programmatically
- •Fetch failure history for pattern analysis
Module 8 (Copilot Web):
- •Create/modify GitHub Actions workflows in browser
- •Your pipeline knowledge speeds up workflow creation
Module 9 (Copilot CLI):
- •Run CI commands locally through CLI
- •Debug workflows from terminal
Module 10 (Agentic SDLC):
- •Automated testing and CI/CD integration
- •Full build → test → deploy pipeline