From 322e285aa42641257336d48cd05c0bf376066141 Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Tue, 17 Dec 2024 16:33:58 +0530
Subject: [PATCH 1/6] ci(workflows): Add code coverage reporting for v2
---
.github/workflows/cypress-tests-runner.yml | 211 ++++++-
cypress-tests-v2/package-lock.json | 657 ++++++++++++++++-----
justfile | 18 +
scripts/execute_cypress_v2.sh | 188 ++++++
4 files changed, 907 insertions(+), 167 deletions(-)
create mode 100755 scripts/execute_cypress_v2.sh
diff --git a/.github/workflows/cypress-tests-runner.yml b/.github/workflows/cypress-tests-runner.yml
index bc83c2388f7e..a4843bc2a01a 100644
--- a/.github/workflows/cypress-tests-runner.yml
+++ b/.github/workflows/cypress-tests-runner.yml
@@ -20,6 +20,7 @@ env:
RUN_TESTS: ${{ ((github.event_name == 'pull_request') && (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)) || (github.event_name == 'merge_group')}}
DEBUG: cypress:cli
RUST_MIN_STACK: 10485760
+ CODECOV_FILE: "lcov.info"
jobs:
formatter:
@@ -149,7 +150,7 @@ jobs:
run: |
LOCAL_ADMIN_API_KEY=$(yq '.secrets.admin_api_key' ${TOML_PATH})
echo "CYPRESS_ADMINAPIKEY=${LOCAL_ADMIN_API_KEY}" >> $GITHUB_ENV
-
+
- name: Install mold linker
if: ${{ runner.os == 'Linux' && env.RUN_TESTS == 'true' }}
uses: rui314/setup-mold@v1
@@ -170,13 +171,6 @@ jobs:
tool: sccache
checksum: true
- - name: Install cargo-nextest
- if: ${{ env.RUN_TESTS == 'true' }}
- uses: taiki-e/install-action@v2.41.10
- with:
- tool: cargo-nextest
- checksum: true
-
- name: Install Diesel CLI
if: ${{ env.RUN_TESTS == 'true' }}
uses: baptiste0928/cargo-install@v3.1.1
@@ -261,3 +255,204 @@ jobs:
path: |
cypress-tests/cypress/reports/
retention-days: 1
+
+ runner_v2:
+ name: Run Cypress tests on v2 and generate coverage report
+ runs-on: ubuntu-latest
+
+ services:
+ redis:
+ image: "public.ecr.aws/docker/library/redis:alpine"
+ options: >-
+ --health-cmd "redis-cli ping"
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ - 6379:6379
+ postgres:
+ image: "public.ecr.aws/docker/library/postgres:alpine"
+ env:
+ POSTGRES_USER: db_user
+ POSTGRES_PASSWORD: db_pass
+ POSTGRES_DB: hyperswitch_db
+ options: >-
+ --health-cmd pg_isready
+ --health-interval 10s
+ --health-timeout 5s
+ --health-retries 5
+ ports:
+ - 5432:5432
+
+ steps:
+ - name: Skip tests for PRs from forks
+ shell: bash
+ if: ${{ env.RUN_TESTS == 'false' }}
+ run: echo 'Skipping tests for PRs from forks'
+
+ - name: Checkout repository
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: actions/checkout@v4
+
+ - name: Download Encrypted TOML from S3 and Decrypt
+ if: ${{ env.RUN_TESTS == 'true' }}
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.CONNECTOR_CREDS_AWS_ACCESS_KEY_ID }}
+ AWS_REGION: ${{ secrets.CONNECTOR_CREDS_AWS_REGION }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.CONNECTOR_CREDS_AWS_SECRET_ACCESS_KEY }}
+ CONNECTOR_AUTH_PASSPHRASE: ${{ secrets.CONNECTOR_AUTH_PASSPHRASE }}
+ CONNECTOR_CREDS_S3_BUCKET_URI: ${{ secrets.CONNECTOR_CREDS_S3_BUCKET_URI}}
+ DESTINATION_FILE_NAME: "creds.json.gpg"
+ S3_SOURCE_FILE_NAME: "6f8289a9-6da0-433b-8a24-18d4d7257b7f.json.gpg"
+ shell: bash
+ run: |
+ mkdir -p ".github/secrets" ".github/test"
+
+ aws s3 cp "${CONNECTOR_CREDS_S3_BUCKET_URI}/${S3_SOURCE_FILE_NAME}" ".github/secrets/${DESTINATION_FILE_NAME}"
+ gpg --quiet --batch --yes --decrypt --passphrase="${CONNECTOR_AUTH_PASSPHRASE}" --output ".github/test/creds.json" ".github/secrets/${DESTINATION_FILE_NAME}"
+
+ - name: Set paths in env
+ if: ${{ env.RUN_TESTS == 'true' }}
+ shell: bash
+ run: |
+ echo "CYPRESS_CONNECTOR_AUTH_FILE_PATH=${{ github.workspace }}/.github/test/creds.json" >> $GITHUB_ENV
+
+ - name: Fetch keys
+ if: ${{ env.RUN_TESTS == 'true' }}
+ env:
+ TOML_PATH: "./config/development.toml"
+ run: |
+ LOCAL_ADMIN_API_KEY=$(yq '.secrets.admin_api_key' ${TOML_PATH})
+ echo "CYPRESS_ADMINAPIKEY=${LOCAL_ADMIN_API_KEY}" >> $GITHUB_ENV
+
+ - name: Install mold linker
+ if: ${{ runner.os == 'Linux' && env.RUN_TESTS == 'true' }}
+ uses: rui314/setup-mold@v1
+ with:
+ make-default: true
+
+ - name: Install Rust
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: dtolnay/rust-toolchain@master
+ with:
+ toolchain: stable 2 weeks ago
+ components: clippy llvm-tools-preview
+
+ - name: Install sccache
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: taiki-e/install-action@v2.41.10
+ with:
+ tool: sccache
+ checksum: true
+
+ - name: Install Diesel CLI
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: baptiste0928/cargo-install@v3.1.1
+ with:
+ crate: diesel_cli
+ features: postgres
+ args: --no-default-features
+
+ - name: Install grcov
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: baptiste0928/cargo-install@v3.1.1
+ with:
+ crate: grcov
+
+ - name: Install Just
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: taiki-e/install-action@v2.41.10
+ with:
+ tool: just
+ checksum: true
+
+ - name: Install Node.js
+ if: ${{ env.RUN_TESTS == 'true' }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20'
+ cache: 'npm'
+
+ - name: Install Cypress and dependencies
+ if: ${{ env.RUN_TESTS == 'true' }}
+ run: |
+ npm ci --prefix ./cypress-tests-v2
+
+ - name: Run database migrations
+ if: ${{ env.RUN_TESTS == 'true' }}
+ shell: bash
+ env:
+ DATABASE_URL: postgres://db_user:db_pass@localhost:5432/hyperswitch_db
+ run: just migrate_v2 run --locked-schema
+
+ - name: Insert card info into the database
+ if: ${{ env.RUN_TESTS == 'true' }}
+ run: |
+ PGPASSWORD=db_pass psql --host=localhost --port=5432 --username=db_user --dbname=hyperswitch_db --command "\copy cards_info FROM '.github/data/cards_info.csv' DELIMITER ',' CSV HEADER;"
+
+ - name: Build project
+ if: ${{ env.RUN_TESTS == 'true' }}
+ env:
+ RUSTFLAGS: "-Cinstrument-coverage"
+ run: just build_v2 --jobs 3
+
+ - name: Setup Local Server
+ if: ${{ env.RUN_TESTS == 'true' }}
+ env:
+ LLVM_PROFILE_FILE: "coverage.profraw"
+ run: |
+ # Start the server in the background
+ target/debug/router &
+
+ SERVER_PID=$!
+ echo "PID=${SERVER_PID}" >> $GITHUB_ENV
+
+ # Wait for the server to start in port 8080
+ COUNT=0
+ while ! nc -z localhost 8080; do
+ if [ $COUNT -gt 12 ]; then # Wait for up to 2 minutes (12 * 10 seconds)
+ echo "Server did not start within a reasonable time. Exiting."
+ kill ${SERVER_PID}
+ exit 1
+ else
+ COUNT=$((COUNT+1))
+ sleep 10
+ fi
+ done
+
+ - name: Run Cypress tests
+ if: ${{ env.RUN_TESTS == 'true' }}
+ env:
+ CYPRESS_BASEURL: "http://localhost:8080"
+ ROUTER__SERVER__WORKERS: 4
+ shell: bash -leuo pipefail {0}
+ continue-on-error: true
+ run: |
+ scripts/execute_cypress_v2.sh
+
+ - name: Stop running server
+ if: ${{ env.RUN_TESTS == 'true' }} && always()
+ run: |
+ kill "${{ env.PID }}"
+
+ - name: Upload Cypress test results
+ if: env.RUN_TESTS == 'true' && failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: cypress-v2-test-results
+ path: |
+ cypress-tests-v2/cypress/reports/
+ retention-days: 1
+
+ - name: Process coverage report
+ if: ${{ env.RUN_TESTS == 'true' }}
+ run: |
+ grcov . --source-dir . --output-types lcov --output-path ${{ env.CODECOV_FILE }} --binary-path ./target/debug --ignore "*cargo*" --ignore "target/*" --ignore "/*"
+
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v5
+ if: ${{ env.RUN_TESTS == 'true' }}
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ files: ${{ env.CODECOV_FILE }}
+ disable_search: true
\ No newline at end of file
diff --git a/cypress-tests-v2/package-lock.json b/cypress-tests-v2/package-lock.json
index cac88cab055b..644b9c9faedc 100644
--- a/cypress-tests-v2/package-lock.json
+++ b/cypress-tests-v2/package-lock.json
@@ -29,9 +29,9 @@
}
},
"node_modules/@cypress/request": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz",
- "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==",
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz",
+ "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -48,7 +48,7 @@
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"performance-now": "^2.1.0",
- "qs": "6.13.0",
+ "qs": "6.13.1",
"safe-buffer": "^5.1.2",
"tough-cookie": "^5.0.0",
"tunnel-agent": "^0.6.0",
@@ -79,6 +79,128 @@
"ms": "^2.1.1"
}
},
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@isaacs/cliui/node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
"node_modules/@types/fs-extra": {
"version": "11.0.4",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
@@ -101,13 +223,13 @@
}
},
"node_modules/@types/node": {
- "version": "22.5.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz",
- "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
+ "version": "22.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
+ "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~6.19.2"
+ "undici-types": "~6.20.0"
}
},
"node_modules/@types/sinonjs__fake-timers": {
@@ -118,9 +240,9 @@
"license": "MIT"
},
"node_modules/@types/sizzle": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.8.tgz",
- "integrity": "sha512-0vWLNK2D5MT9dg0iOo8GlKguPAU02QjmZitPEsXRuJXU/OGIOt9vT9Fc26wtYuavLxtO45v9PGleoL9Z0k1LHg==",
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz",
+ "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==",
"dev": true,
"license": "MIT"
},
@@ -460,18 +582,29 @@
"node": ">=6"
}
},
- "node_modules/call-bind": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
- "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
+ "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.1"
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
+ "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "get-intrinsic": "^1.2.6"
},
"engines": {
"node": ">= 0.4"
@@ -568,9 +701,9 @@
}
},
"node_modules/ci-info": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz",
- "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz",
+ "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==",
"dev": true,
"funding": [
{
@@ -729,7 +862,7 @@
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -742,9 +875,9 @@
}
},
"node_modules/cypress": {
- "version": "13.16.0",
- "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz",
- "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==",
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.17.0.tgz",
+ "integrity": "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -882,9 +1015,9 @@
"license": "MIT"
},
"node_modules/debug": {
- "version": "4.3.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
- "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -913,24 +1046,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/define-data-property": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@@ -951,6 +1066,29 @@
"node": ">=0.3.1"
}
},
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -994,14 +1132,11 @@
}
},
"node_modules/es-define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
- "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "get-intrinsic": "^1.2.4"
- },
"engines": {
"node": ">= 0.4"
}
@@ -1016,6 +1151,19 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -1057,7 +1205,7 @@
"dev": true,
"license": "MIT",
"dependencies": {
- "cross-spawn": "^7.0.6",
+ "cross-spawn": "^7.0.0",
"get-stream": "^5.0.0",
"human-signals": "^1.1.1",
"is-stream": "^2.0.0",
@@ -1194,6 +1342,38 @@
"flat": "cli.js"
}
},
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/foreground-child/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -1286,17 +1466,22 @@
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
- "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz",
+ "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "dunder-proto": "^1.0.0",
+ "es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
"function-bind": "^1.1.2",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0"
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -1342,22 +1527,22 @@
}
},
"node_modules/glob": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
- "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"dev": true,
"license": "ISC",
"peer": true,
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^5.0.1",
- "once": "^1.3.0"
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
},
- "engines": {
- "node": ">=12"
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -1377,6 +1562,23 @@
"node": ">= 6"
}
},
+ "node_modules/glob/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/global-dirs": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz",
@@ -1394,13 +1596,13 @@
}
},
"node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "get-intrinsic": "^1.1.3"
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1423,36 +1625,10 @@
"node": ">=8"
}
},
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-proto": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
- "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
"license": "MIT",
"engines": {
@@ -1716,6 +1892,23 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "peer": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -1973,6 +2166,24 @@
"loose-envify": "cli.js"
}
},
+ "node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -2037,10 +2248,21 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "license": "ISC",
+ "peer": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
"node_modules/mocha": {
- "version": "10.7.3",
- "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz",
- "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==",
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz",
+ "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==",
"dev": true,
"license": "MIT",
"peer": true,
@@ -2052,7 +2274,7 @@
"diff": "^5.2.0",
"escape-string-regexp": "^4.0.0",
"find-up": "^5.0.0",
- "glob": "^8.1.0",
+ "glob": "^10.4.5",
"he": "^1.2.0",
"js-yaml": "^4.1.0",
"log-symbols": "^4.1.0",
@@ -2071,7 +2293,7 @@
"mocha": "bin/mocha.js"
},
"engines": {
- "node": ">= 14.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/mocha/node_modules/escape-string-regexp": {
@@ -2447,9 +2669,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz",
- "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.9.tgz",
+ "integrity": "sha512-Aooyr6MXU6HpvvWXKoVoXwKMs/KyVakWwg7xQfv5/S/RIgJMy0Ifa45H9qqYy7pTCszrHzP21Uk4PZq2HpEM8Q==",
"dev": true,
"funding": [
{
@@ -2500,9 +2722,9 @@
}
},
"node_modules/object-inspect": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
- "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2615,6 +2837,14 @@
"node": ">=6"
}
},
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "peer": true
+ },
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -2645,6 +2875,24 @@
"node": ">=8"
}
},
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "peer": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -2684,9 +2932,9 @@
}
},
"node_modules/prettier": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
- "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
+ "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
@@ -2753,9 +3001,9 @@
}
},
"node_modules/qs": {
- "version": "6.13.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
- "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+ "version": "6.13.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz",
+ "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -2917,24 +3165,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -2959,16 +3189,73 @@
}
},
"node_modules/side-channel": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
- "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.7",
"es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.4",
- "object-inspect": "^1.13.1"
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -3040,6 +3327,23 @@
"node": ">=8"
}
},
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -3053,6 +3357,21 @@
"node": ">=8"
}
},
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/strip-final-newline": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
@@ -3128,22 +3447,22 @@
"license": "MIT"
},
"node_modules/tldts": {
- "version": "6.1.59",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.59.tgz",
- "integrity": "sha512-472ilPxsRuqBBpn+KuRBHJvZhk6tTo4yTVsmODrLBNLwRYJPkDfMEHivgNwp5iEl+cbrZzzRtLKRxZs7+QKkRg==",
+ "version": "6.1.69",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.69.tgz",
+ "integrity": "sha512-Oh/CqRQ1NXNY7cy9NkTPUauOWiTro0jEYZTioGbOmcQh6EC45oribyIMJp0OJO3677r13tO6SKdWoGZUx2BDFw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "tldts-core": "^6.1.59"
+ "tldts-core": "^6.1.69"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
- "version": "6.1.59",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.59.tgz",
- "integrity": "sha512-EiYgNf275AQyVORl8HQYYe7rTVnmLb4hkWK7wAk/12Ksy5EiHpmUmTICa4GojookBPC8qkLMBKKwCmzNA47ZPQ==",
+ "version": "6.1.69",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.69.tgz",
+ "integrity": "sha512-nygxy9n2PBUFQUtAXAc122gGo+04/j5qr5TGQFZTHafTKYvmARVXt2cA5rgero2/dnXUfkdPtiJoKmrd3T+wdA==",
"dev": true,
"license": "MIT"
},
@@ -3195,9 +3514,9 @@
}
},
"node_modules/tslib": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz",
- "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==",
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
@@ -3235,9 +3554,9 @@
}
},
"node_modules/undici-types": {
- "version": "6.19.8",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
- "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
"dev": true,
"license": "MIT"
},
@@ -3345,6 +3664,26 @@
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/justfile b/justfile
index 43fca4afc893..eeb465152c33 100644
--- a/justfile
+++ b/justfile
@@ -64,6 +64,24 @@ check_v2 *FLAGS:
cargo check {{ check_flags }} --no-default-features --features "${FEATURES}" -- {{ FLAGS }}
set +x
+build_v2 *FLAGS:
+ #! /usr/bin/env bash
+ set -euo pipefail
+
+ FEATURES="$(cargo metadata --all-features --format-version 1 --no-deps | \
+ jq -r '
+ [ .packages[] | select(.name == "router") | .features | keys[] # Obtain features of `router` package
+ | select( any( . ; test("(([a-z_]+)_)?v2") ) ) ] # Select v2 features
+ | join(",") # Construct a comma-separated string of features for passing to `cargo`
+ ')"
+
+ set -x
+ cargo build --package router --bin router --no-default-features --features "${FEATURES}" {{ FLAGS }}
+ set +x
+
+alias bb := build_v2
+
+
run_v2:
#! /usr/bin/env bash
set -euo pipefail
diff --git a/scripts/execute_cypress_v2.sh b/scripts/execute_cypress_v2.sh
new file mode 100755
index 000000000000..bcd6664e59f0
--- /dev/null
+++ b/scripts/execute_cypress_v2.sh
@@ -0,0 +1,188 @@
+#! /usr/bin/env bash
+
+set -euo pipefail
+
+# Initialize tmp_file globally
+tmp_file=""
+
+# Define arrays for services, etc.
+# Read service arrays from environment variables
+read -r -a payments <<< "${PAYMENTS_CONNECTORS[@]:-}"
+read -r -a payouts <<< "${PAYOUTS_CONNECTORS[@]:-}"
+read -r -a payment_method_list <<< "${PAYMENT_METHOD_LIST[@]:-}"
+read -r -a routing <<< "${ROUTING[@]:-}"
+
+# Define arrays
+connector_map=()
+failed_connectors=()
+
+# Define an associative array to map environment variables to service names
+declare -A services=(
+ ["PAYMENTS_CONNECTORS"]="payments"
+ ["PAYOUTS_CONNECTORS"]="payouts"
+ ["PAYMENT_METHOD_LIST"]="payment_method_list"
+ ["ROUTING"]="routing"
+)
+
+# Function to print messages in color
+function print_color() {
+ # Input params
+ local color="$1"
+ local message="$2"
+
+ # Define colors
+ local reset='\033[0m'
+ local red='\033[0;31m'
+ local green='\033[0;32m'
+ local yellow='\033[0;33m'
+
+ # Use indirect reference to get the color value
+ echo -e "${!color}${message}${reset}"
+}
+export -f print_color
+
+# Function to check if a command exists
+function command_exists() {
+ command -v "$1" > /dev/null 2>&1
+}
+
+# Function to read service arrays from environment variables
+function read_service_arrays() {
+ # Loop through the associative array and check if each service is exported
+ for var in "${!services[@]}"; do
+ if [[ -n "${!var+x}" ]]; then
+ connector_map+=("${services[$var]}")
+ else
+ print_color "yellow" "Environment variable ${var} is not set. Skipping..."
+ fi
+ done
+}
+
+# Function to execute Cypress tests
+function execute_test() {
+ if [[ $# -lt 3 ]]; then
+ print_color "red" "ERROR: Insufficient arguments provided to execute_test."
+ exit 1
+ fi
+
+ local connector="$1"
+ local service="$2"
+ local tmp_file="$3"
+
+ print_color "yellow" "Executing tests for ${service} with connector ${connector}..."
+
+ export REPORT_NAME="${service}_${connector}_report"
+
+ if ! CYPRESS_CONNECTOR="$connector" npm run "cypress:$service"; then
+ echo "${service}-${connector}" >> "${tmp_file}"
+ fi
+}
+export -f execute_test
+
+# Function to run tests
+function run_tests() {
+ local jobs="${1:-1}"
+ tmp_file=$(mktemp)
+
+ # Ensure temporary file is removed on script exit
+ trap 'cleanup' EXIT
+
+ for service in "${connector_map[@]}"; do
+ declare -n connectors="$service"
+
+ if [[ ${#connectors[@]} -eq 0 ]]; then
+ # Service-level test (e.g., payment-method-list or routing)
+ [[ $service == "payment_method_list" ]] && service="payment-method-list"
+
+ echo "Running ${service} tests without connectors..."
+ export REPORT_NAME="${service}_report"
+
+ if ! npm run "cypress:${service}"; then
+ echo "${service}" >> "${tmp_file}"
+ fi
+ else
+ # Connector-specific tests (e.g., payments or payouts)
+ print_color "yellow" "Running tests for service: '${service}' with connectors: [${connectors[*]}] in batches of ${jobs}..."
+
+ # Execute tests in parallel
+ printf '%s\n' "${connectors[@]}" | parallel --jobs "${jobs}" execute_test {} "${service}" "${tmp_file}"
+ fi
+ done
+
+ # Collect failed connectors
+ if [[ -s "${tmp_file}" ]]; then
+ failed_connectors=($(< "${tmp_file}"))
+ print_color "red" "One or more connectors failed to run:"
+ printf '%s\n' "${failed_connectors[@]}"
+ exit 1
+ else
+ print_color "green" "Cypress tests execution successful!"
+ fi
+}
+
+# Function to check and install dependencies
+function check_dependencies() {
+ # parallel and npm are mandatory dependencies. exit the script if not found.
+ local dependencies=("parallel" "npm")
+
+ for cmd in "${dependencies[@]}"; do
+ if ! command_exists "$cmd"; then
+ print_color "red" "ERROR: ${cmd^} is not installed!"
+ exit 1
+ else
+ print_color "green" "${cmd^} is installed already!"
+
+ if [[ ${cmd} == "npm" ]]; then
+ npm ci || {
+ print_color "red" "Command \`npm ci\` failed!"
+ exit 1
+ }
+ fi
+ fi
+ done
+}
+
+# Cleanup function to handle exit
+function cleanup() {
+ print_color "yellow" "Cleaning up..."
+ if [[ -d "cypress-tests" ]]; then
+ cd -
+ fi
+
+ if [[ -n "${tmp_file}" && -f "${tmp_file}" ]]; then
+ rm -f "${tmp_file}"
+ fi
+}
+
+# Main function
+function main() {
+ local command="${1:-}"
+ local jobs="${2:-5}"
+
+ # Ensure script runs from 'cypress-tests' directory
+ if [[ "$(basename "$PWD")" != "cypress-tests-v2" ]]; then
+ print_color "yellow" "Changing directory to 'cypress-tests-v2'..."
+ cd cypress-tests-v2 || {
+ print_color "red" "ERROR: Directory 'cypress-tests-v2' not found!"
+ exit 1
+ }
+ fi
+
+ check_dependencies
+ read_service_arrays
+
+ case "$command" in
+ --parallel | -p)
+ print_color "yellow" "WARNING: Running Cypress tests in parallel is more resource-intensive!"
+ # At present, parallel execution is restricted to not run out of memory
+ # But can be scaled up by passing the value as an argument
+ run_tests "$jobs"
+ ;;
+ *)
+ run_tests 1
+ ;;
+ esac
+}
+
+# Execute the main function with passed arguments
+main "$@"
From 336eceb7eaf2211b5352f323e05b185128b81da6 Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Thu, 26 Dec 2024 21:35:12 +0530
Subject: [PATCH 2/6] Add documentation on generating code coverage locally
---
docs/CONTRIBUTING.md | 46 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index feed9b9cb660..61db1a028a29 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -223,6 +223,52 @@ unstable features:
cargo +nightly fmt
```
+### Code Coverage
+
+We value well tested code. You should try to add tests for the code you add.
+
+For generating code coverage, follow the following steps:
+
+- Make sure `grcov` and `llvm-tools-preview` are installed
+
+- Build the project with the `-Cinstrument-coverage` flag:
+
+ ```shell
+ RUSTFLAGS="-Cinstrument-coverage" cargo build --bin=router --package=router
+ ```
+
+ Several `.profraw` files will be generated.
+
+- Run the project using:
+ ```shell
+ LLVM_PROFILE_FILE="coverage.profraw" target/debug/router
+ ```
+
+- Open a separate terminal tab and run the cypress tests, following the README
+
+- After the tests have finished running, stop the `router` process using `Ctrl+C`
+
+- The generated `coverage.profraw` file will contain the code coverage data for `router`
+
+- Generate an html report from the data using:
+ ```shell
+ grcov . --source-dir . --output-type html --binary-path ./target/debug
+ ```
+
+- A folder named `html` will be generated, containing the report. You can view it using:
+ ```shell
+ cd html && python3 -m http.server 8000
+ ```
+
+- You can delete the generated `.profraw` files using:
+ ```shell
+ rm **/*.profraw
+ ```
+
+Note:
+- It is necessary to stop the `router` process to generate the coverage file
+- Branch coverage generation requires nightly and currently `grcov` crashes while trying to include branch coverage. (Checked using `--log-level` parameter in `grcov`)
+
### Commits
It is a recommended best practice to keep your changes as logically grouped as
From a9ec8715ef8ca36670efcfc7a19e4f2574484c1e Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Mon, 30 Dec 2024 16:19:37 +0530
Subject: [PATCH 3/6] Address review comments
---
.github/workflows/cypress-tests-runner.yml | 12 +-
docs/CONTRIBUTING.md | 23 ++-
justfile | 2 -
scripts/execute_cypress.sh | 11 +-
scripts/execute_cypress_v2.sh | 188 ---------------------
5 files changed, 30 insertions(+), 206 deletions(-)
delete mode 100755 scripts/execute_cypress_v2.sh
diff --git a/.github/workflows/cypress-tests-runner.yml b/.github/workflows/cypress-tests-runner.yml
index a4843bc2a01a..973ab4993b25 100644
--- a/.github/workflows/cypress-tests-runner.yml
+++ b/.github/workflows/cypress-tests-runner.yml
@@ -20,7 +20,6 @@ env:
RUN_TESTS: ${{ ((github.event_name == 'pull_request') && (github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name)) || (github.event_name == 'merge_group')}}
DEBUG: cypress:cli
RUST_MIN_STACK: 10485760
- CODECOV_FILE: "lcov.info"
jobs:
formatter:
@@ -259,6 +258,8 @@ jobs:
runner_v2:
name: Run Cypress tests on v2 and generate coverage report
runs-on: ubuntu-latest
+ env:
+ CODECOV_FILE: "lcov.info"
services:
redis:
@@ -336,7 +337,7 @@ jobs:
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable 2 weeks ago
- components: clippy llvm-tools-preview
+ components: llvm-tools-preview
- name: Install sccache
if: ${{ env.RUN_TESTS == 'true' }}
@@ -355,9 +356,10 @@ jobs:
- name: Install grcov
if: ${{ env.RUN_TESTS == 'true' }}
- uses: baptiste0928/cargo-install@v3.1.1
+ uses: taiki-e/install-action@v2.41.10
with:
- crate: grcov
+ tool: grcov
+ checksum: true
- name: Install Just
if: ${{ env.RUN_TESTS == 'true' }}
@@ -428,7 +430,7 @@ jobs:
shell: bash -leuo pipefail {0}
continue-on-error: true
run: |
- scripts/execute_cypress_v2.sh
+ scripts/execute_cypress.sh "" "" "cypress-tests-v2"
- name: Stop running server
if: ${{ env.RUN_TESTS == 'true' }} && always()
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 61db1a028a29..9b7b6790e3c8 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -225,42 +225,51 @@ cargo +nightly fmt
### Code Coverage
-We value well tested code. You should try to add tests for the code you add.
+We appreciate well-tested code, so feel free to add tests when you can.
-For generating code coverage, follow the following steps:
+To generate code coverage using the cypress tests, follow these steps:
- Make sure `grcov` and `llvm-tools-preview` are installed
+ ```shell
+ rustup install llvm-tools-preview
+ cargo install grcov
+ ```
+
- Build the project with the `-Cinstrument-coverage` flag:
```shell
RUSTFLAGS="-Cinstrument-coverage" cargo build --bin=router --package=router
```
- Several `.profraw` files will be generated.
+ Several `.profraw` files will be generated. (Due to the execution of build scripts)
+
+- Execute the binary:
-- Run the project using:
```shell
LLVM_PROFILE_FILE="coverage.profraw" target/debug/router
```
-- Open a separate terminal tab and run the cypress tests, following the README
+- Open a separate terminal tab and run the cypress tests, following the [README]
- After the tests have finished running, stop the `router` process using `Ctrl+C`
- The generated `coverage.profraw` file will contain the code coverage data for `router`
-- Generate an html report from the data using:
+- Generate an html report from the data:
+
```shell
grcov . --source-dir . --output-type html --binary-path ./target/debug
```
- A folder named `html` will be generated, containing the report. You can view it using:
+
```shell
cd html && python3 -m http.server 8000
```
- You can delete the generated `.profraw` files using:
+
```shell
rm **/*.profraw
```
@@ -269,6 +278,8 @@ Note:
- It is necessary to stop the `router` process to generate the coverage file
- Branch coverage generation requires nightly and currently `grcov` crashes while trying to include branch coverage. (Checked using `--log-level` parameter in `grcov`)
+[README]: /cypress-tests-v2/README.md
+
### Commits
It is a recommended best practice to keep your changes as logically grouped as
diff --git a/justfile b/justfile
index eeb465152c33..5a0d13396ba6 100644
--- a/justfile
+++ b/justfile
@@ -79,8 +79,6 @@ build_v2 *FLAGS:
cargo build --package router --bin router --no-default-features --features "${FEATURES}" {{ FLAGS }}
set +x
-alias bb := build_v2
-
run_v2:
#! /usr/bin/env bash
diff --git a/scripts/execute_cypress.sh b/scripts/execute_cypress.sh
index 1f1219ee717c..8d93519b468c 100755
--- a/scripts/execute_cypress.sh
+++ b/scripts/execute_cypress.sh
@@ -158,12 +158,13 @@ function cleanup() {
function main() {
local command="${1:-}"
local jobs="${2:-5}"
+ local test_dir="${3:-cypress-tests}"
- # Ensure script runs from 'cypress-tests' directory
- if [[ "$(basename "$PWD")" != "cypress-tests" ]]; then
- print_color "yellow" "Changing directory to 'cypress-tests'..."
- cd cypress-tests || {
- print_color "red" "ERROR: Directory 'cypress-tests' not found!"
+ # Ensure script runs from the specified test directory (default: cypress-tests)
+ if [[ "$(basename "$PWD")" != "$(basename "$test_dir")" ]]; then
+ print_color "yellow" "Changing directory to '${test_dir}'..."
+ cd "${test_dir}" || {
+ print_color "red" "ERROR: Directory '${test_dir}' not found!"
exit 1
}
fi
diff --git a/scripts/execute_cypress_v2.sh b/scripts/execute_cypress_v2.sh
deleted file mode 100755
index bcd6664e59f0..000000000000
--- a/scripts/execute_cypress_v2.sh
+++ /dev/null
@@ -1,188 +0,0 @@
-#! /usr/bin/env bash
-
-set -euo pipefail
-
-# Initialize tmp_file globally
-tmp_file=""
-
-# Define arrays for services, etc.
-# Read service arrays from environment variables
-read -r -a payments <<< "${PAYMENTS_CONNECTORS[@]:-}"
-read -r -a payouts <<< "${PAYOUTS_CONNECTORS[@]:-}"
-read -r -a payment_method_list <<< "${PAYMENT_METHOD_LIST[@]:-}"
-read -r -a routing <<< "${ROUTING[@]:-}"
-
-# Define arrays
-connector_map=()
-failed_connectors=()
-
-# Define an associative array to map environment variables to service names
-declare -A services=(
- ["PAYMENTS_CONNECTORS"]="payments"
- ["PAYOUTS_CONNECTORS"]="payouts"
- ["PAYMENT_METHOD_LIST"]="payment_method_list"
- ["ROUTING"]="routing"
-)
-
-# Function to print messages in color
-function print_color() {
- # Input params
- local color="$1"
- local message="$2"
-
- # Define colors
- local reset='\033[0m'
- local red='\033[0;31m'
- local green='\033[0;32m'
- local yellow='\033[0;33m'
-
- # Use indirect reference to get the color value
- echo -e "${!color}${message}${reset}"
-}
-export -f print_color
-
-# Function to check if a command exists
-function command_exists() {
- command -v "$1" > /dev/null 2>&1
-}
-
-# Function to read service arrays from environment variables
-function read_service_arrays() {
- # Loop through the associative array and check if each service is exported
- for var in "${!services[@]}"; do
- if [[ -n "${!var+x}" ]]; then
- connector_map+=("${services[$var]}")
- else
- print_color "yellow" "Environment variable ${var} is not set. Skipping..."
- fi
- done
-}
-
-# Function to execute Cypress tests
-function execute_test() {
- if [[ $# -lt 3 ]]; then
- print_color "red" "ERROR: Insufficient arguments provided to execute_test."
- exit 1
- fi
-
- local connector="$1"
- local service="$2"
- local tmp_file="$3"
-
- print_color "yellow" "Executing tests for ${service} with connector ${connector}..."
-
- export REPORT_NAME="${service}_${connector}_report"
-
- if ! CYPRESS_CONNECTOR="$connector" npm run "cypress:$service"; then
- echo "${service}-${connector}" >> "${tmp_file}"
- fi
-}
-export -f execute_test
-
-# Function to run tests
-function run_tests() {
- local jobs="${1:-1}"
- tmp_file=$(mktemp)
-
- # Ensure temporary file is removed on script exit
- trap 'cleanup' EXIT
-
- for service in "${connector_map[@]}"; do
- declare -n connectors="$service"
-
- if [[ ${#connectors[@]} -eq 0 ]]; then
- # Service-level test (e.g., payment-method-list or routing)
- [[ $service == "payment_method_list" ]] && service="payment-method-list"
-
- echo "Running ${service} tests without connectors..."
- export REPORT_NAME="${service}_report"
-
- if ! npm run "cypress:${service}"; then
- echo "${service}" >> "${tmp_file}"
- fi
- else
- # Connector-specific tests (e.g., payments or payouts)
- print_color "yellow" "Running tests for service: '${service}' with connectors: [${connectors[*]}] in batches of ${jobs}..."
-
- # Execute tests in parallel
- printf '%s\n' "${connectors[@]}" | parallel --jobs "${jobs}" execute_test {} "${service}" "${tmp_file}"
- fi
- done
-
- # Collect failed connectors
- if [[ -s "${tmp_file}" ]]; then
- failed_connectors=($(< "${tmp_file}"))
- print_color "red" "One or more connectors failed to run:"
- printf '%s\n' "${failed_connectors[@]}"
- exit 1
- else
- print_color "green" "Cypress tests execution successful!"
- fi
-}
-
-# Function to check and install dependencies
-function check_dependencies() {
- # parallel and npm are mandatory dependencies. exit the script if not found.
- local dependencies=("parallel" "npm")
-
- for cmd in "${dependencies[@]}"; do
- if ! command_exists "$cmd"; then
- print_color "red" "ERROR: ${cmd^} is not installed!"
- exit 1
- else
- print_color "green" "${cmd^} is installed already!"
-
- if [[ ${cmd} == "npm" ]]; then
- npm ci || {
- print_color "red" "Command \`npm ci\` failed!"
- exit 1
- }
- fi
- fi
- done
-}
-
-# Cleanup function to handle exit
-function cleanup() {
- print_color "yellow" "Cleaning up..."
- if [[ -d "cypress-tests" ]]; then
- cd -
- fi
-
- if [[ -n "${tmp_file}" && -f "${tmp_file}" ]]; then
- rm -f "${tmp_file}"
- fi
-}
-
-# Main function
-function main() {
- local command="${1:-}"
- local jobs="${2:-5}"
-
- # Ensure script runs from 'cypress-tests' directory
- if [[ "$(basename "$PWD")" != "cypress-tests-v2" ]]; then
- print_color "yellow" "Changing directory to 'cypress-tests-v2'..."
- cd cypress-tests-v2 || {
- print_color "red" "ERROR: Directory 'cypress-tests-v2' not found!"
- exit 1
- }
- fi
-
- check_dependencies
- read_service_arrays
-
- case "$command" in
- --parallel | -p)
- print_color "yellow" "WARNING: Running Cypress tests in parallel is more resource-intensive!"
- # At present, parallel execution is restricted to not run out of memory
- # But can be scaled up by passing the value as an argument
- run_tests "$jobs"
- ;;
- *)
- run_tests 1
- ;;
- esac
-}
-
-# Execute the main function with passed arguments
-main "$@"
From 0d0e65b2bb366cdea83846010bc6a6c07c210b85 Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Tue, 31 Dec 2024 15:08:09 +0530
Subject: [PATCH 4/6] Improved Documentation
---
.github/workflows/cypress-tests-runner.yml | 12 +++-
README.md | 4 ++
docs/CONTRIBUTING.md | 69 +++++++++++++---------
3 files changed, 54 insertions(+), 31 deletions(-)
diff --git a/.github/workflows/cypress-tests-runner.yml b/.github/workflows/cypress-tests-runner.yml
index 973ab4993b25..896ece73b559 100644
--- a/.github/workflows/cypress-tests-runner.yml
+++ b/.github/workflows/cypress-tests-runner.yml
@@ -429,8 +429,8 @@ jobs:
ROUTER__SERVER__WORKERS: 4
shell: bash -leuo pipefail {0}
continue-on-error: true
- run: |
- scripts/execute_cypress.sh "" "" "cypress-tests-v2"
+ # We aren't specifying `command` and `jobs` arguments currently
+ run: scripts/execute_cypress.sh "" "" "cypress-tests-v2"
- name: Stop running server
if: ${{ env.RUN_TESTS == 'true' }} && always()
@@ -446,6 +446,14 @@ jobs:
cypress-tests-v2/cypress/reports/
retention-days: 1
+ # Notes:
+ # - The `router` process must be killed (using SIGINT/SIGTERM) to generate the `coverage.profraw` file, otherwise the coverage will only be generated for the buildscripts
+ # - Trying to generate branch coverage using "-Z coverage-options=branch" currently fails. Both grcov and cargo-llvm-cov crash when trying
+ # to process the generated `.profraw` files.
+ # - Explanation of ignore flags:
+ # - "*cargo*" : Exclude external crates from the generated `lcov.info` file
+ # - "target/*" : Exclude compile time generated .rs files, e.g. isodata.rs, chrono-tz/timezones.rs
+ # - "/*" : Exclude /Users/../rustlib/src/rust/library/core/src/panic.rs, /Users/../rustlib/src/rust/library/std/src/sys/thread_local/native/mod.rs etc.
- name: Process coverage report
if: ${{ env.RUN_TESTS == 'true' }}
run: |
diff --git a/README.md b/README.md
index 10fdb6afc760..ca98709be792 100644
--- a/README.md
+++ b/README.md
@@ -30,6 +30,10 @@ The single API to access payment ecosystems across 130+ countries
+
+
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 9b7b6790e3c8..9efb6529bf19 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -229,50 +229,61 @@ We appreciate well-tested code, so feel free to add tests when you can.
To generate code coverage using the cypress tests, follow these steps:
-- Make sure `grcov` and `llvm-tools-preview` are installed
+0. Make sure `grcov` and `llvm-tools-preview` are installed
- ```shell
- rustup install llvm-tools-preview
- cargo install grcov
- ```
+ ```shell
+ rustup install llvm-tools-preview
+ cargo install grcov
+ ```
+
+1. Build the project with the `-Cinstrument-coverage` flag:
+
+ ```shell
+ RUSTFLAGS="-Cinstrument-coverage" cargo build --bin=router --package=router
+ ```
+
+ Several `.profraw` files will be generated. (Due to the execution of build scripts)
+
+2. Execute the binary:
-- Build the project with the `-Cinstrument-coverage` flag:
+ ```shell
+ LLVM_PROFILE_FILE="coverage.profraw" target/debug/router
+ ```
- ```shell
- RUSTFLAGS="-Cinstrument-coverage" cargo build --bin=router --package=router
- ```
+3. Open a separate terminal tab and run the cypress tests, following the [README]
- Several `.profraw` files will be generated. (Due to the execution of build scripts)
+4. After the tests have finished running, stop the `router` process using `Ctrl+C`
-- Execute the binary:
+ The generated `coverage.profraw` file will contain the code coverage data for `router`
- ```shell
- LLVM_PROFILE_FILE="coverage.profraw" target/debug/router
- ```
+5. Generate an html report from the data:
-- Open a separate terminal tab and run the cypress tests, following the [README]
+ ```shell
+ grcov . --source-dir . --output-type html --binary-path ./target/debug
+ ```
-- After the tests have finished running, stop the `router` process using `Ctrl+C`
+6. A folder named `html` will be generated, containing the report. You can view it using:
-- The generated `coverage.profraw` file will contain the code coverage data for `router`
+ ```shell
+ cd html && python3 -m http.server 8000
+ ```
-- Generate an html report from the data:
+7. You can delete the generated `.profraw` files:
- ```shell
- grcov . --source-dir . --output-type html --binary-path ./target/debug
- ```
+ ```shell
+ rm **/*.profraw
+ ```
-- A folder named `html` will be generated, containing the report. You can view it using:
+#### Integration with VSCode
+You can also visualize code coverage in VSCode using the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) extension.
- ```shell
- cd html && python3 -m http.server 8000
- ```
+You need to generate an `lcov.info` file in the directory root. After following till step 4 above:
-- You can delete the generated `.profraw` files using:
+```shell
+grcov . -s . -t lcov --output-path lcov.info --binary-path ./target/debug --ignore "*cargo*" --ignore "target/*" --ignore "/*"
+```
- ```shell
- rm **/*.profraw
- ```
+This will generate an `lcov.info` file that can be read by the extension.
Note:
- It is necessary to stop the `router` process to generate the coverage file
From 961ce987a97b07c61f68d47c6a16777787201c41 Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Tue, 31 Dec 2024 17:13:49 +0530
Subject: [PATCH 5/6] Update S3 source
---
.github/workflows/cypress-tests-runner.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/cypress-tests-runner.yml b/.github/workflows/cypress-tests-runner.yml
index 896ece73b559..e7aa9f1d3773 100644
--- a/.github/workflows/cypress-tests-runner.yml
+++ b/.github/workflows/cypress-tests-runner.yml
@@ -304,7 +304,7 @@ jobs:
CONNECTOR_AUTH_PASSPHRASE: ${{ secrets.CONNECTOR_AUTH_PASSPHRASE }}
CONNECTOR_CREDS_S3_BUCKET_URI: ${{ secrets.CONNECTOR_CREDS_S3_BUCKET_URI}}
DESTINATION_FILE_NAME: "creds.json.gpg"
- S3_SOURCE_FILE_NAME: "6f8289a9-6da0-433b-8a24-18d4d7257b7f.json.gpg"
+ S3_SOURCE_FILE_NAME: "aa328308-b34e-41b7-a590-4fe45cfe7991.json.gpg"
shell: bash
run: |
mkdir -p ".github/secrets" ".github/test"
From 95c95ed4a82d2eebd0bb374ca20c5e4bf00b5141 Mon Sep 17 00:00:00 2001
From: Anurag Thakur
Date: Thu, 2 Jan 2025 16:19:24 +0530
Subject: [PATCH 6/6] Address review comments
---
.github/workflows/cypress-tests-runner.yml | 12 ++++--------
.gitignore | 1 +
docs/CONTRIBUTING.md | 17 +++++++++--------
3 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/.github/workflows/cypress-tests-runner.yml b/.github/workflows/cypress-tests-runner.yml
index e7aa9f1d3773..30432945e3b1 100644
--- a/.github/workflows/cypress-tests-runner.yml
+++ b/.github/workflows/cypress-tests-runner.yml
@@ -450,18 +450,14 @@ jobs:
# - The `router` process must be killed (using SIGINT/SIGTERM) to generate the `coverage.profraw` file, otherwise the coverage will only be generated for the buildscripts
# - Trying to generate branch coverage using "-Z coverage-options=branch" currently fails. Both grcov and cargo-llvm-cov crash when trying
# to process the generated `.profraw` files.
- # - Explanation of ignore flags:
- # - "*cargo*" : Exclude external crates from the generated `lcov.info` file
- # - "target/*" : Exclude compile time generated .rs files, e.g. isodata.rs, chrono-tz/timezones.rs
- # - "/*" : Exclude /Users/../rustlib/src/rust/library/core/src/panic.rs, /Users/../rustlib/src/rust/library/std/src/sys/thread_local/native/mod.rs etc.
+ # - --keep-only argument is used to exclude external crates in generated lcov.info file (~500MiB -> ~70MiB)
- name: Process coverage report
- if: ${{ env.RUN_TESTS == 'true' }}
- run: |
- grcov . --source-dir . --output-types lcov --output-path ${{ env.CODECOV_FILE }} --binary-path ./target/debug --ignore "*cargo*" --ignore "target/*" --ignore "/*"
+ if: ${{ env.RUN_TESTS == 'true' && github.event_name != 'merge_group' }}
+ run: grcov . --source-dir . --output-types lcov --output-path ${{ env.CODECOV_FILE }} --binary-path ./target/debug --keep-only "crates/*"
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
- if: ${{ env.RUN_TESTS == 'true' }}
+ if: ${{ env.RUN_TESTS == 'true' && github.event_name != 'merge_group'}}
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ${{ env.CODECOV_FILE }}
diff --git a/.gitignore b/.gitignore
index dcbeddf7adab..d53145b33ee9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -241,6 +241,7 @@ $RECYCLE.BIN/
# hyperswitch Project specific excludes
# code coverage report
*.profraw
+lcov.info
html/
coverage.json
# other
diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md
index 9efb6529bf19..d9314ceb9196 100644
--- a/docs/CONTRIBUTING.md
+++ b/docs/CONTRIBUTING.md
@@ -34,6 +34,7 @@ Please join us!
- [Resolving a Bug Report](#resolving-a-bug-report)
- [Pull Requests](#pull-requests)
- [Cargo Commands](#cargo-commands)
+ - [Code Coverage](#code-coverage)
- [Commits](#commits)
- [Opening the Pull Request](#opening-the-pull-request)
- [Discuss and update](#discuss-and-update)
@@ -232,7 +233,7 @@ To generate code coverage using the cypress tests, follow these steps:
0. Make sure `grcov` and `llvm-tools-preview` are installed
```shell
- rustup install llvm-tools-preview
+ rustup component add llvm-tools-preview
cargo install grcov
```
@@ -250,7 +251,7 @@ To generate code coverage using the cypress tests, follow these steps:
LLVM_PROFILE_FILE="coverage.profraw" target/debug/router
```
-3. Open a separate terminal tab and run the cypress tests, following the [README]
+3. Open a separate terminal tab and run the cypress tests, following the [README][cypress-v2-readme]
4. After the tests have finished running, stop the `router` process using `Ctrl+C`
@@ -274,22 +275,22 @@ To generate code coverage using the cypress tests, follow these steps:
rm **/*.profraw
```
+Note:
+- It is necessary to stop the `router` process to generate the coverage file
+- Branch coverage generation requires nightly and currently `grcov` crashes while trying to include branch coverage. (Checked using `--log-level` parameter in `grcov`)
+
#### Integration with VSCode
You can also visualize code coverage in VSCode using the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) extension.
You need to generate an `lcov.info` file in the directory root. After following till step 4 above:
```shell
-grcov . -s . -t lcov --output-path lcov.info --binary-path ./target/debug --ignore "*cargo*" --ignore "target/*" --ignore "/*"
+grcov . -s . -t lcov --output-path lcov.info --binary-path ./target/debug --keep-only "crates/*"
```
This will generate an `lcov.info` file that can be read by the extension.
-Note:
-- It is necessary to stop the `router` process to generate the coverage file
-- Branch coverage generation requires nightly and currently `grcov` crashes while trying to include branch coverage. (Checked using `--log-level` parameter in `grcov`)
-
-[README]: /cypress-tests-v2/README.md
+[cypress-v2-readme]: /cypress-tests-v2/README.md
### Commits