claude-git-hooks 2.30.2 → 2.32.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/CHANGELOG.md +60 -9
- package/CLAUDE.md +117 -87
- package/README.md +117 -93
- package/lib/commands/close-release.js +7 -7
- package/lib/commands/create-pr.js +34 -21
- package/lib/utils/authorization.js +6 -7
- package/lib/utils/github-api.js +92 -60
- package/lib/utils/github-client.js +5 -105
- package/lib/utils/label-resolver.js +232 -0
- package/lib/utils/remote-config.js +102 -0
- package/lib/utils/reviewer-selector.js +154 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,16 +36,30 @@ claude-hooks create-pr develop
|
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
**Auto-push feature (v2.11.0):**
|
|
39
|
+
|
|
39
40
|
- Detects unpublished branches or unpushed commits
|
|
40
41
|
- Shows commit preview before pushing
|
|
41
42
|
- Prompts for confirmation (configurable)
|
|
42
43
|
- Handles diverged branches gracefully
|
|
43
44
|
|
|
44
45
|
**Merge strategy awareness (v2.25.0):**
|
|
46
|
+
|
|
45
47
|
- Auto-detects required strategy from branch naming: `feature/*`/`release-fix/*` → squash, `release-candidate/*`/`hotfix/*`/`→ main` → merge commit
|
|
46
48
|
- Displays strategy in PR preview; adds `merge-strategy:squash` or `merge-strategy:merge-commit` label
|
|
47
49
|
- Prepends body reminder for merge-commit PRs; unknown patterns prompt user to select manually
|
|
48
50
|
|
|
51
|
+
**Automatic label resolution (v2.31.0):**
|
|
52
|
+
|
|
53
|
+
- Resolves labels from 5 rule types: preset, size, quality, strategy, and defaults
|
|
54
|
+
- Remote config priority (`mscope-S-L/git-hooks-config/labels.json`) with local fallback
|
|
55
|
+
- Size labels: `size:S` (<10 files), `size:M` (10-50), `size:L` (50-100), `size:XL` (>100) — thresholds configurable remotely
|
|
56
|
+
- Quality labels: `breaking-change`, `security`, `performance` from analysis result
|
|
57
|
+
- Each rule type independently enabled/disabled via remote config
|
|
58
|
+
|
|
59
|
+
### Team Configuration
|
|
60
|
+
|
|
61
|
+
Label rules, PR categories, and role-based permissions are managed centrally in [`mscope-S-L/git-hooks-config`](https://github.com/mscope-S-L/git-hooks-config). Changes there take effect immediately across all governed repositories — no tool update or deploy required.
|
|
62
|
+
|
|
49
63
|
### Token Setup
|
|
50
64
|
|
|
51
65
|
```bash
|
|
@@ -54,12 +68,14 @@ claude-hooks setup-linear # Configure Linear token for ticket enrichment
|
|
|
54
68
|
```
|
|
55
69
|
|
|
56
70
|
**Option 1 - Settings file (recommended):**
|
|
71
|
+
|
|
57
72
|
```json
|
|
58
73
|
// .claude/settings.local.json (gitignored)
|
|
59
74
|
{ "githubToken": "ghp_..." }
|
|
60
75
|
```
|
|
61
76
|
|
|
62
77
|
**Option 2 - Environment variable:**
|
|
78
|
+
|
|
63
79
|
```bash
|
|
64
80
|
export GITHUB_TOKEN="ghp_..."
|
|
65
81
|
```
|
|
@@ -82,12 +98,13 @@ claude-hooks analyze --all
|
|
|
82
98
|
```
|
|
83
99
|
|
|
84
100
|
**What it does:**
|
|
101
|
+
|
|
85
102
|
- Analyzes selected file scope (staged, unstaged, or all)
|
|
86
103
|
- Shows all issues (INFO, MINOR, MAJOR, CRITICAL, BLOCKER)
|
|
87
104
|
- Interactive prompt with options:
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
105
|
+
- **Continue**: Creates commit automatically with auto-generated message
|
|
106
|
+
- **Abort**: Generate resolution prompt and fix issues
|
|
107
|
+
- **View**: Show detailed issue list
|
|
91
108
|
- Executes `git commit -m "auto" --no-verify` on confirmation
|
|
92
109
|
- Works outside git hooks (no stdin limitations)
|
|
93
110
|
|
|
@@ -143,6 +160,7 @@ claude-hooks bump-version patch --no-commit
|
|
|
143
160
|
```
|
|
144
161
|
|
|
145
162
|
**What it does:**
|
|
163
|
+
|
|
146
164
|
- Detects project type (Node.js, Maven, or monorepo with both)
|
|
147
165
|
- Updates `package.json` and/or `pom.xml`
|
|
148
166
|
- Generates CHANGELOG entry with Claude (analyzes commits)
|
|
@@ -151,6 +169,7 @@ claude-hooks bump-version patch --no-commit
|
|
|
151
169
|
- Tags stay local by default (use `--push` to push immediately, or let `create-pr` handle it)
|
|
152
170
|
|
|
153
171
|
**Version workflow:**
|
|
172
|
+
|
|
154
173
|
```
|
|
155
174
|
2.7.0 → 2.8.0-SNAPSHOT # Start development
|
|
156
175
|
2.8.0-SNAPSHOT → 2.8.0-RC # Release candidate
|
|
@@ -158,6 +177,7 @@ claude-hooks bump-version patch --no-commit
|
|
|
158
177
|
```
|
|
159
178
|
|
|
160
179
|
**Integration with create-pr:**
|
|
180
|
+
|
|
161
181
|
- Validates version alignment (package.json, pom.xml, CHANGELOG, tags)
|
|
162
182
|
- Detects and prompts to push unpushed tags
|
|
163
183
|
- Warns if local version ≤ remote version
|
|
@@ -178,6 +198,7 @@ claude-hooks generate-changelog --base-branch develop
|
|
|
178
198
|
```
|
|
179
199
|
|
|
180
200
|
**What it does:**
|
|
201
|
+
|
|
181
202
|
- Analyzes commits since last tag using Claude
|
|
182
203
|
- Categorizes by Conventional Commits types (feat, fix, refactor, etc.)
|
|
183
204
|
- Generates Keep a Changelog format entries
|
|
@@ -206,14 +227,14 @@ claude-hooks --set-preset backend # Set preset
|
|
|
206
227
|
claude-hooks preset current # Show current
|
|
207
228
|
```
|
|
208
229
|
|
|
209
|
-
| Preset
|
|
210
|
-
|
|
211
|
-
| backend
|
|
212
|
-
| frontend
|
|
213
|
-
| fullstack | all above
|
|
214
|
-
| database
|
|
215
|
-
| ai
|
|
216
|
-
| default
|
|
230
|
+
| Preset | Extensions | Focus |
|
|
231
|
+
| --------- | ---------------------------------------- | ------------------------ |
|
|
232
|
+
| backend | .java, .xml, .yml, .yaml | Spring Boot, JPA, OWASP |
|
|
233
|
+
| frontend | .js, .jsx, .ts, .tsx, .css, .scss, .html | React, XSS, a11y |
|
|
234
|
+
| fullstack | all above | API contract consistency |
|
|
235
|
+
| database | .sql | SQL injection, indexes |
|
|
236
|
+
| ai | .js, .json, .md, .sh | Node.js, Claude API |
|
|
237
|
+
| default | multiple | General quality |
|
|
217
238
|
|
|
218
239
|
### Skip Analysis
|
|
219
240
|
|
|
@@ -267,60 +288,61 @@ claude-hooks update # Update to latest version
|
|
|
267
288
|
|
|
268
289
|
### Directory Map
|
|
269
290
|
|
|
270
|
-
| Path
|
|
271
|
-
|
|
272
|
-
| `bin/claude-hooks` | **Thin CLI router** - argument parsing, command dispatch | -
|
|
273
|
-
| `lib/commands/`
|
|
274
|
-
| `lib/config.js`
|
|
275
|
-
| `lib/hooks/`
|
|
276
|
-
| `lib/utils/`
|
|
277
|
-
| `templates/`
|
|
291
|
+
| Path | Purpose | Key Exports |
|
|
292
|
+
| ------------------ | -------------------------------------------------------- | ---------------------------------------- |
|
|
293
|
+
| `bin/claude-hooks` | **Thin CLI router** - argument parsing, command dispatch | - |
|
|
294
|
+
| `lib/commands/` | **Command modules** - one file per CLI command | See table below |
|
|
295
|
+
| `lib/config.js` | **Config system** - load/merge configuration | `getConfig()` |
|
|
296
|
+
| `lib/hooks/` | **Git hook logic** - Node.js implementations | `pre-commit.js`, `prepare-commit-msg.js` |
|
|
297
|
+
| `lib/utils/` | **Reusable utilities** - shared across commands | See table below |
|
|
298
|
+
| `templates/` | **Static assets** - bash wrappers, prompts, presets | Copied during install |
|
|
278
299
|
|
|
279
300
|
### Command Modules (`lib/commands/`)
|
|
280
301
|
|
|
281
|
-
| Module
|
|
282
|
-
|
|
283
|
-
| `helpers.js`
|
|
284
|
-
| `install.js`
|
|
285
|
-
| `hooks.js`
|
|
286
|
-
| `analyze.js`
|
|
287
|
-
| `analyze-diff.js`
|
|
288
|
-
| `analyze-pr.js`
|
|
289
|
-
| `create-pr.js`
|
|
290
|
-
| `bump-version.js`
|
|
291
|
-
| `generate-changelog.js` | **CHANGELOG generation** - standalone command
|
|
292
|
-
| `setup-github.js`
|
|
293
|
-
| `setup-linear.js`
|
|
294
|
-
| `presets.js`
|
|
295
|
-
| `update.js`
|
|
296
|
-
| `migrate-config.js`
|
|
297
|
-
| `debug.js`
|
|
298
|
-
| `telemetry-cmd.js`
|
|
299
|
-
| `diff-batch-info.js`
|
|
300
|
-
| `help.js`
|
|
302
|
+
| Module | Purpose | Key Exports |
|
|
303
|
+
| ----------------------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------- |
|
|
304
|
+
| `helpers.js` | **Shared CLI utilities** - colors, output, platform detection | `colors`, `error()`, `success()`, `info()`, `checkGitRepo()`, `Entertainment` |
|
|
305
|
+
| `install.js` | **Installation logic** - dependencies, hooks, templates | `runInstall()`, `extractLegacySettings()` |
|
|
306
|
+
| `hooks.js` | **Hook management** - enable, disable, status, uninstall | `runEnable()`, `runDisable()`, `runStatus()`, `runUninstall()` |
|
|
307
|
+
| `analyze.js` | **Interactive code analysis** - analyze before committing | `runAnalyze()` |
|
|
308
|
+
| `analyze-diff.js` | **Diff analysis** - generate PR metadata from git diff | `runAnalyzeDiff()` |
|
|
309
|
+
| `analyze-pr.js` | **PR analysis** - analyze GitHub PR with team guidelines | `runAnalyzePr()` |
|
|
310
|
+
| `create-pr.js` | **PR creation** - full workflow via Octokit | `runCreatePr()` |
|
|
311
|
+
| `bump-version.js` | **Version management** - bump with CHANGELOG and Git tag | `runBumpVersion()` |
|
|
312
|
+
| `generate-changelog.js` | **CHANGELOG generation** - standalone command | `runGenerateChangelog()` |
|
|
313
|
+
| `setup-github.js` | **Token setup** - interactive GitHub configuration | `runSetupGitHub()` |
|
|
314
|
+
| `setup-linear.js` | **Token setup** - interactive Linear configuration | `runSetupLinear()` |
|
|
315
|
+
| `presets.js` | **Preset management** - list, set, show current | `runShowPresets()`, `runSetPreset()`, `runCurrentPreset()` |
|
|
316
|
+
| `update.js` | **Self-update** - check and install latest version | `runUpdate()` |
|
|
317
|
+
| `migrate-config.js` | **Config migration** - legacy to v2.8.0 format | `runMigrateConfig()` |
|
|
318
|
+
| `debug.js` | **Debug toggle** - enable/disable verbose logging | `runSetDebug()` |
|
|
319
|
+
| `telemetry-cmd.js` | **Telemetry commands** - show/clear statistics | `runShowTelemetry()`, `runClearTelemetry()` |
|
|
320
|
+
| `diff-batch-info.js` | **Batch info** - orchestration config + per-model speed telemetry | `runDiffBatchInfo()` |
|
|
321
|
+
| `help.js` | **Help, AI help, report-issue** | `runShowHelp()`, `showStaticHelp()`, `runShowVersion()` |
|
|
301
322
|
|
|
302
323
|
### Utility Modules (`lib/utils/`)
|
|
303
324
|
|
|
304
|
-
| Module
|
|
305
|
-
|
|
306
|
-
| `analysis-engine.js`
|
|
307
|
-
| `diff-analysis-orchestrator.js` | **Intelligent orchestration** - semantic batch grouping via Opus (v2.20.0)
|
|
308
|
-
| `claude-client.js`
|
|
309
|
-
| `prompt-builder.js`
|
|
310
|
-
| `git-operations.js`
|
|
311
|
-
| `pr-metadata-engine.js`
|
|
312
|
-
| `github-api.js`
|
|
313
|
-
| `token-store.js`
|
|
314
|
-
| `linear-connector.js`
|
|
315
|
-
| `pr-statistics.js`
|
|
316
|
-
| `github-client.js`
|
|
317
|
-
| `
|
|
318
|
-
| `
|
|
319
|
-
| `
|
|
320
|
-
| `
|
|
321
|
-
| `
|
|
322
|
-
| `
|
|
323
|
-
| `
|
|
325
|
+
| Module | Purpose | Key Exports |
|
|
326
|
+
| ------------------------------- | -------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
327
|
+
| `analysis-engine.js` | **Shared analysis logic** - file data, orchestration, results (v2.13.0) | `buildFilesData()`, `runAnalysis()`, `consolidateResults()`, `displayResults()` |
|
|
328
|
+
| `diff-analysis-orchestrator.js` | **Intelligent orchestration** - semantic batch grouping via Opus (v2.20.0) | `orchestrateBatches()`, `buildFileOverview()`, `detectDependencies()` |
|
|
329
|
+
| `claude-client.js` | **Claude CLI wrapper** - spawn, retry, model override | `analyzeCode()`, `executeClaudeWithRetry()`, `extractJSON()` |
|
|
330
|
+
| `prompt-builder.js` | **Prompt construction** - load templates, replace variables, inject commit context | `buildAnalysisPrompt()`, `loadPrompt()` |
|
|
331
|
+
| `git-operations.js` | **Git abstractions** - staged files, diff, branch comparison | `getStagedFiles()`, `getDiff()`, `getRepoRoot()`, `resolveBaseBranch()`, `getDiffBetweenRefs()` |
|
|
332
|
+
| `pr-metadata-engine.js` | **PR metadata generation** - branch context, diff reduction (v2.14.0) | `getBranchContext()`, `buildDiffPayload()`, `generatePRMetadata()`, `analyzeBranchForPR()` |
|
|
333
|
+
| `github-api.js` | **Octokit integration** - PR creation, PR analysis, token validation, content fetching | `createPullRequest()`, `fetchPullRequest()`, `fetchPullRequestFiles()`, `createPullRequestReview()`, `parseGitHubPRUrl()`, `validateToken()`, `saveGitHubToken()`, `fetchFileContent()`, `fetchDirectoryListing()`, `createIssue()` |
|
|
334
|
+
| `token-store.js` | **Token persistence** - centralized settings.local.json read/write | `loadToken()`, `saveToken()`, `hasToken()`, `loadLocalSettings()` |
|
|
335
|
+
| `linear-connector.js` | **Linear integration** - ticket context fetching with retry | `fetchTicket()`, `extractLinearTicketFromTitle()`, `testConnection()`, `loadLinearToken()` |
|
|
336
|
+
| `pr-statistics.js` | **PR statistics** - write-only JSONL analytics | `recordPRAnalysis()` |
|
|
337
|
+
| `github-client.js` | **GitHub helpers** - repo parsing, config-based reviewers | `getReviewersForFiles()`, `parseGitHubRepo()` |
|
|
338
|
+
| `reviewer-selector.js` | **Team-based reviewer selection** - GitHub Teams API resolution (v2.32.0) | `selectReviewers()` |
|
|
339
|
+
| `preset-loader.js` | **Preset system** - load tech-stack configurations | `loadPreset()`, `listPresets()` |
|
|
340
|
+
| `task-id.js` | **Task ID extraction** - Jira, GitHub, Linear patterns | `getOrPromptTaskId()`, `formatWithTaskId()` |
|
|
341
|
+
| `judge.js` | **Auto-fix judge** - LLM verdict + search/replace fixes (v2.20.0) | `judgeAndFix()`, `applyFix()` |
|
|
342
|
+
| `resolution-prompt.js` | **Issue resolution** - AI-friendly fix prompts | `generateResolutionPrompt()` |
|
|
343
|
+
| `logger.js` | **Logging system** - centralized output with debug mode | `info()`, `warning()`, `error()`, `debug()` |
|
|
344
|
+
| `interactive-ui.js` | **CLI UI components** - previews, prompts, spinners | `showPRPreview()`, `promptConfirmation()`, `promptMenu()` |
|
|
345
|
+
| `telemetry.js` | **Local telemetry** - track JSON parsing, retries | `recordEvent()`, `displayStatistics()` |
|
|
324
346
|
|
|
325
347
|
### Execution Flow
|
|
326
348
|
|
|
@@ -396,20 +418,20 @@ Preset always wins - tech-stack specific has priority over user preferences.
|
|
|
396
418
|
|
|
397
419
|
```json
|
|
398
420
|
{
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
421
|
+
"version": "2.8.0",
|
|
422
|
+
"preset": "backend",
|
|
423
|
+
"overrides": {
|
|
424
|
+
"github": {
|
|
425
|
+
"pr": {
|
|
426
|
+
"defaultBase": "develop",
|
|
427
|
+
"reviewers": ["user"],
|
|
428
|
+
"autoPush": true, // Auto-push unpublished branches (v2.11.0)
|
|
429
|
+
"pushConfirm": true, // Prompt before push (v2.11.0)
|
|
430
|
+
"showCommits": true, // Show commit preview (v2.11.0)
|
|
431
|
+
"verifyRemote": true // Verify remote exists (v2.11.0)
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
413
435
|
}
|
|
414
436
|
```
|
|
415
437
|
|
|
@@ -423,22 +445,22 @@ Preset always wins - tech-stack specific has priority over user preferences.
|
|
|
423
445
|
|
|
424
446
|
### Modification Guide
|
|
425
447
|
|
|
426
|
-
| To change...
|
|
427
|
-
|
|
428
|
-
| CLI argument parsing
|
|
429
|
-
| Install workflow
|
|
430
|
-
| PR creation flow
|
|
431
|
-
| PR analysis from URL
|
|
432
|
-
| Analysis logic
|
|
433
|
-
| Message generation
|
|
434
|
-
| Prompt templates
|
|
435
|
-
| Preset definitions
|
|
436
|
-
| Config defaults
|
|
437
|
-
| GitHub integration
|
|
438
|
-
| Claude CLI calls
|
|
439
|
-
| Batch orchestration logic | `lib/utils/diff-analysis-orchestrator.js`
|
|
440
|
-
| Orchestration prompt
|
|
441
|
-
| Auto-fix judge logic
|
|
448
|
+
| To change... | Edit... |
|
|
449
|
+
| ------------------------- | ------------------------------------------------- |
|
|
450
|
+
| CLI argument parsing | `bin/claude-hooks` |
|
|
451
|
+
| Install workflow | `lib/commands/install.js` |
|
|
452
|
+
| PR creation flow | `lib/commands/create-pr.js` |
|
|
453
|
+
| PR analysis from URL | `lib/commands/analyze-pr.js` |
|
|
454
|
+
| Analysis logic | `lib/hooks/pre-commit.js` |
|
|
455
|
+
| Message generation | `lib/hooks/prepare-commit-msg.js` |
|
|
456
|
+
| Prompt templates | `templates/*.md` or `.claude/prompts/*.md` |
|
|
457
|
+
| Preset definitions | `templates/presets/{name}/` |
|
|
458
|
+
| Config defaults | `lib/config.js` |
|
|
459
|
+
| GitHub integration | `lib/utils/github-api.js` |
|
|
460
|
+
| Claude CLI calls | `lib/utils/claude-client.js` |
|
|
461
|
+
| Batch orchestration logic | `lib/utils/diff-analysis-orchestrator.js` |
|
|
462
|
+
| Orchestration prompt | `templates/DIFF_ANALYSIS_ORCHESTRATION_PROMPT.md` |
|
|
463
|
+
| Auto-fix judge logic | `lib/utils/judge.js` |
|
|
442
464
|
|
|
443
465
|
### File Structure
|
|
444
466
|
|
|
@@ -483,12 +505,13 @@ claude-git-hooks/
|
|
|
483
505
|
|
|
484
506
|
Two-tier strategy based on file count:
|
|
485
507
|
|
|
486
|
-
| Files | Strategy
|
|
487
|
-
|
|
488
|
-
| 1–2
|
|
489
|
-
| 3+
|
|
508
|
+
| Files | Strategy | Details |
|
|
509
|
+
| ----- | ----------------------------- | ------------------------------------------------------------------------------ |
|
|
510
|
+
| 1–2 | Sequential | Single Claude call, full context |
|
|
511
|
+
| 3+ | **Intelligent orchestration** | Opus groups files semantically, assigns model per batch, shared commit context |
|
|
490
512
|
|
|
491
513
|
**Orchestration flow (3+ files):**
|
|
514
|
+
|
|
492
515
|
1. Opus reads a lightweight file overview + detected cross-file dependencies
|
|
493
516
|
2. Groups related files into semantically coherent batches
|
|
494
517
|
3. Assigns model per batch: `haiku` (config/docs), `sonnet` (business logic), `opus` (security-critical)
|
|
@@ -496,6 +519,7 @@ Two-tier strategy based on file count:
|
|
|
496
519
|
5. Falls back to one-file-per-batch if orchestration fails
|
|
497
520
|
|
|
498
521
|
**Inspect orchestration settings:**
|
|
522
|
+
|
|
499
523
|
```bash
|
|
500
524
|
claude-hooks batch-info # Shows config + per-model avg speed from telemetry
|
|
501
525
|
```
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
promptEditField
|
|
36
36
|
} from '../utils/interactive-ui.js';
|
|
37
37
|
import logger from '../utils/logger.js';
|
|
38
|
+
import { resolveLabels } from '../utils/label-resolver.js';
|
|
38
39
|
import { colors, error, checkGitRepo } from './helpers.js';
|
|
39
40
|
|
|
40
41
|
/** Prefix for release-candidate branches */
|
|
@@ -43,9 +44,6 @@ const RC_PREFIX = 'release-candidate';
|
|
|
43
44
|
/** Target branch for the release PR */
|
|
44
45
|
const TARGET_BRANCH = 'main';
|
|
45
46
|
|
|
46
|
-
/** Label added to the created PR to signal merge-commit strategy */
|
|
47
|
-
const MERGE_COMMIT_LABEL = 'merge-strategy:merge-commit';
|
|
48
|
-
|
|
49
47
|
/** Body reminder prepended to PR description */
|
|
50
48
|
const MERGE_COMMIT_REMINDER =
|
|
51
49
|
'> ⚠️ This PR must be merged with **merge commit** (not squash)\n\n';
|
|
@@ -201,7 +199,7 @@ function _showDryRunPreview({ rcBranch, version, description, featureList, optio
|
|
|
201
199
|
console.log(` 3. git push --force-with-lease origin ${rcBranch}`);
|
|
202
200
|
if (!options.noPr) {
|
|
203
201
|
console.log(` 4. Create PR: ${rcBranch} → ${TARGET_BRANCH}`);
|
|
204
|
-
console.log(
|
|
202
|
+
console.log(' Label: merge-strategy:merge-commit');
|
|
205
203
|
} else {
|
|
206
204
|
console.log(' 4. PR creation skipped (--no-pr)');
|
|
207
205
|
}
|
|
@@ -411,13 +409,15 @@ export async function runCloseRelease(args) {
|
|
|
411
409
|
const { createPullRequest, validateToken } = await import('../utils/github-api.js');
|
|
412
410
|
const { parseGitHubRepo } = await import('../utils/github-client.js');
|
|
413
411
|
|
|
412
|
+
const prLabels = await resolveLabels({ mergeStrategy: 'merge-commit' });
|
|
413
|
+
|
|
414
414
|
const tokenValidation = await validateToken();
|
|
415
415
|
if (!tokenValidation.valid) {
|
|
416
416
|
showWarning(`GitHub token invalid — PR not created: ${tokenValidation.error}`);
|
|
417
417
|
console.log('');
|
|
418
418
|
console.log('Create the PR manually:');
|
|
419
419
|
console.log(
|
|
420
|
-
` gh pr create --base ${TARGET_BRANCH} --head ${rcBranch} --label "
|
|
420
|
+
` gh pr create --base ${TARGET_BRANCH} --head ${rcBranch} --label "merge-strategy:merge-commit"`
|
|
421
421
|
);
|
|
422
422
|
} else {
|
|
423
423
|
const repoInfo = parseGitHubRepo();
|
|
@@ -435,7 +435,7 @@ export async function runCloseRelease(args) {
|
|
|
435
435
|
body: prBody,
|
|
436
436
|
head: rcBranch,
|
|
437
437
|
base: TARGET_BRANCH,
|
|
438
|
-
labels:
|
|
438
|
+
labels: prLabels
|
|
439
439
|
});
|
|
440
440
|
prUrl = pr.html_url;
|
|
441
441
|
showSuccess(`✓ PR created: ${prUrl}`);
|
|
@@ -444,7 +444,7 @@ export async function runCloseRelease(args) {
|
|
|
444
444
|
console.log('');
|
|
445
445
|
console.log('Create the PR manually:');
|
|
446
446
|
console.log(
|
|
447
|
-
` gh pr create --base ${TARGET_BRANCH} --head ${rcBranch} --label "
|
|
447
|
+
` gh pr create --base ${TARGET_BRANCH} --head ${rcBranch} --label "merge-strategy:merge-commit"`
|
|
448
448
|
);
|
|
449
449
|
}
|
|
450
450
|
}
|
|
@@ -9,7 +9,7 @@ import path from 'path';
|
|
|
9
9
|
import { analyzeBranchForPR } from '../utils/pr-metadata-engine.js';
|
|
10
10
|
import { getConfig } from '../config.js';
|
|
11
11
|
import { getOrPromptTaskId, formatWithTaskId } from '../utils/task-id.js';
|
|
12
|
-
import {
|
|
12
|
+
import { selectReviewers } from '../utils/reviewer-selector.js';
|
|
13
13
|
import {
|
|
14
14
|
showPRPreview,
|
|
15
15
|
promptMenu,
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from '../utils/interactive-ui.js';
|
|
22
22
|
import { getBranchPushStatus, pushBranch } from '../utils/git-operations.js';
|
|
23
23
|
import logger from '../utils/logger.js';
|
|
24
|
+
import { resolveLabels } from '../utils/label-resolver.js';
|
|
24
25
|
import { error, checkGitRepo } from './helpers.js';
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -557,19 +558,8 @@ export async function runCreatePr(args) {
|
|
|
557
558
|
bodyLength: prBody.length
|
|
558
559
|
});
|
|
559
560
|
|
|
560
|
-
// Step 9:
|
|
561
|
-
logger.debug('create-pr', 'Step 9:
|
|
562
|
-
let labels = [];
|
|
563
|
-
if (config.preset && config.github?.pr?.labelRules) {
|
|
564
|
-
labels = config.github.pr.labelRules[config.preset] || [];
|
|
565
|
-
}
|
|
566
|
-
if (analysisResult.breakingChanges) {
|
|
567
|
-
labels.push('breaking-change');
|
|
568
|
-
}
|
|
569
|
-
logger.debug('create-pr', 'Labels determined', { labels, preset: config.preset });
|
|
570
|
-
|
|
571
|
-
// Step 9.5: Detect merge strategy
|
|
572
|
-
logger.debug('create-pr', 'Step 9.5: Detecting merge strategy', {
|
|
561
|
+
// Step 9: Detect merge strategy (needed before label resolution)
|
|
562
|
+
logger.debug('create-pr', 'Step 9: Detecting merge strategy', {
|
|
573
563
|
sourceBranch: currentBranch,
|
|
574
564
|
targetBranch: baseBranch
|
|
575
565
|
});
|
|
@@ -591,9 +581,25 @@ export async function runCreatePr(args) {
|
|
|
591
581
|
else if (strategyChoice === 'm') mergeStrategy = 'merge-commit';
|
|
592
582
|
}
|
|
593
583
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
584
|
+
// Step 9.5: Resolve labels
|
|
585
|
+
logger.debug('create-pr', 'Step 9.5: Resolving labels');
|
|
586
|
+
let labels = [];
|
|
587
|
+
try {
|
|
588
|
+
labels = await resolveLabels({
|
|
589
|
+
preset: config.preset,
|
|
590
|
+
fileCount: filesArray.length,
|
|
591
|
+
mergeStrategy,
|
|
592
|
+
analysisResult: {
|
|
593
|
+
breakingChanges: analysisResult.breakingChanges || false,
|
|
594
|
+
hasSecurityIssues: analysisResult.hasSecurityIssues || false,
|
|
595
|
+
hasPerformanceIssues: analysisResult.hasPerformanceIssues || false
|
|
596
|
+
},
|
|
597
|
+
localLabelRules: config.github?.pr?.labelRules
|
|
598
|
+
});
|
|
599
|
+
logger.debug('create-pr', 'Labels resolved', { labels, preset: config.preset });
|
|
600
|
+
} catch (labelError) {
|
|
601
|
+
logger.warning('create-pr', 'Label resolution failed, continuing without labels', { error: labelError.message });
|
|
602
|
+
showWarning('Failed to resolve labels - continuing with PR creation');
|
|
597
603
|
}
|
|
598
604
|
|
|
599
605
|
let finalBody = prBody;
|
|
@@ -601,12 +607,19 @@ export async function runCreatePr(args) {
|
|
|
601
607
|
finalBody = `> ⚠️ This PR must be merged with **merge commit** (not squash)\n\n${prBody}`;
|
|
602
608
|
}
|
|
603
609
|
|
|
604
|
-
// Step 10: Get reviewers from
|
|
605
|
-
logger.debug('create-pr', 'Step 10:
|
|
606
|
-
const reviewers = await
|
|
610
|
+
// Step 10: Get reviewers from team + config fallback
|
|
611
|
+
logger.debug('create-pr', 'Step 10: Selecting reviewers via team resolution');
|
|
612
|
+
const reviewers = await selectReviewers({
|
|
613
|
+
org: repoInfo.owner,
|
|
614
|
+
repoFullName: repoInfo.fullName,
|
|
615
|
+
teamSlug: config.github?.pr?.teamSlug || 'automation',
|
|
616
|
+
prAuthor: tokenValidation.user,
|
|
617
|
+
configReviewers: config.github?.pr?.reviewers || [],
|
|
618
|
+
excludeReviewers: config.github?.pr?.excludeReviewers || []
|
|
619
|
+
});
|
|
607
620
|
logger.debug('create-pr', 'Reviewers determined', {
|
|
608
621
|
reviewers,
|
|
609
|
-
sources: '
|
|
622
|
+
sources: 'team + config fallback'
|
|
610
623
|
});
|
|
611
624
|
|
|
612
625
|
// Step 11: Show PR preview
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Purpose: Role-based authorization for protected workflow commands
|
|
4
4
|
*
|
|
5
5
|
* Design:
|
|
6
|
-
* - Permissions are sourced from a centralized GitHub repo (mscope-S-L/
|
|
6
|
+
* - Permissions are sourced from a centralized GitHub repo (mscope-S-L/git-hooks-config)
|
|
7
7
|
* - Role hierarchy is defined in permissions.json (ordered lowest → highest)
|
|
8
8
|
* - Commands not in commandPermissions are open to all
|
|
9
9
|
* - All failure scenarios are fail-closed (block on any error)
|
|
@@ -31,14 +31,13 @@ import {
|
|
|
31
31
|
} from './github-api.js';
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Constants for the centralized
|
|
34
|
+
* Constants for the centralized config repository
|
|
35
35
|
*
|
|
36
|
-
* PERMISSIONS_REPO_OWNER/NAME: where the permissions file lives (
|
|
37
|
-
*
|
|
38
|
-
* PERMISSIONS_ORG: the GitHub org used for membership checks — stable regardless of repo location.
|
|
36
|
+
* PERMISSIONS_REPO_OWNER/NAME: where the permissions file lives (mscope-S-L org).
|
|
37
|
+
* PERMISSIONS_ORG: the GitHub org used for membership checks.
|
|
39
38
|
*/
|
|
40
|
-
const PERMISSIONS_REPO_OWNER = '
|
|
41
|
-
const PERMISSIONS_REPO_NAME = '
|
|
39
|
+
const PERMISSIONS_REPO_OWNER = 'mscope-S-L';
|
|
40
|
+
const PERMISSIONS_REPO_NAME = 'git-hooks-config';
|
|
42
41
|
const PERMISSIONS_FILE_PATH = 'permissions.json';
|
|
43
42
|
const PERMISSIONS_ORG = 'mscope-S-L';
|
|
44
43
|
|