Skip to content

[codex] replace fs-extra and execa in scaffold#1

Merged
edhor1608 merged 1 commit into
mainfrom
codex/replace-execa-fs-extra-dockerignore
Mar 30, 2026
Merged

[codex] replace fs-extra and execa in scaffold#1
edhor1608 merged 1 commit into
mainfrom
codex/replace-execa-fs-extra-dockerignore

Conversation

@edhor1608
Copy link
Copy Markdown
Owner

What changed

  • replaced fs-extra usage in the scaffold with Node built-ins from node:fs/promises
  • removed the unused execa dependency
  • added a scaffold template dockerignore that is emitted as .dockerignore
  • remove .dockerignore together with deployment files when deployment is disabled

Why

This reduces direct package surface in the CLI without changing the generated project behavior.

Impact

Generated projects keep the same deployment-related output, but the scaffold now depends on fewer external packages.

Validation

  • bun install
  • bun run build

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 30, 2026

Walkthrough

This PR updates the CLI scaffold to replace the fs-extra dependency with Node's native node:fs/promises APIs and removes the unused execa dependency. A new .dockerignore template file is added to be generated alongside existing deployment files when scaffolding includes deployment configuration. When deployment scaffolding is disabled, .dockerignore is now omitted along with Dockerfile and fly.toml. A decisions log entry documents these changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: replacing fs-extra and execa dependencies in the scaffold, which aligns with the core objectives of the pull request.
Description check ✅ Passed The description is well-organized and directly related to the changeset, covering what changed, why, and validation steps performed.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/replace-execa-fs-extra-dockerignore

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

Copy link
Copy Markdown

@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: 5

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

Inline comments:
In `@docs/plans/decisions-log.md`:
- Around line 5-14: Add blank lines before and after the top-level headings
"Context", "Decision", "Rationale", and "Consequences" in
docs/plans/decisions-log.md to satisfy MD022; locate the heading lines that
currently read "### Context", "### Decision", "### Rationale", and "###
Consequences" and ensure there is an empty line above and below each heading so
markdown linting no longer flags those lines.

In `@src/index.ts`:
- Around line 57-64: The pathExists helper is duplicated in index.ts and
scaffold.ts; extract it into a shared utility module (e.g., create utils.ts
exporting async function pathExists(targetPath: string): Promise<boolean>),
replace the local implementations in both index.ts and scaffold.ts with imports
from that utils module (import { pathExists } from './utils'), and remove the
duplicate function declarations so both files use the single exported pathExists
implementation.

In `@src/scaffold.ts`:
- Around line 99-106: The helper function pathExists in src/scaffold.ts is
duplicated (same implementation exists in index.ts); remove the duplicate and
import the shared implementation from a single utility module (create or use
utils.ts). Specifically, move the pathExists implementation into utils.ts
(exported as pathExists), then update src/scaffold.ts to remove its local
pathExists and add an import for pathExists from utils, ensuring any callers
(pathExists in scaffold) continue to work; also update index.ts to import the
same exported function if it isn’t already.
- Around line 52-54: Remove the unnecessary recursive option from the three file
deletion calls: update the rm calls that target "Dockerfile", "fly.toml", and
".dockerignore" (the calls using rm(path.join(targetDir, "Dockerfile"), ...),
rm(path.join(targetDir, "fly.toml"), ...), and rm(path.join(targetDir,
".dockerignore"), ...)) to use only { force: true } since these are regular
files and do not require { recursive: true }.

In `@templates/base/dockerignore`:
- Around line 1-8: Add a pattern to the .dockerignore content to exclude
environment files (use .env* to cover .env, .env.local, .env.production, etc.)
so secrets don’t get sent to the Docker build context; locate the existing
ignore list (entries like node_modules, .git, .next, dist) and append the .env*
pattern to it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: aa767c8a-bce6-4603-8b41-556d2cef8998

📥 Commits

Reviewing files that changed from the base of the PR and between e54e639 and 9a99c23.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (5)
  • docs/plans/decisions-log.md
  • package.json
  • src/index.ts
  • src/scaffold.ts
  • templates/base/dockerignore
💤 Files with no reviewable changes (1)
  • package.json
📜 Review details
🧰 Additional context used
🪛 markdownlint-cli2 (0.22.0)
docs/plans/decisions-log.md

[warning] 5-5: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 8-8: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 11-11: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 14-14: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🔇 Additional comments (3)
src/index.ts (1)

4-4: Migration from fs-extra to node:fs/promises looks correct.

The access + try/catch pattern for existence checking and rm with { force: true, recursive: true } for removal are idiomatic replacements for fs.pathExists and fs.remove.

Also applies to: 18-18, 29-29

src/scaffold.ts (2)

1-1: Clean migration to node:fs/promises APIs.

The replacements are idiomatic:

  • mkdir(..., { recursive: true }) for ensureDir
  • readdir(..., { withFileTypes: true }) preserves the dirent behavior
  • readFile/writeFile with encoding

Also applies to: 9-9, 17-18, 69-70, 83-83, 86-86, 94-94


77-79: Good addition of .dockerignore template renaming.

The pattern matches the existing gitignore.gitignore handling, maintaining consistency.

Comment on lines +5 to +14
### Context
The scaffold CLI depended on `fs-extra` for directory and file helpers and declared `execa` without using it. The package already runs on modern Node/Bun runtimes, so Node's built-in filesystem APIs cover the needed behavior.

### Decision
Replace `fs-extra` usage with `node:fs/promises`, remove the unused `execa` dependency, and add template `.dockerignore` generation alongside the existing deployment files.

### Rationale
This keeps the same scaffold behavior while reducing direct dependencies and aligns with the package replacement guidance from the JavaScript bloat review.

### Consequences
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add blank lines around headings to fix markdown linting warnings.

Static analysis flagged MD022 violations on lines 5, 8, 11, and 14.

Suggested fix
 ### Context
+
 The scaffold CLI depended on `fs-extra` for directory and file helpers and declared `execa` without using it. The package already runs on modern Node/Bun runtimes, so Node's built-in filesystem APIs cover the needed behavior.

 ### Decision
+
 Replace `fs-extra` usage with `node:fs/promises`, remove the unused `execa` dependency, and add template `.dockerignore` generation alongside the existing deployment files.

 ### Rationale
+
 This keeps the same scaffold behavior while reducing direct dependencies and aligns with the package replacement guidance from the JavaScript bloat review.

 ### Consequences
+
 The CLI depends on fewer packages, generated deployment templates now include `.dockerignore`, and deployment-disabled scaffolds remove that file together with `Dockerfile` and `fly.toml`.
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 5-5: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 8-8: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 11-11: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 14-14: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

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

In `@docs/plans/decisions-log.md` around lines 5 - 14, Add blank lines before and
after the top-level headings "Context", "Decision", "Rationale", and
"Consequences" in docs/plans/decisions-log.md to satisfy MD022; locate the
heading lines that currently read "### Context", "### Decision", "###
Rationale", and "### Consequences" and ensure there is an empty line above and
below each heading so markdown linting no longer flags those lines.

Comment thread src/index.ts
Comment on lines +57 to +64
async function pathExists(targetPath: string): Promise<boolean> {
try {
await access(targetPath);
return true;
} catch {
return false;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Duplicate pathExists helper exists in both index.ts and scaffold.ts.

This function is identical to the one in scaffold.ts. Consider extracting it to a shared utility (e.g., utils.ts) to avoid duplication.

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

In `@src/index.ts` around lines 57 - 64, The pathExists helper is duplicated in
index.ts and scaffold.ts; extract it into a shared utility module (e.g., create
utils.ts exporting async function pathExists(targetPath: string):
Promise<boolean>), replace the local implementations in both index.ts and
scaffold.ts with imports from that utils module (import { pathExists } from
'./utils'), and remove the duplicate function declarations so both files use the
single exported pathExists implementation.

Comment thread src/scaffold.ts
Comment on lines +52 to +54
await rm(path.join(targetDir, "Dockerfile"), { force: true, recursive: true });
await rm(path.join(targetDir, "fly.toml"), { force: true, recursive: true });
await rm(path.join(targetDir, ".dockerignore"), { force: true, recursive: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

{ recursive: true } is unnecessary when removing single files.

rm with { force: true } alone is sufficient for Dockerfile, fly.toml, and .dockerignore since they are regular files. The recursive option only matters for directories.

Suggested simplification
-    await rm(path.join(targetDir, "Dockerfile"), { force: true, recursive: true });
-    await rm(path.join(targetDir, "fly.toml"), { force: true, recursive: true });
-    await rm(path.join(targetDir, ".dockerignore"), { force: true, recursive: true });
+    await rm(path.join(targetDir, "Dockerfile"), { force: true });
+    await rm(path.join(targetDir, "fly.toml"), { force: true });
+    await rm(path.join(targetDir, ".dockerignore"), { force: true });
📝 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
await rm(path.join(targetDir, "Dockerfile"), { force: true, recursive: true });
await rm(path.join(targetDir, "fly.toml"), { force: true, recursive: true });
await rm(path.join(targetDir, ".dockerignore"), { force: true, recursive: true });
await rm(path.join(targetDir, "Dockerfile"), { force: true });
await rm(path.join(targetDir, "fly.toml"), { force: true });
await rm(path.join(targetDir, ".dockerignore"), { force: true });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/scaffold.ts` around lines 52 - 54, Remove the unnecessary recursive
option from the three file deletion calls: update the rm calls that target
"Dockerfile", "fly.toml", and ".dockerignore" (the calls using
rm(path.join(targetDir, "Dockerfile"), ...), rm(path.join(targetDir,
"fly.toml"), ...), and rm(path.join(targetDir, ".dockerignore"), ...)) to use
only { force: true } since these are regular files and do not require {
recursive: true }.

Comment thread src/scaffold.ts
Comment on lines +99 to +106
async function pathExists(targetPath: string): Promise<boolean> {
try {
await access(targetPath);
return true;
} catch {
return false;
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Duplicate pathExists helper—same as in index.ts.

As noted earlier, consider extracting this to utils.ts for reuse.

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

In `@src/scaffold.ts` around lines 99 - 106, The helper function pathExists in
src/scaffold.ts is duplicated (same implementation exists in index.ts); remove
the duplicate and import the shared implementation from a single utility module
(create or use utils.ts). Specifically, move the pathExists implementation into
utils.ts (exported as pathExists), then update src/scaffold.ts to remove its
local pathExists and add an import for pathExists from utils, ensuring any
callers (pathExists in scaffold) continue to work; also update index.ts to
import the same exported function if it isn’t already.

Comment on lines +1 to +8
node_modules
.git
.turbo
.next
.output
dist
coverage
.DS_Store
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding .env* to prevent secrets from leaking into Docker build context.

The current patterns cover common build artifacts. However, .env files containing secrets could inadvertently be included in the Docker build context if not ignored.

Suggested addition
 node_modules
 .git
 .turbo
 .next
 .output
 dist
 coverage
 .DS_Store
+.env*
📝 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
node_modules
.git
.turbo
.next
.output
dist
coverage
.DS_Store
node_modules
.git
.turbo
.next
.output
dist
coverage
.DS_Store
.env*
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/base/dockerignore` around lines 1 - 8, Add a pattern to the
.dockerignore content to exclude environment files (use .env* to cover .env,
.env.local, .env.production, etc.) so secrets don’t get sent to the Docker build
context; locate the existing ignore list (entries like node_modules, .git,
.next, dist) and append the .env* pattern to it.

@edhor1608 edhor1608 marked this pull request as ready for review March 30, 2026 15:31
@edhor1608 edhor1608 merged commit badf808 into main Mar 30, 2026
3 checks passed
@edhor1608 edhor1608 deleted the codex/replace-execa-fs-extra-dockerignore branch March 30, 2026 15:31
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.

1 participant