Skip to content

Latest commit

 

History

History
213 lines (164 loc) · 7.27 KB

File metadata and controls

213 lines (164 loc) · 7.27 KB

Contributing to Node.js Userland Migration

Thank you for your interest in contributing to this project! We value contributions from the community and want to make the process as smooth as possible.

Getting Started

Caution

Do NOT force-push to your PR branch unless absolutely necessary. A force-push breaks the PR review and will cause significant delays to the review process. A clean branch history is not important for merging the PR: this repository uses squash-merge, so each PR is collapsed into a single commit using the PR's title.

Prerequisites

Before you begin, ensure you have the current versions of the following installed:

  • node
  • npm

Project Overview

Our codebase is organized as follows:

  • .github/: Contains GitHub files like issue templates and workflows
  • recipes/: Contains all the codemods
  • utils/: An npm workspace with utility functions used by the codemods (including ast-grep utilities)

Codemod Development

Structure of a Codemod

Each codemod resides in its own directory under recipes/ and should include:

File Purpose
README.md Description, purpose, and usage instructions
package.json Package manifest
src/workflow.ts Main entry point using the jssg codemod API
codemod.yml Codemod manifest file
workflow.yml Workflow definition file
tests/ Test suite using jssg testing utilities
tsconfig.json TypeScript configuration

Note

The workflow.ts naming is conventional but can be changed as needed. Ensure to update the workflow.yml accordingly. We use workflow when there are one step codemods; for multi-step codemods, consider using what-to-change.ts or similar descriptive names.

Example Files

src/workflow.ts example:

import {
	getNodeImportCalls,
	getNodeImportStatements,
} from '@nodejs/codemod-utils/ast-grep/import-statement';
import { getNodeRequireCalls } from "@nodejs/codemod-utils/ast-grep/require-call";
import { resolveBindingPath } from '@nodejs/codemod-utils/ast-grep/resolve-binding-path';
import type { SgRoot, Edit } from "@codemod.com/jssg-types/main";
import type JS from "@codemod.com/jssg-types/langs/javascript";

/**
 * Transform function that converts deprecated api.fn calls
 * to the new api.fn syntax.
 *
 * Handles:
 * 1. api.fn(<args>)
 * 2. api.fn(<args>, { recursive: true })
 * ...
 */
export default function transform(root: SgRoot<JS>): string | null {
	const rootNode = root.root();
	const edits: Edit[] = [];

	const allStatementNodes = [
		...getNodeImportStatements(root, 'api'),
		...getNodeRequireCalls(root, 'api')
		...getNodeImportCalls(root, 'api'),
	];

	// No imports or requires for 'api', skip transformation
	if (!allStatementNodes.length) return null;

	for (const statementNode of allStatementNodes) {
		const bindingPath = resolveBindingPath(statementNode, 'api.fn');

		// Find all calls to the resolved bindingPath
		const callNodes = rootNode.findDescendants((node) => {
			return node.isCallExpression() &&
				node.getChild('callee')?.getText() === bindingPath;
		});

		for (const callNode of callNodes) {
			// Perform transformation on callNode
			// e.g., replace 'api.fn' with 'api.newFn'
			edits.push(...);
		}
	}

	if (!edits.length) return null;

	return rootNode.commitEdits(edits);
}

codemod.yml example:

schema_version: "1.0"
name: "@nodejs/<codemod-name>"
version: 1.0.0
description: <Your codemod description>
author: <Your Name>
license: MIT
workflow: workflow.yaml
category: migration

targets:
  languages:
    - javascript
    - typescript

keywords:
  - transformation
  - migration

registry:
  access: public
  visibility: public

Useful Resources

Development Workflow

Before Pushing a Commit

Run our comprehensive check suite:

node --run pre-commit

This will:

  • Fix formatting and safe linting issues automatically
  • Check types
  • Run tests Be sure to commit any changes resulting from these automated fixes.

Warning

Some integration tests modify fixtures as they run the entire codemod. Remember to use git restore to revert these files before committing.

Commit Messages

Please follow the Conventional Commits specification for your commit messages. This helps with:

  • Automatic changelog generation
  • Understanding the history of changes
  • Semantic versioning

Format:

<type>(<scope>): <description>
  • type: The type of change (e.g., feat, fix, docs, chore, etc.)
  • scope: A short, lowercase description of the section of the codebase affected (e.g., tmpDir-to-tmpdir, esm-migration)
  • description: A concise summary of the change

Examples:

  • feat(tmpDir-to-tmpdir): add new node.js 18 migration codemod
  • fix(esm-migration): correct type checking in ESM migration
  • docs(codemod-usage): improve usage examples

Pull Request Process

When submitting a pull request:

  1. Ensure your changes are well-documented
  2. Run all tests (node --run pre-commit)
  3. Follow the project's coding standards
  4. Use the conventional commit format in your PR title and description
  5. Link to any related issues, using GitHub keywords where applicable.

Acceptance Criteria

For a pull request to be merged, it must:

  • Receive approval from at least 2 reviewers with write access
  • Receive no objections from reviewers with write access
  • Pass all tests
  • Be open for at least 48 hours to allow for review and discussion
    • except hotfixes and trivial corrections (like typos)

Developer's Certificate of Origin 1.1

By contributing to this project, I certify that:

- (a) The contribution was created in whole or in part by me and I have the right to
  submit it under the open source license indicated in the file; or
- (b) The contribution is based upon previous work that, to the best of my knowledge,
  is covered under an appropriate open source license and I have the right under that
  license to submit that work with modifications, whether created in whole or in part
  by me, under the same open source license (unless I am permitted to submit under a
  different license), as indicated in the file; or
- (c) The contribution was provided directly to me by some other person who certified
  (a), (b) or (c) and I have not modified it.
- (d) I understand and agree that this project and the contribution are public and that
  a record of the contribution (including all personal information I submit with it,
  including my sign-off) is maintained indefinitely and may be redistributed consistent
  with this project or the open source license(s) involved.