Skip to content

feat: add an input to run at a subdirectory of the repo root#232

Open
bookchris wants to merge 2 commits intoun-ts:mainfrom
bookchris:cbook/inputpath
Open

feat: add an input to run at a subdirectory of the repo root#232
bookchris wants to merge 2 commits intoun-ts:mainfrom
bookchris:cbook/inputpath

Conversation

@bookchris
Copy link

@bookchris bookchris commented Mar 4, 2026

Allows for situations where the root of the npm workspace is not at the top level.

Fixes #231

Summary by CodeRabbit

  • New Features

    • Action can run from a specified subdirectory (custom working directory), with changeset detection, package discovery, changelog creation, and comments scoped to that subdirectory.
  • Documentation

    • Added documentation for the working-directory input, describing default behavior and how to target a subdirectory within your repository.

- Allows for situations where the root of the npm workspace is not at the top level.
@changeset-bot
Copy link

changeset-bot bot commented Mar 4, 2026

🦋 Changeset detected

Latest commit: 67170aa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
changesets-gitlab Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 90fa6ae8-c563-4633-af8d-b1e73188a934

📥 Commits

Reviewing files that changed from the base of the PR and between 02c352e and 67170aa.

📒 Files selected for processing (1)
  • .changeset/dry-spoons-own.md

📝 Walkthrough

Walkthrough

This PR threads a configurable working directory (cwd) through the codebase, allowing changeset and package path resolution relative to a repo subdirectory rather than the repository root.

Changes

Cohort / File(s) Summary
Documentation
README.md
Added INPUT_CWD documentation describing a relative path to the directory containing package.json and .changeset (defaults to repo root).
Entry Point
src/main.ts
Resolves cwd from an optional input and passes it to readChangesetState, runPublish, and runVersion.
Comment Processing
src/comment.ts
Computes changesetPrefix from cwd, adjusts changed-file mapping to strip subdir prefixes, updates changeset file creation and MR comment logic, and adds changesetPrefix parameter to hasChangesetBeenAdded.
Package Change Detection
src/get-changed-packages.ts
Adds optional cwd?: string parameter (default process.cwd()), and resolves all filesystem reads/writes relative to the provided cwd (package.json, .changeset files, pre.json, pnpm-workspace.yaml, etc.).
Changeset
.changeset/dry-spoons-own.md
New changeset file added indicating a minor feature for running in a subdirectory.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • JounQin

Poem

🐰 I hopped into a nested tree,
Found .changeset hiding under a lea,
A cwd stitched through every line,
Now subdirs sing with paths aligned,
Hooray — small paws made builds agree! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding an input parameter to enable running the action at a subdirectory of the repo root.
Linked Issues check ✅ Passed The PR implements the requested feature from issue #231 by adding an INPUT_CWD parameter to specify the subdirectory containing the npm workspace and .changesets directory.
Out of Scope Changes check ✅ Passed All changes are directly related to supporting subdirectory operation: README documentation, parameter handling, path resolution, and file access adjustments throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Mar 4, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 4, 2026

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/comment.ts`:
- Around line 261-266: Normalize the raw INPUT_CWD before constructing prefixes
and paths: compute a normalizedCwd by stripping a leading "./" and any trailing
slashes from cwdInput (turning "." or "./" into an empty string), then use
normalizedCwd when building changesetPrefix and any diff/path prefixes (e.g.,
replace uses of cwdInput in the changesetPrefix logic and other prefix
constructions around the existing cwdInput references and in the diff matching
code at the regions corresponding to lines ~291-299 and ~321-324); keep
absoluteCwd as path.resolve(process.cwd(), cwdInput ?? '.') but ensure all
string comparisons and prefix concatenations use normalizedCwd so GitLab path
forms like "subdir/file" will match correctly.

In `@src/main.ts`:
- Line 54: The code currently allows getOptionalInput('cwd') to resolve outside
the repo via path.resolve(process.cwd(), ...); change to explicitly resolve the
candidate relative to the repository root and reject or clamp traversals:
capture repoRoot = process.cwd(), compute candidate = getOptionalInput('cwd') ??
'.', then let resolved = path.resolve(repoRoot, candidate); normalize and check
that resolved === repoRoot || resolved.startsWith(repoRoot + path.sep) (use
path.normalize and path.sep), and if the check fails throw an error (or fallback
to repoRoot) before assigning to cwd; update the code around the cwd variable to
use this guarded resolved path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d10c4eec-7e2f-4999-9ea4-d4426c3c69aa

📥 Commits

Reviewing files that changed from the base of the PR and between eccf474 and 02c352e.

📒 Files selected for processing (4)
  • README.md
  • src/comment.ts
  • src/get-changed-packages.ts
  • src/main.ts

Comment on lines +261 to +266
const cwdInput = getOptionalInput('cwd')
const changesetPrefix = cwdInput
? `${cwdInput.replace(/\/$/, '')}/.changeset`
: '.changeset'
const absoluteCwd = path.resolve(process.cwd(), cwdInput ?? '.')

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Normalize INPUT_CWD before building prefixes used for diff matching.

Lines [261]-[266] and [291]-[299] use raw input text, so values like . or ./subdir won’t match GitLab paths. That can incorrectly report no changeset and break package file remapping.

🔧 Suggested normalization
-  const cwdInput = getOptionalInput('cwd')
-  const changesetPrefix = cwdInput
-    ? `${cwdInput.replace(/\/$/, '')}/.changeset`
-    : '.changeset'
-  const absoluteCwd = path.resolve(process.cwd(), cwdInput ?? '.')
+  const repoRoot = process.cwd()
+  const cwdInput = getOptionalInput('cwd')
+  const absoluteCwd = path.resolve(repoRoot, cwdInput ?? '.')
+  const relativeCwd = path
+    .relative(repoRoot, absoluteCwd)
+    .split(path.sep)
+    .join('/')
+  const normalizedCwd = relativeCwd === '' ? '.' : relativeCwd
+  const subdirPrefix = normalizedCwd === '.' ? '' : `${normalizedCwd}/`
+  const changesetPrefix = `${subdirPrefix}.changeset`
@@
-    const subdirPrefix = cwdInput ? cwdInput.replace(/\/$/, '') + '/' : ''
     const packageChangedFiles = changedFilesPromise.then(changedFiles =>
       changedFiles.map(({ new_path }) =>
         subdirPrefix && new_path.startsWith(subdirPrefix)
           ? new_path.slice(subdirPrefix.length)
           : new_path,
       ),
     )

Also applies to: 291-299, 321-324

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/comment.ts` around lines 261 - 266, Normalize the raw INPUT_CWD before
constructing prefixes and paths: compute a normalizedCwd by stripping a leading
"./" and any trailing slashes from cwdInput (turning "." or "./" into an empty
string), then use normalizedCwd when building changesetPrefix and any diff/path
prefixes (e.g., replace uses of cwdInput in the changesetPrefix logic and other
prefix constructions around the existing cwdInput references and in the diff
matching code at the regions corresponding to lines ~291-299 and ~321-324); keep
absoluteCwd as path.resolve(process.cwd(), cwdInput ?? '.') but ensure all
string comparisons and prefix concatenations use normalizedCwd so GitLab path
forms like "subdir/file" will match correctly.

}

const { changesets } = await readChangesetState()
const cwd = path.resolve(process.cwd(), getOptionalInput('cwd') ?? '.')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Enforce INPUT_CWD to stay within the repository root.

Line [54] resolves any path, including absolute or ../ traversal targets. That breaks the “relative to repo root” contract and can run version/publish logic in unintended directories.

🔧 Suggested guard
-  const cwd = path.resolve(process.cwd(), getOptionalInput('cwd') ?? '.')
+  const repoRoot = process.cwd()
+  const cwdInput = getOptionalInput('cwd')
+  const cwd = path.resolve(repoRoot, cwdInput ?? '.')
+  const relativeCwd = path.relative(repoRoot, cwd)
+  if (cwdInput && (path.isAbsolute(cwdInput) || relativeCwd.startsWith('..'))) {
+    throw new Error('INPUT_CWD must be a relative path inside the repository root')
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const cwd = path.resolve(process.cwd(), getOptionalInput('cwd') ?? '.')
const repoRoot = process.cwd()
const cwdInput = getOptionalInput('cwd')
const cwd = path.resolve(repoRoot, cwdInput ?? '.')
const relativeCwd = path.relative(repoRoot, cwd)
if (cwdInput && (path.isAbsolute(cwdInput) || relativeCwd.startsWith('..'))) {
throw new Error('INPUT_CWD must be a relative path inside the repository root')
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main.ts` at line 54, The code currently allows getOptionalInput('cwd') to
resolve outside the repo via path.resolve(process.cwd(), ...); change to
explicitly resolve the candidate relative to the repository root and reject or
clamp traversals: capture repoRoot = process.cwd(), compute candidate =
getOptionalInput('cwd') ?? '.', then let resolved = path.resolve(repoRoot,
candidate); normalize and check that resolved === repoRoot ||
resolved.startsWith(repoRoot + path.sep) (use path.normalize and path.sep), and
if the check fails throw an error (or fallback to repoRoot) before assigning to
cwd; update the code around the cwd variable to use this guarded resolved path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using .changesets from a repository subdirectory

1 participant