chore: replace rimraf with native fs.rm() - #2631
Conversation
There was a problem hiding this comment.
Pull request overview
This PR removes direct usage of the rimraf package and replaces recursive deletions with Node’s built-in fs.rm() / fs.rmSync() to support dependency cleanup and simplify maintenance.
Changes:
- Replaced
rimrafusage in test utilities and common runtime utilities withfs.promises.rm(...). - Added a custom
scripts/clean.jsto replace therimrafCLI usage in npm scripts. - Removed
rimrafand@types/rimraffrompackage.json.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/testutils.ts | Switched test cleanup helper from rimraf to fs.promises.rm. |
| src/common/utils/utils.ts | Replaced rimrafAsync implementation with fs.promises.rm. |
| scripts/clean.js | Introduced a Node-based clean script to replace the rimraf CLI. |
| package.json | Dropped rimraf deps and updated clean scripts to use scripts/clean.js. |
| package-lock.json | Lockfile updated to reflect dependency removal and transitive changes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| await fsPromises.rm(path, { | ||
| recursive: true, | ||
| force: true, | ||
| maxRetries: process.platform === "win32" ? 10 : 0 | ||
| }); |
There was a problem hiding this comment.
Fixed — rmRecursive now wraps fs.promises.rm in try/catch and resolves regardless, with maxRetries: 10 on Windows first. This restores the previous non-flaky teardown behavior and should resolve the four Windows CI failures.
| await fsPromises.rm(path, { | ||
| recursive: true, | ||
| force: true, | ||
| maxRetries: process.platform === "win32" ? 10 : 0 | ||
| }); |
There was a problem hiding this comment.
Resolved by main's engines bump: engines.node is now >= 22.0.0, so fs.promises.rm is guaranteed on every supported version. No fallback needed.
| function rm(target) { | ||
| try { | ||
| fs.rmSync(target, { recursive: true, force: true }); | ||
| } catch (err) { | ||
| if (err.code !== "ENOENT") { | ||
| console.error(`Warning: could not remove ${target}: ${err.message}`); | ||
| } | ||
| } |
There was a problem hiding this comment.
Fixed — the fs.rmSync call now passes maxRetries: 10, retryDelay: 100, matching the retry behavior of the other fs.rm usages in this PR.
| "clean": "node scripts/clean.js", | ||
| "clean:deep": "node scripts/clean.js --deep", |
There was a problem hiding this comment.
Resolved — main has since moved engines.node to >= 22.0.0, which this rebase picks up, so the constraint already guarantees fs.rm support.
|
|
Michael Davey (@md84419), let's address all the issues in the Pull request first. |
|
Akanksha Jain (@jainakanksha-msft) rimraf 3.0.2 is a security vulnerability.
Eliminating the rimraf dependency removes that whole depdency chain and I assume the original author decided it was simpler and more maintainable than getting the code working with the latest rimraf. I guess the bigger question is, what would it take to release a version of azurite with 0 vulnerabilities?
|
|
Michael Davey (@md84419)\ Roli Bosch (@roli-lpci), could you please refresh the PR with main, and address all the issues. |
Replaces the rimraf dependency with Node.js built-in fs.rm()/fs.rmSync(): - src/common/utils/utils.ts: rimrafAsync now wraps fs.promises.rm with recursive/force and Windows retry handling - tests/testutils.ts: rmRecursive uses fs.promises.rm, swallowing cleanup errors to keep test teardown non-flaky (matches prior rimraf behavior) - scripts/clean.js: Node-based clean script replacing the rimraf CLI, with maxRetries/retryDelay for locked files on Windows - package.json / tsconfig.json: drop rimraf and @types/rimraf - package-lock.json: regenerated; rimraf's deprecated dependency chain (glob@7 -> minimatch@3 -> inflight) is fully removed - ChangeLog.md: upcoming-release entry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d988db2 to
4e76c48
Compare
|
Akanksha Jain (@jainakanksha-msft) Done — the branch is refreshed on current main and all four review findings are addressed: |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (2)
scripts/clean.js:56
rmGlob("*.ext")currently deletes dotfiles like.foo.logbecause it matches byendsWith(ext).rimraf/glob-style*.logpatterns typically do not match dotfiles by default, so this can delete more than the old command (and conflicts with the stated “parity”). Consider skipping entries starting with.to better match glob semantics.
for (const entry of entries) {
if (entry.endsWith(ext)) {
rm(path.join(rootDir, entry));
}
}
scripts/clean.js:32
- If
fs.rmSyncfails after retries, the script currently only logs a warning and still exits with status 0. That can mask failures in CI or local workflows that rely onnpm run cleanto guarantee a pristine workspace. Consider setting a non-zero exit code when a removal fails (while still continuing to attempt other targets).
} catch (err) {
if (err.code !== "ENOENT") {
console.error(`Warning: could not remove ${target}: ${err.message}`);
}
}
Summary
rimrafdependency with Node.js built-infs.rm()/fs.rmSync()with{ recursive: true, force: true }rimrafand@types/rimraffrompackage.json(and therimrafentry fromtsconfig.json'stypeslist)scripts/clean.jsto replace therimrafCLI usage in theclean/clean:deepnpm scriptsImpact
Dependency hygiene.
rimraf@3.0.2pins a deprecated dependency chain that npm warns about on every install:rimraf("Rimraf versions prior to v4 are no longer supported"),glob@7("Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version"), andinflight("This module is not supported, and leaks memory"). Removing rimraf eliminates that entire chain — 12 entries drop out ofpackage-lock.json, andrimraf/glob@7no longer appear anywhere in the tree, including transitively.Runtime behavior parity.
rimrafAsyncinsrc/common/utils/utils.tskeeps its exported name and signature, so no call sites change (persistence cleanup in the blob/queue/table Loki stores andFSExtentStore). Like rimraf,fs.rmwithforce: truesucceeds when the target is already missing, andmaxRetries: 10on Windows replaces rimraf's built-in retry behavior for transientEPERM/EBUSYon locked files. Error semantics are unchanged: failures still reject, as the promisified rimraf did.Test helper parity.
rmRecursiveintests/testutils.tspreviously swallowed every cleanup error; the earlier revision of this PR made it reject on non-ENOENTerrors — the likely cause of the four Windows CI job failures (Blob/Queue teardown hitting transientEPERM/EBUSYon locked files). It now retries on Windows and then swallows any remaining error, restoring the original non-flaky teardown behavior.Clean script parity.
scripts/clean.jsremoves exactly the targets the oldrimrafCLI invocation listed (dist typings *.log coverage __testspersistence__ temp __testsstorage__ .nyc_output debug.log *.vsix *.tgz, plus__*forclean:deep), usingfs.rmSyncwithmaxRetries/retryDelayso locked files on Windows are retried rather than left behind.Node compatibility.
fs.rmrequires Node ≥ 14.14.0;main'sengines.nodeis now>= 22.0.0, so it is guaranteed on every supported version. This resolves the two review comments about the old>= 10.0.0engines constraint.Changes since the previous revision
main(resolves the merge conflict)maxRetries/retryDelaytoscripts/clean.jsrimrafentry fromtsconfig.json'stypesarray (new onmainsince the original revision; the build fails without this)Test plan
npm run build,npm run lint— passnpm run test:blob,npm run test:queue,npm run test:package-scripts— pass locally (macOS); these exercisermRecursiveteardown on every suitenpm run clean/npm run clean:deepverified to delete every target of the old rimraf commandsgrep -rn rimraf src/ tests/ scripts/ package.json package-lock.json→ no dependency or import references remain