branch-validator-pro 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +211 -0
- package/cli.js +132 -0
- package/index.js +285 -0
- package/package.json +104 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sanjib Roy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# š Branch Validator Pro
|
|
2
|
+
|
|
3
|
+
A lightweight Node.js package that validates Git branch names and commit messages following consistent conventions and best practices.
|
|
4
|
+
|
|
5
|
+
## š Overview
|
|
6
|
+
|
|
7
|
+
Branch Validator Pro enforces consistent Git naming conventions across your team, ensuring code quality and maintainability through automated validation of branch names and commit messages.
|
|
8
|
+
|
|
9
|
+
## ⨠Features
|
|
10
|
+
|
|
11
|
+
- ā
**Git branch name validation** with proper prefixes (feature/, bugfix/, hotfix/, release/, chore/)
|
|
12
|
+
- ā
**Commit message validation** following consistent patterns
|
|
13
|
+
- ā
**Command-line interface** for easy integration
|
|
14
|
+
- ā
**Programmatic API** for custom implementations
|
|
15
|
+
- ā
**Git hook integration** for automated validation
|
|
16
|
+
- ā
**Zero dependencies** for minimal footprint
|
|
17
|
+
|
|
18
|
+
## š¦ Installation
|
|
19
|
+
|
|
20
|
+
### Global Installation (Recommended)
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g branch-validator-pro
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Local Installation
|
|
26
|
+
```bash
|
|
27
|
+
npm install branch-validator-pro
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## šÆ Quick Start
|
|
31
|
+
|
|
32
|
+
### Basic Usage
|
|
33
|
+
```bash
|
|
34
|
+
# Validate branch names
|
|
35
|
+
validate-git branch feature/SHOP-1234-add-user-authentication
|
|
36
|
+
validate-git branch bugfix/SHOP-5678-fix-login-bug
|
|
37
|
+
validate-git branch hotfix/SHOP-9012-critical-security-patch
|
|
38
|
+
|
|
39
|
+
# Validate commit messages
|
|
40
|
+
validate-git commit SHOP-1234-add-user-authentication
|
|
41
|
+
validate-git commit SHOP-5678-fix-login-bug
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Output
|
|
45
|
+
```
|
|
46
|
+
ā
Branch name is valid: feature/SHOP-1234-add-user-authentication
|
|
47
|
+
ā
Commit message is valid: SHOP-1234-fix-login-bug
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## š Programmatic Usage
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
const { validateBranchName, validateCommitMessage } = require('branch-validator-pro');
|
|
54
|
+
|
|
55
|
+
// Validate branch name
|
|
56
|
+
const branchResult = validateBranchName('feature/SHOP-1234-new-feature');
|
|
57
|
+
console.log(branchResult.valid); // true/false
|
|
58
|
+
console.log(branchResult.message); // validation message
|
|
59
|
+
|
|
60
|
+
// Validate commit message
|
|
61
|
+
const commitResult = validateCommitMessage('SHOP-1234-new-feature');
|
|
62
|
+
console.log(commitResult.valid); // true/false
|
|
63
|
+
console.log(commitResult.message); // validation message
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## š Validation Rules
|
|
67
|
+
|
|
68
|
+
### Branch Names
|
|
69
|
+
- Must start with one of these prefixes:
|
|
70
|
+
- `feature/` - for new features
|
|
71
|
+
- `bugfix/` - for bug fixes
|
|
72
|
+
- `hotfix/` - for critical fixes
|
|
73
|
+
- `release/` - for release branches
|
|
74
|
+
- `chore/` - for maintenance tasks
|
|
75
|
+
- Must contain a ticket pattern: `SHOP-XXXX` (where XXXX is a number)
|
|
76
|
+
- Description must be lowercase
|
|
77
|
+
- Use dashes (-) only, no spaces or underscores
|
|
78
|
+
- **Pattern:** `^[a-z]+/SHOP-\d+-[a-z0-9-]+$`
|
|
79
|
+
|
|
80
|
+
**Valid Examples:**
|
|
81
|
+
- `feature/SHOP-1234-add-payment-gateway`
|
|
82
|
+
- `bugfix/SHOP-5678-fix-validation-error`
|
|
83
|
+
- `hotfix/SHOP-9012-security-patch`
|
|
84
|
+
|
|
85
|
+
**Invalid Examples:**
|
|
86
|
+
- `feature/add-payment` (missing ticket)
|
|
87
|
+
- `Feature/SHOP-1234-payment` (uppercase prefix)
|
|
88
|
+
- `feature/SHOP-1234_payment_gateway` (underscores not allowed)
|
|
89
|
+
- `feature/SHOP-1234-Payment Gateway` (spaces not allowed)
|
|
90
|
+
|
|
91
|
+
### Commit Messages
|
|
92
|
+
- Must follow the pattern: `SHOP-XXXX-description`
|
|
93
|
+
- Use lowercase letters, numbers, and dashes only
|
|
94
|
+
- No spaces or underscores allowed
|
|
95
|
+
- **Pattern:** `^SHOP-\d+-[a-z0-9-]+$`
|
|
96
|
+
|
|
97
|
+
**Valid Examples:**
|
|
98
|
+
- `SHOP-1234-implement-user-registration`
|
|
99
|
+
- `SHOP-5678-fix-database-connection`
|
|
100
|
+
- `SHOP-9012-update-security-headers`
|
|
101
|
+
|
|
102
|
+
**Invalid Examples:**
|
|
103
|
+
- `SHOP-1234 implement user registration` (spaces not allowed)
|
|
104
|
+
- `SHOP-1234_implement_user_registration` (underscores not allowed)
|
|
105
|
+
- `implement user registration` (missing ticket)
|
|
106
|
+
|
|
107
|
+
## šŖ Git Hook Integration
|
|
108
|
+
|
|
109
|
+
Integrate this validator with Git hooks for automatic validation on every commit.
|
|
110
|
+
|
|
111
|
+
### Pre-commit Hook
|
|
112
|
+
Create `.git/hooks/pre-commit`:
|
|
113
|
+
```bash
|
|
114
|
+
#!/bin/bash
|
|
115
|
+
branch_name=$(git symbolic-ref --short HEAD)
|
|
116
|
+
validate-git branch "$branch_name"
|
|
117
|
+
exit_code=$?
|
|
118
|
+
if [ $exit_code -ne 0 ]; then
|
|
119
|
+
echo "Branch name validation failed!"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Commit Message Hook
|
|
125
|
+
Create `.git/hooks/commit-msg`:
|
|
126
|
+
```bash
|
|
127
|
+
#!/bin/bash
|
|
128
|
+
commit_msg=$(cat $1)
|
|
129
|
+
validate-git commit "$commit_msg"
|
|
130
|
+
exit_code=$?
|
|
131
|
+
if [ $exit_code -ne 0 ]; then
|
|
132
|
+
echo "Commit message validation failed!"
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Make hooks executable:
|
|
138
|
+
```bash
|
|
139
|
+
chmod +x .git/hooks/pre-commit
|
|
140
|
+
chmod +x .git/hooks/commit-msg
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## š API Reference
|
|
144
|
+
|
|
145
|
+
### validateBranchName(branchName)
|
|
146
|
+
|
|
147
|
+
Validates a Git branch name against the defined rules.
|
|
148
|
+
|
|
149
|
+
**Parameters:**
|
|
150
|
+
- `branchName` (string): The branch name to validate
|
|
151
|
+
|
|
152
|
+
**Returns:**
|
|
153
|
+
- `valid` (boolean): Whether the branch name is valid
|
|
154
|
+
- `message` (string): Validation result message
|
|
155
|
+
|
|
156
|
+
### validateCommitMessage(commitMessage)
|
|
157
|
+
|
|
158
|
+
Validates a commit message against the defined rules.
|
|
159
|
+
|
|
160
|
+
**Parameters:**
|
|
161
|
+
- `commitMessage` (string): The commit message to validate
|
|
162
|
+
|
|
163
|
+
**Returns:**
|
|
164
|
+
- `valid` (boolean): Whether the commit message is valid
|
|
165
|
+
- `message` (string): Validation result message
|
|
166
|
+
|
|
167
|
+
## šŖ Exit Codes
|
|
168
|
+
|
|
169
|
+
- `0`: Validation successful
|
|
170
|
+
- `1`: Validation failed or invalid usage
|
|
171
|
+
|
|
172
|
+
## š Contributing
|
|
173
|
+
|
|
174
|
+
1. Fork the repository
|
|
175
|
+
2. Create a feature branch: `git checkout -b feature/your-feature`
|
|
176
|
+
3. Commit your changes: `git commit -m "your-feature-description"`
|
|
177
|
+
4. Push to the branch: `git push origin feature/your-feature`
|
|
178
|
+
5. Submit a pull request
|
|
179
|
+
|
|
180
|
+
## š License
|
|
181
|
+
|
|
182
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
183
|
+
|
|
184
|
+
## š¤ Author
|
|
185
|
+
|
|
186
|
+
### **⨠Sanjib Roy**
|
|
187
|
+
|
|
188
|
+
A passionate developer focused on building tools that enhance developer productivity and code quality.
|
|
189
|
+
|
|
190
|
+
**Connect with me:**
|
|
191
|
+
- š **GitHub:** [@snbroy](https://github.com/snbroy)
|
|
192
|
+
- š¼ **LinkedIn:** [Sanjib Roy](https://www.linkedin.com/in/sanjib-r-834947100/)
|
|
193
|
+
- š§ **Email:** [sanjibroy17061995@gmail.com](mailto:sanjibroy17061995@gmail.com)
|
|
194
|
+
- š± **Mobile:** +91 8918132291
|
|
195
|
+
|
|
196
|
+
## š¬ Support
|
|
197
|
+
|
|
198
|
+
For issues or questions, please reach out:
|
|
199
|
+
- š§ Email: [sanjibroy17061995@gmail.com](mailto:sanjibroy17061995@gmail.com)
|
|
200
|
+
- š± Mobile: +91 8918132291
|
|
201
|
+
- š [Open an issue](https://github.com/snbroyvfc95/branch-validator-pro/issues) on GitHub
|
|
202
|
+
|
|
203
|
+
## š Changelog
|
|
204
|
+
|
|
205
|
+
### v1.0.0
|
|
206
|
+
- Initial release
|
|
207
|
+
- Branch name validation
|
|
208
|
+
- Commit message validation
|
|
209
|
+
- CLI interface
|
|
210
|
+
- Programmatic API
|
|
211
|
+
- Git hook integration support
|
package/cli.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
validateBranchName,
|
|
5
|
+
validateCommitMessage,
|
|
6
|
+
validateBoth,
|
|
7
|
+
showConfig
|
|
8
|
+
} = require('./index.js');
|
|
9
|
+
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
|
|
12
|
+
if (args.length === 0) {
|
|
13
|
+
console.log('š« Simple Branch & Commit Validator');
|
|
14
|
+
console.log('');
|
|
15
|
+
console.log('Usage:');
|
|
16
|
+
console.log(' validate-git branch <branch-name> - Validate branch name format');
|
|
17
|
+
console.log(' validate-git commit <commit-message> - Validate commit message format');
|
|
18
|
+
console.log(' validate-git both <branch> <commit> - Validate both branch and commit');
|
|
19
|
+
console.log(' validate-git config - Show current configuration');
|
|
20
|
+
console.log('');
|
|
21
|
+
console.log('Examples:');
|
|
22
|
+
console.log(' validate-git branch "feature/SHOP-1234-fix-user-login"');
|
|
23
|
+
console.log(' validate-git commit "SHOP-1234-fix-user-login"');
|
|
24
|
+
console.log(' validate-git both "feature/SHOP-1234-fix-bug" "SHOP-1234-fix-bug"');
|
|
25
|
+
console.log('');
|
|
26
|
+
console.log('Environment Variables:');
|
|
27
|
+
console.log(' PROJECT_KEYS - Comma-separated project keys (default: SHOP,PROJ,TASK)');
|
|
28
|
+
console.log(' SKIP_VALIDATION - Set to "true" to skip validation entirely');
|
|
29
|
+
console.log('');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const command = args[0];
|
|
34
|
+
|
|
35
|
+
async function runValidation() {
|
|
36
|
+
try {
|
|
37
|
+
switch (command) {
|
|
38
|
+
case 'branch': {
|
|
39
|
+
const branchName = args[1];
|
|
40
|
+
if (!branchName) {
|
|
41
|
+
console.log('ā Error: Please provide a branch name to validate');
|
|
42
|
+
console.log('Usage: validate-git branch <branch-name>');
|
|
43
|
+
console.log('Example: validate-git branch "feature/SHOP-1234-fix-user-login"');
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(`š Validating branch: ${branchName}`);
|
|
48
|
+
const result = validateBranchName(branchName);
|
|
49
|
+
|
|
50
|
+
console.log('\\n' + result.message);
|
|
51
|
+
if (result.suggestion) {
|
|
52
|
+
console.log(`š” Suggestion: ${result.suggestion}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (result.ticketId) {
|
|
56
|
+
console.log(`š« Ticket ID: ${result.ticketId}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
process.exit(result.valid ? 0 : 1);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
case 'commit': {
|
|
63
|
+
const commitMessage = args[1];
|
|
64
|
+
if (!commitMessage) {
|
|
65
|
+
console.log('ā Error: Please provide a commit message to validate');
|
|
66
|
+
console.log('Usage: validate-git commit <commit-message>');
|
|
67
|
+
console.log('Example: validate-git commit "SHOP-1234-fix-user-login"');
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
console.log(`š Validating commit: ${commitMessage}`);
|
|
72
|
+
const result = validateCommitMessage(commitMessage);
|
|
73
|
+
|
|
74
|
+
console.log('\\n' + result.message);
|
|
75
|
+
if (result.suggestion) {
|
|
76
|
+
console.log(`š” Suggestion: ${result.suggestion}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (result.ticketId) {
|
|
80
|
+
console.log(`š« Ticket ID: ${result.ticketId}`);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
process.exit(result.valid ? 0 : 1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
case 'both': {
|
|
87
|
+
const branchName = args[1];
|
|
88
|
+
const commitMessage = args[2];
|
|
89
|
+
if (!branchName || !commitMessage) {
|
|
90
|
+
console.log('ā Error: Please provide both branch name and commit message');
|
|
91
|
+
console.log('Usage: validate-git both <branch-name> <commit-message>');
|
|
92
|
+
console.log('Example: validate-git both "feature/SHOP-1234-fix-bug" "SHOP-1234-fix-bug"');
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
console.log(`š Validating both branch and commit...`);
|
|
97
|
+
const result = validateBoth(branchName, commitMessage);
|
|
98
|
+
|
|
99
|
+
console.log('\\nš Validation Results:');
|
|
100
|
+
console.log(`šæ Branch: ${result.branchResult.valid ? 'ā
' : 'ā'} ${result.branchResult.message}`);
|
|
101
|
+
console.log(`š¬ Commit: ${result.commitResult.valid ? 'ā
' : 'ā'} ${result.commitResult.message}`);
|
|
102
|
+
|
|
103
|
+
if (result.branchResult.suggestion) {
|
|
104
|
+
console.log(`š” Branch suggestion: ${result.branchResult.suggestion}`);
|
|
105
|
+
}
|
|
106
|
+
if (result.commitResult.suggestion) {
|
|
107
|
+
console.log(`š” Commit suggestion: ${result.commitResult.suggestion}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
console.log(`\\nšÆ Overall: ${result.valid ? 'ā
Valid' : 'ā Invalid'}`);
|
|
111
|
+
|
|
112
|
+
process.exit(result.valid ? 0 : 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
case 'config': {
|
|
116
|
+
const result = showConfig();
|
|
117
|
+
process.exit(0);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
default: {
|
|
121
|
+
console.log(`ā Unknown command: ${command}`);
|
|
122
|
+
console.log('Run "validate-git" without arguments to see usage information.');
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
console.error('ā Validation error:', error.message);
|
|
128
|
+
process.exit(1);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
runValidation();
|
package/index.js
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Branch Name and Commit Message Validator
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Validates branch name format and patterns
|
|
6
|
+
* - Validates commit message format
|
|
7
|
+
* - Supports multiple project keys
|
|
8
|
+
* - Simple format validation without external API calls
|
|
9
|
+
*
|
|
10
|
+
* Rules:
|
|
11
|
+
* - Branch name must start with feature/, bugfix/, hotfix/, release/, or chore/
|
|
12
|
+
* - Must contain a valid ticket pattern like SHOP-1234
|
|
13
|
+
* - Description must be lowercase, use dashes (-), no spaces or underscores
|
|
14
|
+
* - Commit message must follow: SHOP-1234-description format
|
|
15
|
+
*
|
|
16
|
+
* Environment Variables:
|
|
17
|
+
* - PROJECT_KEYS: Comma-separated list of valid project keys (default: SHOP,PROJ,TASK)
|
|
18
|
+
* - SKIP_VALIDATION: Set to 'true' to skip validation entirely
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Load environment variables from .env file if available
|
|
22
|
+
try {
|
|
23
|
+
require('dotenv').config();
|
|
24
|
+
} catch (e) {
|
|
25
|
+
// dotenv not available, use system environment variables
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
|
|
31
|
+
// Basic Configuration
|
|
32
|
+
const CONFIG = {
|
|
33
|
+
projectKeys: (process.env.PROJECT_KEYS || 'SHOP,PROJ,TASK').split(',').map(key => key.trim()),
|
|
34
|
+
skipValidation: process.env.SKIP_VALIDATION === 'true'
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Simple validation patterns
|
|
38
|
+
const PATTERNS = {
|
|
39
|
+
branch: /^(feature|bugfix|hotfix|release|chore)\/([A-Z]+)-(\d+)-(.+)$/,
|
|
40
|
+
commit: /^([A-Z]+)-(\d+)-(.+)$/,
|
|
41
|
+
ticketId: /([A-Z]+)-(\d+)/
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Extract ticket ID from branch or commit name
|
|
46
|
+
*/
|
|
47
|
+
function extractTicketId(name) {
|
|
48
|
+
const matches = name.match(PATTERNS.ticketId);
|
|
49
|
+
return matches ? matches[0] : null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get expected format description for error messages
|
|
54
|
+
*/
|
|
55
|
+
function getExpectedFormat(type) {
|
|
56
|
+
switch (type) {
|
|
57
|
+
case 'branch':
|
|
58
|
+
return `${CONFIG.projectKeys[0]}-1234-description (feature/bugfix/hotfix/release/chore prefix required)`;
|
|
59
|
+
case 'commit':
|
|
60
|
+
return `${CONFIG.projectKeys[0]}-1234-description`;
|
|
61
|
+
default:
|
|
62
|
+
return 'Valid format required';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Validate basic format patterns
|
|
68
|
+
*/
|
|
69
|
+
function validateFormat(name, type) {
|
|
70
|
+
const pattern = PATTERNS[type];
|
|
71
|
+
if (!pattern) return { valid: false, message: 'Unknown validation type' };
|
|
72
|
+
|
|
73
|
+
const match = name.match(pattern);
|
|
74
|
+
if (!match) {
|
|
75
|
+
return {
|
|
76
|
+
valid: false,
|
|
77
|
+
message: `ā Invalid ${type} format. Expected: ${getExpectedFormat(type)}`
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const ticketId = extractTicketId(name);
|
|
82
|
+
if (!ticketId) {
|
|
83
|
+
return {
|
|
84
|
+
valid: false,
|
|
85
|
+
message: `ā No valid ticket ID found in ${type}`
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const projectKey = ticketId.split('-')[0];
|
|
90
|
+
if (!CONFIG.projectKeys.includes(projectKey)) {
|
|
91
|
+
return {
|
|
92
|
+
valid: false,
|
|
93
|
+
message: `ā Invalid project key '${projectKey}'. Valid keys: ${CONFIG.projectKeys.join(', ')}`
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
valid: true,
|
|
99
|
+
message: `ā
${type.charAt(0).toUpperCase() + type.slice(1)} format is valid`,
|
|
100
|
+
ticketId: ticketId,
|
|
101
|
+
projectKey: projectKey
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Validate branch name format
|
|
107
|
+
*/
|
|
108
|
+
function validateBranchName(branchName) {
|
|
109
|
+
console.log(`š« Validating branch: ${branchName}`);
|
|
110
|
+
|
|
111
|
+
// Skip validation if disabled
|
|
112
|
+
if (CONFIG.skipValidation) {
|
|
113
|
+
return {
|
|
114
|
+
valid: true,
|
|
115
|
+
message: 'ā
Branch validation skipped (SKIP_VALIDATION=true)',
|
|
116
|
+
skipped: true
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Basic format validation
|
|
121
|
+
const formatResult = validateFormat(branchName, 'branch');
|
|
122
|
+
if (!formatResult.valid) {
|
|
123
|
+
return formatResult;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Check description format (lowercase, dashes only)
|
|
127
|
+
const parts = branchName.match(PATTERNS.branch);
|
|
128
|
+
if (parts && parts[4]) {
|
|
129
|
+
const description = parts[4];
|
|
130
|
+
|
|
131
|
+
// Check for spaces
|
|
132
|
+
if (description.includes(' ')) {
|
|
133
|
+
return {
|
|
134
|
+
valid: false,
|
|
135
|
+
message: 'ā Branch description cannot contain spaces. Use dashes (-) instead',
|
|
136
|
+
suggestion: `${parts[1]}/${parts[2]}-${parts[3]}-${description.replace(/\s+/g, '-')}`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Check for underscores
|
|
141
|
+
if (description.includes('_')) {
|
|
142
|
+
return {
|
|
143
|
+
valid: false,
|
|
144
|
+
message: 'ā Branch description cannot contain underscores. Use dashes (-) instead',
|
|
145
|
+
suggestion: `${parts[1]}/${parts[2]}-${parts[3]}-${description.replace(/_/g, '-')}`
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Check for uppercase
|
|
150
|
+
if (description !== description.toLowerCase()) {
|
|
151
|
+
return {
|
|
152
|
+
valid: false,
|
|
153
|
+
message: 'ā Branch description must be lowercase',
|
|
154
|
+
suggestion: `${parts[1]}/${parts[2]}-${parts[3]}-${description.toLowerCase()}`
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
valid: true,
|
|
161
|
+
message: `ā
Branch name is valid`,
|
|
162
|
+
ticketId: formatResult.ticketId,
|
|
163
|
+
projectKey: formatResult.projectKey
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Validate commit message format
|
|
169
|
+
*/
|
|
170
|
+
function validateCommitMessage(commitMessage) {
|
|
171
|
+
console.log(`š Validating commit: ${commitMessage}`);
|
|
172
|
+
|
|
173
|
+
// Skip validation if disabled
|
|
174
|
+
if (CONFIG.skipValidation) {
|
|
175
|
+
return {
|
|
176
|
+
valid: true,
|
|
177
|
+
message: 'ā
Commit validation skipped (SKIP_VALIDATION=true)',
|
|
178
|
+
skipped: true
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Basic format validation
|
|
183
|
+
const formatResult = validateFormat(commitMessage, 'commit');
|
|
184
|
+
if (!formatResult.valid) {
|
|
185
|
+
return formatResult;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Check description format (lowercase, dashes only)
|
|
189
|
+
const parts = commitMessage.match(PATTERNS.commit);
|
|
190
|
+
if (parts && parts[3]) {
|
|
191
|
+
const description = parts[3];
|
|
192
|
+
|
|
193
|
+
// Check for spaces
|
|
194
|
+
if (description.includes(' ')) {
|
|
195
|
+
return {
|
|
196
|
+
valid: false,
|
|
197
|
+
message: 'ā Commit description cannot contain spaces. Use dashes (-) instead',
|
|
198
|
+
suggestion: `${parts[1]}-${parts[2]}-${description.replace(/\s+/g, '-')}`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Check for underscores
|
|
203
|
+
if (description.includes('_')) {
|
|
204
|
+
return {
|
|
205
|
+
valid: false,
|
|
206
|
+
message: 'ā Commit description cannot contain underscores. Use dashes (-) instead',
|
|
207
|
+
suggestion: `${parts[1]}-${parts[2]}-${description.replace(/_/g, '-')}`
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Check for uppercase
|
|
212
|
+
if (description !== description.toLowerCase()) {
|
|
213
|
+
return {
|
|
214
|
+
valid: false,
|
|
215
|
+
message: 'ā Commit description must be lowercase',
|
|
216
|
+
suggestion: `${parts[1]}-${parts[2]}-${description.toLowerCase()}`
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
valid: true,
|
|
223
|
+
message: `ā
Commit message is valid`,
|
|
224
|
+
ticketId: formatResult.ticketId,
|
|
225
|
+
projectKey: formatResult.projectKey
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Validate both branch and commit together
|
|
231
|
+
*/
|
|
232
|
+
function validateBoth(branchName, commitMessage) {
|
|
233
|
+
console.log(`š Validating both branch and commit...`);
|
|
234
|
+
|
|
235
|
+
const branchResult = validateBranchName(branchName);
|
|
236
|
+
const commitResult = validateCommitMessage(commitMessage);
|
|
237
|
+
|
|
238
|
+
// Check if ticket IDs match
|
|
239
|
+
if (branchResult.valid && commitResult.valid &&
|
|
240
|
+
branchResult.ticketId && commitResult.ticketId &&
|
|
241
|
+
branchResult.ticketId !== commitResult.ticketId) {
|
|
242
|
+
return {
|
|
243
|
+
valid: false,
|
|
244
|
+
message: `ā Ticket ID mismatch: Branch has ${branchResult.ticketId}, commit has ${commitResult.ticketId}`,
|
|
245
|
+
branchResult,
|
|
246
|
+
commitResult
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
valid: branchResult.valid && commitResult.valid,
|
|
252
|
+
message: branchResult.valid && commitResult.valid
|
|
253
|
+
? 'ā
Both branch and commit are valid'
|
|
254
|
+
: 'ā Validation failed',
|
|
255
|
+
branchResult,
|
|
256
|
+
commitResult
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Show configuration info
|
|
262
|
+
*/
|
|
263
|
+
function showConfig() {
|
|
264
|
+
console.log('\nš§ Validator Configuration:');
|
|
265
|
+
console.log(`š Valid Project Keys: ${CONFIG.projectKeys.join(', ')}`);
|
|
266
|
+
console.log(`āļø Skip Validation: ${CONFIG.skipValidation}`);
|
|
267
|
+
console.log('\nš Expected Formats:');
|
|
268
|
+
console.log(`šæ Branch: feature/${CONFIG.projectKeys[0]}-1234-description`);
|
|
269
|
+
console.log(`š¬ Commit: ${CONFIG.projectKeys[0]}-1234-description`);
|
|
270
|
+
console.log('\nš Valid Prefixes: feature/, bugfix/, hotfix/, release/, chore/');
|
|
271
|
+
|
|
272
|
+
return {
|
|
273
|
+
valid: true,
|
|
274
|
+
config: CONFIG
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
module.exports = {
|
|
279
|
+
validateBranchName,
|
|
280
|
+
validateCommitMessage,
|
|
281
|
+
validateBoth,
|
|
282
|
+
showConfig,
|
|
283
|
+
extractTicketId,
|
|
284
|
+
CONFIG
|
|
285
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "branch-validator-pro",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Professional Git branch and commit validator for consistent naming conventions. Validates format and ensures proper ticket ID patterns without external API dependencies. Perfect for teams worldwide.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"validate-git": "cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
11
|
+
"start": "node cli.js",
|
|
12
|
+
"validate-branch": "node cli.js branch",
|
|
13
|
+
"validate-commit": "node cli.js commit",
|
|
14
|
+
"validate-both": "node cli.js both",
|
|
15
|
+
"config": "node cli.js config"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"git",
|
|
19
|
+
"branch",
|
|
20
|
+
"commit",
|
|
21
|
+
"validator",
|
|
22
|
+
"naming",
|
|
23
|
+
"convention",
|
|
24
|
+
"validation",
|
|
25
|
+
"cli",
|
|
26
|
+
"git-hooks",
|
|
27
|
+
"branch-naming",
|
|
28
|
+
"commit-message",
|
|
29
|
+
"ticket-format",
|
|
30
|
+
"development-tools",
|
|
31
|
+
"format-validation",
|
|
32
|
+
"git-workflow",
|
|
33
|
+
"code-quality",
|
|
34
|
+
"devops",
|
|
35
|
+
"pro",
|
|
36
|
+
"branch-validator",
|
|
37
|
+
"git-validator",
|
|
38
|
+
"commit-validator",
|
|
39
|
+
"code-standards",
|
|
40
|
+
"linter",
|
|
41
|
+
"git-linter",
|
|
42
|
+
"branch-rules",
|
|
43
|
+
"git-conventions",
|
|
44
|
+
"semantic-versioning",
|
|
45
|
+
"code-review",
|
|
46
|
+
"team-tools",
|
|
47
|
+
"automation",
|
|
48
|
+
"ci-cd",
|
|
49
|
+
"continuous-integration",
|
|
50
|
+
"git-best-practices",
|
|
51
|
+
"code-organization",
|
|
52
|
+
"developer-tools",
|
|
53
|
+
"productivity",
|
|
54
|
+
"workflow-automation",
|
|
55
|
+
"git-management",
|
|
56
|
+
"branch-strategy",
|
|
57
|
+
"quality-assurance",
|
|
58
|
+
"qa-tools",
|
|
59
|
+
"testing-tools",
|
|
60
|
+
"node",
|
|
61
|
+
"nodejs",
|
|
62
|
+
"npm-package",
|
|
63
|
+
"open-source",
|
|
64
|
+
"lightweight",
|
|
65
|
+
"fast",
|
|
66
|
+
"efficient",
|
|
67
|
+
"zero-dependencies",
|
|
68
|
+
"standalone",
|
|
69
|
+
"easy-setup",
|
|
70
|
+
"easy-to-use",
|
|
71
|
+
"universal"
|
|
72
|
+
],
|
|
73
|
+
"author": {
|
|
74
|
+
"name": "Sanjib Roy",
|
|
75
|
+
"email": "sanjibroy17061995@gmail.com",
|
|
76
|
+
"url": "https://github.com/snbroy",
|
|
77
|
+
"github": "https://github.com/snbroy",
|
|
78
|
+
"linkedin": "https://www.linkedin.com/in/sanjib-r-834947100/",
|
|
79
|
+
"phone": "+91 8918132291"
|
|
80
|
+
},
|
|
81
|
+
"license": "MIT",
|
|
82
|
+
"repository": {
|
|
83
|
+
"type": "git",
|
|
84
|
+
"url": "git+https://github.com/snbroyvfc95/branch-validator-pro.git"
|
|
85
|
+
},
|
|
86
|
+
"bugs": {
|
|
87
|
+
"url": "https://github.com/snbroyvfc95/branch-validator-pro/issues",
|
|
88
|
+
"email": "sanjibroy17061995@gmail.com"
|
|
89
|
+
},
|
|
90
|
+
"homepage": "https://github.com/snbroyvfc95/branch-validator-pro#readme",
|
|
91
|
+
"engines": {
|
|
92
|
+
"node": ">=12.0.0"
|
|
93
|
+
},
|
|
94
|
+
"files": [
|
|
95
|
+
"index.js",
|
|
96
|
+
"cli.js",
|
|
97
|
+
"README.md"
|
|
98
|
+
],
|
|
99
|
+
"preferGlobal": true,
|
|
100
|
+
"dependencies": {
|
|
101
|
+
"dotenv": "^16.3.1"
|
|
102
|
+
},
|
|
103
|
+
"devDependencies": {}
|
|
104
|
+
}
|