Add config export utility for verbose webpack/rspack analysis#647
Add config export utility for verbose webpack/rspack analysis#647
Conversation
|
Warning Rate limit exceeded@justin808 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 33 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (7)
WalkthroughAdds a config-exporting toolchain: a Node CLI shim and gem shim, a Rake task, a TypeScript config-exporter package (CLI, serializer, file writer, types, docs), docs updates for usage, and small doctor output guidance referencing the new tool. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer
participant Rake as Rake Task<br/>(shakapacker:export_bundler_config)
participant Bin as bin/export-bundler-config
participant Shim as lib/install/bin/export-bundler-config
participant NodePkg as package/configExporter (run)
participant AppCfg as App Configs
participant Writer as FileWriter / YamlSerializer
participant Out as Output (stdout/files)
Dev->>Rake: rake shakapacker:export_bundler_config [args]
alt binstub present
Rake->>Bin: exec with forwarded args
Bin->>NodePkg: require(...).run(args)
else fallback
Rake->>Shim: exec node install/bin/export-bundler-config [args]
Shim->>NodePkg: require(...).run(args)
end
Note right of NodePkg: parse args, detect bundler/env, load configs
NodePkg->>AppCfg: loadConfigsForEnv(env, bundler)
alt save/write
NodePkg->>Writer: writeMultipleFiles / writeSingleFile(outputs)
Writer-->>Out: files on disk
else stdout
NodePkg-->>Out: printed YAML/JSON/inspect
end
sequenceDiagram
autonumber
actor Dev as Developer
participant Doctor as shakapacker Doctor
participant Console as Console Output
Dev->>Doctor: run diagnostics
Doctor-->>Console: print fix command
Doctor-->>Console: print empty line
Doctor-->>Console: print export-bundler-config guidance (doctor mode) and `--help` hint
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
Code Review for PR #647: Config Export UtilityI've reviewed the pull request and here's my detailed feedback: ✅ Strengths
🔍 Code Quality Issues1. Rake Task Missing Environment Dependency (lib/tasks/shakapacker/export_config.rake:5)The rake task doesn't have :environment dependency like other tasks in the codebase (e.g., doctor.rake). This could cause issues since it references Rails.root. However, looking at info.rake, some tasks don't require :environment. Since this task runs a Node script, :environment may not be necessary, but you should verify Rails.root is available without it. 2. Error Handling in Rake Task (lib/tasks/shakapacker/export_config.rake:16)The system call doesn't check the return value. Consider using exec or checking the result for better error handling. 3. Argument Parsing Fragility (bin/export-config:95-111)Using arg.split('=')[1] doesn't handle edge cases like empty values, multiple equals signs, or space-separated arguments. Consider more robust parsing or document the limitation. 4. NODE_PATH Platform Dependency (bin/export-config:75-76)Uses colon as path separator, which won't work on Windows. Consider using path.delimiter from Node's path module or document Unix-only support. 5. Potential Security Issue (bin/export-config:303)Using require(configFile) with a user-controlled path could be risky if the config file path can be manipulated. While auto-detection mitigates this, consider validating the resolved path is within expected directories. 🐛 Potential Bugs
⚡ Performance Considerations
🔒 Security Concerns
📝 Test CoverageMissing Tests: No automated tests were added for this functionality. Consider adding:
📋 Additional Suggestions
🎯 RecommendationsBefore Merging:
Nice to Have:
Overall AssessmentThis is a well-implemented and useful utility that adds significant debugging value to Shakapacker. The code quality is good, and it follows project conventions. With the suggested fixes, particularly around error handling and testing, this would be production-ready. The PR description shows thorough testing and attention to detail. Great work! 👍 |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
docs/troubleshooting.md (1)
26-46: Add a language hint to the new shell blockmarkdownlint is flagging this fence (MD040). Please tag it as Bash to keep lint clean.
- ```bash + ```bash # Export production config for analysis
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
bin/export-config(1 hunks)docs/troubleshooting.md(12 hunks)lib/install/bin/export-config(1 hunks)lib/shakapacker/doctor.rb(1 hunks)lib/tasks/shakapacker/export_config.rake(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
lib/shakapacker/**/*.rb
📄 CodeRabbit inference engine (CLAUDE.md)
When changing
lib/shakapacker/**/*.rb, run the corresponding spec atspec/shakapacker/**/*_spec.rb
Files:
lib/shakapacker/doctor.rb
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: This gem supports both webpack and rspack configurations
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: This gem supports both webpack and rspack configurations
Applied to files:
lib/install/bin/export-configlib/tasks/shakapacker/export_config.rakebin/export-configdocs/troubleshooting.md
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: Applies to lib/shakapacker/**/*.rb : When changing `lib/shakapacker/**/*.rb`, run the corresponding spec at `spec/shakapacker/**/*_spec.rb`
Applied to files:
lib/tasks/shakapacker/export_config.rake
🪛 GitHub Actions: Ruby based checks
lib/shakapacker/doctor.rb
[error] 834-834: Shakapacker::Doctor with optional peer dependencies doctor reporting with optional dependencies when running full diagnostic provides helpful information about optional dependencies
🪛 markdownlint-cli2 (0.18.1)
docs/troubleshooting.md
52-52: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Test with RSpack
- GitHub Check: Test with Webpack
- GitHub Check: claude-review
- GitHub Check: test
🔇 Additional comments (1)
lib/shakapacker/doctor.rb (1)
832-835: Align Doctor specs with the new guidance linesThe added instructions change the doctor report text, and the CI run is already failing the
Shakapacker::Doctor ... provides helpful information about optional dependenciesspec. Please update the corresponding expectation (or shared fixture) so the test covers the new export-config guidance. See the pipeline failure log linked in the run.
| let config | ||
| try { | ||
| config = require(configFile) | ||
| console.log(`[Config Exporter] Config loaded successfully`) | ||
| } catch (error) { | ||
| console.error(`[Config Exporter] Error loading config:`, error) | ||
| process.exit(1) | ||
| } | ||
|
|
There was a problem hiding this comment.
Support TypeScript configs before requiring them
When the project’s config is webpack.config.ts/rspack.config.ts, require(configFile) throws ERR_UNKNOWN_FILE_EXTENSION because we never register ts-node. Load the TS handler (following the main binstub’s approach) before the require, and unwrap module.default exports so the exporter works for TypeScript setups.
+if (configFile.endsWith(".ts")) {
+ try {
+ require("ts-node/register/transpile-only")
+ } catch (error) {
+ console.error("[Config Exporter] TypeScript config detected but ts-node/register is unavailable.")
+ console.error("Install ts-node (dev dependency) so the exporter can execute TypeScript configs.")
+ process.exit(1)
+ }
+}
+
config = require(configFile)
+if (config && config.__esModule && config.default) {
+ config = config.default
+}📝 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.
| let config | |
| try { | |
| config = require(configFile) | |
| console.log(`[Config Exporter] Config loaded successfully`) | |
| } catch (error) { | |
| console.error(`[Config Exporter] Error loading config:`, error) | |
| process.exit(1) | |
| } | |
| let config | |
| try { | |
| if (configFile.endsWith(".ts")) { | |
| try { | |
| require("ts-node/register/transpile-only") | |
| } catch (error) { | |
| console.error("[Config Exporter] TypeScript config detected but ts-node/register is unavailable.") | |
| console.error("Install ts-node (dev dependency) so the exporter can execute TypeScript configs.") | |
| process.exit(1) | |
| } | |
| } | |
| config = require(configFile) | |
| if (config && config.__esModule && config.default) { | |
| config = config.default | |
| } | |
| console.log(`[Config Exporter] Config loaded successfully`) | |
| } catch (error) { | |
| console.error(`[Config Exporter] Error loading config:`, error) | |
| process.exit(1) | |
| } |
🤖 Prompt for AI Agents
In bin/export-config around lines 398–406, requiring a TypeScript config throws
ERR_UNKNOWN_FILE_EXTENSION because we never register the TS handler; load the
same TS registration used by the main binstub (i.e. require the project's
TS/register module or ts-node/register variant) before calling
require(configFile), then after require unwrap module.default if present (use
config = module.default ?? module) so .ts config files work; keep the existing
try/catch and log/exit behavior.
| let config | ||
| try { | ||
| config = require(configFile) | ||
| console.log(`[Config Exporter] Config loaded successfully`) | ||
| } catch (error) { | ||
| console.error(`[Config Exporter] Error loading config:`, error) | ||
| process.exit(1) | ||
| } | ||
|
|
There was a problem hiding this comment.
Support TypeScript configs before requiring them
We already search for .ts configs in the detection step, but require(configFile) will throw ERR_UNKNOWN_FILE_EXTENSION when the project’s config is written in TypeScript (a common setup for Shakapacker apps). We need to register ts-node (or the same helper we use in the main binstub) before requiring the file, otherwise the exporter exits immediately. Please load the TS loader and, after requiring, unwrap any default export. Mirror the fix here and in bin/export-config.
+ if (configFile.endsWith(".ts")) {
+ try {
+ require("ts-node/register/transpile-only")
+ } catch (error) {
+ console.error("[Config Exporter] TypeScript config detected but ts-node/register is unavailable.")
+ console.error("Install ts-node (dev dependency) so the exporter can execute TypeScript configs.")
+ process.exit(1)
+ }
+ }
+
config = require(configFile)
+ if (config && config.__esModule && config.default) {
+ config = config.default
+ }📝 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.
| let config | |
| try { | |
| config = require(configFile) | |
| console.log(`[Config Exporter] Config loaded successfully`) | |
| } catch (error) { | |
| console.error(`[Config Exporter] Error loading config:`, error) | |
| process.exit(1) | |
| } | |
| let config | |
| try { | |
| if (configFile.endsWith(".ts")) { | |
| try { | |
| require("ts-node/register/transpile-only") | |
| } catch (error) { | |
| console.error("[Config Exporter] TypeScript config detected but ts-node/register is unavailable.") | |
| console.error("Install ts-node (dev dependency) so the exporter can execute TypeScript configs.") | |
| process.exit(1) | |
| } | |
| } | |
| config = require(configFile) | |
| if (config && config.__esModule && config.default) { | |
| config = config.default | |
| } | |
| console.log(`[Config Exporter] Config loaded successfully`) | |
| } catch (error) { | |
| console.error(`[Config Exporter] Error loading config:`, error) | |
| process.exit(1) | |
| } |
🤖 Prompt for AI Agents
In lib/install/bin/export-config around lines 398 to 406, the code uses
require(configFile) which will fail for TypeScript configs; before requiring the
config, require and initialize the project's TS loader (e.g. ts-node/register or
the same helper used by the main binstub) so .ts files can be imported, then
require the config file and if the imported module has a .default export, unwrap
it to get the actual config object; apply the same change to the sibling
bin/export-config script so both paths handle TypeScript configs consistently.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
bin/export-bundler-config (1)
395-403: Handle TypeScript configs before requiring them
webpack.config.ts/rspack.config.tscurrently blow up withERR_UNKNOWN_FILE_EXTENSION, and default-exported configs remain wrapped. Mirror the main binstub: registerts-nodebeforerequire, bail with guidance if it’s missing, and unwrap anymodule.defaultafterwards.+if (configFile.endsWith(".ts")) { + try { + require("ts-node/register/transpile-only") + } catch (error) { + console.error( + "[Config Exporter] TypeScript config detected but ts-node/register is unavailable." + ) + console.error( + "Install ts-node (dev dependency) so the exporter can execute TypeScript configs." + ) + process.exit(1) + } +} + config = require(configFile) +if (config && typeof config === "object" && "default" in config) { + config = config.default +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
bin/export-bundler-config(1 hunks)docs/troubleshooting.md(12 hunks)lib/install/bin/export-bundler-config(1 hunks)lib/shakapacker/doctor.rb(1 hunks)lib/tasks/shakapacker/export_bundler_config.rake(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/shakapacker/doctor.rb
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: This gem supports both webpack and rspack configurations
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: Test changes with both bundlers (webpack and rspack) when modifying core functionality
Applied to files:
bin/export-bundler-config
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: Applies to lib/shakapacker/**/*.rb : When changing `lib/shakapacker/**/*.rb`, run the corresponding spec at `spec/shakapacker/**/*_spec.rb`
Applied to files:
lib/tasks/shakapacker/export_bundler_config.rake
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: This gem supports both webpack and rspack configurations
Applied to files:
lib/tasks/shakapacker/export_bundler_config.rakedocs/troubleshooting.md
🪛 markdownlint-cli2 (0.18.1)
docs/troubleshooting.md
60-60: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (20)
- GitHub Check: Testing (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.6.1.x)
- GitHub Check: Testing (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.6.0.x)
- GitHub Check: Test Bundler Switching
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.4, gemfiles/Gemfile-rails.8.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.0, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: test
- GitHub Check: claude-review
| let config | ||
| try { | ||
| config = require(configFile) | ||
| console.log(`[Config Exporter] Config loaded successfully`) | ||
| } catch (error) { | ||
| console.error(`[Config Exporter] Error loading config:`, error) | ||
| process.exit(1) | ||
| } | ||
|
|
There was a problem hiding this comment.
Handle TypeScript configs before requiring them
Requiring webpack.config.ts/rspack.config.ts fails (ERR_UNKNOWN_FILE_EXTENSION) because we never register the TS loader, and TS configs using export default stay wrapped in module.default. Register ts-node (same as the main binstub) before the require, and unwrap the default export afterwards so .ts configs work end to end.
+```diff
+if (configFile.endsWith(".ts")) {
- try {
- require("ts-node/register/transpile-only")
- } catch (error) {
- console.error(
-
"[Config Exporter] TypeScript config detected but ts-node/register is unavailable." - )
- console.error(
-
"Install ts-node (dev dependency) so the exporter can execute TypeScript configs." - )
- process.exit(1)
- }
+}
config = require(configFile)
+if (config && typeof config === "object" && "default" in config) {
- config = config.default
+}
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **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.
```suggestion
let config
try {
if (configFile.endsWith(".ts")) {
try {
require("ts-node/register/transpile-only")
} catch (error) {
console.error(
"[Config Exporter] TypeScript config detected but ts-node/register is unavailable."
)
console.error(
"Install ts-node (dev dependency) so the exporter can execute TypeScript configs."
)
process.exit(1)
}
}
config = require(configFile)
if (config && typeof config === "object" && "default" in config) {
config = config.default
}
console.log(`[Config Exporter] Config loaded successfully`)
} catch (error) {
console.error(`[Config Exporter] Error loading config:`, error)
process.exit(1)
}
🤖 Prompt for AI Agents
In lib/install/bin/export-bundler-config around lines 395 to 403, the code
directly requires the config file which breaks for TypeScript configs
(ERR_UNKNOWN_FILE_EXTENSION) and leaves default-exported configs under
module.default; before calling require, register ts-node the same way the main
binstub does (import/require and configure ts-node/register or
ts-node/register/transpile-only as appropriate) so .ts files can be required,
then after loading unwrap module.default if present (use config = config &&
config.default ? config.default : config) and proceed; keep existing try/catch
and logging behavior.
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (3)
package/configExporter/fileWriter.ts (2)
19-22: Sanitize filenames to prevent path traversal and accidental absolute pathsIf output.filename is absolute or contains separators, resolve(targetDir, output.filename) can escape targetDir. Use basename to constrain writes to targetDir.
Apply this diff:
- const filePath = resolve(targetDir, output.filename) + const safeName = require("path").basename(output.filename) + const filePath = resolve(targetDir, safeName) this.writeFile(filePath, output.content)
13-27: Call validateOutputPath before writing to diskCurrently validateOutputPath isn’t used. Invoke it to warn users automatically.
Apply this diff:
writeMultipleFiles(outputs: FileOutput[], targetDir: string): void { // Ensure directory exists this.ensureDirectory(targetDir) // Write each file outputs.forEach((output) => { - const filePath = resolve(targetDir, output.filename) + const safeName = require("path").basename(output.filename) + const filePath = resolve(targetDir, safeName) + this.validateOutputPath(filePath) this.writeFile(filePath, output.content) console.log(`[Config Exporter] Created: ${filePath}`) }) @@ writeSingleFile(filePath: string, content: string): void { // Ensure parent directory exists const dir = dirname(filePath) this.ensureDirectory(dir) + this.validateOutputPath(filePath) this.writeFile(filePath, content) console.log(`[Config Exporter] Config exported to: ${filePath}`) }Also applies to: 32-39
package/configExporter/yamlSerializer.ts (1)
1-222: Consider delegating YAML emission to js-yaml and customizing only special casesManually emitting YAML is brittle (quoting, edge cases, anchors, escapes). Use js-yaml for core serialization and post-process functions/RegExps as strings or via custom types. This reduces correctness risks and maintenance.
Based on learnings (js-yaml 4.1.0): Prefer yaml.dump(obj, { lineWidth: 120, noRefs: true, sortKeys: true }) and pre-walk the config to stringify functions/RegExps; or define custom types for them.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
bin/export-bundler-config(1 hunks)lib/install/bin/export-bundler-config(1 hunks)package.json(1 hunks)package/configExporter/cli.ts(1 hunks)package/configExporter/configDocs.ts(1 hunks)package/configExporter/fileWriter.ts(1 hunks)package/configExporter/index.ts(1 hunks)package/configExporter/types.ts(1 hunks)package/configExporter/yamlSerializer.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
package/configExporter/cli.ts (2)
package/configExporter/types.ts (3)
ExportOptions(1-15)FileOutput(32-36)ConfigMetadata(17-30)package/configExporter/yamlSerializer.ts (1)
makePathRelative(208-221)
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
docs/troubleshooting.md (1)
78-80: Add the fenced code language.This block still needs a language hint for markdownlint (MD040). Please change the opening fence to ```bash.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
docs/troubleshooting.md(12 hunks)lib/shakapacker/doctor.rb(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- lib/shakapacker/doctor.rb
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-28T02:23:21.827Z
Learnt from: CR
PR: shakacode/shakapacker#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-28T02:23:21.827Z
Learning: This gem supports both webpack and rspack configurations
Applied to files:
docs/troubleshooting.md
🪛 markdownlint-cli2 (0.18.1)
docs/troubleshooting.md
78-78: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Generator specs (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
- GitHub Check: Generator specs (ubuntu-latest, 2.7, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.1.x)
- GitHub Check: Generator specs (ubuntu-latest, 3.1, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Testing (ubuntu-latest, 3.3, gemfiles/Gemfile-rails.7.2.x)
- GitHub Check: Testing (ubuntu-latest, 3.2, gemfiles/Gemfile-rails.7.0.x)
|
@claude review this PR |
|
Claude finished @justin808's task —— View job PR Review: Config Export UtilityI've completed a thorough review of this PR. This is a well-designed and useful utility that will significantly help users debug webpack/rspack configurations. However, there are several critical issues that must be addressed before merging, plus some important improvements. 🔴 Critical Issues1. TypeScript Config Support Missing (cli.ts:278, both bin files)Impact: The utility will crash with Fix Required: Before // Handle TypeScript configs
if (configFile.endsWith(".ts")) {
try {
require("ts-node/register/transpile-only")
} catch (error) {
throw new Error(
"TypeScript config detected but ts-node/register/transpile-only could not be loaded. " +
"Install ts-node as a dev dependency to execute TypeScript configs."
)
}
}
delete require.cache[require.resolve(configFile)]
let loadedConfig = require(configFile)
// Unwrap default exports from ES modules
if (loadedConfig && typeof loadedConfig === "object" && "default" in loadedConfig) {
loadedConfig = loadedConfig.default
}Apply the same fix to both Reference: CodeRabbit correctly identified this issue in their review. 2. Default Values Not Applied (cli.ts:126-138)Impact: The
Fix Required: function applyDefaults(options: ExportOptions): void {
if (options.doctor) {
options.save = true
}
if (options.format === undefined) {
options.format = options.doctor || options.save ? "yaml" : "inspect"
}
if (options.annotate === undefined) {
options.annotate = Boolean(options.doctor || options.save)
}
}Reference: CodeRabbit identified this in their review at cli.ts:138. 3. YAML Serialization Produces Invalid YAMLMultiple Problems: a) Function serialization breaks (yamlSerializer.ts:109-126): Functions containing quotes are wrapped in raw double quotes without escaping: private serializeFunction(fn: Function): string {
const source = fn.toString()
const compacted = source
.split("\n")
.map((line) => line.trim())
.filter((line) => line.length > 0)
.join(" ")
if (compacted.length > 500) {
return this.serializeString(compacted.substring(0, 500) + "...") // ← Use existing escaper
}
return this.serializeString(compacted) // ← Use existing escaper
}b) Array items with objects/multiline mis-indented (yamlSerializer.ts:128-149): Nested objects in arrays lose indentation: private serializeArray(arr: any[], indent: number, keyPath: string): string {
if (arr.length === 0) return "[]"
const lines: string[] = []
const itemIndent = " ".repeat(indent + 2)
const nestedIndent = indent + 4
arr.forEach((item, index) => {
const itemPath = `${keyPath}[${index}]`
if (item && typeof item === "object" && !Array.isArray(item)) {
// Nested object → dash on own line, then indented block
lines.push(`${itemIndent}-`)
lines.push(this.serializeObject(item, nestedIndent, itemPath))
} else if (Array.isArray(item)) {
lines.push(`${itemIndent}-`)
lines.push(this.serializeArray(item, nestedIndent, itemPath))
} else if (typeof item === "string" && item.includes("\n")) {
lines.push(`${itemIndent}- |`)
for (const line of item.split("\n")) {
lines.push(`${" ".repeat(nestedIndent)}${line}`)
}
} else {
const serialized = this.serializeValue(item, indent + 2, itemPath)
lines.push(`${itemIndent}- ${serialized}`)
}
})
return "\n" + lines.join("\n")
}c) Multiline string values under keys (yamlSerializer.ts:161-202): Block scalars need proper indentation: // In serializeObject, before const serialized = ... line:
if (typeof value === "string" && value.includes("\n")) {
lines.push(`${keyIndent}${key}: |`)
for (const line of value.split("\n")) {
lines.push(`${valueIndent}${line}`)
}
return // early return
}Reference: CodeRabbit identified all three YAML issues. 4. Path Validation Issues (fileWriter.ts:72-81)Problems:
Fix Required: import { resolve, dirname, relative, isAbsolute } from "path"
import { tmpdir } from "os"
validateOutputPath(outputPath: string): void {
const absPath = resolve(outputPath)
const cwd = process.cwd()
const isWithin = (base: string, target: string) => {
const rel = relative(base, target)
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel))
}
if (!isWithin(cwd, absPath) && !isWithin(tmpdir(), absPath)) {
console.warn(
`[Config Exporter] Warning: Writing to ${absPath} which is outside ` +
`current directory (${cwd}) or temp (${tmpdir()})`
)
}
}5. Windows Path Handling (yamlSerializer.ts:208-221)Problem: Fix Required: import { relative, isAbsolute } from "path"
private makePathRelative(str: string): string {
if (typeof str !== "string") return str
try {
const rel = relative(this.appRoot, str)
const within = rel === "" || (!rel.startsWith("..") && !isAbsolute(rel))
if (within) return rel === "" ? "." : `./${rel}`
} catch {
// fall through
}
return str
}🟡 Major Issues6. Missing TestsNo automated tests were added for this significant new feature. The PR description mentions manual testing, but lacks:
Recommendation: Add at least basic integration tests before merge. Consider testing:
7. Doctor.rb Spec FailureThe changes to Fix Required: Update the corresponding spec to expect the new guidance text about 8. validateOutputPath Never CalledThe Fix Required: Call it before writes: writeSingleFile(filePath: string, content: string): void {
const dir = dirname(filePath)
this.ensureDirectory(dir)
this.validateOutputPath(filePath) // ← Add this
this.writeFile(filePath, content)
console.log(`[Config Exporter] Config exported to: ${filePath}`)
}Also add to 9. Filename Sanitization Missing (fileWriter.ts:19-22)If Fix Required: import { basename } from "path"
writeMultipleFiles(outputs: FileOutput[], targetDir: string): void {
this.ensureDirectory(targetDir)
outputs.forEach((output) => {
const safeName = basename(output.filename) // ← Sanitize
const filePath = resolve(targetDir, safeName)
this.validateOutputPath(filePath)
this.writeFile(filePath, output.content)
console.log(`[Config Exporter] Created: ${filePath}`)
})
// ...
}🔵 Minor Issues & Suggestions10. Consider Using js-yaml for YAMLThe manual YAML serialization in Benefits:
Reference: CodeRabbit suggested this. 11. Markdownlint Warning (docs/troubleshooting.md:78-80)Missing language hint on fenced code block triggers MD040: -```
+```bash
NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.json |
|
@claude review this PR |
|
Claude finished @justin808's task —— View job Code Review for PR #647: Config Export UtilityI've completed a comprehensive review of this PR. This is excellent work that adds significant value for debugging webpack/rspack configurations. The TypeScript refactoring is well-structured and the feature is thoughtfully designed. However, I found that all critical issues identified by CodeRabbit have already been fixed in recent commits! 🎉 ✅ Previously Critical Issues - NOW FIXED1. ✅ TypeScript Config Support (cli.ts:277-290)Status: Fixed in commit 0b2275f The code now properly handles TypeScript configs: if (configFile.endsWith(".ts")) {
require("ts-node/register/transpile-only")
}
// ...
if (typeof loadedConfig === "object" && "default" in loadedConfig) {
loadedConfig = loadedConfig.default
}2. ✅ Default Value Logic (cli.ts:126-138)Status: Fixed in commits 0b2275f and e5e3e54 Defaults now correctly check for if (options.format === undefined) {
options.format = options.doctor || options.save ? "yaml" : "inspect"
}3. ✅ YAML Function Serialization (yamlSerializer.ts:111-129)Status: Fixed in commit 0b2275f Functions now use return this.serializeString(compacted) // ✓ Properly escaped4. ✅ YAML Array Indentation (yamlSerializer.ts:131-163)Status: Fixed in commit 0b2275f Arrays with nested objects now properly indent content: if (typeof item === "object" && !Array.isArray(item) && item !== null) {
lines.push(`${itemIndent}-`)
serialized.split("\n").forEach((line: string) => {
lines.push(contentIndent + line)
})
}5. ✅ YAML Multiline Strings (yamlSerializer.ts:188-192)Status: Fixed in commit 0b2275f Multiline strings now use block scalar syntax: if (typeof value === "string" && value.includes("\n")) {
lines.push(`${keyIndent}${key}: |`)
for (const line of value.split("\n")) {
lines.push(`${valueIndent}${line}`)
}
}6. ✅ Path Validation (fileWriter.ts:76-89)Status: Fixed in commit 0b2275f Now uses const isWithin = (base: string, target: string) => {
const rel = relative(base, target)
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel))
}
if (!isWithin(cwd, absPath) && !isWithin(tmpdir(), absPath)) {
console.warn(...)
}7. ✅ Cross-Platform Path Handling (yamlSerializer.ts:226-243)Status: Fixed in commit 0b2275f Now uses Node's const rel = relative(this.appRoot, str)
if (rel === "") return "."
if (rel.startsWith("..") || isAbsolute(rel)) return str
return "./" + rel8. ✅ Filename Sanitization (fileWriter.ts:19-25)Status: Fixed in commit 4062ada Filenames are now sanitized with const safeName = basename(output.filename)
const filePath = resolve(targetDir, safeName)9. ✅ validateOutputPath Called (fileWriter.ts:22, 40)Status: Fixed in commit 4062ada Validation is now invoked before writes: this.validateOutputPath(filePath) // ✓ Called
this.writeFile(filePath, output.content)🟢 Code Quality AssessmentStrengths
🟡 Minor Issues & Suggestions1. Documentation Reference Inconsistency (docs/troubleshooting.md)Severity: Minor (cosmetic) The troubleshooting docs were updated in commit 471fc3e to reference the new utility, but all examples still use the correct command name 2. Markdown Linting (docs/troubleshooting.md:78-80)Severity: Trivial One fenced code block is missing a language hint: -```
+```bash
NODE_ENV=development bin/shakapacker --profile --json > /tmp/webpack-stats.jsonHowever, the current manual approach gives you more control over formatting and annotations, which is valuable for this use case. Either approach is valid. 4. Test CoverageSeverity: Recommended No automated tests were added for this new functionality. Consider adding:
Per CLAUDE.md guidelines, you should also update the doctor.rb spec since you modified that file (line 832-836). 📋 Project Guidelines Compliance✅ Followed Correctly
|
This commit adds a new bin/export-config utility and rake task for exporting webpack or rspack configurations in a verbose, human-readable format. This tool is useful for comparing configurations across different environments, bundle types, and bundlers. Features: - Auto-detects bundler from shakapacker.yml or accepts --bundler flag - Supports all environments: development, production, test - Supports bundle types: client, server, both (via env vars like WEBPACK_SERVE) - Two output formats: inspect (default, colored) and json - Outputs to file or stdout - Includes metadata about export context (env vars, timestamps, etc.) Usage examples: bin/export-config --bundle-type=client bin/export-config --env=production --bundle-type=both --format=json --output=config.json bundle exec rake shakapacker:export_config -- --bundler=rspack Files added: - bin/export-config: Main Node.js CLI utility - lib/install/bin/export-config: Installable version for new projects - lib/tasks/shakapacker/export_config.rake: Rake task wrapper 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit addresses security and cross-platform concerns in the config export utility based on code review feedback. Changes: - Use path.delimiter instead of hardcoded ':' for NODE_PATH (Windows support) - Fix root directory detection to work on Windows (use path.sep) - Improve argument parsing with validation for empty values - Add default depth of 10 to prevent stack overflow with circular refs - Add path validation warning when writing outside current directory - Replace system() with exec() in rake task for proper exit code handling - Use Shakapacker::Env.current_dir instead of Rails.root (no :environment dependency) - Document Module._initPaths() as internal API with version requirement Security improvements: - Validate output paths and warn on suspicious locations - Prevent empty argument values - Better error handling throughout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
This commit enhances documentation and tooling around the new config export utility to make it more discoverable for users debugging issues or performing migrations. Documentation updates (docs/troubleshooting.md): - Add comprehensive section on exporting webpack/rspack configs - Highlight three key use cases: migrations, debugging, AI analysis - Provide practical examples for common scenarios: - Comparing webpack vs rspack configs - Exporting client/server bundle configs - Using JSON format for programmatic analysis - Reorder existing documentation for better flow Doctor command integration (lib/shakapacker/doctor.rb): - Add helpful reminder at end of doctor output - Suggest running export-config when issues are found - Include current environment in suggestion - Point users to --help for more options Benefits: - Users debugging config issues will discover the export tool via doctor - Migration paths between webpack/rspack are clearer - Easier troubleshooting with AI tools (ChatGPT, etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…nv.current_dir The export_config rake task was incorrectly trying to use Shakapacker::Env.current_dir which doesn't exist. Changed to use Rails.root which is the standard approach used by other rake tasks in the codebase (see info.rake, binstubs.rake). Fixes NoMethodError when running: rake shakapacker:export_config 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Users upgrading shakapacker shouldn't need to reinstall binstubs just to use the new export-config utility. The rake task now: 1. First tries to use bin/export-config if it exists (installed via binstubs) 2. Falls back to using the gem's version directly with a helpful note 3. Suggests running 'rake shakapacker:binstubs' to install the binstub This provides a seamless experience for existing users while still encouraging the binstub installation for better performance and convenience. Before: - Would error if bin/export-config wasn't installed - Required running shakapacker:binstubs first After: - Works immediately without any installation - Provides a helpful note about installing the binstub - Both paths tested and working 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
The verbose output was overwhelming with noise: - 100+ environment variables from EnvironmentPlugin (repeated per bundle) - Long absolute paths taking up space - Functions shown as '[Function: name]' without useful info This commit adds --compact and --show-functions flags: --compact (recommended): - Filters EnvironmentPlugin to only show webpack/shakapacker relevant vars (NODE_ENV, RAILS_ENV, WEBPACK_SERVE, etc.) - Converts absolute paths to relative paths (./public/packs vs /full/path/...) - Reduces output by ~120 lines while keeping all important config --show-functions: - Includes full function source code for generators/loaders - Useful for debugging custom webpack functions - Verbose, so off by default Example usage: bin/export-config --compact # Cleaner output (recommended) bin/export-config --compact --show-functions # See function code Benefits: - Easier to compare configs (less noise to scroll through) - Better for AI analysis (more signal, less noise) - Paths are portable (relative vs absolute) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Based on feedback, made --compact mode even better:
1. **Completely remove EnvironmentPlugin keys and defaultValues**:
- Before: Filtered to ~10 relevant vars, still showing keys/defaultValues arrays
- After: Removes keys/defaultValues entirely from EnvironmentPlugin
- Saves even more lines of noise
2. **Always show function source code in compact mode**:
- Before: Functions shown as '[Function: functionName]' (not useful)
- After: Shows actual function source, compacted to single line
- Example: 'generate: function(seed, files) { return files.reduce(...) }'
- Useful for understanding webpack loaders, generators, and hooks
3. **Remove --show-functions flag** (no longer needed):
- Compact mode now always includes function source
- Functions are compacted (whitespace removed) to keep output dense
Results:
- **171 lines removed** from original (724 → 553 lines)
- **24% smaller** while showing MORE useful information
- EnvironmentPlugin completely clean (no env var noise)
- Functions are inspectable (not opaque)
- Paths are relative (portable)
Perfect for comparing configs or feeding to AI tools.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
The name 'export-config' was too generic. 'export-bundler-config' makes it clear this utility exports webpack/rspack bundler configurations specifically. Changes: - Renamed bin/export-config → bin/export-bundler-config - Renamed lib/install/bin/export-config → lib/install/bin/export-bundler-config - Renamed rake task: export_config → export_bundler_config - Updated all documentation references in docs/troubleshooting.md - Updated doctor.rb to reference new name - Added --compact flag to all examples (recommended default) - Updated help text and usage examples in the script Usage: bin/export-bundler-config --compact rake shakapacker:export_bundler_config -- --compact 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…React on Rails compatibility This change improves the export-bundler-config utility to better support React on Rails applications that use separate client and server webpack configs. Key improvements: - Replace --bundle-type=client|server|both with --client-only and --server-only flags - Add validation to ensure --client-only and --server-only are mutually exclusive - Set CLIENT_BUNDLE_ONLY=yes for --client-only (instead of WEBPACK_SERVE) - Set SERVER_BUNDLE_ONLY=yes for --server-only - Default behavior (no flags) generates both client and server configs - Improve multi-config array output handling: - Display total config count when N > 1 - Label each config in array: "--- Config [0] ---", "--- Config [1] ---" - Apply cleaning to each config individually in compact mode - Add configCount to metadata - Remove WEBPACK_SERVE from metadata (no longer used) - Update all documentation and examples - Function source code is always shown (removed --show-functions flag) - Compact mode is now the default (use --verbose for raw output) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Webpack/rspack configs can have deeply nested structures (e.g., module.rules[].use[].options.jsc.parser.syntax is depth 7). Setting depth to 20 ensures we don't truncate nested config objects. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Created modular TypeScript architecture in package/configExporter/: - types.ts: Interfaces for ExportOptions, ConfigMetadata, FileOutput - configDocs.ts: Documentation mapping for webpack/rspack config keys This is the foundation for the --doctor and --save features. Next steps: yamlSerializer, fileWriter, cli modules. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Complete core TypeScript modules for config export feature:
- yamlSerializer.ts: Serializes configs to YAML with optional inline docs
- Handles functions (show source), RegExp, special objects
- Makes paths relative for cleaner output
- Adds documentation comments when --annotate enabled
- fileWriter.ts: Writes config files with smart naming
- Generates filenames: {bundler}-{env}-{type}.{ext}
- Supports multi-file output (one per config)
- Creates directories as needed
Still TODO: cli.ts (main CLI logic), then compile and test.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Major refactoring from 502-line bin script to modular TypeScript:
**New TypeScript Modules** (package/configExporter/):
- cli.ts: Main CLI logic (~571 lines) with arg parsing, validation, config loading
- index.ts: Public API exports
- Fixed type errors and added package.json export
**Simplified bin script**:
- Reduced from 502 lines to 11 lines
- Now just a shim that calls the TS module
- All logic moved to maintainable TypeScript
**Features Implemented**:
- --doctor: Export both dev + prod configs (annotated YAML)
- --save: Export current env with auto-generated filenames
- --save-dir: Specify output directory
- Multi-file output (one per config type: client/server)
- YAML format with inline documentation
- Backward compatible with all existing flags
**File naming**: {bundler}-{env}-{type}.{ext}
Examples: webpack-development-client.yaml, rspack-production-server.yaml
Help command working. Next: test functionality, update docs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <[email protected]>
Updated troubleshooting guide and doctor command: **docs/troubleshooting.md**: - Prominently feature --doctor as RECOMMENDED quick troubleshooting - Show all new flags: --save, --save-dir, --no-annotate - Document auto-generated filename pattern - Explain YAML annotations and multi-file output - Add comparison workflow examples **lib/shakapacker/doctor.rb**: - Update suggestion to use --doctor flag - Explain it exports dev + prod configs with annotations - Better help text for users The --doctor flag is now the recommended way to export configs for troubleshooting, AI analysis, and configuration comparison. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
**Path handling fixes:** - Replace string startsWith checks with path.relative for proper cross-platform path validation - Fix makePathRelative to use path.relative instead of hardcoded "/" separator - Update validateOutputPath to use os.tmpdir() instead of hardcoded "/tmp" - Add proper isAbsolute guards to prevent false positives on Windows **YAML serialization fixes:** - Fix multiline string indentation to use dynamic indent based on nesting level - Fix array item indentation to properly indent nested objects and multiline strings - Emit array markers on separate lines for complex content with proper 2-space sub-indentation - Fix function source escaping to use serializeString helper for proper quote/special char handling **TypeScript config loading:** - Add ts-node/register/transpile-only support for loading .ts config files - Handle ES module default exports by checking for .default property - Prevent ERR_UNKNOWN_FILE_EXTENSION errors when requiring TypeScript configs All changes maintain backward compatibility and improve reliability across platforms. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Changed null checks to undefined checks in applyDefaults() so that defaults are properly applied when values are unset. Previously, parseArguments set options to undefined but applyDefaults checked for null, causing defaults to never apply. This ensures: - --doctor mode defaults to YAML + annotated when not explicitly set - --save mode defaults to YAML + annotated when not explicitly set - stdout mode defaults to inspect + no annotations when not explicitly set - Explicitly provided flags (including false) are never overwritten 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
**YAML Serialization Fixes:** - Fix multiline string values under object keys to use proper block scalar (|) syntax - Multiline strings in objects now properly indented with valueIndent **File Security & Validation:** - Add basename() sanitization to prevent path traversal in writeMultipleFiles - Call validateOutputPath() in both writeSingleFile and writeMultipleFiles - Ensure filenames cannot escape target directory **Documentation:** - Add bash language hint to code fence at line 78 (fixes MD040 markdownlint warning) All changes address issues identified in code review while maintaining backward compatibility. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
**Output organization:** - Create dedicated `shakapacker-config-exports/` subdirectory for --doctor output - Add directory to .gitignore to keep working directory tidy **YAML formatting improvements:** - Remove extra blank lines between array items for cleaner output - Pretty-print functions with proper indentation instead of single-line compacting - Add documentation comments for array items (including plugins) - Skip empty lines in serialized content **Environment isolation:** - Fix dev/prod configs being identical by clearing module cache more aggressively - Clear all webpack/rspack config modules from require cache between environment loads - Ensures NODE_ENV changes properly affect config generation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
4062ada to
441c850
Compare
|
Claude finished @justin808's task —— View job Code Review for PR #647: Config Export UtilityI've completed a thorough review of this PR. This is an excellent and well-designed feature that adds significant value for debugging webpack/rspack configurations. The TypeScript refactoring is clean and the implementation is comprehensive. However, I found one critical issue that must be fixed before merging. 🔴 Critical IssueRegExp/String Escaping Missing Backslash Handling (yamlSerializer.ts:105)Severity: Critical - Can produce invalid YAML output The string serialization at line 105 in Problem Example:
Current code (line 105): return `"${cleaned.replace(/"/g, '\\"')}"`Fixed code (escape backslashes FIRST, then quotes): // Escape backslashes first, then quotes to avoid double-escaping
return `"${cleaned.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`Why this matters: Webpack/rspack configs commonly use RegExp patterns with backslashes (e.g., Note: I see commit 9b773fd titled "Fix RegExp serialization to properly escape quotes and backslashes" but the actual code at line 105 doesn't escape backslashes. This fix needs to be applied. ✅ Previously Critical Issues - NOW FIXEDExcellent work! All the critical issues identified by CodeRabbit in previous reviews have been properly addressed:
📋 Code Quality AssessmentStrengths ⭐⭐⭐⭐⭐
🟡 Minor Issues & Suggestions1. Documentation Integration (docs/troubleshooting.md)✅ Well done! The documentation is comprehensive with:
The only minor note: Line 78 has a code block without a language hint (markdown lint warning), but this is trivial. 2. Doctor.rb Integration (lib/shakapacker/doctor.rb:877-892)✅ Great addition! The guidance about using
3. Rake Task (lib/tasks/shakapacker/export_bundler_config.rake)✅ Excellent implementation!
4. Consider js-yaml for YAML Generation (Suggestion, Not Required)The manual YAML serialization is well-implemented and handles edge cases correctly. However, using
But the current approach gives you fine control over formatting and annotations, which is valuable. Either approach is valid. 🧪 Test CoverageIssue: No automated tests were added for this significant new feature. Missing:
Per CLAUDE.md Guidelines:
Action Required: bundle exec rspec spec/shakapacker/doctor_spec.rb
# Update expectations if the new output text breaks testsRecommendation: Add at least basic integration tests before or shortly after merge. Consider:
🎯 Required Before MergeMust Fix (Blocking):
Recommended (Strongly Advised):
💯 Overall AssessmentRating: ⭐⭐⭐⭐½ (4.5/5) This is outstanding work! The feature is thoughtfully designed, comprehensively implemented, and solves a real pain point for debugging webpack/rspack configurations. The What Makes This Excellent:
What Needs Fixing:
Verdict: The PR is in excellent shape overall. Fix the backslash escaping bug (critical), verify the doctor spec passes, run linters, and this is ready to merge. The missing automated tests are a concern but not blocking given the comprehensive manual testing described in the PR and the 28 commits of iteration showing thorough testing. 🔧 Quick Fix Checklist
🎉 Closing ThoughtsThis is a fantastic addition to Shakapacker! The Once the small escaping fix is applied and specs/linters pass, this will be an excellent contribution. Great work, Justin! 👏 View job • Branch: |
- Detailed usage instructions with examples - Documents all common options - Explains rake vs rails invocation differences - Notes about binstub fallback behavior
Critical fixes: - Escape backslashes before quotes in serializeString to prevent invalid YAML - Handles RegExp patterns correctly (e.g., patterns with backslashes and quotes) Spec updates: - Updated doctor_spec.rb binstub checks to cover both shakapacker and export-bundler-config - Added comprehensive test cases for all binstub scenarios - All 93 examples passing
|
@claude review this pr |
|
Claude finished @justin808's task —— View job Code Review for PR #647: Config Export UtilityI've completed a comprehensive review of this PR. This is excellent work that adds significant value for debugging webpack/rspack configurations. The TypeScript refactoring is clean and the implementation is thorough. However, I found one critical issue that must be fixed before merging. 🔴 Critical IssueRegExp Serialization Missing Escaping (yamlSerializer.ts:71)Severity: Critical - Produces invalid YAML output The RegExp serialization wraps Current code (line 70-72): if (value instanceof RegExp) {
return `"${value.toString()}"` // ❌ No escaping
}Example failure: The regex Fix Required: Use the existing if (value instanceof RegExp) {
return this.serializeString(value.toString()) // ✅ Properly escaped
}Location: 🟡 Major Issues1. Missing ts-node Error Handling (cli.ts:321-324)Severity: Major - Will crash with unhelpful error if ts-node not installed The code attempts to Fix Required: if (configFile.endsWith(".ts")) {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
require("ts-node/register/transpile-only")
} catch (error) {
throw new Error(
"TypeScript config detected but ts-node is not available. " +
"Install ts-node as a dev dependency: npm install --save-dev ts-node"
)
}
}Location: 2. Doctor.rb Spec May Fail (spec impact)The changes to Action Required: Update the corresponding spec at ✅ Strengths
📋 Code Quality AssessmentSecurity ✅
Performance ✅
Maintainability ✅
🧪 Test CoverageIssue: No automated tests were added for this significant new feature. Missing:
Recommendation: Add at least:
📏 Project Guidelines Compliance (CLAUDE.md)✅ Followed
|
- Set release date for v9.1.1 as October 9, 2025 - Add note about switch_bundler integration in CHANGELOG - Add Debugging Configuration section to README - Add config export utility to rspack migration guide with comparison workflow - Document integration with switch_bundler feature
Summary
bin/export-bundler-configutility for exporting webpack/rspack configurationsMotivation
When comparing webpack/rspack configurations across different environments or debugging configuration issues, it's helpful to have a utility that can export the entire resolved configuration in a verbose, inspectable format. This is particularly useful for:
Key Features
🏥 Doctor Mode (Recommended)
shakapacker-config-exports/.gitignoresuggestions💾 Save Mode
📺 Stdout Mode
Implementation Highlights
Smart Environment Isolation
require.cachefor config files AND shakapacker modulesNODE_ENV/RAILS_ENVchanges are properly detectedYAML Serialization
Security & Validation
shakapacker.yml(prevents typos)User Experience
shakapacker.yml--helpdocumentationUsage Examples
Test Plan
bundle exec rubocopyarn lintFiles Changed
New Files
package/configExporter/cli.ts- Main CLI logic with doctor/save/stdout modespackage/configExporter/yamlSerializer.ts- Custom YAML serializerpackage/configExporter/fileWriter.ts- Safe file writing with validationpackage/configExporter/index.ts- Public APIlib/install/bin/export-bundler-config- Binary for new installationslib/tasks/shakapacker/export_bundler_config.rake- Rake task wrapperModified Files
docs/troubleshooting.md- Added comprehensive export utility documentation.gitignore- Addedshakapacker-config-exports/Breaking Changes
None - this is a new utility.
Related Issues
Lays groundwork for future config diff feature tracked in #667
🤖 Generated with Claude Code
Summary by CodeRabbit