Skip to content

Conversation

@michieldegezelle
Copy link
Contributor

Fixes # (link to the corresponding issue if applicable)

Description

Include a summary of the changes made

Testing Instructions

Steps:

  1. ...
  2. ...
  3. ...

Author Checklist

  • Skip bumping the CLI version

Reviewer Checklist

  • PR has a clear title and description
  • Manually tested the changes that the PR introduces
  • Changes introduced are covered by tests of acceptable quality

@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

Walkthrough

Adds variadic CLI options for run-test, refactors runTestsStatusOnly to accept and evaluate multiple handles in parallel (aggregating PASSED/FAILED), updates control flow for status vs non-status modes, bumps package to 1.52.0 and adds a changelog entry.

Changes

Cohort / File(s) Summary
Package & Changelog
CHANGELOG.md, package.json
Bumped package version to 1.52.0 and added a changelog entry describing parallel status-mode test execution when multiple handles are supplied.
CLI command
bin/cli.js
run-test options changed to variadic: -h, --handle <handle...> and -at, --account-template <name...>; action handler made async; input validation added to require --status for multiple names and to route to status vs non-status execution paths (status: allow arrays; non-status: use first name).
Test runner
lib/liquidTestRunner.js
runTestsStatusOnly signature changed to accept handles (array); added runSingleHandle helper; per-handle evaluation runs in parallel via Promise.all; aggregates per-handle results into an overall PASSED/FAILED return and logs per-handle statuses and failed test names.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is an unfilled template with only placeholder text and no actual implementation details, testing steps, changes summary, or information about the corresponding issue. Provide a concrete description summarizing the changes: explain that multiple handles are now supported in parallel for run-test with --status flag, add actual testing steps, and link to the corresponding issue if applicable.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Run multiple handles in parallel' directly describes the main change—enabling parallel test execution for multiple handles with the --status flag, which is the core feature of this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
bin/cli.js (1)

466-477: Reject --handle and --account-template used together (ambiguous template type).

Both options can currently be passed simultaneously. When they are, templateType silently prefers --handle (line 476), leaving --account-template ignored without warning. Add an explicit mutual-exclusion check to prevent this ambiguity.

Proposed fix
   .action(async (options) => {
     if (!options.handle && !options.accountTemplate) {
       consola.error("You need to specify either a reconciliation handle or an account template");
       process.exit(1);
     }

+    if (options.handle && options.accountTemplate) {
+      consola.error('You cannot use both "--handle" and "--account-template" at the same time');
+      process.exit(1);
+    }
🤖 Fix all issues with AI agents
In @bin/cli.js:
- Around line 495-499: The CLI ignores the return value of
liquidTestRunner.runTestsStatusOnly in the options.status branch causing tests
to always exit 0; capture the result of liquidTestRunner.runTestsStatusOnly
(which returns "PASSED" or "FAILED") and call process.exit(1) when the result
indicates failure (e.g., result !== "PASSED"), otherwise exit 0 or simply
return; update the block handling options.status (where runTestsStatusOnly is
invoked) to check the returned status and propagate a non-zero exit code for
failures so CI/CD can detect test failures.

In @CHANGELOG.md:
- Around line 5-8: The changelog uses a locale-ambiguous date format in the
release header "## [1.52.0] (12/01/2026)"; update that header to use an
unambiguous ISO-8601 date like "## [1.52.0] (2026-01-12)" so the date format is
consistent and clear across locales.

In @package.json:
- Line 3: The package.json "version" field was changed to "1.52.0"—confirm
whether this version bump is intentional per your release process and the PR
template checkbox "Skip bumping the CLI version"; if it was unintentional,
revert the change to the version field in package.json, otherwise add a note in
the PR description documenting that the bump is deliberate and aligns with the
release workflow.
🧹 Nitpick comments (1)
lib/liquidTestRunner.js (1)

518-522: Consider a concurrency limit for many handles (avoid API rate limiting / noisy logs).

Promise.all will fan out requests for all handles at once; if users pass many handles, this can spike load and increase failures. Consider bounding concurrency (e.g., p-limit).

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0736b0 and 4178f1e.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (4)
  • CHANGELOG.md
  • bin/cli.js
  • lib/liquidTestRunner.js
  • package.json
🧰 Additional context used
🧬 Code graph analysis (1)
bin/cli.js (3)
lib/liquidTestRunner.js (1)
  • options (16-16)
lib/cli/utils.js (1)
  • options (89-89)
lib/cli/devMode.js (1)
  • liquidTestRunner (4-4)

Comment on lines 495 to +499
if (options.status) {
liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
} else {
if (options.previewOnly && !options.htmlInput && !options.htmlPreview) {
consola.info(`When using "--preview-only" you need to specify at least one of the following options: "--html-input", "--html-preview"`);
process.exit(1);
}
liquidTestRunner.runTestsWithOutput(options.firm, templateType, templateName, options.test, options.previewOnly, options.htmlInput, options.htmlPreview, options.pattern);
// Status mode: allow multiple, pass array of template names
await liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
return;
}
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

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the structure of the repository
git ls-files | grep -E "(cli|test)" | head -20

Repository: silverfin/silverfin-cli

Length of output: 659


🏁 Script executed:

# Find the CLI file and examine the status mode code
fd cli.js

Repository: silverfin/silverfin-cli

Length of output: 77


🏁 Script executed:

# Let's read the relevant section of bin/cli.js
wc -l bin/cli.js

Repository: silverfin/silverfin-cli

Length of output: 81


🏁 Script executed:

# Read around lines 495-499 with more context
sed -n '480,520p' bin/cli.js

Repository: silverfin/silverfin-cli

Length of output: 2096


🏁 Script executed:

# Find where runTestsStatusOnly is defined
rg "runTestsStatusOnly" --type js -B 2 -A 5

Repository: silverfin/silverfin-cli

Length of output: 1298


🏁 Script executed:

# Check the return type/value of runTestsStatusOnly
ast-grep --pattern 'runTestsStatusOnly($$$) { $$$ }'

Repository: silverfin/silverfin-cli

Length of output: 49


🏁 Script executed:

# Let's also check how other test modes handle exit codes
sed -n '450,550p' bin/cli.js

Repository: silverfin/silverfin-cli

Length of output: 4967


🏁 Script executed:

# Get the full implementation of runTestsStatusOnly
sed -n '1,100p' lib/liquidTestRunner.js | grep -A 50 "async function runTestsStatusOnly"

Repository: silverfin/silverfin-cli

Length of output: 49


🏁 Script executed:

# Search for return statements in runTestsStatusOnly function
rg -A 100 "async function runTestsStatusOnly" lib/liquidTestRunner.js | head -120

Repository: silverfin/silverfin-cli

Length of output: 1910


Status mode should propagate failure via exit code (required for CI/CD workflows).

runTestsStatusOnly() returns "PASSED" or "FAILED", but the CLI ignores this return value and always exits with code 0, breaking CI/CD integrations that depend on non-zero exit codes to detect test failures.

Proposed fix
     if (options.status) {
       // Status mode: allow multiple, pass array of template names
-      await liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
-      return;
+      const overallStatus = await liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
+      process.exitCode = overallStatus === "PASSED" ? 0 : 1;
+      return;
     }
📝 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
if (options.status) {
liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
} else {
if (options.previewOnly && !options.htmlInput && !options.htmlPreview) {
consola.info(`When using "--preview-only" you need to specify at least one of the following options: "--html-input", "--html-preview"`);
process.exit(1);
}
liquidTestRunner.runTestsWithOutput(options.firm, templateType, templateName, options.test, options.previewOnly, options.htmlInput, options.htmlPreview, options.pattern);
// Status mode: allow multiple, pass array of template names
await liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
return;
}
if (options.status) {
// Status mode: allow multiple, pass array of template names
const overallStatus = await liquidTestRunner.runTestsStatusOnly(options.firm, templateType, templateName, options.test, options.pattern);
process.exitCode = overallStatus === "PASSED" ? 0 : 1;
return;
}
🤖 Prompt for AI Agents
In @bin/cli.js around lines 495 - 499, The CLI ignores the return value of
liquidTestRunner.runTestsStatusOnly in the options.status branch causing tests
to always exit 0; capture the result of liquidTestRunner.runTestsStatusOnly
(which returns "PASSED" or "FAILED") and call process.exit(1) when the result
indicates failure (e.g., result !== "PASSED"), otherwise exit 0 or simply
return; update the block handling options.status (where runTestsStatusOnly is
invoked) to check the returned status and propagate a non-zero exit code for
failures so CI/CD can detect test failures.

Comment on lines +5 to +8
## [1.52.0] (12/01/2026)
This update improves test execution performance when running tests with status checks across multiple template handles.
Tests are now run in parallel for multiple handles when using the `--status` flag, significantly reducing the overall execution time. Previously, tests with status checks for multiple handles would run sequentially, but now they leverage parallel processing for better efficiency. This change only affects the `silverfin run-test` command when both multiple handles and the status flag are used together.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use an unambiguous date format in the changelog.

(12/01/2026) is locale-ambiguous; consider 2026-01-12 (ISO-8601) for consistency and clarity.

🤖 Prompt for AI Agents
In @CHANGELOG.md around lines 5 - 8, The changelog uses a locale-ambiguous date
format in the release header "## [1.52.0] (12/01/2026)"; update that header to
use an unambiguous ISO-8601 date like "## [1.52.0] (2026-01-12)" so the date
format is consistent and clear across locales.

Comment on lines 472 to 523
async function runTestsStatusOnly(firmId, templateType, handles, testName = "", pattern = "") {
if (templateType !== "reconciliationText" && templateType !== "accountTemplate") {
consola.error(`Template type is missing or invalid`);
process.exit(1);
}

let status = "FAILED";
const testResult = await runTests(firmId, templateType, handle, testName, false, "none", pattern);
const runSingleHandle = async (singleHandle) => {
let status = "FAILED";
const failedTestNames = [];
const testResult = await runTests(firmId, templateType, singleHandle, testName, false, "none", pattern);

if (!testResult) {
status = "PASSED";
consola.success(status);
return status;
}
if (!testResult) {
status = "PASSED";
} else {
const testRun = testResult?.testRun;

const testRun = testResult?.testRun;
if (testRun && testRun?.status === "completed") {
const errorsPresent = checkAllTestsErrorsPresent(testRun.tests);
if (errorsPresent === false) {
status = "PASSED";
} else {
// Extract failed test names
const testNames = Object.keys(testRun.tests).sort();
testNames.forEach((testName) => {
const testErrorsPresent = checkTestErrorsPresent(testName, testRun.tests);
if (testErrorsPresent) {
failedTestNames.push(testName);
}
});
}
}
}

if (testRun && testRun?.status === "completed") {
const errorsPresent = checkAllTestsErrorsPresent(testRun.tests);
if (errorsPresent === false) {
status = "PASSED";
consola.success(status);
return status;
if (status === "PASSED") {
consola.log(`${singleHandle}: ${status}`);
} else {
consola.log(`${singleHandle}: ${status}`);
// Display failed test names
failedTestNames.forEach((testName) => {
consola.log(` ${testName}: FAILED`);
});
}
}
consola.error(status);
return status;

return { handle: singleHandle, status, failedTestNames };
};

const results = await Promise.all(handles.map(runSingleHandle));

const overallStatus = results.every((result) => result.status === "PASSED") ? "PASSED" : "FAILED";

return overallStatus;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Validate handles and don’t treat “no result” as PASS (can mask real failures).

Two issues:

  • handles.map(...) will throw if handles isn’t an array (public API).
  • if (!testResult) status = "PASSED"; can incorrectly PASS when runTests(...) fails/returns nothing due to setup/API errors.
Proposed fix (within this function)
 async function runTestsStatusOnly(firmId, templateType, handles, testName = "", pattern = "") {
   if (templateType !== "reconciliationText" && templateType !== "accountTemplate") {
     consola.error(`Template type is missing or invalid`);
     process.exit(1);
   }
+
+  if (!Array.isArray(handles) || handles.length === 0) {
+    consola.error(`You need to provide one or more handles`);
+    process.exit(1);
+  }

   const runSingleHandle = async (singleHandle) => {
     let status = "FAILED";
     const failedTestNames = [];
     const testResult = await runTests(firmId, templateType, singleHandle, testName, false, "none", pattern);

-    if (!testResult) {
-      status = "PASSED";
-    } else {
+    if (!testResult) {
+      // If we couldn't start/read a run, treat as failure (otherwise CI can silently pass).
+      status = "FAILED";
+    } else {
       const testRun = testResult?.testRun;

       if (testRun && testRun?.status === "completed") {
         const errorsPresent = checkAllTestsErrorsPresent(testRun.tests);
         if (errorsPresent === false) {
           status = "PASSED";
         } else {
           // Extract failed test names
           const testNames = Object.keys(testRun.tests).sort();
           testNames.forEach((testName) => {
             const testErrorsPresent = checkTestErrorsPresent(testName, testRun.tests);
             if (testErrorsPresent) {
               failedTestNames.push(testName);
             }
           });
         }
       }
     }

{
"name": "silverfin-cli",
"version": "1.51.0",
"version": "1.52.0",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, find and read the package.json file
fd package.json -type f

Repository: silverfin/silverfin-cli

Length of output: 237


🏁 Script executed:

# Search for PR template files
fd -i pull_request_template -type f

Repository: silverfin/silverfin-cli

Length of output: 237


🏁 Script executed:

# Also check for common template locations
ls -la .github/ 2>/dev/null || echo "No .github directory"

Repository: silverfin/silverfin-cli

Length of output: 369


🏁 Script executed:

# Get git diff to see what actually changed in package.json
git diff HEAD -- package.json 2>/dev/null || echo "Git diff not available"

Repository: silverfin/silverfin-cli

Length of output: 49


🏁 Script executed:

# Read package.json
cat package.json | head -20

Repository: silverfin/silverfin-cli

Length of output: 585


🏁 Script executed:

# Read the PR template
cat .github/pull_request_template.md

Repository: silverfin/silverfin-cli

Length of output: 482


Confirm the version bump is intentional for this PR.

The PR template checklist includes "Skip bumping the CLI version", but package.json shows the version was updated to 1.52.0. Please clarify whether this version bump matches your release process.

🤖 Prompt for AI Agents
In @package.json at line 3, The package.json "version" field was changed to
"1.52.0"—confirm whether this version bump is intentional per your release
process and the PR template checkbox "Skip bumping the CLI version"; if it was
unintentional, revert the change to the version field in package.json, otherwise
add a note in the PR description documenting that the bump is deliberate and
aligns with the release workflow.

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: 1

🤖 Fix all issues with AI agents
In @bin/cli.js:
- Around line 476-477: The code silently prefers options.handle over
options.accountTemplate when both are provided; add a mutual-exclusivity check
before computing templateType/templateName by calling
cliUtils.checkUniqueOption(["handle", "accountTemplate"], options) (or
equivalent) to validate that only one of these options is set, then keep the
existing logic that sets templateType and templateName based on options.handle;
ensure you reference options, templateType, and templateName in the same scope
so the check runs first.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4178f1e and 261fe7c.

📒 Files selected for processing (1)
  • bin/cli.js
🧰 Additional context used
🧬 Code graph analysis (1)
bin/cli.js (3)
lib/liquidTestRunner.js (1)
  • options (16-16)
lib/cli/utils.js (1)
  • options (89-89)
lib/cli/devMode.js (1)
  • liquidTestRunner (4-4)
🔇 Additional comments (4)
bin/cli.js (4)

456-457: LGTM - Variadic options for parallel execution.

The option definitions correctly use commander's variadic syntax (<handle...>, <name...>) to accept multiple values, which aligns with the PR objective of running multiple handles in parallel.


479-488: LGTM - Proper validation for multiple templates.

The validation correctly:

  1. Ensures at least one handle/template is provided (lines 479-482)
  2. Blocks multiple handles/templates unless --status is specified (lines 484-488)

This prevents users from accidentally providing multiple templates in non-status mode where only the first would be used.


490-494: LGTM - Status mode correctly passes array and awaits.

The status mode correctly passes the array of template names to runTestsStatusOnly and properly awaits the result before returning. The early return ensures non-status mode logic is skipped.


496-513: LGTM - Non-status mode correctly extracts single template.

The non-status execution path properly extracts the first template name from the array and passes all required parameters to runTestsWithOutput in the correct order matching the documented signature.

Comment on lines 476 to 477
const templateType = options.handle ? "reconciliationText" : "accountTemplate";
const templateName = options.handle ? options.handle : options.accountTemplate;
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

Missing mutual exclusivity check for handle and accountTemplate.

If both --handle and --account-template are provided, handle silently wins and accountTemplate is ignored. Other commands in this file use cliUtils.checkUniqueOption() to enforce mutual exclusivity (e.g., line 721 in development-mode).

🔧 Proposed fix
   const templateType = options.handle ? "reconciliationText" : "accountTemplate";
   const templateName = options.handle ? options.handle : options.accountTemplate;

+  if (options.handle && options.accountTemplate) {
+    consola.error("You cannot use both --handle and --account-template options at the same time");
+    process.exit(1);
+  }
+
   if (!templateName || templateName.length === 0) {

Alternatively, use the existing utility:

cliUtils.checkUniqueOption(["handle", "accountTemplate"], options);
🤖 Prompt for AI Agents
In @bin/cli.js around lines 476 - 477, The code silently prefers options.handle
over options.accountTemplate when both are provided; add a mutual-exclusivity
check before computing templateType/templateName by calling
cliUtils.checkUniqueOption(["handle", "accountTemplate"], options) (or
equivalent) to validate that only one of these options is set, then keep the
existing logic that sets templateType and templateName based on options.handle;
ensure you reference options, templateType, and templateName in the same scope
so the check runs first.

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: 1

🤖 Fix all issues with AI agents
In @lib/liquidTestRunner.js:
- Around line 472-476: runTestsStatusOnly is assuming handles is an array but
can receive a string (which makes .map iterate chars); add a defensive
validation at the top of runTestsStatusOnly: check if (!Array.isArray(handles))
then log an error via consola.error('handles must be an array') and exit
(process.exit(1)); alternatively, fix the caller that invokes runTestsStatusOnly
(the CLI invocation that passes templateName) to pass an array (e.g.,
[templateName]) so handles is always an array.
🧹 Nitpick comments (2)
lib/liquidTestRunner.js (2)

489-503: Variable shadowing: testName shadows the outer parameter.

The testName variable in the forEach callback at line 496 shadows the outer function parameter testName from line 472. This can cause confusion during maintenance and may lead to subtle bugs if the outer testName is needed later.

♻️ Proposed fix
           } else {
             // Extract failed test names
             const testNames = Object.keys(testRun.tests).sort();
-            testNames.forEach((testName) => {
-              const testErrorsPresent = checkTestErrorsPresent(testName, testRun.tests);
+            testNames.forEach((name) => {
+              const testErrorsPresent = checkTestErrorsPresent(name, testRun.tests);
               if (testErrorsPresent) {
-                failedTestNames.push(testName);
+                failedTestNames.push(name);
               }
             });
           }

506-514: Simplify duplicate logging statement.

The consola.log call on lines 507 and 509 is identical. The conditional branches only differ in whether failed test names are printed.

♻️ Proposed simplification
-    if (status === "PASSED") {
-      consola.log(`${singleHandle}: ${status}`);
-    } else {
-      consola.log(`${singleHandle}: ${status}`);
+    consola.log(`${singleHandle}: ${status}`);
+    if (status !== "PASSED") {
       // Display failed test names
       failedTestNames.forEach((testName) => {
         consola.log(`  ${testName}: FAILED`);
       });
     }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 261fe7c and e37358c.

📒 Files selected for processing (1)
  • lib/liquidTestRunner.js
🧰 Additional context used
🧬 Code graph analysis (1)
lib/liquidTestRunner.js (2)
bin/cli.js (2)
  • templateType (476-476)
  • testName (525-525)
lib/cli/spinner.js (1)
  • process (1-1)
🔇 Additional comments (1)
lib/liquidTestRunner.js (1)

519-523: LGTM on parallel execution and aggregation logic.

The use of Promise.all for parallel execution is appropriate here and aligns with the PR objective. The aggregation using .every() correctly returns "PASSED" only when all handles pass.

One edge case to be aware of: if handles is an empty array, [].every() returns true, so the function would return "PASSED". Verify this is the intended behavior for your use case (e.g., GitHub Actions).

Comment on lines +472 to 476
async function runTestsStatusOnly(firmId, templateType, handles, testName = "", pattern = "") {
if (templateType !== "reconciliationText" && templateType !== "accountTemplate") {
consola.error(`Template type is missing or invalid`);
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's examine the function implementation around lines 472-476
sed -n '472,530p' lib/liquidTestRunner.js | cat -n

Repository: silverfin/silverfin-cli

Length of output: 2354


🏁 Script executed:

#!/bin/bash
# Search for all calls to runTestsStatusOnly in the codebase
rg -n 'runTestsStatusOnly\s*\(' --type js -A 2

Repository: silverfin/silverfin-cli

Length of output: 579


Add input validation to guard against string being passed to handles parameter.

The function expects handles to be an array, but the only caller in bin/cli.js:492 passes templateName (a string). When a string is passed to .map(), it iterates over individual characters instead of array items, causing incorrect behavior.

Add defensive validation at the beginning of the function:

if (!Array.isArray(handles)) {
  consola.error('handles must be an array');
  process.exit(1);
}

Alternatively, update the caller to wrap templateName in an array: [templateName] or ensure it's always passed as an array.

🤖 Prompt for AI Agents
In @lib/liquidTestRunner.js around lines 472 - 476, runTestsStatusOnly is
assuming handles is an array but can receive a string (which makes .map iterate
chars); add a defensive validation at the top of runTestsStatusOnly: check if
(!Array.isArray(handles)) then log an error via consola.error('handles must be
an array') and exit (process.exit(1)); alternatively, fix the caller that
invokes runTestsStatusOnly (the CLI invocation that passes templateName) to pass
an array (e.g., [templateName]) so handles is always an array.

@michieldegezelle michieldegezelle merged commit 70754a0 into main Jan 12, 2026
3 checks passed
@michieldegezelle michieldegezelle deleted the restore-parallel-handles branch January 12, 2026 15:53
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.

3 participants