Thank you for your interest in contributing to CopyTree! This document provides guidelines and instructions for contributing.
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
- Node.js 22.12.0 or higher (matches
enginesinpackage.json) - npm (comes with Node.js)
- Git
-
Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/copytree.git cd copytree -
Install dependencies
npm install
-
Run tests to verify setup
npm test -
Link the CLI for local development
npm link
Now you can run copytree commands and they'll use your local development version.
We follow Git Flow:
main- Production-ready codedevelop- Main development branchfeature/*- New featuresbugfix/*- Bug fixesrelease/*- Release preparationhotfix/*- Critical production fixes
-
Create a branch from
developgit checkout develop git pull origin develop git checkout -b feature/your-feature-name
-
Make your changes
- Write clear, concise code
- Follow existing code style (ESM, async/await, etc.)
- Add tests for new functionality
- Update documentation as needed
-
Test your changes
npm test # Run all tests npm run test:coverage # Check coverage npm run lint # Check code style npm run format:check # Check formatting
-
Commit your changes
- Use clear, descriptive commit messages
- Reference issue numbers when applicable
git commit -m "feat: add new transformer for XYZ files - Implement XYZTransformer class - Add unit tests - Update documentation Closes #123"
-
Push and create a pull request
git push origin feature/your-feature-name
- Use ES Modules (
import/export, notrequire/module.exports) - Async/await - No callbacks, use promises
- Descriptive names - Clear variable and function names
- No unused imports - Clean up imports
- Classes:
PascalCase(e.g.,BinaryTransformer,GitUtils) - Files:
camelCase.jsorPascalCase.jsmatching class name - Functions/Variables:
camelCase - Constants:
UPPER_SNAKE_CASE - Events:
namespace:event(e.g.,pipeline:start,stage:complete)
- Strategy pattern: Transformers, Formatters
- Pipeline pattern: Stage-based processing
- Observer pattern: Event emission throughout
- Singleton pattern: Config, Logger instances
- Factory pattern: Registry creation
tests/
├── unit/ # Unit tests
├── integration/ # Integration tests
├── e2e/ # End-to-end tests
├── performance/ # Performance benchmarks
├── fixtures/ # Test data
└── mocks/ # Mock implementations
- Unit tests for individual classes and functions
- Integration tests for pipeline stages and workflows
- E2E tests for CLI commands
- Aim for 80%+ coverage (enforced by CI)
Example:
import MyTransformer from '../src/transforms/transformers/MyTransformer.js';
describe('MyTransformer', () => {
it('should transform files correctly', async () => {
const transformer = new MyTransformer();
const file = { path: 'test.txt', content: 'test' };
const result = await transformer.transform(file);
expect(result.transformed).toBe(true);
});
});- Create transformer class in
src/transforms/transformers/ - Extend
BaseTransformer - Define transformer traits (inputTypes, outputTypes, heavy, etc.)
- Implement
transform(file)method - Register in
TransformerRegistry.js - Add configuration options to profile schema
- Write unit tests
- Update documentation
- Create stage class in
src/pipeline/stages/ - Extend
Stagefromsrc/pipeline/Stage.js - Implement
process(input)method - Add lifecycle hooks if needed
- Add stage to pipeline in desired order
- Write unit tests
- Update documentation
- Update
README.mdfor user-facing changes - Update
CLAUDE.mdfor architectural changes - Add/update docs in
docs/directory for detailed guides - Include JSDoc comments for public APIs
- Ensure all tests pass and coverage is maintained
- Update documentation as needed
- Follow commit message conventions (feat, fix, docs, etc.)
- Reference related issues in PR description
- Request review from maintainers
- Address feedback promptly and professionally
- Tests pass locally (
npm test) - Code follows style guidelines (
npm run lint) - New tests added for new functionality
- Documentation updated
- Commit messages are clear and descriptive
- No breaking changes (or clearly documented)
- CHANGELOG.md updated (if applicable)
Include:
- Description of the bug
- Steps to reproduce
- Expected behavior
- Actual behavior
- Environment (OS, Node version, CopyTree version)
- Error messages or logs
Include:
- Clear description of the feature
- Use case - Why is this needed?
- Proposed implementation (optional)
- Alternatives considered (optional)
(For maintainers)
Releases are automated. Pushing a v* tag runs .github/workflows/publish.yml,
which verifies, packs, publishes and then creates the GitHub release — in that
order, so a failed publish cannot produce a release for a version nobody can
install.
- Update the version in
package.jsononly. Everything else reads it:src/version.jsis the single source of truth,config/app.jsimports it, and the declarations carry no version at all. - Update
CHANGELOG.md. - Create a
release/*branch, merge it per Git Flow. - Run
npm run verify:release— the same gate the workflow runs: lint, formatting, generated-document drift, types, dead code, the full suite with coverage, and the packed-tarball consumer tests. - Tag
vX.Y.Zonmainand push the tag. - Watch the workflow. It confirms the tag matches
package.json, publishes the exact tarball it verified, waits for the registry to report the version, and only then cuts the GitHub release.
Do not run npm publish by hand. prepublishOnly runs the full verifier, so a
manual publish is slow rather than dangerous, but it bypasses provenance and the
tag/version check.
- Documentation: https://copytree.dev or
docs/directory - Issues: https://github.com/gregpriday/copytree/issues
- Email: greg@siteorigin.com
By contributing, you agree that your contributions will be licensed under the MIT License.
Contributors will be recognized in:
- GitHub contributors page
- CHANGELOG.md for significant contributions
- README.md for major features
Thank you for contributing to CopyTree!