split-by-codeowners 1.0.4 → 1.1.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/README.md CHANGED
@@ -32,7 +32,6 @@ steps:
32
32
  - name: Split into CODEOWNERS PRs
33
33
  uses: anatoliisf/split-by-codeowners@v1
34
34
  with:
35
- create_prs: "true"
36
35
  github_token: ${{ github.token }}
37
36
  ```
38
37
 
@@ -55,34 +54,35 @@ npx split-by-codeowners --create-prs --base-branch main
55
54
 
56
55
  ### Inputs
57
56
 
58
- | Name | Required | Default | Description |
59
- | --- | --- | --- | --- |
60
- | `codeowners_path` | no | `CODEOWNERS` | Path to CODEOWNERS file |
61
- | `base_ref` | no | `""` | Base ref for changed-files discovery (currently workspace-focused; see notes) |
62
- | `include_unowned` | no | `"true"` | Include files with no owners in a special bucket |
63
- | `unowned_bucket_key` | no | `__UNOWNED__` | Bucket key for unowned files |
64
- | `max_buckets` | no | `"30"` | Fail if buckets exceed this number |
65
- | `exclude_patterns` | no | `""` | Newline-separated glob patterns to exclude (minimatch) |
66
- | `patch_dir` | no | `bucket-patches` | Directory to write per-bucket patch files |
67
- | `bucket_prefix` | no | `bucket` | Patch file prefix |
68
- | `dry_run` | no | `"false"` | Compute buckets but don’t write patches |
69
- | `cleanup_patches` | no | `"false"` | Delete `patch_dir` after a successful run |
70
- | `create_prs` | no | `"false"` | Create/update one PR per bucket |
71
- | `github_token` | no | `""` | Token used for pushing branches + GitHub API (defaults to env `GITHUB_TOKEN`) |
72
- | `base_branch` | no | `""` | Base branch for PRs (defaults to repo default branch) |
73
- | `branch_prefix` | no | `codemods/` | Prefix for created branches |
74
- | `commit_message` | no | `chore: automated changes` | Commit message for bucket PRs |
75
- | `pr_title` | no | `chore: automated changes ({owners})` | PR title template (`{owners}`, `{bucket_key}`) |
76
- | `pr_body` | no | *(see `action.yml`)* | PR body template (`{owners}`, `{bucket_key}`, `{files}`) |
77
- | `draft` | no | `"false"` | Create PRs as drafts |
57
+ | Name | Required | Default | Description |
58
+ | -------------------- | -------- | ------------------------------------- | ----------------------------------------------------------------------------- |
59
+ | `repo_path` | no | `.` | Repo root path relative to `GITHUB_WORKSPACE` |
60
+ | `codeowners_path` | no | `CODEOWNERS` | Path to CODEOWNERS file |
61
+ | `base_ref` | no | `""` | Base ref for changed-files discovery (currently workspace-focused; see notes) |
62
+ | `include_unowned` | no | `"true"` | Include files with no owners in a special bucket |
63
+ | `unowned_bucket_key` | no | `__UNOWNED__` | Bucket key for unowned files |
64
+ | `max_buckets` | no | `"30"` | Fail if buckets exceed this number |
65
+ | `exclude_patterns` | no | `""` | Newline-separated glob patterns to exclude (minimatch) |
66
+ | `patch_dir` | no | `bucket-patches` | Directory to write per-bucket patch files |
67
+ | `bucket_prefix` | no | `bucket` | Patch file prefix |
68
+ | `dry_run` | no | `"false"` | Compute buckets but don’t write patches |
69
+ | `cleanup_patches` | no | `"false"` | Delete `patch_dir` after a successful run |
70
+ | `create_prs` | no | `"true"` | Create/update one PR per bucket |
71
+ | `github_token` | no | `""` | Token used for pushing branches + GitHub API (defaults to env `GITHUB_TOKEN`) |
72
+ | `base_branch` | no | `""` | Base branch for PRs (defaults to repo default branch) |
73
+ | `branch_prefix` | no | `codemods/` | Prefix for created branches |
74
+ | `commit_message` | no | `chore: automated changes` | Commit message for bucket PRs |
75
+ | `pr_title` | no | `chore: automated changes ({owners})` | PR title template (`{owners}`, `{bucket_key}`) |
76
+ | `pr_body` | no | *(see `action.yml`)* | PR body template (`{owners}`, `{bucket_key}`, `{files}`) |
77
+ | `draft` | no | `"false"` | Create PRs as drafts |
78
78
 
79
79
  ### Outputs
80
80
 
81
- | Name | Description |
82
- | --- | --- |
83
- | `matrix_json` | JSON for `strategy.matrix` (`{ include: [...] }`) |
81
+ | Name | Description |
82
+ | -------------- | ------------------------------------------------- |
83
+ | `matrix_json` | JSON for `strategy.matrix` (`{ include: [...] }`) |
84
84
  | `buckets_json` | Full buckets JSON (owners + files + matched rule) |
85
- | `prs_json` | If `create_prs=true`, list of created/updated PRs |
85
+ | `prs_json` | If `create_prs=true`, list of created/updated PRs |
86
86
 
87
87
  ### Example: bucketize only (matrix + patches)
88
88
 
@@ -91,7 +91,7 @@ npx split-by-codeowners --create-prs --base-branch main
91
91
  id: split
92
92
  uses: anatoliisf/split-by-codeowners@v1
93
93
  with:
94
- create_prs: "false"
94
+ draft: "true"
95
95
 
96
96
  - name: Use matrix
97
97
  run: echo '${{ steps.split.outputs.matrix_json }}'
@@ -117,6 +117,33 @@ The CLI operates on your **current working tree** (modified + untracked files) a
117
117
  npx split-by-codeowners --help
118
118
  ```
119
119
 
120
+ ### Options
121
+
122
+ #### Common
123
+
124
+ - **`--repo-path <path>`**: Repo root path (relative to current working directory)
125
+ - **`--codeowners <path>`**: Path to CODEOWNERS file (default: `CODEOWNERS`)
126
+ - **`--exclude <file|->`**: File containing newline-separated glob patterns to exclude, or `-` to read from stdin
127
+ - **`--include-unowned <true|false>`**: Include files with no owners in an `__UNOWNED__` bucket (default: `true`)
128
+ - **`--unowned-bucket-key <key>`**: Bucket key for unowned files (default: `__UNOWNED__`)
129
+ - **`--max-buckets <n>`**: Fail if number of buckets exceeds `n` (default: `30`)
130
+ - **`--patch-dir <dir>`**: Directory to write patch files (default: `bucket-patches`)
131
+ - **`--bucket-prefix <prefix>`**: Patch file prefix (default: `bucket`)
132
+ - **`--dry-run`**: Compute buckets but don’t write patches
133
+ - **`--cleanup-patches`**: Delete `patch_dir` after a successful run (default in this repo: enabled)
134
+
135
+ #### PR creation
136
+
137
+ - **`--create-prs`**: Create/update one PR per bucket (local: uses `gh` auth)
138
+ - **`--base-branch <branch>`**: Base branch for PRs (default: repo default branch)
139
+ - **`--branch-prefix <prefix>`**: Branch prefix for bucket branches (default: `codemods/`)
140
+ - **`--commit-message <msg>`**: Commit message for bucket commits
141
+ - **`--pr-title <tpl>`**: Title template (supports `{owners}`, `{bucket_key}`)
142
+ - **`--pr-body <tpl>`**: Body template (supports `{owners}`, `{bucket_key}`, `{files}`)
143
+ - **`--pr-body-mode <mode>`**: `custom|template|template_with_bucket|none`
144
+ - **`--pr-template-path <path>`**: PR template file path (used when `pr_body_mode=template*`)
145
+ - **`--draft <true|false>`**: Create PRs as drafts (default: `false`)
146
+
120
147
  ### Common examples
121
148
 
122
149
  Exclude some paths:
@@ -131,11 +158,10 @@ Create/update PRs:
131
158
  npx split-by-codeowners --create-prs --base-branch main
132
159
  ```
133
160
 
134
- Force token auth locally (instead of `gh`):
161
+ Use the repo PR template for PR creation (recommended):
135
162
 
136
163
  ```bash
137
- export GH_TOKEN=...
138
- npx split-by-codeowners --create-prs --token "$GH_TOKEN" --base-branch main
164
+ npx split-by-codeowners --create-prs --pr-body-mode template_with_bucket
139
165
  ```
140
166
 
141
167
  ### Notes on local PR creation
@@ -176,6 +202,5 @@ npm run build
176
202
 
177
203
  This repo includes a manual workflow: `.github/workflows/publish-npm.yml`.
178
204
 
179
- - Create an npm token with publish rights and add it as repo secret **`NPM_TOKEN`**.
180
205
  - Bump `package.json` version and ensure `dist/` and `dist-cli/` are up to date.
181
206
  - Run the workflow from the GitHub Actions UI (`workflow_dispatch`).
package/action.yml CHANGED
@@ -6,6 +6,11 @@ branding:
6
6
  color: "blue"
7
7
 
8
8
  inputs:
9
+ repo_path:
10
+ description: "Relative path under GITHUB_WORKSPACE to the repo root."
11
+ required: false
12
+ default: "."
13
+
9
14
  codeowners_path:
10
15
  description: "Path to CODEOWNERS. Defaults to CODEOWNERS at repo root."
11
16
  required: false
@@ -59,7 +64,7 @@ inputs:
59
64
  create_prs:
60
65
  description: "If true, create/update one PR per bucket by pushing branches and calling GitHub API."
61
66
  required: false
62
- default: "false"
67
+ default: "true"
63
68
 
64
69
  github_token:
65
70
  description: "GitHub token used for API + pushing branches. Defaults to GITHUB_TOKEN."
package/dist/index.js CHANGED
@@ -27482,134 +27482,140 @@ function ensureDirExists(dir) {
27482
27482
  (0, buckets_1.ensureDir)(dir);
27483
27483
  }
27484
27484
  async function runSplit(config, logger) {
27485
- if (config.createPrs && config.dryRun) {
27486
- throw new Error("create_prs=true requires dry_run=false (we need patch files to create bucket branches/PRs).");
27487
- }
27488
- // 1) discover + filter changed files
27489
- const changed = (0, git_1.getChangedFiles)(config.baseRef);
27490
- const filtered = (0, buckets_1.applyExcludes)(changed, config.excludePatterns);
27491
- logger.info(`Changed files: ${changed.length} (after excludes: ${filtered.length})`);
27492
- if (!filtered.length) {
27493
- return { buckets: [], matrix: { include: [] }, prs: [] };
27494
- }
27495
- // 2) parse CODEOWNERS + bucketize by owners-set
27496
- const rules = (0, codeowners_1.parseCodeowners)(config.codeownersPath);
27497
- const bucketsMap = new Map();
27498
- for (const file of filtered) {
27499
- const { owners, rule } = (0, codeowners_1.ownersForFile)(file, rules);
27500
- const sortedOwners = (owners ?? []).slice().sort();
27501
- const isUnowned = sortedOwners.length === 0;
27502
- if (isUnowned && !config.includeUnowned)
27503
- continue;
27504
- const key = isUnowned
27505
- ? config.unownedBucketKey
27506
- : sortedOwners.join("|").replaceAll("@", "").replaceAll("/", "-").replaceAll(" ", "");
27507
- const existing = bucketsMap.get(key);
27508
- if (!existing) {
27509
- bucketsMap.set(key, {
27510
- key,
27511
- owners: sortedOwners,
27512
- files: [{ file, owners: sortedOwners, rule }]
27513
- });
27514
- }
27515
- else {
27516
- existing.files.push({ file, owners: sortedOwners, rule });
27485
+ const originalCwd = process.cwd();
27486
+ let resolvedRepoPath;
27487
+ if (config.repoPath) {
27488
+ resolvedRepoPath = node_path_1.default.resolve(originalCwd, config.repoPath);
27489
+ if (!node_fs_1.default.existsSync(resolvedRepoPath)) {
27490
+ throw new Error(`repo_path does not exist: ${resolvedRepoPath}`);
27517
27491
  }
27492
+ process.chdir(resolvedRepoPath);
27493
+ logger.info(`Using repo_path: ${resolvedRepoPath}`);
27518
27494
  }
27519
- const buckets = [...bucketsMap.values()].sort((a, b) => a.key.localeCompare(b.key));
27520
- if (buckets.length > config.maxBuckets) {
27521
- throw new Error(`Too many buckets: ${buckets.length} > max_buckets=${config.maxBuckets}`);
27522
- }
27523
- // 3) write per-bucket patches
27524
- if (!config.dryRun) {
27525
- ensureDirExists(config.patchDir);
27526
- buckets.forEach((b, idx) => {
27527
- const patchPath = node_path_1.default.posix.join(config.patchDir.replaceAll("\\", "/"), `${config.bucketPrefix}-${idx + 1}.patch`);
27528
- const paths = b.files.map((f) => f.file);
27529
- logger.info(`Writing ${patchPath} (${paths.length} files) for bucket=${b.key}`);
27530
- (0, git_1.writePatchForPaths)(patchPath, paths);
27531
- });
27532
- }
27533
- else {
27534
- logger.info("dry_run=true; not generating patches.");
27535
- }
27536
- const matrix = (0, buckets_1.toMatrix)(buckets, config.patchDir, config.bucketPrefix);
27537
- // 4) optionally create PRs (worktrees so we don't disturb the current working tree)
27538
- let prs = undefined;
27539
- if (config.createPrs) {
27540
- const token = config.githubToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN || "";
27541
- const repo = config.repo ?? (0, git_1.parseGitHubRemote)((0, git_1.getRemoteUrl)(config.remoteName));
27542
- const isGitHubActions = process.env.GITHUB_ACTIONS === "true";
27543
- // Auth mode selection:
27544
- // - In GitHub Actions: ALWAYS use token-based API (gh may not be installed/auth'd).
27545
- // - Locally: prefer gh CLI for best DevX, but if gh isn't auth'd and a token is available, fall back to token.
27546
- if (isGitHubActions && !token) {
27547
- throw new Error("Missing GitHub token (set github_token input or GITHUB_TOKEN / GH_TOKEN env var)");
27548
- }
27549
- let useGhCli = !isGitHubActions;
27550
- let octokit = useGhCli ? null : (0, github_1.getOctokit)(token);
27551
- let baseBranch;
27552
- if (useGhCli) {
27553
- try {
27554
- const cwd = process.cwd();
27555
- (0, ghcli_1.assertGhAuthenticated)(cwd);
27556
- baseBranch = config.baseBranch || (0, ghcli_1.getDefaultBranchViaGh)(cwd);
27495
+ try {
27496
+ if (config.createPrs && config.dryRun) {
27497
+ throw new Error("create_prs=true requires dry_run=false (we need patch files to create bucket branches/PRs).");
27498
+ }
27499
+ // 1) discover + filter changed files
27500
+ const changed = (0, git_1.getChangedFiles)(config.baseRef);
27501
+ const filtered = (0, buckets_1.applyExcludes)(changed, config.excludePatterns);
27502
+ logger.info(`Changed files: ${changed.length} (after excludes: ${filtered.length})`);
27503
+ if (!filtered.length) {
27504
+ return { buckets: [], matrix: { include: [] }, prs: [] };
27505
+ }
27506
+ // 2) parse CODEOWNERS + bucketize by owners-set
27507
+ const rules = (0, codeowners_1.parseCodeowners)(config.codeownersPath);
27508
+ const bucketsMap = new Map();
27509
+ for (const file of filtered) {
27510
+ const { owners, rule } = (0, codeowners_1.ownersForFile)(file, rules);
27511
+ const sortedOwners = (owners ?? []).slice().sort();
27512
+ const isUnowned = sortedOwners.length === 0;
27513
+ if (isUnowned && !config.includeUnowned)
27514
+ continue;
27515
+ const key = isUnowned
27516
+ ? config.unownedBucketKey
27517
+ : sortedOwners.join("|").replaceAll("@", "").replaceAll("/", "-").replaceAll(" ", "");
27518
+ const existing = bucketsMap.get(key);
27519
+ if (!existing) {
27520
+ bucketsMap.set(key, {
27521
+ key,
27522
+ owners: sortedOwners,
27523
+ files: [{ file, owners: sortedOwners, rule }]
27524
+ });
27557
27525
  }
27558
- catch (e) {
27559
- if (token) {
27560
- logger.warn("gh is not authenticated; falling back to token auth.");
27561
- useGhCli = false;
27562
- octokit = (0, github_1.getOctokit)(token);
27563
- baseBranch = config.baseBranch || (await (0, github_1.getDefaultBranch)(octokit, repo));
27564
- }
27565
- else {
27566
- throw e;
27567
- }
27526
+ else {
27527
+ existing.files.push({ file, owners: sortedOwners, rule });
27568
27528
  }
27569
27529
  }
27530
+ const buckets = [...bucketsMap.values()].sort((a, b) => a.key.localeCompare(b.key));
27531
+ if (buckets.length > config.maxBuckets) {
27532
+ throw new Error(`Too many buckets: ${buckets.length} > max_buckets=${config.maxBuckets}`);
27533
+ }
27534
+ // 3) write per-bucket patches
27535
+ if (!config.dryRun) {
27536
+ ensureDirExists(config.patchDir);
27537
+ buckets.forEach((b, idx) => {
27538
+ const patchPath = node_path_1.default.posix.join(config.patchDir.replaceAll("\\", "/"), `${config.bucketPrefix}-${idx + 1}.patch`);
27539
+ const paths = b.files.map((f) => f.file);
27540
+ logger.info(`Writing ${patchPath} (${paths.length} files) for bucket=${b.key}`);
27541
+ (0, git_1.writePatchForPaths)(patchPath, paths);
27542
+ });
27543
+ }
27570
27544
  else {
27571
- baseBranch = config.baseBranch || (await (0, github_1.getDefaultBranch)(octokit, repo));
27572
- }
27573
- const baseRef = "HEAD";
27574
- ensureDirExists((0, git_1.worktreeBaseDir)());
27575
- prs = [];
27576
- for (let i = 0; i < buckets.length; i++) {
27577
- const b = buckets[i];
27578
- const patchPath = node_path_1.default.posix.join(config.patchDir.replaceAll("\\", "/"), `${config.bucketPrefix}-${i + 1}.patch`);
27579
- const branch = `${config.branchPrefix}${b.key}`.replaceAll(" ", "");
27580
- const worktreeDir = (0, git_1.tempDirForBucket)(b.key);
27581
- logger.info(`Creating PR for bucket=${b.key} on branch=${branch}`);
27582
- (0, git_1.worktreeAdd)(branch, baseRef, worktreeDir);
27583
- try {
27584
- (0, git_1.applyPatch)(patchPath, worktreeDir);
27585
- const committed = (0, git_1.commitAllStaged)(config.commitMessage, worktreeDir);
27586
- if (!committed) {
27587
- logger.warn(`No staged changes for bucket=${b.key}; skipping push/PR.`);
27588
- continue;
27589
- }
27590
- (0, git_1.pushBranch)(config.remoteName, branch, worktreeDir);
27591
- const ownersStr = b.owners.length ? b.owners.join(", ") : "(unowned)";
27592
- const filesStr = b.files.map(f => `- ${f.file}`).join("\n");
27593
- const bucketInfo = formatTemplate("Automated changes bucketed by CODEOWNERS.\n\nOwners: {owners}\nBucket key: {bucket_key}\n\nFiles:\n{files}\n", { owners: ownersStr, bucket_key: b.key, files: filesStr });
27594
- const title = formatTemplate(config.prTitle, { owners: ownersStr, bucket_key: b.key });
27595
- let body;
27596
- if (config.prBodyMode === "none") {
27597
- body = undefined;
27598
- }
27599
- else if (config.prBodyMode === "custom") {
27600
- body = formatTemplate(config.prBody, { owners: ownersStr, bucket_key: b.key, files: filesStr });
27601
- }
27602
- else {
27603
- const template = (0, pr_template_1.readPrTemplate)(worktreeDir, config.prTemplatePath) ?? "";
27604
- body =
27605
- config.prBodyMode === "template_with_bucket"
27606
- ? (template ? template.trimEnd() + "\n\n---\n\n" + bucketInfo : bucketInfo)
27607
- : (template || bucketInfo);
27545
+ logger.info("dry_run=true; not generating patches.");
27546
+ }
27547
+ const matrix = (0, buckets_1.toMatrix)(buckets, config.patchDir, config.bucketPrefix);
27548
+ // 4) optionally create PRs (worktrees so we don't disturb the current working tree)
27549
+ let prs = undefined;
27550
+ if (config.createPrs) {
27551
+ const token = config.githubToken || process.env.GITHUB_TOKEN || process.env.GH_TOKEN || "";
27552
+ const repo = config.repo ?? (0, git_1.parseGitHubRemote)((0, git_1.getRemoteUrl)(config.remoteName));
27553
+ const isGitHubActions = process.env.GITHUB_ACTIONS === "true";
27554
+ // Auth mode selection:
27555
+ // - In GitHub Actions: ALWAYS use token-based API (gh may not be installed/auth'd).
27556
+ // - Locally: ALWAYS use gh CLI for best DevX (no token-based local mode).
27557
+ if (isGitHubActions) {
27558
+ if (!token) {
27559
+ throw new Error("Missing GitHub token (set github_token input or GITHUB_TOKEN / GH_TOKEN env var)");
27608
27560
  }
27609
- const pr = useGhCli
27610
- ? (() => {
27611
- return (0, ghcli_1.upsertPullRequestViaGh)({
27612
- cwd: worktreeDir,
27561
+ }
27562
+ else {
27563
+ (0, ghcli_1.assertGhAuthenticated)(process.cwd());
27564
+ }
27565
+ const useGhCli = !isGitHubActions;
27566
+ const octokit = useGhCli ? null : (0, github_1.getOctokit)(token);
27567
+ const baseBranch = config.baseBranch || (useGhCli ? (0, ghcli_1.getDefaultBranchViaGh)(process.cwd()) : await (0, github_1.getDefaultBranch)(octokit, repo));
27568
+ const baseRef = "HEAD";
27569
+ ensureDirExists((0, git_1.worktreeBaseDir)());
27570
+ prs = [];
27571
+ for (let i = 0; i < buckets.length; i++) {
27572
+ const b = buckets[i];
27573
+ const patchPath = node_path_1.default.posix.join(config.patchDir.replaceAll("\\", "/"), `${config.bucketPrefix}-${i + 1}.patch`);
27574
+ const branch = `${config.branchPrefix}${b.key}`.replaceAll(" ", "");
27575
+ const worktreeDir = (0, git_1.tempDirForBucket)(b.key);
27576
+ logger.info(`Creating PR for bucket=${b.key} on branch=${branch}`);
27577
+ (0, git_1.worktreeAdd)(branch, baseRef, worktreeDir);
27578
+ try {
27579
+ (0, git_1.applyPatch)(patchPath, worktreeDir);
27580
+ const committed = (0, git_1.commitAllStaged)(config.commitMessage, worktreeDir);
27581
+ if (!committed) {
27582
+ logger.warn(`No staged changes for bucket=${b.key}; skipping push/PR.`);
27583
+ continue;
27584
+ }
27585
+ (0, git_1.pushBranch)(config.remoteName, branch, worktreeDir);
27586
+ const ownersStr = b.owners.length ? b.owners.join(", ") : "(unowned)";
27587
+ const filesStr = b.files.map(f => `- ${f.file}`).join("\n");
27588
+ const bucketInfo = formatTemplate("Automated changes bucketed by CODEOWNERS.\n\nOwners: {owners}\nBucket key: {bucket_key}\n\nFiles:\n{files}\n", { owners: ownersStr, bucket_key: b.key, files: filesStr });
27589
+ const title = formatTemplate(config.prTitle, { owners: ownersStr, bucket_key: b.key });
27590
+ let body;
27591
+ if (config.prBodyMode === "none") {
27592
+ body = undefined;
27593
+ }
27594
+ else if (config.prBodyMode === "custom") {
27595
+ body = formatTemplate(config.prBody, { owners: ownersStr, bucket_key: b.key, files: filesStr });
27596
+ }
27597
+ else {
27598
+ const template = (0, pr_template_1.readPrTemplate)(worktreeDir, config.prTemplatePath) ?? "";
27599
+ body =
27600
+ config.prBodyMode === "template_with_bucket"
27601
+ ? (template ? template.trimEnd() + "\n\n---\n\n" + bucketInfo : bucketInfo)
27602
+ : (template || bucketInfo);
27603
+ }
27604
+ const pr = useGhCli
27605
+ ? (() => {
27606
+ return (0, ghcli_1.upsertPullRequestViaGh)({
27607
+ cwd: worktreeDir,
27608
+ base: baseBranch,
27609
+ head: branch,
27610
+ title,
27611
+ body: body ?? "",
27612
+ draft: config.draft,
27613
+ bucketKey: b.key
27614
+ });
27615
+ })()
27616
+ : await (0, github_1.upsertPullRequest)({
27617
+ octokit: octokit,
27618
+ repo,
27613
27619
  base: baseBranch,
27614
27620
  head: branch,
27615
27621
  title,
@@ -27617,41 +27623,35 @@ async function runSplit(config, logger) {
27617
27623
  draft: config.draft,
27618
27624
  bucketKey: b.key
27619
27625
  });
27620
- })()
27621
- : await (0, github_1.upsertPullRequest)({
27622
- octokit: octokit,
27623
- repo,
27624
- base: baseBranch,
27625
- head: branch,
27626
- title,
27627
- body: body ?? "",
27628
- draft: config.draft,
27629
- bucketKey: b.key
27630
- });
27631
- prs.push(pr);
27632
- logger.info(`PR: ${pr.url}`);
27626
+ prs.push(pr);
27627
+ logger.info(`PR: ${pr.url}`);
27628
+ }
27629
+ finally {
27630
+ (0, git_1.worktreeRemove)(worktreeDir);
27631
+ }
27632
+ }
27633
+ }
27634
+ if (config.cleanupPatches && !config.dryRun) {
27635
+ const cwd = process.cwd();
27636
+ const abs = node_path_1.default.resolve(cwd, config.patchDir);
27637
+ const safePrefix = cwd.endsWith(node_path_1.default.sep) ? cwd : cwd + node_path_1.default.sep;
27638
+ if (!abs.startsWith(safePrefix)) {
27639
+ throw new Error(`Refusing to delete patch_dir outside repo: ${abs}`);
27640
+ }
27641
+ if (abs === cwd) {
27642
+ throw new Error("Refusing to delete patch_dir equal to repo root.");
27633
27643
  }
27634
- finally {
27635
- (0, git_1.worktreeRemove)(worktreeDir);
27644
+ if (node_fs_1.default.existsSync(abs)) {
27645
+ logger.info(`Cleaning up patches dir: ${config.patchDir}`);
27646
+ node_fs_1.default.rmSync(abs, { recursive: true, force: true });
27636
27647
  }
27637
27648
  }
27649
+ return { buckets, matrix, prs };
27638
27650
  }
27639
- if (config.cleanupPatches && !config.dryRun) {
27640
- const cwd = process.cwd();
27641
- const abs = node_path_1.default.resolve(cwd, config.patchDir);
27642
- const safePrefix = cwd.endsWith(node_path_1.default.sep) ? cwd : cwd + node_path_1.default.sep;
27643
- if (!abs.startsWith(safePrefix)) {
27644
- throw new Error(`Refusing to delete patch_dir outside repo: ${abs}`);
27645
- }
27646
- if (abs === cwd) {
27647
- throw new Error("Refusing to delete patch_dir equal to repo root.");
27648
- }
27649
- if (node_fs_1.default.existsSync(abs)) {
27650
- logger.info(`Cleaning up patches dir: ${config.patchDir}`);
27651
- node_fs_1.default.rmSync(abs, { recursive: true, force: true });
27652
- }
27651
+ finally {
27652
+ if (resolvedRepoPath)
27653
+ process.chdir(originalCwd);
27653
27654
  }
27654
- return { buckets, matrix, prs };
27655
27655
  }
27656
27656
 
27657
27657
 
@@ -28172,13 +28172,23 @@ var __importStar = (this && this.__importStar) || (function () {
28172
28172
  return result;
28173
28173
  };
28174
28174
  })();
28175
+ var __importDefault = (this && this.__importDefault) || function (mod) {
28176
+ return (mod && mod.__esModule) ? mod : { "default": mod };
28177
+ };
28175
28178
  Object.defineProperty(exports, "__esModule", ({ value: true }));
28176
28179
  const core = __importStar(__nccwpck_require__(7484));
28180
+ const node_path_1 = __importDefault(__nccwpck_require__(6760));
28177
28181
  const buckets_1 = __nccwpck_require__(4140);
28178
28182
  const app_1 = __nccwpck_require__(168);
28179
28183
  async function run() {
28180
28184
  try {
28185
+ const repoPathInput = core.getInput("repo_path") || ".";
28186
+ const workspace = process.env.GITHUB_WORKSPACE || "";
28187
+ const repoPath = repoPathInput
28188
+ ? (node_path_1.default.isAbsolute(repoPathInput) ? repoPathInput : node_path_1.default.resolve(workspace || process.cwd(), repoPathInput))
28189
+ : undefined;
28181
28190
  const cfg = {
28191
+ repoPath,
28182
28192
  codeownersPath: core.getInput("codeowners_path") || "CODEOWNERS",
28183
28193
  baseRef: core.getInput("base_ref") || "",
28184
28194
  includeUnowned: (0, buckets_1.parseBool)(core.getInput("include_unowned")),