Thank you for your interest in contributing to GitHub Archiver! This document provides guidelines and instructions for contributing.
Be respectful, inclusive, and constructive in all interactions.
- Node.js 22+
- bun
- Git
# Clone the repository
git clone https://github.com/mynameistito/github-archiver.git
cd github-archiver
# Install dependencies
bun install
# Verify setup
bun run typecheck
bun run test
bun run buildgit checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bug-fixUse descriptive branch names:
feature/for new featuresfix/for bug fixesdocs/for documentationtest/for test additionsrefactor/for code improvements
Follow the code standards below and make atomic commits with clear messages.
# Run tests
bun test
# Check TypeScript
bun run typecheck
# Check code style
bun run lint
# Auto-format code
bun run format
# Build the project
bun run buildPush your branch and create a PR with:
- Clear title describing the change
- Detailed description of what and why
- Reference to any related issues
- Screenshots/examples if applicable
This project uses Ultracite (Biome-based) code standards. Key principles:
- Always use explicit types for function parameters and returns
- Use
unknowninstead ofanywhen type is genuinely unknown - No implicit
anyallowed - Leverage TypeScript's type narrowing
- Throw
Errorobjects with descriptive messages, not strings - Use meaningful error messages with context
- Provide recovery suggestions in user-facing errors
- Use try-catch for async operations appropriately
- Keep functions focused and reasonably sized
- Extract complex conditions into named boolean variables
- Use early returns to reduce nesting
- Group related code together
- Always
awaitpromises in async functions - Use
async/awaitinstead of promise chains - Handle errors appropriately
- Write assertions inside
it()ortest()blocks - Avoid done callbacks - use async/await
- Don't use
.onlyor.skipin committed code - Keep test suites flat
- Add
rel="noopener"when usingtarget="_blank" - Avoid
dangerouslySetInnerHTML - Don't use
eval()or directdocument.cookieassignment - Validate and sanitize user input
- Avoid spread syntax in loop accumulators
- Use top-level regex literals, not in loops
- Prefer specific imports over namespaces
- Avoid barrel files (index.ts re-exports)
When you've made changes that should be included in a release:
-
Create a changeset file:
bun run changeset:add
-
Answer the prompts:
- Which packages are affected? → Select
github-archiver - What's the type of change? → Choose:
patch- bug fixes (1.0.0 → 1.0.1)minor- new features (1.0.0 → 1.1.0)major- breaking changes (1.0.0 → 2.0.0)
- Write a description of your change
- Which packages are affected? → Select
-
Commit the generated changeset file:
git add .changeset/*.md git commit -m "docs: add changeset for feature X"
-
Push your branch and open a PR as usual
Once your PR is merged to main:
- GitHub Actions detects the changeset files
- Creates a "Version Packages" PR with:
- Updated
package.jsonversion - Updated
CHANGELOG.mdwith your descriptions - Commit message ready to merge
- Updated
- Merge the "Version Packages" PR
- GitHub Actions automatically:
- Publishes to npm
- Creates a GitHub release with automatic release notes
- Tags the commit with the version
Example: .changeset/excited-newts-talk.md
---
"github-archiver": minor
---
Add support for custom GitHub token configuration in config fileNote: Changeset filenames are auto-generated with whimsical names. Feel free to edit the description after generation.
Always run these checks:
# Format code
bun run format
# Type check
bun run typecheck
# Run tests
bun test
# Lint
bun run lint
# Build
bun run buildAll of these must pass before submitting a PR.
src/
├── commands/ # CLI command implementations
├── services/ # Business logic services
├── utils/ # Reusable utilities
├── types/ # TypeScript interfaces and types
└── constants/ # Configuration and constants
tests/
└── unit/ # Unit tests
- Define Types First: Add interfaces/types in
src/types/ - Create Service: Add business logic in
src/services/ - Add Utility Functions: Extract reusable logic to
src/utils/ - Create Command: Implement CLI command in
src/commands/ - Write Tests: Add tests in
tests/unit/ - Update Documentation: Update README and CHANGELOG
- Create new file in
src/commands/your-command.ts - Export a
createYourCommand()function returningCommand - Register in
src/index.ts - Add tests in
tests/unit/your-command.test.ts - Document in README.md
Example:
// src/commands/your-command.ts
import { Command } from 'commander'
export function createYourCommand(): Command {
return new Command('your-command')
.description('What this command does')
.option('--option <value>', 'Option description')
.action(async (options) => {
// Implementation
})
}Use clear, descriptive commit messages:
feat: add new feature description
fix: fix specific bug
docs: update documentation
test: add tests for feature
refactor: improve code organization
chore: update dependencies or config
Example:
feat: add support for archiving by repository age
- Allow filtering repositories older than X days
- Add --min-age and --max-age options
- Add tests for age-based filtering
Before submitting:
- Code follows Ultracite standards
- All tests pass (
npm run test) - TypeScript compilation succeeds (
npm run typecheck) - Code is formatted (
npm run format) - Linting passes (
npm run lint) - Build succeeds (
npm run build) - Commit messages are clear and descriptive
- PR description explains the changes
- Related issues are referenced
- Documentation is updated if needed
- Test utilities and isolated functions
- Use descriptive test names
- Keep tests focused on one thing
- Mock external dependencies
Example:
import { describe, it, expect } from 'vitest'
import { URLParser } from '../utils/parser'
describe('URLParser', () => {
it('should parse HTTPS GitHub URLs', () => {
const result = URLParser.parseRepositoryUrl('https://github.com/owner/repo')
expect(result.owner).toBe('owner')
expect(result.repo).toBe('repo')
})
})- Test command workflows end-to-end
- Use mock GitHub responses
- Verify complete user flows
- Test error scenarios
When adding features:
-
Update README.md with:
- Command description
- Usage examples
- Options and parameters
- Troubleshooting tips
-
Update CHANGELOG.md with:
- Feature description
- Breaking changes (if any)
- Migration guide (if needed)
-
Add code comments for:
- Complex algorithms
- Non-obvious business logic
- Important decisions
When reporting bugs:
-
Check existing issues - Don't duplicate
-
Provide details:
- OS and Node version
- Steps to reproduce
- Expected vs actual behavior
- Error messages and logs
- Screenshots if applicable
-
Example issue:
Title: Archive command fails with permission error Steps to reproduce: 1. Run `github-archiver auth login` 2. Run `github-archiver archive --file repos.txt` 3. Wait for processing... Expected: Repositories should be archived Actual: Permission denied error appears Environment: - OS: Windows 11 - Node: 18.12.0 - CLI version: 1.0.0
When requesting features:
- Be specific about what you need
- Explain the use case and why it's useful
- Consider alternatives you've tried
- Provide examples if applicable
Example:
Title: Add option to archive repositories by age
Description:
I need a way to archive all repositories that haven't
been updated in more than a year. Currently I have to
manually check each repository.
Suggested solution:
Add --min-age and --max-age options to filter repositories
- Check existing issues and discussions
- Open a new issue to ask for help
- Start a discussion for design questions
By contributing, you agree that your contributions will be licensed under the same MIT license as the project.
Thank you for contributing! 🎉