Skip to content

Commit 892df51

Browse files
committed
test(contracts): parallelise integration tests and shard CI coverage
Shard the mega-asset integration suite for parallel mocha workers (shared suiteDiscovery + atsShardRunner; ats.test.ts delegates, ats.shard.1..8 are the local parallel entries) and split solidity-coverage across a weight-balanced 4-way CI matrix that merges per-shard lcov into a single Codecov upload via an in-repo merger preserving function coverage. Skip the redundant test-phase recompile during coverage runs, cache CI deps, and make the workflow contracts-only. Signed-off-by: Miguel_LZPF <miguel.carpena@io.builders>
1 parent 07b4990 commit 892df51

19 files changed

Lines changed: 712 additions & 136 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hashgraph/asset-tokenization-contracts": patch
3+
---
4+
5+
Shard contracts solidity-coverage across parallel CI runners (one shared mega-asset deploy per shard plus a weight-balanced split of the standalone suites) and merge the per-shard lcov reports into a single Codecov upload matching the local single-run report. Test/CI only — no contract behaviour change; also fixes a test-isolation leak in the registry unit suite by adding a `resetOrchestratorLibraryAddresses()` helper that clears the shared orchestrator-library singleton between runs.

.github/workflows/100-flow-ats-test.yaml

Lines changed: 160 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ on:
55
branches: [main]
66
pull_request:
77
paths:
8-
- "packages/ats/**"
9-
- "apps/ats/**"
8+
- "packages/ats/contracts/**"
109
- "package.json"
1110
- ".github/workflows/*ats*.yaml"
1211
workflow_dispatch:
@@ -20,35 +19,12 @@ permissions:
2019

2120
jobs:
2221
test-ats:
23-
name: testing
22+
name: contracts scripts tests
2423
runs-on: token-studio-linux-large
2524
timeout-minutes: 45
2625
env:
2726
CONTRACT_SIZER_RUN_ON_COMPILE: "false"
2827
REPORT_GAS: "false"
29-
CLIENT_PRIVATE_KEY_ECDSA_1: ${{ secrets.CLIENT_PRIVATE_KEY_ECDSA_1 }}
30-
CLIENT_PUBLIC_KEY_ECDSA_1: ${{ secrets.CLIENT_PUBLIC_KEY_ECDSA_1 }}
31-
CLIENT_ACCOUNT_ID_ECDSA_1: "0.0.1328"
32-
CLIENT_EVM_ADDRESS_ECDSA_1_CORRECT: "0x97C50bb12E1C6284cF2855cdba95c5D60AEE44CF"
33-
CLIENT_EVM_ADDRESS_ECDSA_1: "0x0000000000000000000000000000000000000530"
34-
CLIENT_PRIVATE_KEY_ECDSA_2: ${{ secrets.CLIENT_PRIVATE_KEY_ECDSA_2 }}
35-
CLIENT_PUBLIC_KEY_ECDSA_2: ${{ secrets.CLIENT_PUBLIC_KEY_ECDSA_2 }}
36-
CLIENT_ACCOUNT_ID_ECDSA_2: "0.0.2168740"
37-
CLIENT_EVM_ADDRESS_ECDSA_2: "0x00000000000000000000000000000000002117A4"
38-
FACTORY_ADDRESS: "0.0.5480051"
39-
RESOLVER_ADDRESS: "0.0.5479997"
40-
FIREBLOCKS_HEDERA_ACCOUNT_ID: "0.0.2168740"
41-
FIREBLOCKS_HEDERA_PUBLIC_KEY: ${{ secrets.CLIENT_PUBLIC_KEY_ECDSA_2 }}
42-
DFNS_HEDERA_ACCOUNT_ID: "0.0.2168740"
43-
DFNS_WALLET_PUBLIC_KEY: ${{ secrets.CLIENT_PUBLIC_KEY_ECDSA_2 }}
44-
AWS_KMS_HEDERA_ACCOUNT_ID: "0.0.4394946"
45-
AWS_KMS_HEDERA_PUBLIC_KEY: "302d300706052b8104000a03220003ee815bb9b5e53f5dbe7264a77e586127dfcb75da8c1246f5aa6ededdb13e6c21"
46-
REACT_APP_MIRROR_NODE: "https://testnet.mirrornode.hedera.com/api/v1/"
47-
REACT_APP_RPC_NODE: "https://testnet.hashio.io/api"
48-
REACT_APP_RESOLVER: "0.0.5479997"
49-
REACT_APP_FACTORY: "0.0.5480051"
50-
REACT_APP_SHOW_DISCLAIMER: "true"
51-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
5228

5329
steps:
5430
- name: Harden Runner
@@ -65,33 +41,164 @@ jobs:
6541
node-version-file: .nvmrc
6642
cache: "npm"
6743

44+
# Shared dependency cache across every job in this workflow (and matched by the other ATS
45+
# workflows on the same key), so node_modules is restored instead of reinstalled. On a hit
46+
# the install below is skipped entirely.
47+
- name: Restore dependencies from cache
48+
id: deps-cache
49+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
50+
with:
51+
path: |
52+
node_modules
53+
*/*/node_modules
54+
*/*/*/node_modules
55+
~/.npm
56+
key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
57+
58+
# --ignore-scripts skips the contracts `prepare` hook (a *production* `hardhat compile`).
59+
# Every job here recompiles in test/coverage mode anyway and regenerates the gitignored
60+
# resolver registry as part of that compile, so the prepare compile is pure duplicated work.
6861
- name: Install dependencies
69-
run: npm run ats:install
70-
71-
# BBND-1766: `atsRegistry.generated.ts` is gitignored and regenerated
72-
# by the contracts package's `prepare` script during `npm ci`. This
73-
# step is the clean-checkout guard for that contract — if the file is
74-
# missing after install, `prepare` regressed and every downstream
75-
# build / test step would fail with a confusing module-not-found.
76-
- name: Verify auto-generated registry produced by prepare hook
62+
if: steps.deps-cache.outputs.cache-hit != 'true'
63+
run: npm ci --ignore-scripts
64+
65+
# Contracts integration tests run under coverage in the parallel `coverage-ats` matrix below
66+
# (which doubles as their gate), so this job only runs the scripts/* suite that coverage does
67+
# not exercise. SDK and web are deprecated and no longer tested here.
68+
#
69+
# The scripts suite deploys the system and exercises test-only facets (EvmAccessors,
70+
# MockDiamondCut, …), so it needs a TEST-MODE compile — which also regenerates the test-mode
71+
# resolver registry — before the run. `--force` is mandatory: without it Hardhat sees no
72+
# source change and skips, leaving a registry with no key for EvmAccessorsFacet.
73+
- name: Run contracts scripts tests
74+
working-directory: packages/ats/contracts
75+
env:
76+
ATS_TEST_MODE: "true"
7777
run: |
78-
REGISTRY_PATH="packages/ats/contracts/scripts/domain/atsRegistry.generated.ts"
79-
if [[ ! -f "${REGISTRY_PATH}" ]]; then
80-
echo "::error::${REGISTRY_PATH} missing after npm ci. The contracts package's 'prepare' script (hardhat compile) likely regressed."
81-
exit 1
82-
fi
83-
if ! grep -q "^export const FACET_REGISTRY" "${REGISTRY_PATH}"; then
84-
echo "::error::${REGISTRY_PATH} missing FACET_REGISTRY export — generator produced a malformed file."
85-
exit 1
86-
fi
87-
echo "✓ ${REGISTRY_PATH} auto-regenerated by prepare hook"
88-
89-
- name: Build ATS packages
90-
run: npm run ats:build
91-
92-
- name: Run ATS tests
93-
run: npm run ats:test:ci
94-
95-
- name: Upload coverage report
96-
if: ${{ !cancelled() && always() }}
78+
npm run compile:force
79+
npm run test:scripts
80+
81+
# Contracts coverage is sharded across parallel runners: solidity-coverage re-instruments and
82+
# recompiles per shard (unavoidable on Hardhat 2), but each shard runs on its own runner so the
83+
# ~3 min compile overlaps instead of serializing. Each shard runs the mega-asset entry once for
84+
# its `i % SHARD_TOTAL` slice plus a round-robined share of the standalone suites, computed by
85+
# scripts/tools/coverage-shard/planShard.ts. Shards upload their lcov as artifacts; the
86+
# merge-coverage job below combines them into a single report and uploads it once to Codecov.
87+
coverage-ats:
88+
name: coverage (shard ${{ matrix.shard }})
89+
runs-on: token-studio-linux-large
90+
timeout-minutes: 45
91+
strategy:
92+
fail-fast: false
93+
matrix:
94+
# Keep this list's length equal to SHARD_TOTAL below (indices 0..N-1).
95+
shard: [0, 1, 2, 3]
96+
env:
97+
CONTRACT_SIZER_RUN_ON_COMPILE: "false"
98+
REPORT_GAS: "false"
99+
SHARD_INDEX: ${{ matrix.shard }}
100+
SHARD_TOTAL: "4"
101+
102+
steps:
103+
- name: Harden Runner
104+
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
105+
with:
106+
egress-policy: audit
107+
108+
- name: Checkout repository
109+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
110+
111+
- name: Setup NodeJS Environment
112+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
113+
with:
114+
node-version-file: .nvmrc
115+
cache: "npm"
116+
117+
- name: Restore dependencies from cache
118+
id: deps-cache
119+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
120+
with:
121+
path: |
122+
node_modules
123+
*/*/node_modules
124+
*/*/*/node_modules
125+
~/.npm
126+
key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
127+
128+
- name: Install dependencies
129+
if: steps.deps-cache.outputs.cache-hit != 'true'
130+
run: npm ci --ignore-scripts
131+
132+
- name: Run contracts coverage shard
133+
run: npm run test:coverage:shard --workspace=packages/ats/contracts
134+
135+
- name: Upload coverage shard artifact
136+
if: ${{ !cancelled() }}
137+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
138+
with:
139+
name: coverage-shard-${{ matrix.shard }}
140+
path: packages/ats/contracts/coverage/lcov.info
141+
if-no-files-found: error
142+
retention-days: 1
143+
144+
# Merge the per-shard lcov reports into a single report and upload it once to Codecov — matching
145+
# the local `npm run test:coverage` single report, instead of uploading partial per-shard pieces.
146+
# Runs only when every shard succeeded, so the merged report is complete.
147+
merge-coverage:
148+
name: merge coverage + upload
149+
needs: coverage-ats
150+
runs-on: token-studio-linux-large
151+
timeout-minutes: 15
152+
env:
153+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
154+
155+
steps:
156+
- name: Harden Runner
157+
uses: step-security/harden-runner@58077d3c7e43986b6b15fba718e8ea69e387dfcc # v2.15.1
158+
with:
159+
egress-policy: audit
160+
161+
- name: Checkout repository
162+
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
163+
164+
- name: Setup NodeJS Environment
165+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
166+
with:
167+
node-version-file: .nvmrc
168+
cache: "npm"
169+
170+
- name: Restore dependencies from cache
171+
id: deps-cache
172+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
173+
with:
174+
path: |
175+
node_modules
176+
*/*/node_modules
177+
*/*/*/node_modules
178+
~/.npm
179+
key: ${{ runner.os }}-deps-${{ hashFiles('package-lock.json') }}
180+
181+
- name: Install dependencies
182+
if: steps.deps-cache.outputs.cache-hit != 'true'
183+
run: npm ci --ignore-scripts
184+
185+
- name: Download all coverage shard artifacts
186+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
187+
with:
188+
pattern: coverage-shard-*
189+
path: coverage-shards
190+
191+
# Sum line/function/branch hits across the disjoint shards into one lcov, written to the same
192+
# path a local single-run coverage produces, so the Codecov upload is identical to local. Uses
193+
# the in-repo merger (preserves function coverage, which lcov-result-merger drops; no
194+
# runtime-fetched dependency).
195+
- name: Merge shard lcov reports
196+
working-directory: packages/ats/contracts
197+
run: npm run coverage:merge -- coverage/lcov.info "${GITHUB_WORKSPACE}/coverage-shards"
198+
199+
- name: Upload merged coverage to Codecov
97200
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v5.4.0
201+
with:
202+
token: ${{ secrets.CODECOV_TOKEN }}
203+
files: packages/ats/contracts/coverage/lcov.info
204+
disable_search: true

packages/ats/contracts/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,9 @@
127127
"compile:forceBuild": "npx hardhat compile --force && npm run build",
128128
"typechain": "npx hardhat typechain",
129129
"clean:cache": "npx hardhat clean",
130-
"test": "bash -c 'npx hardhat test $(find test/contracts/integration test/scripts -name \"*.test.ts\")'",
131-
"test:parallel": "bash -c 'NODE_OPTIONS=\"--import tsx\" npx hardhat test --parallel $(find test/contracts/integration test/scripts -name \"*.test.ts\")'",
130+
"test": "bash -c 'npx hardhat test $(find test/contracts/integration test/scripts -name \"*.test.ts\" -not -name \"ats.shard.*.test.ts\")'",
131+
"test:parallel": "bash -c 'ATS_TEST_MODE=true NODE_OPTIONS=\"--import tsx\" npx hardhat test --parallel $(find test/contracts/integration test/scripts -name \"*.test.ts\" -not -name \"ats.test.ts\")'",
132+
"test:parallel:ats": "bash -c 'ATS_TEST_MODE=true NODE_OPTIONS=\"--import tsx\" npx hardhat test --parallel $(find test/contracts/integration -name \"ats.shard.*.test.ts\")'",
132133
"test:contracts": "npx hardhat test",
133134
"test:contracts:parallel": "NODE_OPTIONS='--import tsx' npx hardhat test --parallel",
134135
"test:scripts": "bash -c 'npx hardhat test --no-compile $(find test/scripts -name \"*.test.ts\")'",
@@ -143,11 +144,13 @@
143144
"test:factory": "npx hardhat test test/contracts/integration/factory/factory.test.ts",
144145
"test:resolver": "npx hardhat test test/contracts/integration/resolver/BusinessLogicResolver.test.ts",
145146
"test:coverage": "npm run test:coverage:all",
146-
"test:coverage:all": "npx hardhat coverage --testfiles 'test/contracts/integration/**/*.ts'",
147+
"test:coverage:all": "SHARD_TOTAL=1 SHARD_INDEX=0 npm run test:coverage:shard",
147148
"test:coverage:layer1": "npx hardhat coverage --testfiles 'test/contracts/integration/layer_1/**/*.ts'",
148149
"test:coverage:factory": "npx hardhat coverage --testfiles 'test/contracts/integration/factory/**/*.ts'",
149150
"test:coverage:resolver": "npx hardhat coverage --testfiles 'test/contracts/integration/resolver/**/*.ts'",
150151
"test:coverage:resolverProxy": "npx hardhat coverage --testfiles 'test/contracts/integration/resolverProxy/**/*.ts'",
152+
"test:coverage:shard": "npx tsx scripts/tools/coverage-shard/runShardCoverage.ts",
153+
"coverage:merge": "npx tsx scripts/tools/coverage-shard/mergeLcov.ts",
151154
"test:ci": "npm run test",
152155
"size": "npx hardhat size-contracts",
153156
"keccak256": "npx hardhat keccak256",

0 commit comments

Comments
 (0)