PromucFlow_constructor/.cursor/rules/quality/pre-commit-checks.mdc

310 lines
8.2 KiB
Plaintext
Raw Normal View History

refactor: restructure .cursor directory for improved organization and clarity (#40196) # refactor: restructure .cursor directory for improved organization and clarity ## Description This PR refactors the `.cursor` directory to enhance organization, clarity, and maintainability. ### Problem The existing `.cursor` directory lacked clear organization, making it difficult to find specific files, understand their purpose, and add new components consistently. ### Solution A comprehensive restructuring: #### New Directory Structure ``` .cursor/ ├── settings.json # Main configuration file ├── docs/ # Documentation │ ├── guides/ # In-depth guides │ ├── references/ # Quick references │ └── practices/ # Best practices ├── rules/ # Rule definitions │ ├── commit/ # Commit-related rules │ ├── quality/ # Code quality rules │ ├── testing/ # Testing rules │ └── verification/ # Verification rules └── hooks/ # Git hooks and scripts ``` #### Key Changes 1. **Logical Categorization**: Organized files into clear categories based on purpose 2. **Improved Documentation**: Added comprehensive README files for each directory 3. **Standardized Naming**: Implemented consistent kebab-case naming convention 4. **Reference Updates**: Updated all internal references to point to new file locations ### Benefits - **Easier Navigation**: Clear categorization makes finding files intuitive - **Improved Understanding**: Comprehensive documentation explains purpose and usage - **Simplified Maintenance**: Logical structure makes updates and additions easier - **Better Onboarding**: New team members can quickly understand the system This refactoring sets a solid foundation for all Cursor AI-related configurations and rules, making it easier for the team to leverage Cursor's capabilities.
2025-04-11 06:34:33 +00:00
---
description:
globs:
alwaysApply: true
---
# Pre-Commit Quality Checks
```yaml
name: Pre-Commit Quality Checks
description: Runs quality checks similar to GitHub Actions locally before commits
author: Cursor AI
version: 1.0.0
tags:
- quality
- pre-commit
- testing
- linting
activation:
always: true
events:
- pre_commit
- command
triggers:
- pre_commit
- command: "run_quality_checks"
```
## Rule Definition
This rule runs the same quality checks locally that would normally run in CI, preventing commits that would fail in the GitHub workflow quality-checks.yml.
## Implementation
```javascript
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
/**
* Determines which checks to run based on changed files
* @param {string[]} changedFiles - List of changed files
* @returns {Object} Object indicating which checks to run
*/
function determineChecksToRun(changedFiles) {
const checks = {
serverChecks: false,
clientChecks: false,
};
// Check if server files have changed
checks.serverChecks = changedFiles.some(file =>
file.startsWith('app/server/')
);
// Check if client files have changed
checks.clientChecks = changedFiles.some(file =>
file.startsWith('app/client/')
);
return checks;
}
/**
* Gets a list of changed files in the current git staging area
* @returns {string[]} List of changed files
*/
function getChangedFiles() {
try {
const output = execSync('git diff --cached --name-only', { encoding: 'utf8' });
return output.split('\n').filter(Boolean);
} catch (error) {
console.error('Error getting changed files:', error.message);
return [];
}
}
/**
* Runs client-side quality checks
* @returns {Object} Results of the checks
*/
function runClientChecks() {
const results = {
success: true,
errors: [],
output: []
};
try {
// Run client lint
console.log('Running client lint checks...');
try {
const lintOutput = execSync('cd app/client && yarn lint', { encoding: 'utf8' });
results.output.push('✅ Client lint passed');
} catch (error) {
results.success = false;
results.errors.push('Client lint failed');
results.output.push(`❌ Client lint failed: ${error.message}`);
}
// Run client unit tests
console.log('Running client unit tests...');
try {
const testOutput = execSync('cd app/client && yarn test', { encoding: 'utf8' });
results.output.push('✅ Client unit tests passed');
} catch (error) {
results.success = false;
results.errors.push('Client unit tests failed');
results.output.push(`❌ Client unit tests failed: ${error.message}`);
}
// Check for cyclic dependencies
console.log('Checking for cyclic dependencies...');
try {
const cyclicCheckOutput = execSync('cd app/client && yarn check-circular-deps', { encoding: 'utf8' });
results.output.push('✅ No cyclic dependencies found');
} catch (error) {
results.success = false;
results.errors.push('Cyclic dependencies check failed');
results.output.push(`❌ Cyclic dependencies found: ${error.message}`);
}
// Run prettier check
console.log('Running prettier check...');
try {
const prettierOutput = execSync('cd app/client && yarn prettier', { encoding: 'utf8' });
results.output.push('✅ Prettier check passed');
} catch (error) {
results.success = false;
results.errors.push('Prettier check failed');
results.output.push(`❌ Prettier check failed: ${error.message}`);
}
} catch (error) {
results.success = false;
results.errors.push(`General error in client checks: ${error.message}`);
}
return results;
}
/**
* Runs server-side quality checks
* @returns {Object} Results of the checks
*/
function runServerChecks() {
const results = {
success: true,
errors: [],
output: []
};
try {
// Run server unit tests
console.log('Running server unit tests...');
try {
const testOutput = execSync('cd app/server && ./gradlew test', { encoding: 'utf8' });
results.output.push('✅ Server unit tests passed');
} catch (error) {
results.success = false;
results.errors.push('Server unit tests failed');
results.output.push(`❌ Server unit tests failed: ${error.message}`);
}
// Run server spotless check
console.log('Running server spotless check...');
try {
const spotlessOutput = execSync('cd app/server && ./gradlew spotlessCheck', { encoding: 'utf8' });
results.output.push('✅ Server spotless check passed');
} catch (error) {
results.success = false;
results.errors.push('Server spotless check failed');
results.output.push(`❌ Server spotless check failed: ${error.message}`);
}
} catch (error) {
results.success = false;
results.errors.push(`General error in server checks: ${error.message}`);
}
return results;
}
/**
* Runs all quality checks
* @param {Object} context - The execution context
* @returns {Object} Results of the checks
*/
function runQualityChecks(context) {
console.log('Running pre-commit quality checks...');
const changedFiles = getChangedFiles();
if (!changedFiles.length) {
return {
status: 'success',
message: 'No files to check'
};
}
const checksToRun = determineChecksToRun(changedFiles);
const results = {
success: true,
output: ['Starting quality checks for staged files...'],
clientChecks: null,
serverChecks: null
};
// Run client checks if client files have changed
if (checksToRun.clientChecks) {
results.output.push('\n=== Client Checks ===');
results.clientChecks = runClientChecks();
results.output = results.output.concat(results.clientChecks.output);
results.success = results.success && results.clientChecks.success;
}
// Run server checks if server files have changed
if (checksToRun.serverChecks) {
results.output.push('\n=== Server Checks ===');
results.serverChecks = runServerChecks();
results.output = results.output.concat(results.serverChecks.output);
results.success = results.success && results.serverChecks.success;
}
// If no checks were run, note that
if (!checksToRun.clientChecks && !checksToRun.serverChecks) {
results.output.push('No client or server files were changed, skipping checks');
}
if (results.success) {
return {
status: 'success',
message: 'All quality checks passed',
details: results.output.join('\n')
};
} else {
return {
status: 'failure',
message: 'Quality checks failed',
details: results.output.join('\n')
};
}
}
/**
* Register command and hooks
* @param {Object} context - The cursor context
*/
function activate(context) {
// Register pre-commit hook
context.on('pre_commit', (event) => {
return runQualityChecks(context);
});
// Register command for manual validation
context.registerCommand('run_quality_checks', () => {
return runQualityChecks(context);
});
}
module.exports = {
activate,
runQualityChecks
};
```
## Usage
This rule runs automatically on pre-commit events. You can also manually trigger it with the command `run_quality_checks`.
### What It Checks
1. **For Client-side Changes:**
- Runs linting checks
- Runs unit tests
- Checks for cyclic dependencies
- Runs prettier formatting validation
2. **For Server-side Changes:**
- Runs unit tests
- Runs spotless formatting checks
### Behavior
- Only runs checks relevant to the files being committed (client and/or server)
- Prevents commits if any checks fail
- Provides detailed output about which checks passed or failed
### Requirements
- Node.js and yarn for client-side checks
- Java and Gradle for server-side checks
- Git for determining changed files
### Customization
You can customize which checks are run by modifying the `runClientChecks` and `runServerChecks` functions.
### Example Output
```
Running pre-commit quality checks...
Starting quality checks for staged files...
=== Client Checks ===
✅ Client lint passed
✅ Client unit tests passed
✅ No cyclic dependencies found
✅ Prettier check passed
=== Server Checks ===
✅ Server unit tests passed
✅ Server spotless check passed
```