@elsikora/git-branch-lint 1.2.1-dev.1 → 1.2.2-dev.1
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.md +3 -15
- package/README.md +131 -241
- package/bin/application/type/branch-placeholder-definition.type.d.ts +7 -0
- package/bin/application/type/build-branch-name-parameters.type.d.ts +4 -0
- package/bin/application/type/get-branch-placeholder-definitions-parameters.type.d.ts +4 -0
- package/bin/application/type/validate-branch-placeholder-value-parameters.type.d.ts +6 -0
- package/bin/application/use-cases/build-branch-name.use-case.d.ts +10 -0
- package/bin/application/use-cases/get-branch-pattern.use-case.d.ts +8 -0
- package/bin/application/use-cases/get-branch-placeholder-definitions.use-case.d.ts +11 -0
- package/bin/application/use-cases/get-current-branch.use-case.d.ts +1 -5
- package/bin/application/use-cases/lint-branch-name.use-case.d.ts +3 -9
- package/bin/application/use-cases/normalize-ticket-id.use-case.d.ts +9 -0
- package/bin/application/use-cases/validate-branch-placeholder-value.use-case.d.ts +8 -0
- package/bin/domain/config/default-branch-lint-config.d.ts +2 -0
- package/bin/domain/constant/branch-pattern.constant.d.ts +1 -0
- package/bin/domain/constant/ticket-id.constant.d.ts +3 -0
- package/bin/domain/errors/lint.error.d.ts +6 -0
- package/bin/domain/policy/branch-template.policy.d.ts +18 -0
- package/bin/domain/policy/ticket-id.policy.d.ts +9 -0
- package/bin/domain/type/branch-subject-pattern.type.d.ts +1 -0
- package/bin/domain/type/input-validation-result.type.d.ts +4 -0
- package/bin/domain/type/rules.type.d.ts +2 -1
- package/bin/index.js +340 -166
- package/bin/index.js.map +1 -1
- package/bin/infrastructure/config/cosmiconfig.repository.d.ts +0 -4
- package/bin/presentation/cli/controllers/create-branch.controller.d.ts +11 -1
- package/bin/presentation/cli/controllers/lint.controller.d.ts +1 -0
- package/bin/presentation/cli/formatters/branch-choice.formatter.d.ts +1 -6
- package/bin/presentation/cli/prompts/branch-creation.prompt.d.ts +8 -11
- package/bin/presentation/cli/type/branch-choice-formatted.type.d.ts +5 -0
- package/bin/presentation/cli/type/branch-placeholder-prompt-options.type.d.ts +6 -0
- package/bin/presentation/cli/type/branch-type-answer.type.d.ts +3 -0
- package/bin/presentation/cli/type/placeholder-answer.type.d.ts +3 -0
- package/bin/presentation/cli/type/push-branch-answer.type.d.ts +3 -0
- package/package.json +28 -28
- package/bin/application/use-cases/check-working-directory-use-case.d.ts +0 -13
- package/bin/application/use-cases/create-branch-use-case.d.ts +0 -14
- package/bin/application/use-cases/validate-branch-name-use-case.d.ts +0 -15
- package/bin/application/use-cases/validate-branch-name.use-case.d.ts +0 -15
package/LICENSE.md
CHANGED
|
@@ -2,20 +2,8 @@ The MIT License (MIT)
|
|
|
2
2
|
|
|
3
3
|
Copyright (c) 2022 Bogdan Kolesnyk (bogdan.kolesnyk@gmail.com)
|
|
4
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:
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
11
6
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
all copies or substantial portions of the Software.
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
14
8
|
|
|
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
|
|
21
|
-
THE SOFTWARE.
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,83 +1,66 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://6jft62zmy9nx2oea.public.blob.vercel-storage.com/git-branch-lint-myXi2xH8jqeEIqScu1S9NymOOJVD9I.png" width="500" alt="project-logo"
|
|
2
|
+
<img src="https://6jft62zmy9nx2oea.public.blob.vercel-storage.com/git-branch-lint-myXi2xH8jqeEIqScu1S9NymOOJVD9I.png" width="500" alt="project-logo" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
<h1 align="center"
|
|
6
|
-
<p align="center"><em>
|
|
5
|
+
<h1 align="center">Git-Branch-Lint</h1>
|
|
6
|
+
<p align="center"><em>CLI tool for consistent, enforceable Git branch naming.</em></p>
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
<a aria-label="ElsiKora logo" href="https://elsikora.com">
|
|
10
|
-
<img src="https://img.shields.io/badge/MADE%20BY%20ElsiKora-333333.svg?style=for-the-badge" alt="ElsiKora">
|
|
11
|
-
</a> <img src="https://img.shields.io/badge/TypeScript-3178C6.svg?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript"> <img src="https://img.shields.io/badge/Node.js-339933.svg?style=for-the-badge&logo=node.js&logoColor=white" alt="Node.js"> <img src="https://img.shields.io/badge/npm-CB3837.svg?style=for-the-badge&logo=npm&logoColor=white" alt="npm"> <img src="https://img.shields.io/badge/ESLint-4B32C3.svg?style=for-the-badge&logo=eslint&logoColor=white" alt="ESLint"> <img src="https://img.shields.io/badge/Prettier-F7B93E.svg?style=for-the-badge&logo=prettier&logoColor=black" alt="Prettier"> <img src="https://img.shields.io/badge/Vitest-6E9F18.svg?style=for-the-badge&logo=vitest&logoColor=white" alt="Vitest"> <img src="https://img.shields.io/badge/Rollup-EC4A3F.svg?style=for-the-badge&logo=rollup&logoColor=white" alt="Rollup"> <img src="https://img.shields.io/badge/Git-F05032.svg?style=for-the-badge&logo=git&logoColor=white" alt="Git"> <img src="https://img.shields.io/badge/GitHub%20Actions-2088FF.svg?style=for-the-badge&logo=github-actions&logoColor=white" alt="GitHub Actions">
|
|
12
|
-
</p>
|
|
8
|
+
## Table Of Contents
|
|
13
9
|
|
|
10
|
+
- [Description](#description)
|
|
11
|
+
- [Features](#features)
|
|
12
|
+
- [Installation](#installation)
|
|
13
|
+
- [Usage](#usage)
|
|
14
|
+
- [Configuration](#configuration)
|
|
15
|
+
- [Clean Architecture Rules](#clean-architecture-rules)
|
|
16
|
+
- [Development](#development)
|
|
17
|
+
- [License](#license)
|
|
14
18
|
|
|
15
|
-
##
|
|
16
|
-
- [Description](#-description)
|
|
17
|
-
- [Features](#-features)
|
|
18
|
-
- [Installation](#-installation)
|
|
19
|
-
- [Usage](#-usage)
|
|
20
|
-
- [Roadmap](#-roadmap)
|
|
21
|
-
- [FAQ](#-faq)
|
|
22
|
-
- [License](#-license)
|
|
19
|
+
## Description
|
|
23
20
|
|
|
21
|
+
`@elsikora/git-branch-lint` validates branch names against team rules and includes an interactive branch-creation flow.
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
Git-Branch-Lint is a powerful, TypeScript-based CLI tool that brings order to your Git workflow by enforcing consistent branch naming conventions across your entire development team. Built with clean architecture principles, it not only validates branch names but also provides an interactive branch creation wizard that guides developers through creating properly formatted branches. Whether you're managing a small project or a large enterprise codebase, Git-Branch-Lint helps maintain a clean, organized repository structure that makes tracking features, fixes, and releases effortless. It seamlessly integrates with Git hooks, CI/CD pipelines, and supports multiple configuration formats, making it the perfect addition to any modern development workflow.
|
|
23
|
+
The project follows layered clean architecture:
|
|
27
24
|
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
- ✨ **📏 **Length Validation** - Set minimum and maximum length constraints to keep branch names concise and meaningful**
|
|
33
|
-
- ✨ **🎨 **Beautiful CLI Output** - Colored terminal output with helpful error messages and hints that guide developers to fix issues quickly**
|
|
34
|
-
- ✨ **⚙️ **Flexible Configuration** - Support for multiple config formats (JS, TS, JSON, YAML) with intelligent config discovery via cosmiconfig**
|
|
35
|
-
- ✨ **🔄 **Git Hooks Ready** - Seamlessly integrate with Husky, lint-staged, or any Git hook manager for automatic validation**
|
|
36
|
-
- ✨ **📦 **Zero Config Option** - Works out of the box with sensible defaults while allowing complete customization when needed**
|
|
37
|
-
- ✨ **🏗️ **Clean Architecture** - Built with Domain-Driven Design principles, making the codebase maintainable and extensible**
|
|
25
|
+
- `domain` - business rules, entities, policies, contracts
|
|
26
|
+
- `application` - use cases and orchestration logic
|
|
27
|
+
- `infrastructure` - adapters (git, config loading)
|
|
28
|
+
- `presentation` - CLI controllers, prompts, formatters
|
|
38
29
|
|
|
39
|
-
##
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- Template-driven branch validation using placeholders (for example `:type/:name` or `:scope/:type/:description`).
|
|
33
|
+
- Optional ticket-id support with pattern `:type/:ticket-:name` (ticket part can be omitted).
|
|
34
|
+
- Interactive branch creation command (`-b` / `--branch`) built directly from configured placeholders.
|
|
35
|
+
- Branch constraints: prohibited names, min/max length, subject regex.
|
|
36
|
+
- Helpful CLI error/hint formatting.
|
|
37
|
+
- Cosmiconfig-based configuration discovery.
|
|
42
38
|
|
|
43
|
-
|
|
39
|
+
## Installation
|
|
44
40
|
|
|
41
|
+
Install as a dev dependency:
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
```bash
|
|
47
44
|
npm install --save-dev @elsikora/git-branch-lint
|
|
45
|
+
```
|
|
48
46
|
|
|
49
|
-
|
|
50
|
-
yarn add -D @elsikora/git-branch-lint
|
|
47
|
+
Or with other package managers:
|
|
51
48
|
|
|
52
|
-
|
|
49
|
+
```bash
|
|
50
|
+
yarn add -D @elsikora/git-branch-lint
|
|
53
51
|
pnpm add -D @elsikora/git-branch-lint
|
|
54
|
-
|
|
55
|
-
# Using bun
|
|
56
52
|
bun add -d @elsikora/git-branch-lint
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
### Global Installation
|
|
60
|
-
|
|
61
|
-
For system-wide usage across multiple projects:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
npm install -g @elsikora/git-branch-lint
|
|
65
53
|
```
|
|
66
54
|
|
|
67
|
-
##
|
|
68
|
-
## 🚀 Usage
|
|
55
|
+
## Usage
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Validate your current Git branch name:
|
|
57
|
+
Validate current branch:
|
|
73
58
|
|
|
74
59
|
```bash
|
|
75
60
|
npx @elsikora/git-branch-lint
|
|
76
61
|
```
|
|
77
62
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
Create a new branch with the interactive wizard:
|
|
63
|
+
Start interactive branch creation:
|
|
81
64
|
|
|
82
65
|
```bash
|
|
83
66
|
npx @elsikora/git-branch-lint -b
|
|
@@ -85,223 +68,130 @@ npx @elsikora/git-branch-lint -b
|
|
|
85
68
|
npx @elsikora/git-branch-lint --branch
|
|
86
69
|
```
|
|
87
70
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
Git-Branch-Lint uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file discovery. Create any of these files:
|
|
91
|
-
|
|
92
|
-
#### JavaScript Configuration (`.elsikora/git-branch-lint.config.js`)
|
|
93
|
-
|
|
94
|
-
```javascript
|
|
95
|
-
export default {
|
|
96
|
-
branches: {
|
|
97
|
-
feature: {
|
|
98
|
-
title: "Feature",
|
|
99
|
-
description: "🆕 New functionality"
|
|
100
|
-
},
|
|
101
|
-
bugfix: {
|
|
102
|
-
title: "Bugfix",
|
|
103
|
-
description: "🐛 Bug fixes"
|
|
104
|
-
},
|
|
105
|
-
hotfix: {
|
|
106
|
-
title: "Hotfix",
|
|
107
|
-
description: "🚑 Urgent production fixes"
|
|
108
|
-
},
|
|
109
|
-
release: {
|
|
110
|
-
title: "Release",
|
|
111
|
-
description: "📦 Release preparation"
|
|
112
|
-
},
|
|
113
|
-
chore: {
|
|
114
|
-
title: "Chore",
|
|
115
|
-
description: "🔧 Maintenance tasks"
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
ignore: ["dev", "develop", "staging"],
|
|
119
|
-
rules: {
|
|
120
|
-
"branch-pattern": ":type/:name",
|
|
121
|
-
"branch-subject-pattern": "[a-z0-9-]+",
|
|
122
|
-
"branch-prohibited": ["main", "master", "prod"],
|
|
123
|
-
"branch-min-length": 5,
|
|
124
|
-
"branch-max-length": 60
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
#### TypeScript Configuration (`.elsikora/git-branch-lint.config.ts`)
|
|
130
|
-
|
|
131
|
-
```typescript
|
|
132
|
-
import type { IBranchLintConfig } from '@elsikora/git-branch-lint';
|
|
133
|
-
|
|
134
|
-
const config: IBranchLintConfig = {
|
|
135
|
-
branches: {
|
|
136
|
-
feat: { title: "Feature", description: "✨ New features" },
|
|
137
|
-
fix: { title: "Fix", description: "🐛 Bug fixes" },
|
|
138
|
-
docs: { title: "Docs", description: "📚 Documentation" },
|
|
139
|
-
style: { title: "Style", description: "💄 Styling" },
|
|
140
|
-
refactor: { title: "Refactor", description: "♻️ Code refactoring" },
|
|
141
|
-
perf: { title: "Performance", description: "⚡ Performance improvements" },
|
|
142
|
-
test: { title: "Test", description: "✅ Testing" },
|
|
143
|
-
build: { title: "Build", description: "📦 Build system" },
|
|
144
|
-
ci: { title: "CI", description: "👷 CI/CD" }
|
|
145
|
-
},
|
|
146
|
-
rules: {
|
|
147
|
-
"branch-pattern": ":type/:name",
|
|
148
|
-
"branch-subject-pattern": "[a-z0-9-]+",
|
|
149
|
-
"branch-min-length": 8,
|
|
150
|
-
"branch-max-length": 72
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
export default config;
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
#### Package.json Configuration
|
|
71
|
+
Behavior notes:
|
|
158
72
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"branch-pattern": ":type/:name",
|
|
166
|
-
"branch-prohibited": ["main", "master"]
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
```
|
|
73
|
+
- When `:ticket` is present in `branch-pattern`, both forms are valid:
|
|
74
|
+
- with ticket: `feature/proj-123-user-authentication`
|
|
75
|
+
- without ticket: `feature/user-authentication`
|
|
76
|
+
- Interactive prompt normalizes ticket-id to lowercase before branch creation.
|
|
77
|
+
- Placeholder prompts are generated from `branch-pattern` in declared order.
|
|
78
|
+
- Validation and branch creation use the same template/pattern rules.
|
|
172
79
|
|
|
173
|
-
|
|
80
|
+
## Configuration
|
|
174
81
|
|
|
175
|
-
|
|
82
|
+
Configuration is loaded via `cosmiconfig` (for example `package.json`, `.elsikora/git-branch-lint.config.js`, `.elsikora/git-branch-lint.config.ts`).
|
|
176
83
|
|
|
177
|
-
|
|
178
|
-
# Install Husky
|
|
179
|
-
npm install --save-dev husky
|
|
180
|
-
|
|
181
|
-
# Initialize Husky
|
|
182
|
-
npx husky init
|
|
84
|
+
Rule semantics:
|
|
183
85
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
86
|
+
- `branch-pattern` defines placeholders with `:placeholder` tokens.
|
|
87
|
+
- Placeholder naming supports lowercase letters, digits, and hyphens (for example `:jira-ticket`).
|
|
88
|
+
- `:type` is validated against configured `branches`.
|
|
89
|
+
- `branch-subject-pattern` supports:
|
|
90
|
+
- `string` - shared regex for all non-`type` placeholders.
|
|
91
|
+
- `object` - regex per placeholder key (for example `scope`, `description`, `ticket`).
|
|
92
|
+
- Optional placeholders are supported when the token is followed by `-` in `branch-pattern` (for example `:ticket-`).
|
|
93
|
+
- Before branch creation, the final assembled name is validated again with full lint rules.
|
|
187
94
|
|
|
188
|
-
|
|
95
|
+
### JavaScript Example
|
|
189
96
|
|
|
190
97
|
```javascript
|
|
191
|
-
// lint-staged.config.js
|
|
192
98
|
export default {
|
|
193
|
-
|
|
99
|
+
branches: {
|
|
100
|
+
feature: { title: "Feature", description: "New functionality" },
|
|
101
|
+
bugfix: { title: "Bugfix", description: "Bug fixes" },
|
|
102
|
+
hotfix: { title: "Hotfix", description: "Urgent fixes" },
|
|
103
|
+
},
|
|
104
|
+
ignore: ["dev"],
|
|
105
|
+
rules: {
|
|
106
|
+
"branch-pattern": ":type/:ticket-:name",
|
|
107
|
+
"branch-subject-pattern": "[a-z0-9-]+",
|
|
108
|
+
"branch-prohibited": ["main", "master", "release"],
|
|
109
|
+
"branch-min-length": 5,
|
|
110
|
+
"branch-max-length": 50,
|
|
111
|
+
},
|
|
194
112
|
};
|
|
195
113
|
```
|
|
196
114
|
|
|
197
|
-
###
|
|
198
|
-
|
|
199
|
-
#### GitHub Actions
|
|
115
|
+
### Advanced Placeholder Example
|
|
200
116
|
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
node-version: '20'
|
|
213
|
-
- run: npm ci
|
|
214
|
-
- run: npx @elsikora/git-branch-lint
|
|
117
|
+
```javascript
|
|
118
|
+
export default {
|
|
119
|
+
branches: ["feat", "fix", "chore"],
|
|
120
|
+
rules: {
|
|
121
|
+
"branch-pattern": ":scope/:type/:description",
|
|
122
|
+
"branch-subject-pattern": {
|
|
123
|
+
scope: "(web|api|shared)",
|
|
124
|
+
description: "[a-z0-9-]+",
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
};
|
|
215
128
|
```
|
|
216
129
|
|
|
217
|
-
|
|
130
|
+
Valid branch example: `web/feat/shopping-cart`.
|
|
218
131
|
|
|
219
|
-
|
|
220
|
-
branch-lint:
|
|
221
|
-
stage: test
|
|
222
|
-
script:
|
|
223
|
-
- npm ci
|
|
224
|
-
- npx @elsikora/git-branch-lint
|
|
225
|
-
only:
|
|
226
|
-
- branches
|
|
227
|
-
```
|
|
132
|
+
### TypeScript Example
|
|
228
133
|
|
|
229
|
-
|
|
134
|
+
```typescript
|
|
135
|
+
import type { IBranchLintConfig } from "@elsikora/git-branch-lint";
|
|
230
136
|
|
|
231
|
-
|
|
137
|
+
const config: IBranchLintConfig = {
|
|
138
|
+
branches: {
|
|
139
|
+
feature: { title: "Feature", description: "New functionality" },
|
|
140
|
+
bugfix: { title: "Bugfix", description: "Bug fixes" },
|
|
141
|
+
hotfix: { title: "Hotfix", description: "Urgent fixes" },
|
|
142
|
+
},
|
|
143
|
+
ignore: ["dev"],
|
|
144
|
+
rules: {
|
|
145
|
+
"branch-pattern": ":type/:ticket-:name",
|
|
146
|
+
"branch-subject-pattern": "[a-z0-9-]+",
|
|
147
|
+
"branch-prohibited": ["main", "master", "release"],
|
|
148
|
+
"branch-min-length": 5,
|
|
149
|
+
"branch-max-length": 50,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
232
152
|
|
|
233
|
-
|
|
234
|
-
{
|
|
235
|
-
rules: {
|
|
236
|
-
"branch-pattern": ":type/:ticket-:description",
|
|
237
|
-
"branch-subject-pattern": {
|
|
238
|
-
"ticket": "[a-z]{2,}-[0-9]+",
|
|
239
|
-
"description": "[a-z0-9-]+"
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
// Valid: feature/proj-123-user-authentication
|
|
153
|
+
export default config;
|
|
244
154
|
```
|
|
245
155
|
|
|
246
|
-
|
|
156
|
+
### `package.json` Example
|
|
247
157
|
|
|
248
|
-
```
|
|
158
|
+
```json
|
|
249
159
|
{
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
160
|
+
"elsikora": {
|
|
161
|
+
"git-branch-lint": {
|
|
162
|
+
"branches": ["feature", "bugfix", "hotfix"],
|
|
163
|
+
"rules": {
|
|
164
|
+
"branch-pattern": ":type/:ticket-:name",
|
|
165
|
+
"branch-subject-pattern": "[a-z0-9-]+",
|
|
166
|
+
"branch-prohibited": ["main", "master", "release"]
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
258
170
|
}
|
|
259
|
-
// Valid: web/feat/shopping-cart
|
|
260
171
|
```
|
|
261
172
|
|
|
262
|
-
##
|
|
263
|
-
| Task / Feature | Status |
|
|
264
|
-
|----------------|--------|
|
|
265
|
-
| Core branch validation engine | ✅ Done |
|
|
266
|
-
| Interactive branch creation wizard | ✅ Done |
|
|
267
|
-
| Multiple configuration format support | ✅ Done |
|
|
268
|
-
| TypeScript support | ✅ Done |
|
|
269
|
-
| Comprehensive test coverage | ✅ Done |
|
|
270
|
-
| VS Code extension | 🚧 In Progress |
|
|
271
|
-
| Branch name auto-suggestions | 🚧 In Progress |
|
|
272
|
-
| Custom validation rules plugin system | 🚧 In Progress |
|
|
273
|
-
| Branch naming statistics dashboard | 🚧 In Progress |
|
|
274
|
-
| Integration with popular Git GUIs | 🚧 In Progress |
|
|
275
|
-
| AI-powered branch name generator | 🚧 In Progress |
|
|
276
|
-
|
|
277
|
-
## ❓ FAQ
|
|
278
|
-
## ❓ Frequently Asked Questions
|
|
279
|
-
|
|
280
|
-
### **Q: Can I use this with existing branches?**
|
|
281
|
-
A: Yes! The `ignore` configuration option allows you to exclude existing branches from validation. This is perfect for grandfathering in old branches while enforcing rules on new ones.
|
|
282
|
-
|
|
283
|
-
### **Q: How do I handle different patterns for different teams?**
|
|
284
|
-
A: You can create team-specific configuration files and use environment variables or Git config to load the appropriate one:
|
|
285
|
-
```bash
|
|
286
|
-
GIT_BRANCH_LINT_CONFIG=.team-frontend.config.js npx @elsikora/git-branch-lint
|
|
287
|
-
```
|
|
173
|
+
## Clean Architecture Rules
|
|
288
174
|
|
|
289
|
-
|
|
290
|
-
A: While we're working on official IDE extensions, you can configure your IDE to run the validation as an external tool or use it with pre-commit hooks.
|
|
175
|
+
Repository standards enforced in this codebase:
|
|
291
176
|
|
|
292
|
-
|
|
293
|
-
|
|
177
|
+
- Business rules live in `domain` and are consumed via `application` use cases.
|
|
178
|
+
- `presentation` does I/O only; it must not own business validation rules.
|
|
179
|
+
- `infrastructure` contains adapters only; default domain rules are defined outside adapter implementation.
|
|
180
|
+
- `application` depends on domain contracts, not concrete infrastructure classes.
|
|
181
|
+
- Types/interfaces are extracted into dedicated type/interface files for reusable contracts.
|
|
182
|
+
- Import order and class member ordering are lint-enforced and must remain consistent.
|
|
294
183
|
|
|
295
|
-
|
|
296
|
-
A: Absolutely! The `branch-subject-pattern` rule accepts any valid JavaScript regex pattern, giving you complete control over validation.
|
|
184
|
+
## Development
|
|
297
185
|
|
|
298
|
-
|
|
299
|
-
A: Yes! The default configuration works well with both workflows, and you can easily customize it to match your specific flow requirements.
|
|
186
|
+
Common scripts:
|
|
300
187
|
|
|
301
|
-
|
|
302
|
-
|
|
188
|
+
```bash
|
|
189
|
+
npm run lint
|
|
190
|
+
npm run lint:types
|
|
191
|
+
npm run test:unit
|
|
192
|
+
npm run test:e2e
|
|
193
|
+
```
|
|
303
194
|
|
|
304
|
-
##
|
|
305
|
-
This project is licensed under **MIT License - see the [LICENSE](LICENSE) file for details.
|
|
195
|
+
## License
|
|
306
196
|
|
|
307
|
-
|
|
197
|
+
MIT. See [`LICENSE`](LICENSE).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { IBuildBranchNameParameters } from "../type/build-branch-name-parameters.type";
|
|
2
|
+
import { BranchTemplatePolicy } from "../../domain/policy/branch-template.policy";
|
|
3
|
+
/**
|
|
4
|
+
* Use case for assembling a branch name from validated user inputs.
|
|
5
|
+
*/
|
|
6
|
+
export declare class BuildBranchNameUseCase {
|
|
7
|
+
private readonly branchTemplatePolicy;
|
|
8
|
+
constructor(branchTemplatePolicy?: BranchTemplatePolicy);
|
|
9
|
+
execute(parameters: IBuildBranchNameParameters): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IBranchLintConfig } from "../../domain/type/config.type";
|
|
2
|
+
/**
|
|
3
|
+
* Use case for retrieving effective branch pattern.
|
|
4
|
+
*/
|
|
5
|
+
export declare class GetBranchPatternUseCase {
|
|
6
|
+
private readonly DEFAULT_BRANCH_PATTERN;
|
|
7
|
+
execute(config: IBranchLintConfig): string;
|
|
8
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IBranchPlaceholderDefinition } from "../type/branch-placeholder-definition.type";
|
|
2
|
+
import type { IGetBranchPlaceholderDefinitionsParameters } from "../type/get-branch-placeholder-definitions-parameters.type";
|
|
3
|
+
import { BranchTemplatePolicy } from "../../domain/policy/branch-template.policy";
|
|
4
|
+
/**
|
|
5
|
+
* Use case for resolving placeholder definitions from branch pattern config.
|
|
6
|
+
*/
|
|
7
|
+
export declare class GetBranchPlaceholderDefinitionsUseCase {
|
|
8
|
+
private readonly branchTemplatePolicy;
|
|
9
|
+
constructor(branchTemplatePolicy?: BranchTemplatePolicy);
|
|
10
|
+
execute(parameters: IGetBranchPlaceholderDefinitionsParameters): Array<IBranchPlaceholderDefinition>;
|
|
11
|
+
}
|
|
@@ -3,11 +3,7 @@ import type { IBranchRepository } from "../../domain/interface/branch.repository
|
|
|
3
3
|
* Use case for getting the current branch name
|
|
4
4
|
*/
|
|
5
5
|
export declare class GetCurrentBranchUseCase {
|
|
6
|
-
private readonly
|
|
7
|
-
/**
|
|
8
|
-
* Constructor
|
|
9
|
-
* @param branchRepository The branch repository
|
|
10
|
-
*/
|
|
6
|
+
private readonly branchRepository;
|
|
11
7
|
constructor(branchRepository: IBranchRepository);
|
|
12
8
|
/**
|
|
13
9
|
* Execute the use case
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { IBranchLintConfig } from "../../domain/type/config.type";
|
|
2
|
+
import { BranchTemplatePolicy } from "../../domain/policy/branch-template.policy";
|
|
2
3
|
/**
|
|
3
4
|
* Use case for linting branch names
|
|
4
5
|
*/
|
|
5
6
|
export declare class LintBranchNameUseCase {
|
|
7
|
+
private readonly BRANCH_TEMPLATE_POLICY;
|
|
8
|
+
constructor(branchTemplatePolicy?: BranchTemplatePolicy);
|
|
6
9
|
/**
|
|
7
10
|
* Execute the use case
|
|
8
11
|
* @param branchName The branch name to lint
|
|
@@ -13,15 +16,6 @@ export declare class LintBranchNameUseCase {
|
|
|
13
16
|
* @throws {BranchTooLongError} When branch name is longer than the maximum length
|
|
14
17
|
*/
|
|
15
18
|
execute(branchName: string, config: IBranchLintConfig): void;
|
|
16
|
-
/**
|
|
17
|
-
* Test a branch name against a specific pattern
|
|
18
|
-
* @param branchName The branch name to test
|
|
19
|
-
* @param pattern The pattern to test against
|
|
20
|
-
* @param branchTypes Available branch types
|
|
21
|
-
* @param subjectNamePattern Pattern for the name/description part
|
|
22
|
-
* @returns true if pattern matches
|
|
23
|
-
*/
|
|
24
|
-
private testPattern;
|
|
25
19
|
/**
|
|
26
20
|
* Validate the branch name against the pattern
|
|
27
21
|
* @param branchName The branch name to validate
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { TicketIdPolicy } from "../../domain/policy/ticket-id.policy";
|
|
2
|
+
/**
|
|
3
|
+
* Use case for normalizing optional ticket identifier input.
|
|
4
|
+
*/
|
|
5
|
+
export declare class NormalizeTicketIdUseCase {
|
|
6
|
+
private readonly ticketIdPolicy;
|
|
7
|
+
constructor(ticketIdPolicy?: TicketIdPolicy);
|
|
8
|
+
execute(ticketId: string): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IInputValidationResult } from "../../domain/type/input-validation-result.type";
|
|
2
|
+
import type { IValidateBranchPlaceholderValueParameters } from "../type/validate-branch-placeholder-value-parameters.type";
|
|
3
|
+
/**
|
|
4
|
+
* Use case for validating interactive placeholder values.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ValidateBranchPlaceholderValueUseCase {
|
|
7
|
+
execute(parameters: IValidateBranchPlaceholderValueParameters): IInputValidationResult;
|
|
8
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_BRANCH_SUBJECT_PATTERN_SOURCE: string;
|
|
@@ -16,6 +16,12 @@ export declare class BranchTooLongError extends LintError {
|
|
|
16
16
|
export declare class BranchTooShortError extends LintError {
|
|
17
17
|
constructor(branchName: string, minLength: number);
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Error thrown when a branch placeholder pattern in config is invalid.
|
|
21
|
+
*/
|
|
22
|
+
export declare class InvalidBranchPatternConfigError extends LintError {
|
|
23
|
+
constructor(placeholderName: string, patternSource: string);
|
|
24
|
+
}
|
|
19
25
|
/**
|
|
20
26
|
* Error thrown when branch name doesn't match the pattern
|
|
21
27
|
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TBranchSubjectPattern } from "../type/branch-subject-pattern.type";
|
|
2
|
+
/**
|
|
3
|
+
* Domain policy for working with branch templates and placeholders.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BranchTemplatePolicy {
|
|
6
|
+
private static readonly PLACEHOLDER_PATTERN;
|
|
7
|
+
buildBranchName(branchPattern: string, placeholderValues: Record<string, string>): string;
|
|
8
|
+
buildValidationPatterns(branchPattern: string): Array<string>;
|
|
9
|
+
getPlaceholders(branchPattern: string): Array<string>;
|
|
10
|
+
isPlaceholderOptional(branchPattern: string, placeholderName: string): boolean;
|
|
11
|
+
resolvePlaceholderPatternSource(placeholderName: string, branchTypes: Array<string>, subjectPattern?: TBranchSubjectPattern): string;
|
|
12
|
+
private createAlternationPattern;
|
|
13
|
+
private escapeRegex;
|
|
14
|
+
private isDelimiter;
|
|
15
|
+
private normalizeBranchNameDelimiters;
|
|
16
|
+
private removeOptionalPlaceholder;
|
|
17
|
+
private trimDelimiterEdges;
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Domain policy for ticket identifier normalization and validation.
|
|
3
|
+
*/
|
|
4
|
+
export declare class TicketIdPolicy {
|
|
5
|
+
private static readonly TICKET_ID_PATTERN;
|
|
6
|
+
isEmpty(candidate: string): boolean;
|
|
7
|
+
isValid(candidate: string): boolean;
|
|
8
|
+
normalize(candidate: string): string;
|
|
9
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type TBranchSubjectPattern = Record<string, string> | string;
|