meld
Version:
Meld: A template language for LLM prompts
361 lines (276 loc) • 9.98 kB
Markdown
Clean-Repo is a Node package that helps maintainers create and manage clean public repositories by automatically handling development files, setting up branch management, and establishing proper Git practices.
- Automate the separation of development files from public code
- Provide scripts for branch management
- Add Git hooks to prevent accidental commits
- Set up CI workflows for repository hygiene
- Infer project-specific settings where possible
- Require minimal configuration
1. **Configuration Manager**
- Infers settings from package.json where possible
- Handles user-provided overrides
- Sets sensible defaults when needed
2. **File Manager**
- Generates/updates .gitignore
- Generates/updates .gitattributes
- Creates Git hooks
- Creates CI workflows
3. **Script Generator**
- Produces branch management scripts
- Adapts scripts to project-specific needs
4. **Command Line Interface**
- Provides commands for initialization and updates
- Handles one-time setup
1. Command line arguments
2. `.clean-repo.json` configuration file
3. `package.json` "clean-repo" field
4. Inferred from project structure
5. Default settings
- **Auto-detect repository type**
- Identify language (Node.js, Python, etc.)
- Identify package manager (npm, yarn, pnpm)
- Identify framework (if applicable)
- **Auto-detect existing patterns**
- Find common temporary file patterns
- Identify work directories
- **Analyze existing .gitignore**
- Parse and categorize existing rules
- Identify missing rules
### 2. Configuration
Auto-detect configuration from `package.json`:
```json
{
"name": "my-package",
"version": "1.0.0",
"clean-repo": {
"ignoreDirs": ["_docs", "tmp", "notes"],
"protectedBranches": ["main", "release"],
"publicBranch": "public",
"developmentBranch": "develop",
"ignorePatterns": ["*.log", "*.tmp", "temp_*"]
}
}
```
Or use a separate `.clean-repo.json` configuration file:
```json
{
"ignoreDirs": ["_docs", "tmp", "notes"],
"protectedBranches": ["main", "release"],
"publicBranch": "public",
"developmentBranch": "develop",
"ignorePatterns": ["*.log", "*.tmp", "temp_*"]
}
```
- Install pre-commit hook
- Install pre-push hook
- Ensure hooks are executable
- Support common hook managers (husky, simple-git-hooks)
### 4. Branch Management Scripts
- **prepare-public.js** - Creates/updates a clean public branch
- **sync-public.js** - Syncs development changes to public branch
- **verify-public.js** - Checks if the public branch is clean
### 5. CI Workflow Templates
- GitHub Actions workflow
- GitLab CI workflow
- Circle CI workflow
### 6. Documentation Templates
- `CONTRIBUTING.md` template
- `RELEASE_GUIDE.md` template
## Implementation Plan
### Dependencies
- **cosmiconfig**: For flexible configuration loading
- **simple-git**: For Git operations
- **inquirer** (optional): For interactive setup
- **chalk**: For terminal styling
- **commander**: For CLI argument parsing
- **ignore**: For .gitignore parsing and manipulation
- **fs-extra**: For file operations
- **globby**: For file pattern matching
- **detect-indent**: For preserving file formatting
### CLI Commands
```
clean-repo init # Set up clean-repo in the current project
clean-repo update # Update configuration and scripts
clean-repo prepare-public # Create/update the public branch
clean-repo sync # Sync changes to the public branch
clean-repo verify # Verify the public branch is clean
```
### File Structure
```
clean-repo/
├── bin/
│ └── clean-repo.js # CLI entry point
├── lib/
│ ├── config.js # Configuration manager
│ ├── git.js # Git operations
│ ├── hooks.js # Git hooks generator
│ ├── ignore.js # .gitignore manager
│ ├── scripts.js # Script generator
│ ├── templates.js # Template manager
│ └── workflows.js # CI workflow generator
├── templates/
│ ├── contributing.md # Template for CONTRIBUTING.md
│ ├── gitattributes # Template for .gitattributes
│ ├── githooks/ # Git hook templates
│ ├── gitignore # Template for .gitignore
│ ├── release-guide.md # Template for RELEASE_GUIDE.md
│ └── workflows/ # CI workflow templates
└── package.json
```
## Implementation Details
### Configuration Manager
1. Load configuration from all sources
2. Merge with default settings
3. Validate configuration
4. Generate effective configuration
```javascript
// Example configuration loading
const { cosmiconfigSync } = require('cosmiconfig');
const explorer = cosmiconfigSync('clean-repo');
const result = explorer.search() || { config: {} };
// Merge with defaults
const config = {
ignoreDirs: ['_dev', 'notes', 'tmp'],
protectedBranches: ['main', 'master'],
publicBranch: 'public',
developmentBranch: 'develop',
...result.config
};
```
Create pre-commit hook to prevent committing ignored files to protected branches:
```javascript
// Example hook generation
const fs = require('fs-extra');
const path = require('path');
function installPreCommitHook(config) {
const hookPath = path.join('.git', 'hooks', 'pre-commit');
const hookTemplate = fs.readFileSync(path.join(__dirname, '../templates/githooks/pre-commit'), 'utf8');
// Replace placeholders with configuration
const hook = hookTemplate
.replace('{{PROTECTED_BRANCHES}}', JSON.stringify(config.protectedBranches))
.replace('{{IGNORED_DIRS}}', JSON.stringify(config.ignoreDirs))
.replace('{{IGNORED_PATTERNS}}', JSON.stringify(config.ignorePatterns));
fs.writeFileSync(hookPath, hook);
fs.chmodSync(hookPath, '0755');
}
```
Generate script for preparing a clean public branch:
```javascript
// Example script generation
function generatePreparePublicScript(config) {
const scriptTemplate = fs.readFileSync(path.join(__dirname, '../templates/scripts/prepare-public.js'), 'utf8');
// Replace placeholders with configuration
const script = scriptTemplate
.replace('{{PUBLIC_BRANCH}}', config.publicBranch)
.replace('{{DEVELOPMENT_BRANCH}}', config.developmentBranch)
.replace('{{IGNORED_DIRS}}', JSON.stringify(config.ignoreDirs))
.replace('{{IGNORED_PATTERNS}}', JSON.stringify(config.ignorePatterns));
fs.writeFileSync('scripts/prepare-public.js', script);
fs.chmodSync('scripts/prepare-public.js', '0755');
}
```
Append rules to existing .gitignore or create a new one:
```javascript
// Example .gitignore management
const { parseIgnore } = require('ignore');
function updateGitignore(config) {
let content = '';
// Try to read existing .gitignore
try {
content = fs.readFileSync('.gitignore', 'utf8');
} catch (error) {
// File doesn't exist, create new
}
// Parse existing content
const ignore = parseIgnore(content);
// Add new rules if they don't exist
let newRules = '';
for (const dir of config.ignoreDirs) {
if (!ignore.ignores(dir)) {
newRules += `/${dir}/\n`;
}
}
for (const pattern of config.ignorePatterns) {
if (!ignore.ignores(pattern)) {
newRules += `${pattern}\n`;
}
}
// Append new rules to .gitignore
if (newRules) {
fs.appendFileSync('.gitignore', `\n
}
}
```
```bash
npx clean-repo init
```
```bash
npx clean-repo init --interactive
```
Users can provide custom templates in `.clean-repo/templates/`:
```
.clean-repo/
├── templates/
│ ├── contributing.md
│ ├── gitattributes
│ └── release-guide.md
```
Support for custom plugins to extend functionality:
```javascript
// Example plugin
module.exports = function(cleanRepo) {
cleanRepo.hooks.afterInit.tap('my-plugin', (config) => {
// Do something after initialization
});
};
```
For projects already using manual methods:
```bash
npx clean-repo migrate
```
This command will:
1. Detect existing scripts and hooks
2. Convert them to clean-repo configuration
3. Update all components to use clean-repo managed versions
1. Support for monorepos (workspaces)
2. Integration with CI/CD pipelines
3. Automated branch protection rules
4. Statistics and reporting on repository cleanliness
5. Visual interface for managing ignored files
## Conclusion
The Clean-Repo package provides a comprehensive solution for maintaining a clean public repository while allowing developers to work with necessary development files. By automating the setup of Git hooks, branch management scripts, and configuration, it ensures consistent practices across all contributors with minimal effort.
The package balances automation with flexibility, providing sensible defaults while allowing customization where needed. It integrates with existing tools and workflows, making adoption straightforward for projects of any size.