Skip to main content
Codemods modify your source code automatically. Following these best practices ensures safe, reliable transformations.
CRITICAL: Always commit your changes before running codemods. Codemods change source code. Uncommitted changes may be lost or corrupted. This is not optional.

Pre-Flight Checklist

Before running any codemod:
1

Commit all changes

Ensure your working directory is clean with git status
git status
# Should show: "nothing to commit, working tree clean"
2

Create a dedicated branch

Make changes on a separate branch for easy rollback
git checkout -b migration/util-is-to-native
3

Backup important work

For critical migrations, create a backup branch
git branch backup/before-codemod
4

Review the codemod documentation

Understand what the codemod will change
npx codemod @nodejs/<recipe> --help

Running Codemods Safely

Start with a Dry Run

Many codemods support dry-run mode to preview changes:
# Preview without modifying files
npx codemod @nodejs/util-is --dry-run
Not all codemods support --dry-run. Check the codemod’s documentation or try running with --help.

Test on a Small Scope First

Before running on your entire codebase:
# Test on a single directory
cd src/utils
npx codemod @nodejs/util-is

# Review the changes
git diff

# If good, proceed with the rest
cd ../..
npx codemod @nodejs/util-is

Review Changes Immediately

After running a codemod:
# See what changed
git diff

# See which files were modified
git status

# Review changes file by file
git diff src/file1.js
git diff src/file2.js
Use a visual diff tool like git difftool or your IDE’s built-in diff viewer for easier review.

Validation Strategy

1. Run Your Test Suite

Your existing tests are the first line of defense:
# Run all tests
npm test

# Run specific test suites
npm test -- --grep "utility functions"
What to check:
  • All tests pass
  • No new warnings or errors
  • Test coverage hasn’t decreased
  • Performance hasn’t degraded

2. Check Linting and Type Checking

Ensure code quality standards are maintained:
# Run linter
npm run lint

# Run TypeScript type checking
npm run typecheck
# or
tsc --noEmit
Common issues after codemods:
  • Unused imports (codemod removed usage but not import)
  • Type errors (API signature changes)
  • Formatting issues (indentation, spacing)
Many codemods try to preserve formatting, but some manual cleanup may be needed. Run your formatter:
npm run format
# or
prettier --write .

3. Manual Code Review

Spot-check transformed code: Focus areas:
  • Edge cases: Look for unusual patterns the codemod might mishandle
  • Complex expressions: Nested calls, ternaries, template literals
  • Comments: Ensure comments still make sense after transformation
  • Formatting: Check indentation and readability
Example review:
// Before codemod
const isValid = util.isArray(data) && data.length > 0;

// After codemod - verify logic is preserved
const isValid = Array.isArray(data) && data.length > 0; // ✅ Correct

// Watch for complex cases
const check = condition ? util.isArray : util.isObject;
// Did the codemod handle this correctly? ⚠️ Needs review

4. Integration Testing

If you have integration or e2e tests:
# Run integration tests
npm run test:integration

# Run e2e tests
npm run test:e2e
Integration tests catch issues that unit tests miss:
  • API contract changes
  • Behavior differences in edge cases
  • Performance regressions

5. Build and Package

Ensure the project still builds:
# Build the project
npm run build

# Check the build output
ls -la dist/

# Try packaging (if applicable)
npm pack

Rollback Strategies

Quick Rollback with Git

If something goes wrong:
# Discard all changes (if not committed)
git checkout .

# Undo the last commit (if you committed)
git reset --hard HEAD~1

# Return to a specific commit
git reset --hard <commit-hash>

# Switch to your backup branch
git checkout backup/before-codemod
git reset --hard permanently deletes uncommitted changes. Use with caution.

Selective Rollback

Rollback specific files:
# Restore a single file
git checkout HEAD -- src/problematic-file.js

# Restore multiple files
git checkout HEAD -- src/file1.js src/file2.js

# Restore entire directory
git checkout HEAD -- src/utils/

Revert Merged Changes

If the codemod was already merged:
# Create a revert commit
git revert <merge-commit-hash>

# Push the revert
git push origin main

Advanced Safety Techniques

Incremental Migration

For large codebases, migrate incrementally:
1

Phase 1: Core utilities

Run codemod on your utility library first
npx codemod @nodejs/util-is src/utils/
2

Phase 2: Individual modules

Migrate one module at a time
npx codemod @nodejs/util-is src/auth/
git add src/auth && git commit -m "migrate: auth module"
3

Phase 3: Test and iterate

Run tests after each phase, fix issues before proceeding
4

Phase 4: Remaining code

Complete migration across the codebase
Benefits:
  • Easier to isolate issues
  • Smaller, reviewable commits
  • Less risky than “big bang” migration
  • Can pause and resume migration

Automated Safety Checks

Add pre-commit hooks to catch issues:
// package.json
{
  "scripts": {
    "pre-commit": "npm run lint && npm test"
  }
}
Or use tools like husky:
# .husky/pre-commit
npm run lint
npm test

Snapshot Testing

For critical code, create snapshots before migration:
// Save current behavior
const before = {
  result1: myFunction(input1),
  result2: myFunction(input2),
  // ...
};

// After codemod, verify behavior is identical
const after = {
  result1: myFunction(input1),
  result2: myFunction(input2),
};

assert.deepEqual(before, after);

Testing Codemods Locally

If you’re developing or testing a codemod:

From Source

# Clone the repository
git clone https://github.com/nodejs/userland-migrations.git
cd userland-migrations

# Run codemod from local file
cd /path/to/your-project
npx codemod workflow run -w /path/to/userland-migrations/recipes/util-is/workflow.yaml

Test Fixtures

Create test cases before running on real code:
// test-fixture.js
const util = require('util');

// Test various patterns
const test1 = util.isArray([]);
const test2 = util.isString('hello');
const test3 = util.isFunction(() => {});

// Test edge cases
const test4 = condition ? util.isArray : util.isObject;
const test5 = items.filter(util.isArray);
Run the codemod on the fixture and verify results:
cp test-fixture.js test-fixture-backup.js
npx codemod @nodejs/util-is test-fixture.js
diff test-fixture.js test-fixture-backup.js

Common Issues and Solutions

Issue: Codemod Skipped Files

Symptom: Some files weren’t transformed Cause: The codemod didn’t find matching patterns Solution:
# Check if imports exist
grep -r "require('util')" src/
grep -r "from 'util'" src/

# Check file extensions
find src/ -name "*.js" -o -name "*.ts"

Issue: Syntax Errors After Codemod

Symptom: Code doesn’t parse or run Cause: Codemod generated invalid syntax Solution:
# Find syntax errors
npm run lint
# or
node --check src/**/*.js

# Review the problematic files
git diff src/broken-file.js

# Fix manually or rollback
git checkout src/broken-file.js

Issue: Tests Failing

Symptom: Previously passing tests now fail Cause: Behavior change or edge case not handled Solution:
  1. Review the failing test
  2. Check if the transformation was correct
  3. Update test if the change is intentional
  4. Fix the code if the transformation was wrong
# Run specific test
npm test -- --grep "the failing test"

# Debug with verbose output
DEBUG=* npm test

Issue: Merge Conflicts

Symptom: Git conflicts when merging migration branch Cause: Main branch changed during migration Solution:
# Update your migration branch
git checkout migration/util-is
git merge main

# Resolve conflicts
# Then re-run codemod on conflicted files if needed
npx codemod @nodejs/util-is src/conflicted-file.js

git add .
git commit -m "resolve: merge conflicts after codemod"

Team Coordination

When running codemods on shared codebases:

Communication

  1. Announce the migration in your team channel
  2. Freeze PRs temporarily to avoid conflicts
  3. Schedule migration during low-activity periods
  4. Document the process for team reference

Pull Request Best Practices

Good PR structure:
Title: migrate(util-is): replace util.is* with native checks

Description:
- Ran @nodejs/util-is codemod
- Reviewed all changes manually
- All tests passing
- No behavior changes expected

Files changed: 47 files
Breaking changes: None

Testing:
- ✅ Unit tests passing
- ✅ Integration tests passing
- ✅ Linter passing
- ✅ TypeScript types valid

Checklist:
- [x] Committed before running codemod
- [x] Reviewed all diffs
- [x] Ran test suite
- [x] Checked for edge cases
- [x] Updated documentation if needed
Commit strategy:
# Option 1: Single commit (small changes)
git add .
git commit -m "migrate(util-is): replace util.is* with native checks"

# Option 2: Separate commits (large changes)
git add src/utils/
git commit -m "migrate(util-is): transform utils module"

git add src/services/
git commit -m "migrate(util-is): transform services module"

git add .
git commit -m "migrate(util-is): cleanup unused imports"

Code Review Tips

For reviewers:
  • Trust but verify: Codemods are reliable but not perfect
  • Spot-check edge cases: Don’t review every line, focus on complex patterns
  • Run tests locally: Don’t rely solely on CI
  • Check the diff stats: Unusual patterns might indicate issues
# See change statistics
git diff --stat

# See detailed diff for specific file types
git diff -- '*.js' | less

Production Deployment

Before deploying codemod changes to production:
1

Staging environment

Deploy to staging first
git push origin migration/util-is:staging
2

Smoke tests

Run critical path tests in staging
3

Monitor metrics

Check performance, error rates, logs
4

Gradual rollout

Use feature flags or canary deployments if possible
5

Production deployment

Deploy to production with rollback plan ready
For critical production systems, consider deploying migrations during maintenance windows or low-traffic periods.

Next Steps

How Codemods Work

Understand the technical foundation of AST transformations

When to Use Codemods

Learn when codemods are the right choice

Additional Resources

The Node.js Userland codemods are battle-tested and used across thousands of projects. Most issues you encounter will be edge cases specific to your codebase, not bugs in the codemod itself.

Build docs developers (and LLMs) love