Skip to content

Feat/parallel coverage#804

Open
marcosio wants to merge 35 commits intomainfrom
feat/parallel-coverage
Open

Feat/parallel coverage#804
marcosio wants to merge 35 commits intomainfrom
feat/parallel-coverage

Conversation

@marcosio
Copy link
Contributor

@marcosio marcosio commented Jan 26, 2026

Description

Type of change

  • Bug fix 🐞
  • New feature ✨
  • Breaking change 💥
  • Documentation update 📖
  • Refactor 🔧

Testing

Node version:

  • 20
  • 22
  • 24

Checklist

  • Style Guidelines followed ✅
  • Documentation Updated 📚
  • Linters - No New Warnings ⚠️
  • Local Tests Pass ✅
  • Effective Tests Added ✔️
  • No reduction of Coverage

MiguelLZPF and others added 30 commits December 18, 2025 10:07
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: Axel-IoBuilders <108282711+Axel-IoBuilders@users.noreply.github.com>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
…nd bond

Signed-off-by: Axel-IoBuilders <108282711+Axel-IoBuilders@users.noreply.github.com>
Signed-off-by: Axel-IoBuilders <108282711+Axel-IoBuilders@users.noreply.github.com>
… proxies (#755)

Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
…on (#777)

Signed-off-by: Roger Barker <roger.barker@swirldslabs.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Signed-off-by: PavelSBorisov <pavel.s.borisov@gmail.com>
Signed-off-by: Pavel Borisov <37436896+PavelSBorisov@users.noreply.github.com>
Signed-off-by: Miguel Ángel <miguelangel@io.builders>
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Mario Francia <mariofranciarius@gmail.com>
Co-authored-by: Pavel Borisov <37436896+PavelSBorisov@users.noreply.github.com>
Co-authored-by: Andrew Brandt <andrew.brandt@hashgraph.com>
…m-safe characters (#772)

Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
…ix test failures (#780)

Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
#782)

Signed-off-by: Miguel Ángel <miguelangel@io.builders>
Signed-off-by: Alberto Molina <alberto@io.builders>
Co-authored-by: Alberto Molina <alberto@io.builders>
Signed-off-by: Alberto Molina <alberto@io.builders>
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Co-authored-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Signed-off-by: Roger Barker <roger.barker@swirldslabs.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Co-authored-by: Roger Barker <roger.barker@swirldslabs.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: Axel-IoBuilders <108282711+Axel-IoBuilders@users.noreply.github.com>
Co-authored-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: Alberto Molina <alberto@io.builders>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Signed-off-by: Alberto Molina <alberto@io.builders>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
themariofrancia and others added 5 commits January 22, 2026 12:20
…ntation

Signed-off-by: Mario Francia <mariofranciarius@gmail.com>
…#789)

Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
Signed-off-by: jaime-iobermudez <jaime.bermudez@io.builders>
Signed-off-by: Marcos Serradilla Diez <marcos@io.builders>

# Conflicts:
#	packages/ats/contracts/contracts/layer_0/ERC1400/ERC1644/ERC1644StorageWrapper.sol
#	packages/ats/contracts/contracts/mocks/MockComplianceModule.sol
#	packages/ats/contracts/package.json
#	packages/ats/contracts/scripts/workflows/deploySystemWithNewBlr.ts
#	packages/ats/contracts/test/contracts/unit/factory/factory.test.ts
#	packages/ats/contracts/test/contracts/unit/layer_1/bond/bond.test.ts
#	packages/ats/contracts/test/contracts/unit/resolver/diamondCutManager.test.ts
#	packages/ats/contracts/test/contracts/unit/resolver/diamondLoupeFacet.test.ts
  - use node:24.13.0 as base image
  - install system dependencies for solc (libusb, libudev)
  - copy and install root and contracts workspace dependencies
  - create directories for hardhat cache and artifacts
  - switch to hardhatuser for parallel coverage execution
  - run coverage with npx hardhat

Signed-off-by: Marcos Serradilla Diez <marcos@io.builders>
@hedera-eng-infrastructure
Copy link

hedera-eng-infrastructure commented Jan 26, 2026

Snyk checks have passed. No issues have been found so far.

Status Scanner Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@@ -36,11 +36,21 @@
* @returns Array of contract names
*/
export function extractContractNames(source: string): string[] {
// Remove single-line comments (// ...)
let cleanSource = source.replace(/\/\/.*$/gm, "");

Check failure

Code scanning / CodeQL

Polynomial regular expression used on uncontrolled data High

This
regular expression
that depends on
library input
may run slow on strings starting with '//' and with many repetitions of '//'.
// Execute merge
const mergeCommand = `npx nyc merge ${mergeTempDir} ${mergedReportPath}`;
console.log(`Executing: ${mergeCommand}`);
execSync(mergeCommand, { cwd: REPO_ROOT });

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.

Copilot Autofix

AI 12 days ago

In general, to fix shell commands built from environment values, avoid constructing a single shell-escaped string and instead call the program with an argument array using spawn, execFile, or execFileSync (or equivalent). That way, the path values are passed directly to the program without being interpreted by a shell, making spaces and special characters safe.

For this specific case in packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts, the best fix is to stop building mergeCommand and reportCommand as single strings and instead invoke npx via spawnSync (from child_process) with an explicit args array. We already import spawn and execSync; we can extend the import to include spawnSync without affecting existing behavior. The cwd: REPO_ROOT option is preserved. Logging can still show a human-readable string, but the actual execution should use spawnSync with separate arguments:

  • Replace:
    • const mergeCommand = ...; console.log(...); execSync(mergeCommand, { cwd: REPO_ROOT });
    • const reportCommand = ...; console.log(...); execSync(reportCommand, { cwd: REPO_ROOT });
  • With:
    • Construct mergeArgs = ["nyc", "merge", mergeTempDir, mergedReportPath];, log npx plus joined args, then call spawnSync("npx", mergeArgs, { cwd: REPO_ROOT, stdio: "inherit" }) and check status/error.
    • Similarly, reportArgs = ["nyc", "report", "--reporter=html", "--reporter=text", "--temp-dir", COVERAGE_DIR]; and use spawnSync.

Also update the import on line 3 to import spawnSync (alongside execSync and spawn). No other files need changes.

Suggested changeset 1
packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts b/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
--- a/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
+++ b/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
@@ -1,6 +1,6 @@
 import fs from "fs";
 import path from "path";
-import { execSync, spawn } from "child_process";
+import { execSync, spawn, spawnSync } from "child_process";
 import { glob } from "glob";
 // Configuration
 const REPO_ROOT = process.cwd();
@@ -124,14 +124,26 @@
     }
   });
   try {
-    // Execute merge
-    const mergeCommand = `npx nyc merge ${mergeTempDir} ${mergedReportPath}`;
-    console.log(`Executing: ${mergeCommand}`);
-    execSync(mergeCommand, { cwd: REPO_ROOT });
+    // Execute merge using spawnSync with argument array to avoid shell interpretation
+    const mergeArgs = ["nyc", "merge", mergeTempDir, mergedReportPath];
+    console.log(`Executing: npx ${mergeArgs.join(" ")}`);
+    const mergeResult = spawnSync("npx", mergeArgs, {
+      cwd: REPO_ROOT,
+      stdio: "inherit",
+    });
+    if (mergeResult.error || mergeResult.status !== 0) {
+      throw mergeResult.error || new Error(`nyc merge exited with code ${mergeResult.status}`);
+    }
     // Generate final HTML and text report
-    const reportCommand = `npx nyc report --reporter=html --reporter=text --temp-dir ${COVERAGE_DIR}`;
-    console.log(`Generating final report: ${reportCommand}`);
-    execSync(reportCommand, { cwd: REPO_ROOT });
+    const reportArgs = ["nyc", "report", "--reporter=html", "--reporter=text", "--temp-dir", COVERAGE_DIR];
+    console.log(`Generating final report: npx ${reportArgs.join(" ")}`);
+    const reportResult = spawnSync("npx", reportArgs, {
+      cwd: REPO_ROOT,
+      stdio: "inherit",
+    });
+    if (reportResult.error || reportResult.status !== 0) {
+      throw reportResult.error || new Error(`nyc report exited with code ${reportResult.status}`);
+    }
     console.log(`✅ Merged report generated at ${mergedReportPath}`);
   } catch (error) {
     console.error("❌ Error during coverage merging:", error);
EOF
@@ -1,6 +1,6 @@
import fs from "fs";
import path from "path";
import { execSync, spawn } from "child_process";
import { execSync, spawn, spawnSync } from "child_process";
import { glob } from "glob";
// Configuration
const REPO_ROOT = process.cwd();
@@ -124,14 +124,26 @@
}
});
try {
// Execute merge
const mergeCommand = `npx nyc merge ${mergeTempDir} ${mergedReportPath}`;
console.log(`Executing: ${mergeCommand}`);
execSync(mergeCommand, { cwd: REPO_ROOT });
// Execute merge using spawnSync with argument array to avoid shell interpretation
const mergeArgs = ["nyc", "merge", mergeTempDir, mergedReportPath];
console.log(`Executing: npx ${mergeArgs.join(" ")}`);
const mergeResult = spawnSync("npx", mergeArgs, {
cwd: REPO_ROOT,
stdio: "inherit",
});
if (mergeResult.error || mergeResult.status !== 0) {
throw mergeResult.error || new Error(`nyc merge exited with code ${mergeResult.status}`);
}
// Generate final HTML and text report
const reportCommand = `npx nyc report --reporter=html --reporter=text --temp-dir ${COVERAGE_DIR}`;
console.log(`Generating final report: ${reportCommand}`);
execSync(reportCommand, { cwd: REPO_ROOT });
const reportArgs = ["nyc", "report", "--reporter=html", "--reporter=text", "--temp-dir", COVERAGE_DIR];
console.log(`Generating final report: npx ${reportArgs.join(" ")}`);
const reportResult = spawnSync("npx", reportArgs, {
cwd: REPO_ROOT,
stdio: "inherit",
});
if (reportResult.error || reportResult.status !== 0) {
throw reportResult.error || new Error(`nyc report exited with code ${reportResult.status}`);
}
console.log(`✅ Merged report generated at ${mergedReportPath}`);
} catch (error) {
console.error("❌ Error during coverage merging:", error);
Copilot is powered by AI and may make mistakes. Always verify output.
// Generate final HTML and text report
const reportCommand = `npx nyc report --reporter=html --reporter=text --temp-dir ${COVERAGE_DIR}`;
console.log(`Generating final report: ${reportCommand}`);
execSync(reportCommand, { cwd: REPO_ROOT });

Check warning

Code scanning / CodeQL

Shell command built from environment values Medium

This shell command depends on an uncontrolled
absolute path
.

Copilot Autofix

AI 12 days ago

In general, to fix this kind of problem you should avoid constructing a single shell command string that includes environment-derived paths. Instead, use the execFileSync or spawn APIs with a command and an array of arguments, so that the paths are passed directly to the executable without going through a shell. If you must use execSync, pass it a file and args rather than a full shell command, or ensure all interpolated values are safely escaped.

For this specific file, we should modify the two places in mergeReports where we build mergeCommand and reportCommand as interpolated strings and pass them to execSync. The best fix is to call execFileSync from child_process, using npx as the command, "nyc" and the rest as arguments. That way, mergeTempDir, mergedReportPath, and COVERAGE_DIR are not interpreted by a shell at all, avoiding both quoting issues and injection risk. To do this, we need to (1) import execFileSync from child_process, and (2) replace the string-based calls with execFileSync("npx", ["nyc", "merge", mergeTempDir, mergedReportPath], { cwd: REPO_ROOT, stdio: "inherit" }) and similarly for the report invocation. We should also pass stdio: "inherit" to preserve the current behavior of showing nyc output in the console.

Suggested changeset 1
packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts b/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
--- a/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
+++ b/packages/ats/contracts/scripts/tools/runParallelCoverageDocker.ts
@@ -1,6 +1,6 @@
 import fs from "fs";
 import path from "path";
-import { execSync, spawn } from "child_process";
+import { execSync, execFileSync, spawn } from "child_process";
 import { glob } from "glob";
 // Configuration
 const REPO_ROOT = process.cwd();
@@ -127,11 +127,21 @@
     // Execute merge
     const mergeCommand = `npx nyc merge ${mergeTempDir} ${mergedReportPath}`;
     console.log(`Executing: ${mergeCommand}`);
-    execSync(mergeCommand, { cwd: REPO_ROOT });
+    execFileSync("npx", ["nyc", "merge", mergeTempDir, mergedReportPath], {
+      cwd: REPO_ROOT,
+      stdio: "inherit",
+    });
     // Generate final HTML and text report
     const reportCommand = `npx nyc report --reporter=html --reporter=text --temp-dir ${COVERAGE_DIR}`;
     console.log(`Generating final report: ${reportCommand}`);
-    execSync(reportCommand, { cwd: REPO_ROOT });
+    execFileSync(
+      "npx",
+      ["nyc", "report", "--reporter=html", "--reporter=text", "--temp-dir", COVERAGE_DIR],
+      {
+        cwd: REPO_ROOT,
+        stdio: "inherit",
+      }
+    );
     console.log(`✅ Merged report generated at ${mergedReportPath}`);
   } catch (error) {
     console.error("❌ Error during coverage merging:", error);
EOF
@@ -1,6 +1,6 @@
import fs from "fs";
import path from "path";
import { execSync, spawn } from "child_process";
import { execSync, execFileSync, spawn } from "child_process";
import { glob } from "glob";
// Configuration
const REPO_ROOT = process.cwd();
@@ -127,11 +127,21 @@
// Execute merge
const mergeCommand = `npx nyc merge ${mergeTempDir} ${mergedReportPath}`;
console.log(`Executing: ${mergeCommand}`);
execSync(mergeCommand, { cwd: REPO_ROOT });
execFileSync("npx", ["nyc", "merge", mergeTempDir, mergedReportPath], {
cwd: REPO_ROOT,
stdio: "inherit",
});
// Generate final HTML and text report
const reportCommand = `npx nyc report --reporter=html --reporter=text --temp-dir ${COVERAGE_DIR}`;
console.log(`Generating final report: ${reportCommand}`);
execSync(reportCommand, { cwd: REPO_ROOT });
execFileSync(
"npx",
["nyc", "report", "--reporter=html", "--reporter=text", "--temp-dir", COVERAGE_DIR],
{
cwd: REPO_ROOT,
stdio: "inherit",
}
);
console.log(`✅ Merged report generated at ${mergedReportPath}`);
} catch (error) {
console.error("❌ Error during coverage merging:", error);
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link
Contributor

@andrewb1269 andrewb1269 left a comment

Choose a reason for hiding this comment

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

Approve the 3 workflow files, README, and .gitignore. Please ensure you have other folks appropriately review the remainder of the files in the PR before merging. Thanks!

@andrewb1269
Copy link
Contributor

Your DCO signoff needs to be fixed as well.

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.

9 participants