diff --git a/.github/workflows/fe-code-quality.yml b/.github/workflows/fe-code-quality.yml index 250c138b..ab4dac66 100644 --- a/.github/workflows/fe-code-quality.yml +++ b/.github/workflows/fe-code-quality.yml @@ -1,6 +1,26 @@ name: Frontend Code Quality Workflow -on: workflow_call +on: + workflow_call: + secrets: + SONAR_CLOUD_TOKEN: + required: false + inputs: + SONAR_CLOUD_ORG: + required: false + description: "SonarCloud organization key, e.g., 'my-org'" + type: string + default: "collaborationfactory" + SONAR_CLOUD_PROJECT_KEY: + required: false + description: "SonarCloud project key, e.g., 'my-project'" + type: string + default: "" + SONAR_PROPERTIES: + required: false + description: "Additional sonar-project.properties content" + type: string + default: "" jobs: code-quality: @@ -9,6 +29,7 @@ jobs: matrix: target: [ 'test' ] jobIndex: [ 1, 2, 3,4 ] + fail-fast: false # Ensure all jobs run even if one fails env: jobCount: 4 steps: @@ -17,7 +38,7 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} fetch-depth: 0 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: node-version: 22.15.0 - name: Cache Node Modules @@ -37,10 +58,127 @@ jobs: run: git fetch origin ${{ github.event.pull_request.base.ref }}:${{ github.event.pull_request.base.ref }} || true - name: Unit Tests - uses: collaborationFactory/github-actions/.github/actions/run-many@master + id: test + uses: collaborationFactory/github-actions/.github/actions/run-many@poc/code-coverage-in-code-quality-pr-pipeline + continue-on-error: true with: target: ${{ matrix.target }} jobIndex: ${{ matrix.jobIndex }} jobCount: ${{ env.jobCount }} base: ${{ github.event.pull_request.base.ref }} ref: ${{ github.event.pull_request.head.ref }} + + - name: Upload Coverage Reports + uses: actions/upload-artifact@v4 + with: + name: coverage-${{ matrix.jobIndex }} + path: coverage/ + retention-days: 7 + + - name: Fail pipeline if test step failed + run: | + if [ "${{ steps.test.outcome }}" = "failure" ]; then + echo "Unit tests step failed, failing the pipeline." + exit 1 + fi + + sonar: + name: SonarCloud + needs: code-quality + runs-on: ubuntu-latest + steps: + - name: Check if SONAR_CLOUD_TOKEN exists + id: check-secret + run: | + if [ -n "${{ secrets.SONAR_CLOUD_TOKEN }}" ]; then + echo "has_token=true" >> $GITHUB_OUTPUT + else + echo "has_token=false" >> $GITHUB_OUTPUT + echo "SONAR_CLOUD_TOKEN secret must be set to run SonarCloud analysis." + fi + + - name: Set SonarCloud Project Key + id: set-project-key + run: | + if [ -z "${{ inputs.SONAR_CLOUD_PROJECT_KEY }}" ]; then + echo "project_key=collaborationFactory_${{ github.event.repository.name }}" >> $GITHUB_OUTPUT + else + echo "project_key=${{ inputs.SONAR_CLOUD_PROJECT_KEY }}" >> $GITHUB_OUTPUT + fi + + - name: Check if sonar inputs are provided + id: check-inputs + if: steps.check-secret.outputs.has_token == 'true' + run: | + if [ -z "${{ inputs.SONAR_CLOUD_ORG }}" ] || [ -z "${{ steps.set-project-key.outputs.project_key }}" ]; then + echo "run_sonar=false" >> $GITHUB_OUTPUT + echo "SONAR_CLOUD_ORG and SONAR_CLOUD_PROJECT_KEY inputs must be provided when SONAR_CLOUD_TOKEN is set." + else + echo "run_sonar=true" >> $GITHUB_OUTPUT + fi + + - name: Skip SonarCloud steps if no token + if: steps.check-inputs.outputs.run_sonar == 'false' || steps.check-secret.outputs.has_token == 'false' + run: | + echo "Skipping SonarCloud analysis." + exit 0 + + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Write sonar-project.properties + run: | + echo "sonar.host.url=https://sonarcloud.io" > sonar-project.properties + echo "sonar.organization=${{ inputs.SONAR_CLOUD_ORG }}" >> sonar-project.properties + echo "sonar.projectKey=${{ steps.set-project-key.outputs.project_key }}" >> sonar-project.properties + echo "sonar.test.inclusions=**/*.spec.ts,**/*.test.ts,**/*.spec.tsx,**/*.test.tsx" >> sonar-project.properties + echo "sonar.javascript.lcov.reportPaths=./coverage/lcov.info" >> sonar-project.properties + if [ -n "${{ inputs.SONAR_PROPERTIES }}" ]; then + echo "${{ inputs.SONAR_PROPERTIES }}" >> sonar-project.properties + fi + cat sonar-project.properties + + - name: download coverage report + uses: actions/download-artifact@v5 + with: + path: ./coverage + pattern: coverage-* + merge-multiple: true + + - name: Check for LCOV files + id: check-lcov + run: | + if find ./coverage -name "lcov*.info" -type f | grep -q .; then + echo "lcov_exists=true" >> $GITHUB_OUTPUT + echo "LCOV files found, will proceed with merge" + else + echo "lcov_exists=false" >> $GITHUB_OUTPUT + echo "No LCOV files found, skipping merge" + fi + + - name: Merge matrix coverage reports + if: steps.check-lcov.outputs.lcov_exists == 'true' + run: | + echo "=== Finding all LCOV files ===" + find ./coverage -name "lcov*.info" -type f + echo "" + echo "=== Merging coverage files ===" + npx lcov-result-merger "coverage/**/lcov*.info" coverage/lcov.info + echo "" + echo "=== Merge completed ===" + ls -lh ./coverage/lcov.info + + - name: Normalize LCOV paths for Linux + if: steps.check-lcov.outputs.lcov_exists == 'true' + run: | + if [ -f "./coverage/lcov.info" ]; then + sed -i 's|\\|/|g' ./coverage/lcov.info + echo "Normalized LCOV paths to Unix format" + fi + + - name: SonarQube Scan + uses: SonarSource/sonarqube-scan-action@v4 + env: + SONAR_TOKEN: ${{ secrets.SONAR_CLOUD_TOKEN }} diff --git a/package-lock.json b/package-lock.json index b963d2a5..53558eb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@types/jest": "29.5.14", "@types/node": "^22.15.0", "jest": "29.7.0", + "lcov-result-merger": "^5.0.1", "luxon": "^3.3.0", "prettier": "2.8.1", "ts-jest": "29.1.1", @@ -2415,6 +2416,44 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -2948,12 +2987,13 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3451,12 +3491,39 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -3467,10 +3534,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -3580,6 +3648,19 @@ "node": "*" } }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -3710,6 +3791,16 @@ "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/is-electron/-/is-electron-2.2.2.tgz", "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==" }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3728,11 +3819,25 @@ "node": ">=6" } }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -5381,6 +5486,64 @@ "node": ">=6" } }, + "node_modules/lcov-result-merger": { + "version": "5.0.1", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/lcov-result-merger/-/lcov-result-merger-5.0.1.tgz", + "integrity": "sha512-i53RjTYfqbHgerqGtuJjDfARDU340zNxXrJudQZU3o8ak9rrx8FDQUKf38Cjm6MtbqonqiDFmoKuUe++uZbvOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "yargs": "^16.2.0" + }, + "bin": { + "lcov-result-merger": "bin/lcov-result-merger.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/lcov-result-merger/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/lcov-result-merger/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lcov-result-merger/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/leven": { "version": "3.1.0", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/leven/-/leven-3.1.0.tgz", @@ -5489,13 +5652,24 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.8", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -5871,6 +6045,27 @@ "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", "dev": true }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/react-is/-/react-is-18.2.0.tgz", @@ -6015,6 +6210,41 @@ "node": ">= 4" } }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -6233,6 +6463,7 @@ "resolved": "https://cplace.jfrog.io/artifactory/api/npm/cplace-npm/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, diff --git a/package.json b/package.json index a1185037..989201c6 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@types/jest": "29.5.14", "@types/node": "^22.15.0", "jest": "29.7.0", + "lcov-result-merger": "^5.0.1", "luxon": "^3.3.0", "prettier": "2.8.1", "ts-jest": "29.1.1", diff --git a/tools/scripts/run-many/run-many.ts b/tools/scripts/run-many/run-many.ts index c8a9cc34..e4582ad9 100644 --- a/tools/scripts/run-many/run-many.ts +++ b/tools/scripts/run-many/run-many.ts @@ -7,6 +7,15 @@ function getE2ECommand(command: string, base: string): string { return command; } +function getCoverageCommand(command: string): string { + core.info(`Before coverage command: ${command}`); + command = command.concat( + ` --codeCoverage=true --coverageReporters=lcov --coverageReporters=html` + ); + core.info(`After coverage command: ${command}`); + return command; +} + function runCommand(command: string): void { if (command.includes('--targets=e2e')) { const commandArr = command.split(' '); @@ -64,6 +73,14 @@ function main() { cmd = getE2ECommand(cmd, base); } + // Add coverage flag if enabled and target is test + if (target === 'test') { + core.info('Coverage gate is enabled'); + // Add coverage reporters for HTML, JSON, and JUnit output + // Note: Using individual project coverage directories + cmd = getCoverageCommand(cmd); + } + if (projects.length > 0) { runCommand(cmd); } else {