Skip to content

Update Pipeline

Deep dive into the 10-stage pipeline that powers every dependency update.

7 min read

Overview

Every dependency update in Ovvoc runs through a deterministic 10-stage pipeline. If any stage fails, Ovvoc generates a detailed failure report instead of a broken pull request. Your default branch is never affected.

Stage 1
Detect
Stage 2
Clone
Stage 3
Analyze
Stage 4
Classify
Stage 5
Plan
Stage 6
Transform
Stage 7
Install
Stage 8
Build
Stage 9
Test
Stage 10
PR

Stage 1: Detect

Ovvoc monitors the npm registry 24/7 via the _changes feed. When a new version is published for a dependency your project uses, a job is queued automatically. Security advisories are prioritized.

Stage 2: Clone

Each job runs inside an ephemeral Docker container with strict security:

Container security
Container configuration:
  User:        non-root (uid 1000)
  Filesystem:  read-only root, writable /workspace only
  Network:     enabled during clone, disabled during build/test
  Memory:      512MB limit
  CPU:         1 core
  Timeout:     10 minutes
  Cleanup:     destroyed after job completes

Stage 3: Analyze

Ovvoc scans package.json and the lockfile to build a complete dependency graph. It detects both ESM import statements and CommonJS require() calls throughout your codebase.

Scan output
Scanning package.json...
  42 dependencies (28 prod, 14 dev)
  Analyzing source files for import patterns...
  Found 18 files importing express
  Found 3 files using express middleware

  Update target: express 4.21.0 → 5.2.1

Stage 4: Classify

Each update is classified into one or more of the 25 update categories. The highest-complexity category determines the strategy: version-only, AST transform, or AI-assisted migration.

Stage 5: Plan

The MigrationEngine loads rules from the 150+ YAML rule database and generates an ordered migration plan:

Migration plan for express 4→5
Migration plan: express 4.21.0 → 5.2.1
  [1] function_rename: app.del() → app.delete()          confidence: 1.0
  [2] param_signature: res.json(status, body) → chain     confidence: 1.0
  [3] syntax_change: wildcard * → {*path}                 confidence: 1.0
  [4] syntax_change: optional :param? → {/:param}         confidence: 1.0
  [5] deprecated_api: req.host → req.hostname              confidence: 1.0
  [6] deprecated_api: req.acceptsCharset → acceptsCharsets confidence: 1.0
  [7] removed_feature: connect middleware removal          confidence: 0.85
  [8] type_system: req.params string → string|string[]     confidence: 0.9

Stage 6: Transform

Ovvoc uses the OXC parser — the fastest JavaScript/TypeScript AST parser available — to apply code transformations. This is real syntax tree manipulation, not regex find-and-replace:

Before (Express 4)
const express = require('express');
const app = express();
- app.get('*', handler);
- app.get('/users/:id?', getUser);
- app.del('/items/:id', deleteItem);
After (Express 5)
const express = require('express');
const app = express();
+ app.get('{*path}', handler);
+ app.get('/users{/:id}', getUser);
+ app.delete('/items/:id', deleteItem);

Stage 7: Install

After code transforms are applied, Ovvoc runs npm install with the target version. The lockfile is regenerated to ensure consistency.

Stage 8: Build

The project is built using npm run build inside a network-isolated container. No external network access is permitted during the build phase.

Stage 9: Test

Tests run using npm test, also in network isolation. If all tests pass, the pipeline proceeds to PR creation. If any tests fail, a structured failure report is generated instead.

Stage 10: PR creation

Ovvoc pushes the changes to a feature branch and creates a pull request with a confidence score, change summary, and full test output:

PR description
## ovvoc: Update express 4.21.0 → 5.2.1

**Confidence:** 0.95
**Category:** Breaking change (7, 9, 19, 20)
**Strategy:** AST transform

### Changes
- Renamed app.del() → app.delete() (1 file)
- Updated wildcard syntax * → {*path} (3 files)
- Updated optional params :id? → {/:id} (2 files)
- Removed deprecated connect middleware (1 file)

### Test results
  47/47 tests passed (8.3s)

### Pipeline
  All 10 stages passed in 42.7s

Failure handling

When any stage fails, Ovvoc generates a structured failure report that includes:

  • The stage that failed and the specific error
  • Which transforms were applied before the failure
  • Full error output (build errors, test failures)
  • Suggested next steps

Failed updates are never pushed as PRs. Your main branch is always safe.

Timing

  • Version-only updates: 30–60 seconds
  • AST transform updates: 60–120 seconds
  • AI-assisted migrations: 3–5 minutes
  • Security patches: under 60 seconds (prioritized)

Pipeline stage diagram

The pipeline is a strictly linear sequence of 10 stages. Each stage feeds its output into the next. If any stage fails, the pipeline halts immediately and generates a failure report — no partial results are pushed as PRs.

Pipeline flow
Detect → Clone → Analyze → Classify → Plan → Transform → Install → Build → Test → PR/Report

Stage 1-4:   Discovery phase    (understand what needs to change)
Stage 5-6:   Transformation     (plan and apply code changes)
Stage 7-9:   Verification       (install, build, and test)
Stage 10:    Delivery            (create PR or failure report)

Failure at ANY stage → stop → generate report → notify user

This strict linear design ensures that no untested code ever reaches your repository. The pipeline cannot skip stages or proceed past a failure. Every stage must explicitly succeed before the next one begins.

Stage details

Below is a detailed breakdown of each stage, including what happens internally, typical duration, common failure modes, and retry behavior.

Stage 1: Detect (typical: 0.1s)

What happens: Ovvoc watches the npm registry _changes feed continuously. When a new version is published for a dependency used by one of your repositories, a job is queued. Security advisories from npm audit are detected and prioritized above regular updates.

What can go wrong: npm registry downtime or rate limiting can delay detection. Webhook delivery failures from GitHub (for push-triggered scans) can also cause delays. These are transient and resolve automatically.

Retry behavior: Registry polling retries every 60 seconds. Missed updates are caught on the next poll cycle.

Stage 2: Clone (typical: 2–10s)

What happens: An ephemeral Docker container is created with strict security settings (non-root user, read-only filesystem, memory and CPU limits). The repository is cloned into /workspace using a short-lived GitHub installation token.

What can go wrong: GitHub API rate limits, network timeouts during clone, or very large repositories (1GB+) that exceed the container’s disk allocation.

Retry behavior: Retried up to 3 times with exponential backoff (5s, 15s, 45s).

Stage 3: Analyze (typical: 0.5s)

What happens: The scanner parses package.json and the lockfile to build a complete dependency graph. It also scans source files for ESM import statements and CommonJS require() calls to understand how each dependency is used in the codebase.

What can go wrong: Malformed package.json, missing lockfile, or unsupported lockfile format. These generate an immediate failure report with a clear error message.

Retry behavior: Not retried — structural issues require user action.

Stage 4: Classify (typical: 0.1s)

What happens: The update is matched against Ovvoc’s rule database and classified into one or more of the 25 update categories. The highest-complexity match determines the pipeline strategy: version-only, AST transform, or AI-assisted.

What can go wrong: Unknown packages without matching rules fall through to AI classification, which is slightly less reliable. This is rare for popular npm packages.

Retry behavior: Not retried — classification is deterministic.

Stage 5: Plan (typical: 0.2s)

What happens: The MigrationEngine loads relevant YAML rules from the rule registry and generates an ordered migration plan. Each step in the plan has a type, description, and confidence score.

What can go wrong: Conflicting rules for the same code pattern, or rules that target files not present in the project. Missing files are skipped gracefully.

Retry behavior: Not retried — plan generation is deterministic.

Stage 6: Transform (typical: 0.5–5s)

What happens: Code transformations are applied using the OXC AST parser for structural changes, regex-based transforms for simpler patterns, and AI generation for complex categories (14+). Each transform is applied in priority order.

What can go wrong: AST parse errors in source files, transform rules that do not match expected code patterns, or AI-generated code that fails validation.

Retry behavior: AI-assisted transforms are retried up to 2 times with different prompts. Deterministic transforms are not retried.

Stage 7: Install (typical: 5–30s)

What happens: npm install runs with the updated package version. The lockfile is regenerated to ensure consistency. Peer dependency conflicts are resolved automatically where possible.

What can go wrong: npm registry downtime, peer dependency conflicts that cannot be auto-resolved, or packages that have been unpublished.

Retry behavior: Retried up to 3 times with exponential backoff.

Stage 8: Build (typical: 2–60s)

What happens: npm run build executes inside a network-isolated container. No external network access is permitted — all dependencies must already be installed from Stage 7.

What can go wrong: Compilation errors due to type mismatches, missing exports, or breaking API changes not covered by the transform rules.

Retry behavior: Not retried — build failures indicate a real problem that requires rule updates or human review.

Stage 9: Test (typical: 5–120s)

What happens: npm test runs in network isolation. Test results are compared against the baseline (tests that were already failing before the update are excluded from the pass/fail calculation).

What can go wrong: Test regressions caused by behavioral changes in the updated dependency, or flaky tests that fail intermittently.

Retry behavior: Tests are retried once if the failure count is small (fewer than 3 failures) to account for flaky tests.

Stage 10: PR/Report (typical: 1–3s)

What happens: If all stages passed, Ovvoc pushes the update branch to GitHub and creates a pull request with a confidence score, change summary, and test output. If any stage failed, a detailed failure report is generated instead.

What can go wrong: GitHub API rate limits or temporary outages during PR creation. Branch protection rules that prevent the Ovvoc bot from pushing.

Retry behavior: Retried up to 3 times with exponential backoff.

Detailed failure handling

Each pipeline stage generates a specific, actionable failure report when something goes wrong. The report format varies by stage to include the most relevant debugging information:

  • Build failures include the full stderr output, the exit code, the build command that was run, and which files were modified by transforms before the build was attempted.
  • Test failures include which specific tests failed, their error messages, the total test count (passed/failed/skipped), and a baseline comparison showing whether these tests were already failing before the update.
  • Transform failures include which rules were attempted, which files they targeted, the specific error encountered (parse error, pattern not found, etc.), and the partial state of the codebase at the time of failure.
  • Install failures include the npm error output, the specific dependency conflict (if any), and the resolved vs requested version ranges.

All failure reports are visible in the dashboard on the job detail page and include actionable suggestions for resolution. Reports are retained for 30 days and can be exported as JSON.

Pipeline configuration

While the pipeline runs automatically with sensible defaults, several aspects can be configured per repository from the dashboard settings:

  • Stage timeouts: Each stage has a configurable timeout. Defaults are generous (10 minutes overall, 2 minutes for build, 2 minutes for test) but can be increased for large projects with slow test suites.
  • Retry attempts: The default retry count is 3 attempts with exponential backoff for transient failures (clone, install, PR creation). You can reduce this to 1 for faster failure reporting or increase to 5 for unreliable networks.
  • Strategy override: Force a specific strategy for all updates on a repository. Options are version-only (skip transforms entirely), full-migration (always attempt code transforms), or auto (default — let the classifier decide based on category).
  • Skip build/test: For low-risk updates (categories 1–6), you can optionally skip the build and test stages to speed up processing. This is disabled by default for safety — we recommend leaving it off unless you have a separate CI pipeline that runs on every PR.

Need help?

Start with one repo and see verified PRs in minutes.