@gracefullight/validate-branch 1.1.0 → 1.1.2
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/README.ko.md +470 -0
- package/README.md +131 -131
- package/dist/cli.js +47 -41
- package/dist/index.js +46 -40
- package/package.json +21 -12
- package/README.en.md +0 -470
package/dist/index.js
CHANGED
|
@@ -1,7 +1,50 @@
|
|
|
1
|
+
// src/load-config.ts
|
|
2
|
+
import { readFile } from "fs/promises";
|
|
3
|
+
import { resolve } from "path";
|
|
4
|
+
import { cwd } from "process";
|
|
5
|
+
import { pathToFileURL } from "url";
|
|
6
|
+
var CONFIG_FILES = [
|
|
7
|
+
"branch.config.ts",
|
|
8
|
+
"branch.config.mts",
|
|
9
|
+
"branch.config.js",
|
|
10
|
+
"branch.config.cjs",
|
|
11
|
+
"branch.config.mjs"
|
|
12
|
+
];
|
|
13
|
+
async function loadConfig() {
|
|
14
|
+
for (const file of CONFIG_FILES) {
|
|
15
|
+
const configPath = resolve(cwd(), file);
|
|
16
|
+
try {
|
|
17
|
+
await readFile(configPath, "utf-8");
|
|
18
|
+
if (file.endsWith(".ts") || file.endsWith(".mts") || file.endsWith(".mjs")) {
|
|
19
|
+
const fileUrl = pathToFileURL(configPath);
|
|
20
|
+
fileUrl.searchParams.set("ts", Date.now().toString());
|
|
21
|
+
const { default: config } = await import(
|
|
22
|
+
/* @vite-ignore */
|
|
23
|
+
fileUrl.href
|
|
24
|
+
);
|
|
25
|
+
return config;
|
|
26
|
+
}
|
|
27
|
+
if (file.endsWith(".js") || file.endsWith(".cjs")) {
|
|
28
|
+
const fileUrl = pathToFileURL(configPath);
|
|
29
|
+
const { default: config } = await import(
|
|
30
|
+
/* @vite-ignore */
|
|
31
|
+
fileUrl.href
|
|
32
|
+
);
|
|
33
|
+
return config;
|
|
34
|
+
}
|
|
35
|
+
} catch (error) {
|
|
36
|
+
if (error.code !== "ENOENT") {
|
|
37
|
+
console.error(`Error loading config file ${file}:`, error);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
1
44
|
// src/validate-branch-name.ts
|
|
2
|
-
import * as git from "isomorphic-git";
|
|
3
45
|
import * as fs from "fs";
|
|
4
|
-
import { cwd } from "process";
|
|
46
|
+
import { cwd as cwd2 } from "process";
|
|
47
|
+
import * as git from "isomorphic-git";
|
|
5
48
|
var GITFLOW_PATTERN = /^(main|master|develop|stage|feature\/[A-Za-z0-9_-]+|fix\/[A-Za-z0-9_-]+|hotfix\/[A-Za-z0-9_-]+|release\/[A-Za-z0-9_.-]+)$/;
|
|
6
49
|
var JIRA_PATTERN = /^(main|master|develop|stage|[A-Z]+-[0-9]+)$/;
|
|
7
50
|
function validateBranchName(branchName, options) {
|
|
@@ -16,7 +59,7 @@ async function getCurrentBranchName() {
|
|
|
16
59
|
try {
|
|
17
60
|
const branch = await git.currentBranch({
|
|
18
61
|
fs,
|
|
19
|
-
dir:
|
|
62
|
+
dir: cwd2(),
|
|
20
63
|
fullname: false
|
|
21
64
|
});
|
|
22
65
|
return branch ?? null;
|
|
@@ -47,43 +90,6 @@ function validateWithDetails(branchName, options) {
|
|
|
47
90
|
error: `Branch name "${branchName}" does not match pattern: ${pattern.source}`
|
|
48
91
|
};
|
|
49
92
|
}
|
|
50
|
-
|
|
51
|
-
// src/load-config.ts
|
|
52
|
-
import { readFile } from "fs/promises";
|
|
53
|
-
import { resolve } from "path";
|
|
54
|
-
import { cwd as cwd2 } from "process";
|
|
55
|
-
var CONFIG_FILES = [
|
|
56
|
-
"branch.config.ts",
|
|
57
|
-
"branch.config.mts",
|
|
58
|
-
"branch.config.js",
|
|
59
|
-
"branch.config.cjs",
|
|
60
|
-
"branch.config.mjs"
|
|
61
|
-
];
|
|
62
|
-
async function loadConfig() {
|
|
63
|
-
for (const file of CONFIG_FILES) {
|
|
64
|
-
const configPath = resolve(cwd2(), file);
|
|
65
|
-
try {
|
|
66
|
-
await readFile(configPath, "utf-8");
|
|
67
|
-
if (file.endsWith(".ts") || file.endsWith(".mts")) {
|
|
68
|
-
const { default: config } = await import(`file://${configPath}?ts=${Date.now()}`);
|
|
69
|
-
return config;
|
|
70
|
-
}
|
|
71
|
-
if (file.endsWith(".mjs")) {
|
|
72
|
-
const { default: config } = await import(`file://${configPath}?ts=${Date.now()}`);
|
|
73
|
-
return config;
|
|
74
|
-
}
|
|
75
|
-
if (file.endsWith(".js") || file.endsWith(".cjs")) {
|
|
76
|
-
const { default: config } = await import(configPath);
|
|
77
|
-
return config;
|
|
78
|
-
}
|
|
79
|
-
} catch (error) {
|
|
80
|
-
if (error.code !== "ENOENT") {
|
|
81
|
-
console.error(`Error loading config file ${file}:`, error);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
93
|
export {
|
|
88
94
|
getCurrentBranchName,
|
|
89
95
|
loadConfig,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gracefullight/validate-branch",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Git branch name validation tool with custom regexp support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,7 +23,16 @@
|
|
|
23
23
|
"git",
|
|
24
24
|
"branch",
|
|
25
25
|
"validation",
|
|
26
|
-
"cli"
|
|
26
|
+
"cli",
|
|
27
|
+
"git-hooks",
|
|
28
|
+
"lint",
|
|
29
|
+
"naming-convention",
|
|
30
|
+
"workflow",
|
|
31
|
+
"ci",
|
|
32
|
+
"gitflow",
|
|
33
|
+
"husky",
|
|
34
|
+
"standard",
|
|
35
|
+
"quality-control"
|
|
27
36
|
],
|
|
28
37
|
"author": {
|
|
29
38
|
"name": "Eunkwang Shin",
|
|
@@ -31,12 +40,12 @@
|
|
|
31
40
|
},
|
|
32
41
|
"repository": {
|
|
33
42
|
"type": "git",
|
|
34
|
-
"url": "https://github.com/gracefullight/
|
|
43
|
+
"url": "https://github.com/gracefullight/pkgs.git",
|
|
35
44
|
"directory": "packages/validate-branch"
|
|
36
45
|
},
|
|
37
|
-
"homepage": "https://github.com/gracefullight/
|
|
46
|
+
"homepage": "https://github.com/gracefullight/pkgs/tree/main/packages/validate-branch#readme",
|
|
38
47
|
"bugs": {
|
|
39
|
-
"url": "https://github.com/gracefullight/
|
|
48
|
+
"url": "https://github.com/gracefullight/pkgs/issues"
|
|
40
49
|
},
|
|
41
50
|
"license": "MIT",
|
|
42
51
|
"funding": {
|
|
@@ -47,16 +56,16 @@
|
|
|
47
56
|
"access": "public"
|
|
48
57
|
},
|
|
49
58
|
"devDependencies": {
|
|
50
|
-
"@types/node": "^24.10.
|
|
59
|
+
"@types/node": "^24.10.9",
|
|
51
60
|
"tsup": "^8.5.1",
|
|
52
|
-
"tsx": "^4.
|
|
53
|
-
"typescript": "^5
|
|
54
|
-
"vitest": "^4.0.
|
|
61
|
+
"tsx": "^4.21.0",
|
|
62
|
+
"typescript": "^5",
|
|
63
|
+
"vitest": "^4.0.17"
|
|
55
64
|
},
|
|
56
65
|
"dependencies": {
|
|
57
|
-
"chalk": "^5.
|
|
58
|
-
"commander": "^
|
|
59
|
-
"isomorphic-git": "^1.
|
|
66
|
+
"chalk": "^5.6.2",
|
|
67
|
+
"commander": "^14.0.2",
|
|
68
|
+
"isomorphic-git": "^1.36.1"
|
|
60
69
|
},
|
|
61
70
|
"scripts": {
|
|
62
71
|
"build": "tsup",
|
package/README.en.md
DELETED
|
@@ -1,470 +0,0 @@
|
|
|
1
|
-
# @gracefullight/validate-branch
|
|
2
|
-
|
|
3
|
-
> Git branch name validation tool with custom regexp support
|
|
4
|
-
|
|
5
|
-
[](https://www.npmjs.com/package/@gracefullight/validate-branch)
|
|
6
|
-
[](https://opensource.org/licenses/MIT)
|
|
7
|
-
|
|
8
|
-
[한국어](./README.md) | **English**
|
|
9
|
-
|
|
10
|
-
## Features
|
|
11
|
-
|
|
12
|
-
- **Flexible Regular Expression Pattern** - Use default pattern or custom regular expression
|
|
13
|
-
- **Current Branch Detection** - Automatically detect current branch name from Git repository
|
|
14
|
-
- **Config File Support** - Load patterns from `branch.config.{ts,js,mjs}` files
|
|
15
|
-
- **CLI Tool** - Use directly from command line
|
|
16
|
-
- **Detailed Error Messages** - Clear error descriptions on validation failure
|
|
17
|
-
- **Full TypeScript Support** - Complete TypeScript type definitions
|
|
18
|
-
|
|
19
|
-
## Default Pattern
|
|
20
|
-
|
|
21
|
-
By default, the following branch names are allowed:
|
|
22
|
-
|
|
23
|
-
- `main` / `master` - Main branches
|
|
24
|
-
- `develop` / `stage` - Development/staging branches
|
|
25
|
-
- `feature/.*` - Feature branches (e.g., `feature/login`, `feature/user-auth`)
|
|
26
|
-
- `fix/.*` - Bug fix branches (e.g., `fix/memory-leak`, `fix/typo`)
|
|
27
|
-
- `hotfix/.*` - Hotfix branches (e.g., `hotfix/critical-bug`)
|
|
28
|
-
- `release/.*` - Release branches (e.g., `release/v1.0.0`)
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
# Using pnpm
|
|
34
|
-
pnpm add @gracefullight/validate-branch
|
|
35
|
-
|
|
36
|
-
# Using npm
|
|
37
|
-
npm install @gracefullight/validate-branch
|
|
38
|
-
|
|
39
|
-
# Using yarn
|
|
40
|
-
yarn add @gracefullight/validate-branch
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
## Usage
|
|
44
|
-
|
|
45
|
-
### CLI Usage
|
|
46
|
-
|
|
47
|
-
```bash
|
|
48
|
-
# Validate current branch
|
|
49
|
-
npx validate-branch
|
|
50
|
-
|
|
51
|
-
# Validate specific branch
|
|
52
|
-
npx validate-branch --test feature/new-feature
|
|
53
|
-
|
|
54
|
-
# Use custom regular expression
|
|
55
|
-
npx validate-branch --regexp "^(main|develop|feature/.+)$"
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### Programmatic Usage
|
|
59
|
-
|
|
60
|
-
#### Validate with Default Pattern
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { validateBranchName, validateWithDetails } from "@gracefullight/validate-branch";
|
|
64
|
-
|
|
65
|
-
// Simple boolean return
|
|
66
|
-
const isValid = validateBranchName("feature/new-component");
|
|
67
|
-
console.log(isValid); // true
|
|
68
|
-
|
|
69
|
-
// Detailed result return
|
|
70
|
-
const result = validateWithDetails("feature/new-component");
|
|
71
|
-
console.log(result);
|
|
72
|
-
// { valid: true, branchName: "feature/new-component" }
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
#### Validate with Custom Regexp
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
import { validateBranchName } from "@gracefullight/validate-branch";
|
|
79
|
-
|
|
80
|
-
const customPattern = "^(main|develop|story/.+|bugfix/.+)$";
|
|
81
|
-
const isValid = validateBranchName("story/US-123-add-user", { customRegexp: customPattern });
|
|
82
|
-
console.log(isValid); // true
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
#### Get Current Branch Name
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
import { getCurrentBranchName } from "@gracefullight/validate-branch";
|
|
89
|
-
|
|
90
|
-
const currentBranch = await getCurrentBranchName();
|
|
91
|
-
console.log(currentBranch); // "feature/new-component" or null
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
#### Load Config File
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
import { loadConfig } from "@gracefullight/validate-branch";
|
|
98
|
-
|
|
99
|
-
const config = await loadConfig();
|
|
100
|
-
console.log(config);
|
|
101
|
-
// {
|
|
102
|
-
// pattern: "^(main|develop|feature/.+)$",
|
|
103
|
-
// description: "Project branch naming rules"
|
|
104
|
-
// }
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Configuration File
|
|
108
|
-
|
|
109
|
-
Create a `branch.config.ts` or `branch.config.js` file in your project root to define custom patterns.
|
|
110
|
-
|
|
111
|
-
### TypeScript Config (`branch.config.ts`)
|
|
112
|
-
|
|
113
|
-
```typescript
|
|
114
|
-
import type { Config } from "@gracefullight/validate-branch";
|
|
115
|
-
|
|
116
|
-
const config: Config = {
|
|
117
|
-
pattern: "^(main|develop|feature/.+|fix/.+|refactor/.+)$",
|
|
118
|
-
description: "Project branch naming rules",
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
export default config;
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### JavaScript Config (`branch.config.js`)
|
|
125
|
-
|
|
126
|
-
```javascript
|
|
127
|
-
module.exports = {
|
|
128
|
-
pattern: "^(main|develop|feature/.+|fix/.+)$",
|
|
129
|
-
description: "Project branch naming rules",
|
|
130
|
-
};
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Using Presets (`branch.config.ts`)
|
|
134
|
-
|
|
135
|
-
You can use built-in presets instead of custom patterns.
|
|
136
|
-
|
|
137
|
-
```typescript
|
|
138
|
-
import type { Config } from "@gracefullight/validate-branch";
|
|
139
|
-
|
|
140
|
-
const config: Config = {
|
|
141
|
-
preset: "jira", // "gitflow" or "jira"
|
|
142
|
-
description: "JIRA ticket-based branch naming",
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
export default config;
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
**Available Presets:**
|
|
149
|
-
|
|
150
|
-
#### `gitflow` (default)
|
|
151
|
-
|
|
152
|
-
Pattern following Git Flow branching strategy.
|
|
153
|
-
|
|
154
|
-
| Status | Branch Examples |
|
|
155
|
-
|--------|-----------------|
|
|
156
|
-
| ✅ Allowed | `main`, `master`, `develop`, `stage` |
|
|
157
|
-
| ✅ Allowed | `feature/login`, `feature/user-auth`, `feature/add-payment` |
|
|
158
|
-
| ✅ Allowed | `fix/memory-leak`, `fix/typo`, `fix/null-pointer` |
|
|
159
|
-
| ✅ Allowed | `hotfix/critical-bug`, `hotfix/security-patch` |
|
|
160
|
-
| ✅ Allowed | `release/v1.0.0`, `release/2.3.1` |
|
|
161
|
-
| ❌ Rejected | `login`, `bugfix`, `my-branch` (no prefix) |
|
|
162
|
-
| ❌ Rejected | `feature/`, `fix/` (no name) |
|
|
163
|
-
| ❌ Rejected | `Feature/Login`, `FIX/bug` (uppercase prefix) |
|
|
164
|
-
|
|
165
|
-
#### `jira`
|
|
166
|
-
|
|
167
|
-
JIRA ticket number-based branch pattern.
|
|
168
|
-
|
|
169
|
-
| Status | Branch Examples |
|
|
170
|
-
|--------|-----------------|
|
|
171
|
-
| ✅ Allowed | `main`, `master`, `develop`, `stage` |
|
|
172
|
-
| ✅ Allowed | `FEATURE-123`, `FEATURE-1`, `FEATURE-99999` |
|
|
173
|
-
| ✅ Allowed | `BUG-456`, `STORY-789`, `TASK-101`, `HOTFIX-202` |
|
|
174
|
-
| ❌ Rejected | `feature/login` (gitflow style) |
|
|
175
|
-
| ❌ Rejected | `FEATURE-ABC` (not a number) |
|
|
176
|
-
| ❌ Rejected | `feature-123` (lowercase) |
|
|
177
|
-
| ❌ Rejected | `JIRA-123/description` (contains slash) |
|
|
178
|
-
|
|
179
|
-
## API Reference
|
|
180
|
-
|
|
181
|
-
### `validateBranchName(branchName, options?)`
|
|
182
|
-
|
|
183
|
-
Check if a branch name is valid.
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
interface ValidateBranchNameOptions {
|
|
187
|
-
customRegexp?: string;
|
|
188
|
-
preset?: "gitflow" | "jira";
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function validateBranchName(
|
|
192
|
-
branchName: string,
|
|
193
|
-
options?: ValidateBranchNameOptions
|
|
194
|
-
): boolean
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**Parameters:**
|
|
198
|
-
- `branchName`: Branch name to validate
|
|
199
|
-
- `options`: Optional, validation options object
|
|
200
|
-
- `customRegexp`: Custom regular expression string
|
|
201
|
-
- `preset`: Preset pattern (`gitflow` or `jira`, default: `gitflow`)
|
|
202
|
-
|
|
203
|
-
**Returns:** Validity status
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
### `validateWithDetails(branchName, options?)`
|
|
208
|
-
|
|
209
|
-
Return detailed validation result.
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
function validateWithDetails(
|
|
213
|
-
branchName: string,
|
|
214
|
-
options?: ValidateBranchNameOptions
|
|
215
|
-
): ValidationResult
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
**Returns:**
|
|
219
|
-
```typescript
|
|
220
|
-
{
|
|
221
|
-
valid: boolean;
|
|
222
|
-
branchName: string;
|
|
223
|
-
error?: string; // Error message on failure
|
|
224
|
-
}
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
**Example:**
|
|
228
|
-
```typescript
|
|
229
|
-
const result = validateWithDetails("invalid-branch");
|
|
230
|
-
// {
|
|
231
|
-
// valid: false,
|
|
232
|
-
// branchName: "invalid-branch",
|
|
233
|
-
// error: 'Branch name "invalid-branch" does not match pattern: /^(main|master|...)$/'
|
|
234
|
-
// }
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
---
|
|
238
|
-
|
|
239
|
-
### `getCurrentBranchName()`
|
|
240
|
-
|
|
241
|
-
Get current Git branch name.
|
|
242
|
-
|
|
243
|
-
```typescript
|
|
244
|
-
function getCurrentBranchName(): Promise<string | null>
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
**Returns:** Current branch name, `null` if not in a Git repository
|
|
248
|
-
|
|
249
|
-
---
|
|
250
|
-
|
|
251
|
-
### `loadConfig()`
|
|
252
|
-
|
|
253
|
-
Load project configuration file.
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
function loadConfig(): Promise<Config | null>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
**Config file search order:**
|
|
260
|
-
1. `branch.config.ts`
|
|
261
|
-
2. `branch.config.mts`
|
|
262
|
-
3. `branch.config.js`
|
|
263
|
-
4. `branch.config.cjs`
|
|
264
|
-
5. `branch.config.mjs`
|
|
265
|
-
|
|
266
|
-
**Returns:** Configuration object, `null` if no config file exists
|
|
267
|
-
|
|
268
|
-
---
|
|
269
|
-
|
|
270
|
-
## Type Definitions
|
|
271
|
-
|
|
272
|
-
### `Config`
|
|
273
|
-
|
|
274
|
-
```typescript
|
|
275
|
-
interface Config {
|
|
276
|
-
pattern?: string; // Single regex pattern
|
|
277
|
-
patterns?: string[]; // Multiple regex patterns (planned)
|
|
278
|
-
preset?: "gitflow" | "jira"; // Preset pattern (default: "gitflow")
|
|
279
|
-
description?: string; // Config description
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
### `ValidationResult`
|
|
284
|
-
|
|
285
|
-
```typescript
|
|
286
|
-
interface ValidationResult {
|
|
287
|
-
valid: boolean;
|
|
288
|
-
branchName: string;
|
|
289
|
-
error?: string;
|
|
290
|
-
}
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
## Examples
|
|
294
|
-
|
|
295
|
-
### Use with Git Hooks
|
|
296
|
-
|
|
297
|
-
#### With Husky in `package.json`
|
|
298
|
-
|
|
299
|
-
```json
|
|
300
|
-
{
|
|
301
|
-
"husky": {
|
|
302
|
-
"hooks": {
|
|
303
|
-
"pre-commit": "validate-branch"
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
#### Direct Git Hooks
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
#!/bin/sh
|
|
313
|
-
# .git/hooks/pre-commit
|
|
314
|
-
|
|
315
|
-
npx validate-branch
|
|
316
|
-
if [ $? -ne 0 ]; then
|
|
317
|
-
echo "Branch name does not follow naming conventions."
|
|
318
|
-
exit 1
|
|
319
|
-
fi
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
### Use with GitHub Actions
|
|
323
|
-
|
|
324
|
-
```yaml
|
|
325
|
-
name: Branch Validation
|
|
326
|
-
|
|
327
|
-
on:
|
|
328
|
-
pull_request:
|
|
329
|
-
types: [opened, synchronize]
|
|
330
|
-
|
|
331
|
-
jobs:
|
|
332
|
-
validate-branch:
|
|
333
|
-
runs-on: ubuntu-latest
|
|
334
|
-
steps:
|
|
335
|
-
- uses: actions/checkout@v4
|
|
336
|
-
|
|
337
|
-
- name: Setup Node.js
|
|
338
|
-
uses: actions/setup-node@v4
|
|
339
|
-
with:
|
|
340
|
-
node-version: "20"
|
|
341
|
-
|
|
342
|
-
- name: Install validate-branch
|
|
343
|
-
run: npm install -g @gracefullight/validate-branch
|
|
344
|
-
|
|
345
|
-
- name: Validate branch name
|
|
346
|
-
run: validate-branch --test ${{ github.head_ref }}
|
|
347
|
-
```
|
|
348
|
-
|
|
349
|
-
### Use in CI/CD Pipeline
|
|
350
|
-
|
|
351
|
-
```yaml
|
|
352
|
-
# .github/workflows/ci.yml
|
|
353
|
-
|
|
354
|
-
jobs:
|
|
355
|
-
test:
|
|
356
|
-
runs-on: ubuntu-latest
|
|
357
|
-
steps:
|
|
358
|
-
- name: Checkout
|
|
359
|
-
uses: actions/checkout@v4
|
|
360
|
-
|
|
361
|
-
- name: Validate branch name
|
|
362
|
-
run: npx validate-branch
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### Use with ESLint Plugin
|
|
366
|
-
|
|
367
|
-
```javascript
|
|
368
|
-
// .eslintrc.js
|
|
369
|
-
const { execSync } = require("child_process");
|
|
370
|
-
|
|
371
|
-
module.exports = {
|
|
372
|
-
// ... other config
|
|
373
|
-
rules: {
|
|
374
|
-
"custom/validate-branch": {
|
|
375
|
-
meta: {
|
|
376
|
-
type: "suggestion",
|
|
377
|
-
docs: {
|
|
378
|
-
description: "Validate git branch name",
|
|
379
|
-
},
|
|
380
|
-
},
|
|
381
|
-
create(context) {
|
|
382
|
-
return {
|
|
383
|
-
Program() {
|
|
384
|
-
const branch = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
385
|
-
encoding: "utf-8",
|
|
386
|
-
}).trim();
|
|
387
|
-
|
|
388
|
-
const { validateBranchName } = require("@gracefullight/validate-branch");
|
|
389
|
-
|
|
390
|
-
if (!validateBranchName(branch)) {
|
|
391
|
-
context.report({
|
|
392
|
-
node: {},
|
|
393
|
-
message: `Invalid branch name: ${branch}`,
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
},
|
|
397
|
-
};
|
|
398
|
-
},
|
|
399
|
-
},
|
|
400
|
-
},
|
|
401
|
-
};
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
## Development
|
|
405
|
-
|
|
406
|
-
### Setup
|
|
407
|
-
|
|
408
|
-
```bash
|
|
409
|
-
# Clone repository
|
|
410
|
-
git clone https://github.com/gracefullight/saju.git
|
|
411
|
-
cd packages/validate-branch
|
|
412
|
-
|
|
413
|
-
# Install dependencies
|
|
414
|
-
pnpm install
|
|
415
|
-
|
|
416
|
-
# Build
|
|
417
|
-
pnpm build
|
|
418
|
-
|
|
419
|
-
# Test
|
|
420
|
-
pnpm test
|
|
421
|
-
|
|
422
|
-
# Lint
|
|
423
|
-
pnpm lint
|
|
424
|
-
|
|
425
|
-
# Format
|
|
426
|
-
pnpm lint:fix
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
### Test CLI Locally
|
|
430
|
-
|
|
431
|
-
```bash
|
|
432
|
-
# After building, test CLI locally
|
|
433
|
-
node bin/validate-branch.js --test feature/new-feature
|
|
434
|
-
|
|
435
|
-
# Test with custom pattern
|
|
436
|
-
node bin/validate-branch.js --test invalid-name --regexp "^(main|develop)$"
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
## Contributing
|
|
440
|
-
|
|
441
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
442
|
-
|
|
443
|
-
1. Fork repository
|
|
444
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
445
|
-
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
446
|
-
4. Push to branch (`git push origin feature/amazing-feature`)
|
|
447
|
-
5. Open a Pull Request
|
|
448
|
-
|
|
449
|
-
### Guidelines
|
|
450
|
-
|
|
451
|
-
- Write tests for new features
|
|
452
|
-
- Maintain or improve code coverage
|
|
453
|
-
- Follow existing code style (enforced by Biome)
|
|
454
|
-
- Update documentation as needed
|
|
455
|
-
|
|
456
|
-
## License
|
|
457
|
-
|
|
458
|
-
MIT © [gracefullight](https://github.com/gracefullight)
|
|
459
|
-
|
|
460
|
-
## Related Projects
|
|
461
|
-
|
|
462
|
-
- [isomorphic-git](https://isomorphic-git.org/) - Git implementation library
|
|
463
|
-
- [Commander.js](https://commander.js/) - Node.js CLI framework
|
|
464
|
-
- [Chalk](https://chalk.js.org/) - Terminal string styling
|
|
465
|
-
|
|
466
|
-
## Support
|
|
467
|
-
|
|
468
|
-
- [Documentation](https://github.com/gracefullight/saju#readme)
|
|
469
|
-
- [Issue Tracker](https://github.com/gracefullight/saju/issues)
|
|
470
|
-
- [Discussions](https://github.com/gracefullight/saju/discussions)
|