diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..483cf232 --- /dev/null +++ b/.env.example @@ -0,0 +1,12 @@ +# Copy this file to .env and fill in real values. +# .env is gitignored and must never be committed. + +# ── Provar Licensing OAuth (Cognito client credentials) ────────────────────── +# Obtain from the Provar platform team. +PROVAR_OAUTH_CLIENT_ID=your-client-id-here +PROVAR_OAUTH_CLIENT_SECRET=your-client-secret-here + +# ── Dev whitelist keys (comma-separated) ───────────────────────────────────── +# Keys that bypass the licensing API entirely (development / CI only). +# Obtain from the Provar platform team. +PROVAR_DEV_WHITELIST_KEYS=your-dev-key-here diff --git a/.github/workflows/CIRelease_Tagging.yml b/.github/workflows/CIRelease_Tagging.yml index f65d60eb..4693b3e1 100644 --- a/.github/workflows/CIRelease_Tagging.yml +++ b/.github/workflows/CIRelease_Tagging.yml @@ -12,10 +12,10 @@ jobs: runs-on: ubuntu-latest if: github.event.pull_request.merged == true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 - name: Install Dependencies run: | yarn diff --git a/.github/workflows/CI_Execution.yml b/.github/workflows/CI_Execution.yml index a6c33d70..c5d03246 100644 --- a/.github/workflows/CI_Execution.yml +++ b/.github/workflows/CI_Execution.yml @@ -22,8 +22,8 @@ jobs: provardx-ci-execution: strategy: matrix: - os: ${{ fromJSON(format('[{0}]', inputs.OS || '"ubuntu-latest" || "macos-latest"')) }} - nodeversion: [18] + os: ${{ fromJSON(inputs.OS && format('[{0}]', inputs.OS) || '["ubuntu-latest", "macos-latest"]') }} + nodeversion: [20] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 @@ -31,7 +31,7 @@ jobs: with: node-version: ${{ matrix.nodeversion }} - name: 'Cache node_modules' - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ matrix.os == 'windows-latest' && 'C:\\Users\\runneradmin\\AppData\\Roaming\\npm-cache' || '~/.npm' }} key: ${{ runner.os }}-node-v${{ matrix.nodeversion }}-${{ hashFiles('**/package.json') }} @@ -39,7 +39,7 @@ jobs: ${{ runner.os }}-node-v${{ matrix.nodeversion }}- - name: 'sf installation' run: | - npm install -g @salesforce/cli + npm install -g @salesforce/cli - name: Determine Branch Name if: matrix.os == 'windows-latest' @@ -49,7 +49,7 @@ jobs: } else { echo "BRANCH_NAME=$(echo $env:GITHUB_REF -replace 'refs/heads/', '')" | Out-File -FilePath $env:GITHUB_ENV -Append } - + - name: Determine Branch Name for Ubuntu/Mac if: matrix.os != 'windows-latest' run: | @@ -88,23 +88,28 @@ jobs: token: ${{ secrets.PATUTILS }} - name: Utils build and link run: | - cd utils - yarn && yarn prepack - yarn link + cd utils + yarn && yarn prepack + yarn link - name: Install Dependencies run: yarn - name: Link utils package run: yarn link @provartesting/provardx-plugins-utils - name: Build the project run: | - sf plugins link . - yarn prepack + sf plugins link . + yarn prepack + - name: MCP smoke test + timeout-minutes: 5 + env: + PROVAR_DEV_WHITELIST_KEYS: ${{ secrets.PROVAR_DEV_WHITELIST_KEYS }} + run: node scripts/mcp-smoke.cjs - name: Check out Regression repo uses: actions/checkout@v4 with: - repository: ProvarTesting/ProvarRegression + repository: ProvarTesting/provar-manager-regression path: ProvarRegression - ref: AnchalGoel + ref: PM_Grid_AutomationPack token: ${{ secrets.PATREGRESSION }} - name: Change permissions run: | @@ -119,7 +124,7 @@ jobs: sf plugins link . yarn run test:nuts - name: Archive NUTS results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: nuts-report-${{ matrix.os }} path: mochawesome-report diff --git a/.github/workflows/DeployManual.yml b/.github/workflows/DeployManual.yml index 271f1d00..f0eea483 100644 --- a/.github/workflows/DeployManual.yml +++ b/.github/workflows/DeployManual.yml @@ -5,7 +5,7 @@ on: workflow_dispatch: inputs: tag: - description: 'tag name e.g. beta, latest etc.' + description: "tag name e.g. beta, latest etc." jobs: build: runs-on: ubuntu-latest @@ -13,11 +13,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 - registry-url: 'https://registry.npmjs.org' - scope: '@provartesting' + node-version: 20 + registry-url: "https://registry.npmjs.org" + scope: "@provartesting" - name: Install dependencies and build run: | npm install -g @salesforce/cli @@ -28,6 +28,7 @@ jobs: cat /home/runner/work/_temp/.npmrc cat $NPM_CONFIG_USERCONFIG - name: Publish package on NPM - run: yarn publish --tag ${{ inputs.tag }} + run: npm publish --tag "$TAG" --access public env: + TAG: ${{ github.event.inputs.tag || 'latest' }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/UnpublishManual.yml b/.github/workflows/UnpublishManual.yml index 11beb3e7..e8a52bd7 100644 --- a/.github/workflows/UnpublishManual.yml +++ b/.github/workflows/UnpublishManual.yml @@ -10,9 +10,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 registry-url: 'https://registry.npmjs.org' scope: '@provartesting' - name: Unpublish package from NPM diff --git a/.gitignore b/.gitignore index 1120f09f..25e73a53 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,9 @@ tmp/ # never checkin npm config .npmrc +# npm lockfile — this project uses yarn; suppress the warning +package-lock.json + # debug logs npm-error.log yarn-error.log @@ -21,13 +24,11 @@ test/lib coverage test_session* -# generated docs -docs - # ignore sfdx-trust files *.tgz *.sig package.json.bak. +.sfdx # -- CLEAN ALL *.tsbuildinfo @@ -46,4 +47,14 @@ oclif.manifest.json #Mocha Report Directory -mochawesome-report \ No newline at end of file +mochawesome-report +.gstack/ + +# Local environment — never commit real credentials +.env +.env.local +.env.*.local + +# Claude +.claude/skills +CLAUDE.md \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit index 4fbfe02f..669c6d9a 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,2 @@ #!/bin/sh -. "$(dirname "$0")/_/husky.sh" - yarn lint && yarn pretty-quick --staged diff --git a/.husky/pre-push b/.husky/pre-push index 56b63c31..2db7f505 100644 --- a/.husky/pre-push +++ b/.husky/pre-push @@ -1,4 +1,2 @@ #!/bin/sh -. "$(dirname "$0")/_/husky.sh" - yarn build && yarn test diff --git a/README.md b/README.md index e903d77c..7598bca8 100644 --- a/README.md +++ b/README.md @@ -6,27 +6,58 @@ # What is the ProvarDX CLI? -The Provar DX CLI is a Salesforce CLI plugin for Provar customers who want to automate the execution of tests using Provar Automation, and the reporting of test results and other quality-related metrics to Provar Manager. +The Provar DX CLI is a Salesforce CLI plugin for Provar customers who want to automate the execution of tests using Provar Automation, and the reporting of test results and other quality-related metrics to Provar Quality Hub. # Installation, Update, and Uninstall Install the plugin + ```sh-session $ sf plugins install @provartesting/provardx-cli ``` Update plugins + ```sh-session $ sf plugins update ``` Uninstall the plugin + ```sh-session $ sf plugins uninstall @provartesting/provardx-cli ``` +# MCP Server (AI-Assisted Quality) + +The Provar DX CLI includes a built-in **Model Context Protocol (MCP) server** that connects AI assistants (Claude Desktop, Claude Code, Cursor) directly to your Provar project. Once connected, an AI agent can inspect your project structure, generate Page Objects and test cases, and validate every level of the test hierarchy with quality scores that match the Provar Quality Hub API. + +```sh +sf provar mcp start --allowed-paths /path/to/your/provar/project +``` + +📖 **See [docs/mcp.md](https://github.com/ProvarTesting/provardx-cli/blob/main/docs/mcp.md) for full setup and tool documentation.** + +## License Validation + +The MCP server verifies your Provar license before accepting any connections. Validation is automatic — no extra flags are required for standard usage. + +**How it works:** + +1. **Auto-detection** — the server reads `~/Provar/.licenses/*.properties` (the same files written by Provar's IDE plugins). If a valid, activated license is found the server starts immediately. +2. **Cache** — successful validations are cached at `~/Provar/.licenses/.mcp-license-cache.json` (2 h TTL). Subsequent starts within the TTL window skip the disk scan. +3. **Grace fallback** — if the IDE license files cannot be found or read and the cache is stale (but ≤ 48 h old), the server starts with a warning on stderr using the cached result so CI pipelines are not broken by transient local file-access issues. +4. **Fail closed** — if no valid license is detected the command exits with a non-zero exit code and a clear error message. + +**`NODE_ENV=test` fast-path:** + +When `NODE_ENV=test` the validation step is skipped entirely. This is intended only for the plugin's own unit-test suite. + +--- + # Commands +- [`sf provar mcp start`](#sf-provar-mcp-start) - [`sf provar config get`](#sf-provar-config-get) - [`sf provar config set`](#sf-provar-config-set) - [`sf provar automation config generate`](#sf-provar-automation-config-generate) @@ -38,13 +69,89 @@ $ sf plugins uninstall @provartesting/provardx-cli - [`sf provar automation project compile`](#sf-provar-automation-project-compile) - [`sf provar automation metadata download`](#sf-provar-automation-metadata-download) - [`sf provar automation test run`](#sf-provar-automation-test-run) -- [`sf provar manager connect`](#sf-provar-manager-connect) -- [`sf provar manager display`](#sf-provar-manager-display) -- [`sf provar manager open`](#sf-provar-manager-open) -- [`sf provar manager testcase retrieve`](#sf-provar-manager-testcase-retrieve) -- [`sf provar manager test run`](#sf-provar-manager-test-run) -- [`sf provar manager test run report`](#sf-provar-manager-test-run-report) -- [`sf provar manager test run abort`](#sf-provar-manager-test-run-abort) +- [`sf provar quality-hub connect`](#sf-provar-quality-hub-connect) +- [`sf provar quality-hub display`](#sf-provar-quality-hub-display) +- [`sf provar quality-hub open`](#sf-provar-quality-hub-open) +- [`sf provar quality-hub testcase retrieve`](#sf-provar-quality-hub-testcase-retrieve) +- [`sf provar quality-hub test run`](#sf-provar-quality-hub-test-run) +- [`sf provar quality-hub test run report`](#sf-provar-quality-hub-test-run-report) +- [`sf provar quality-hub test run abort`](#sf-provar-quality-hub-test-run-abort) +- [`sf provar manager connect`](#sf-provar-manager-connect) _(deprecated — use `sf provar quality-hub connect`)_ +- [`sf provar manager display`](#sf-provar-manager-display) _(deprecated — use `sf provar quality-hub display`)_ +- [`sf provar manager open`](#sf-provar-manager-open) _(deprecated — use `sf provar quality-hub open`)_ +- [`sf provar manager testcase retrieve`](#sf-provar-manager-testcase-retrieve) _(deprecated — use `sf provar quality-hub testcase retrieve`)_ +- [`sf provar manager test run`](#sf-provar-manager-test-run) _(deprecated — use `sf provar quality-hub test run`)_ +- [`sf provar manager test run report`](#sf-provar-manager-test-run-report) _(deprecated — use `sf provar quality-hub test run report`)_ +- [`sf provar manager test run abort`](#sf-provar-manager-test-run-abort) _(deprecated — use `sf provar quality-hub test run abort`)_ + +## `sf provar mcp start` + +Start a local MCP server for Provar tools over stdio transport. + +``` +USAGE + $ sf provar mcp start [-a ...] + +FLAGS + -a, --allowed-paths=... Allowed base directory paths for file operations. + Defaults to the current working directory. + Repeat the flag to allow multiple paths. + +DESCRIPTION + Launches a stateless MCP (Model Context Protocol) server that exposes Provar tools + to AI assistants (Claude Desktop, Claude Code, Cursor) via stdio transport. All MCP + JSON-RPC communication happens over stdout; all internal logging goes to stderr. + + Note: --json is not available on this command — stdout is reserved for MCP traffic. + +TOOLS EXPOSED + provar.project.inspect — inspect project folder inventory + provar.pageobject.generate — generate Java Page Object skeleton + provar.pageobject.validate — validate Page Object quality (30+ rules) + provar.testcase.generate — generate XML test case skeleton + provar.testcase.validate — validate test case XML (validity + best-practices scores) + provar.testsuite.validate — validate test suite hierarchy + provar.testplan.validate — validate test plan with metadata completeness checks + provar.project.validate — validate full project: cross-cutting rules, connections, environments + provar.properties.generate — generate provardx-properties.json from the standard template + provar.properties.read — read and parse a provardx-properties.json file + provar.properties.set — update fields in a provardx-properties.json file + provar.properties.validate — validate a provardx-properties.json file against the schema + provar.ant.generate — generate an ANT build.xml for CI/CD pipeline execution + provar.ant.validate — validate an ANT build.xml for structural correctness + provar.qualityhub.connect — connect to a Quality Hub org + provar.qualityhub.display — display connected Quality Hub org info + provar.qualityhub.testrun — trigger a Quality Hub test run + provar.qualityhub.testrun.report — poll test run status + provar.qualityhub.testrun.abort — abort an in-progress test run + provar.qualityhub.testcase.retrieve — retrieve test cases by user story / component + provar.automation.setup — detect or download/install Provar Automation binaries + provar.automation.testrun — trigger a Provar Automation test run (LOCAL) + provar.automation.compile — compile Page Objects after changes + provar.automation.config.load — register a provardx-properties.json as the active config (required before compile/testrun) + provar.automation.metadata.download — download Salesforce metadata into the project + provar.qualityhub.defect.create — create Quality Hub defects from failed test executions + provar.testrun.report.locate — resolve artifact paths (JUnit.xml, HTML reports) for a completed test run + provar.testrun.rca — analyse a completed test run: classify failures, extract page objects, detect pre-existing issues + provar.testplan.add-instance — wire a test case into a plan suite by writing a .testinstance file + provar.testplan.create-suite — create a new test suite directory with .planitem inside a plan + provar.testplan.remove-instance — remove a .testinstance file from a plan suite + +EXAMPLES + Start MCP server (accepts stdio connections from Claude Desktop / Cursor): + + $ sf provar mcp start + + Start with an explicit allowed path: + + $ sf provar mcp start --allowed-paths /workspace/provar + + Allow multiple directories: + + $ sf provar mcp start -a /workspace/project-a -a /workspace/project-b +``` + +📖 **Full tool documentation and client configuration: [docs/mcp.md](https://github.com/ProvarTesting/provardx-cli/blob/main/docs/mcp.md)** ## `sf provar config get` @@ -163,7 +270,7 @@ DESCRIPTION EXAMPLES Check if the loaded properties file has all the required properties set: - + $ sf provar automation config validate ``` @@ -301,6 +408,153 @@ EXAMPLES $ sf provar automation test run ``` +## `sf provar quality-hub connect` + +Connect to a Provar Quality Hub org. + +``` +USAGE + $ sf provar quality-hub connect -o [--json] + +FLAGS + -o, --target-org= (required) Username or alias set in the SF CLI which corresponds to the Provar Quality Hub org. + +GLOBAL FLAGS + --json Format output as json. + +DESCRIPTION + Load the alias or username to be used in subsequent Quality Hub commands. + +EXAMPLES + Connect to the Quality Hub org stored with alias "ProvarQualityHub": + + $ sf provar quality-hub connect -o ProvarQualityHub +``` + +## `sf provar quality-hub display` + +Display information about the connected Provar Quality Hub org. + +``` +USAGE + $ sf provar quality-hub display [--json] + +GLOBAL FLAGS + --json Format output as json. + +EXAMPLES + Display information about the connected Quality Hub org: + + $ sf provar quality-hub display +``` + +## `sf provar quality-hub open` + +Open Provar Quality Hub in a browser. + +``` +USAGE + $ sf provar quality-hub open [--json] + +GLOBAL FLAGS + --json Format output as json. + +EXAMPLES + Open Quality Hub in a browser: + + $ sf provar quality-hub open +``` + +## `sf provar quality-hub testcase retrieve` + +Retrieve test cases related to the provided user stories or metadata components. + +``` +USAGE + $ sf provar quality-hub testcase retrieve -p -t Apex|ProvarAutomation [--json] [-m ] [-f ] [-i ] [-o ] [-n ] [-l ] + +FLAGS + -f, --metadata-file= Path to a text file containing the list of metadata components. + -i, --issues= Comma-separated list of issue IDs or keys. + -l, --test-plan= Test Plan name. Use to retrieve test instance file paths. + -m, --metadata-components= Semicolon-separated list of metadata components. + -n, --ignore-metadata= Semicolon-separated list of metadata types to ignore. + -o, --output= Output to a specific file instead of stdout. + -p, --test-project= (required) Test Project key to filter by. + -t, --test-automation-tool=