Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@

## Commands Run (local verification)

<!-- Run `npm run verify` and paste the result. This is the single gate that
mirrors CI: lint -> circular check -> tests -> coverage -> build. -->
- [ ] `npm run verify` passed locally
<!-- Run `npm run presubmit` (or `npm run verify`) and paste the result.
This is the single local gate that mirrors CI:
lint -> circular check -> tests -> coverage -> build. -->
- [ ] `npm run presubmit` passed locally (or `npm run verify`)

```
<paste `npm run verify` output summary here>
<paste `npm run presubmit` / `npm run verify` output summary here>
```

## CI Status
Expand Down
16 changes: 13 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ npm run test:watch
# Type-check without emitting files
npm run lint

# Pre-PR verification (tests, build, docs/CI reminders, acceptance criteria checklist)
# Pre-submission verification (lint, tests, coverage, build — run before opening a PR)
npm run presubmit

# Pre-PR verification (same checks + docs/CI reminders + acceptance criteria checklist)
npm run verify:pr

# Start the dev watcher
Expand Down Expand Up @@ -130,8 +133,14 @@ reminders from your git diff, and prints issue acceptance criteria, run:
npm run verify:pr
```

See [Pre-PR Verification](./docs/pre-pr-verification.md) for checklist
generation and `--issue` / `--checklist` options.
Before that (or as the minimum CI-parity gate), always run:

```bash
npm run presubmit
```

See [Pre-submission Verification](./docs/pre-submission-verification.md) and
[Pre-PR Verification](./docs/pre-pr-verification.md).

All tests must pass. ✅

Expand Down Expand Up @@ -173,6 +182,7 @@ The PocketPay SDK handles sensitive cryptographic keys and financial transaction

Before opening a PR, run through this list:

- [ ] `npm run presubmit` passes (lint, circular deps, tests, coverage, build)
- [ ] `npm run verify:pr` passes (or `npm run lint` + `npm test` at minimum)
- [ ] `npm run lint` passes with no errors
- [ ] `npm test` passes with no failures
Expand Down
25 changes: 16 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ npm install @axionvera/pocketpay-sdk
- [SDK Roadmap](./docs/roadmap.md) - Directional plans and contributor opportunities across the SDK
- [Testing](./docs/testing.md) - Unit vs integration test lanes and the offline guarantee
- [Pre-PR Verification](./docs/pre-pr-verification.md) - Run `npm run verify:pr` before opening a pull request to confirm tests, docs, CI, and issue acceptance criteria
- [Pre-submission Verification](./docs/pre-submission-verification.md) - Run `npm run presubmit` before submitting a PR (lint, tests, coverage, build)
- [Contribution Quality Gate](./docs/contribution-quality-gate.md) - Maintainer checklist and examples of incomplete vs acceptable issue work before approval
- [Getting Started](./docs/getting-started.md) - Step-by-step guide to install, create wallets, fund accounts, check balances, and send payments
- [End-to-End App Integration Blueprint](./docs/app_integration_blueprint.md) - App-level flow combining config, diagnostics, wallet, account, payments, transactions, Soroban, vault, security, and typed error handling
Expand Down Expand Up @@ -101,25 +102,31 @@ alternatives and their cleanup steps.

## Local Verification

Run the full pre-push gate locally so CI stays green:
Before submitting a pull request, run the pre-submission command:

```bash
npm run verify
npm run presubmit
```

`npm run verify` runs, in order: **lint** (`tsc --noEmit`) → **circular-dependency
check** → **unit tests** (`vitest run`) → **coverage** (`vitest run --coverage`)
→ **build** (`tsc`). It stops at the first failure. See
[Local Verification Workflow](./docs/local-verification.md) for step details,
when to run it, and failure-handling guidance. This mirrors what the repo's
automation checks when a PR is opened.
This is the contributor-facing pre-submission command. It runs the same
CI-parity pipeline as `npm run verify`: **lint** → **circular-dependency check**
→ **unit tests** → **coverage** → **build**, stops at the first failure, and
prints fix guidance.

See [Pre-submission Verification](./docs/pre-submission-verification.md) for
usage and failure guidance. Details of each pipeline step also live in
[Local Verification Workflow](./docs/local-verification.md).

```bash
npm run verify # same checks without step banners
```

## Pull Request Expectations

Every PR uses the
[PR template](./.github/PULL_REQUEST_TEMPLATE.md), which requires you to state
the related issue, implementation scope, **tests added** (or why tests don't
apply), the **`npm run verify`** output you ran locally, CI status, and
apply), the **`npm run verify` / `npm run presubmit`** output you ran locally, CI status, and
acceptance-criteria coverage. A merged PR is not automatically payment-approved;
reward eligibility is assessed separately. See [CONTRIBUTING.md](./CONTRIBUTING.md)
for the full checklist.
Expand Down
4 changes: 4 additions & 0 deletions docs/local-verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ npm run verify

All steps must pass locally before opening or updating a PR.

> **Contributor shortcut:** `npm run presubmit` runs this same pipeline with
> labeled steps and failure hints. Prefer it before submitting a PR — see
> [Pre-submission Verification](./pre-submission-verification.md).

## When to run it

- After finishing a change, **before** `git push`.
Expand Down
1 change: 1 addition & 0 deletions docs/pre-pr-verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ PocketPay SDK — Pre-PR Acceptance Verification
## Related docs

- [CONTRIBUTING.md](../CONTRIBUTING.md) — contributor setup and PR checklist
- [Pre-submission Verification](./pre-submission-verification.md) — `npm run presubmit` CI-parity gate before opening a PR
- [Contribution Quality Gate](./contribution-quality-gate.md) — maintainer pass/hold checklist before approval
- [testing.md](./testing.md) — unit vs integration test lanes
- [release-checklist.md](./release-checklist.md) — maintainer release gates (`npm run verify`)
96 changes: 96 additions & 0 deletions docs/pre-submission-verification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Pre-submission Verification

Run **one command** before opening or updating an SDK pull request. It mirrors
the local CI-parity pipeline so lint, typecheck, tests, coverage, and build
failures are caught on your machine instead of in CI.

```bash
npm run presubmit
```

Aliases (same behaviour):

```bash
npm run verify:presubmit
npm run verify # same checks, quieter (no step banners)
```

## What it runs

`npm run presubmit` executes these steps **in order** and **stops at the first failure**:

| Step | Command | Purpose |
| :--- | :--- | :--- |
| Lint / typecheck | `npm run lint` | `tsc --noEmit` — no type errors |
| Circular deps | `npm run check:circular` | No illegal import cycles in `src/` |
| Unit tests | `npm test` | Offline Vitest suite |
| Coverage | `npm run test:coverage` | Coverage report (v8; thresholds informational) |
| Build | `npm run build` | Package compiles to `dist/` |

This is the contributor-facing pre-submission command for issue work. Use it
after your change is complete and before `git push` / opening the PR.

## When to run it

- After finishing a feature or bugfix, **before** submitting a PR
- After rebasing onto `main`
- Before requesting review on an updated PR

For acceptance-criteria reminders and git-based docs/CI hints, also run
`npm run verify:pr` (see [Pre-PR Verification](./pre-pr-verification.md)).

## Failure guidance

| Failed step | What it means | How to fix |
| :--- | :--- | :--- |
| Lint / typecheck | TypeScript errors under `tsc --noEmit` | Fix the reported types; do not hide them with `@ts-ignore` |
| Circular dependency check | A new import cycle was introduced | Break the cycle — move shared code to a leaf module ([dependency map](./dependency_direction_map.md)) |
| Unit tests | A unit test failed | Read Vitest output; fix the cause (or the assertion). Keep tests offline ([testing.md](./testing.md)) |
| Coverage | Coverage runner failed | Run `npm install` so `@vitest/coverage-v8` is present |
| Build | `tsc` cannot emit `dist/` | Usually the same root cause as lint — resolve types first |

After fixing, re-run:

```bash
npm run presubmit
```

A green local run does **not** replace watching GitHub CI on the PR, but it
prevents most avoidable red checks.

## Example success output

```text
PocketPay SDK — Pre-submission verification
==========================================

→ [1/5] Lint / typecheck (`npm run lint`)
✓ Lint / typecheck (4120ms)


✓ Pre-submission verification passed.
You are ready to push and open/update your PR.
```

## Example failure output

```text
→ [3/5] Unit tests (offline) (`npm run test`)

✗ Failed: Unit tests (offline) (1850ms)
Fix: Read the Vitest failure output and fix the cause …

See docs/pre-submission-verification.md#failure-guidance for the full table.
Re-run `npm run presubmit` after fixing.
```

## Related docs

- [Local Verification Workflow](./local-verification.md) — details of the `npm run verify` pipeline
- [Pre-PR Verification](./pre-pr-verification.md) — `npm run verify:pr` checklist / acceptance criteria
- [Contribution Quality Gate](./contribution-quality-gate.md) — maintainer pass/hold before approval
- [CONTRIBUTING.md](../CONTRIBUTING.md) — contributor setup
- [testing.md](./testing.md) — unit vs integration lanes
3 changes: 2 additions & 1 deletion docs/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,5 +55,6 @@ occasionally non-deterministic. Keep them out of the critical path: the default
| `npm run test:unit` | Unit suite (explicit alias of `npm test`) |
| `npm run test:watch` | Unit suite in watch mode |
| `npm run test:integration` | Integration suite (opt-in, needs the env flag)|
| `npm run verify` | Lint, circular-deps check, unit tests, and build |
| `npm run verify` | Lint, circular-deps check, unit tests, coverage, and build |
| `npm run presubmit` | Pre-submission command (same checks + step banners / failure hints) |
| `npm run verify:pr` | Pre-PR script: automated checks + docs/CI/criteria reminders |
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"lint": "tsc --noEmit",
"check:circular": "tsx scripts/check-circular-deps.ts",
"verify": "npm run lint && npm run check:circular && npm run test && npm run test:coverage && npm run build",
"presubmit": "tsx scripts/presubmit.ts",
"verify:presubmit": "tsx scripts/presubmit.ts",
"verify:pr": "tsx scripts/verify-acceptance.ts",
"prepack": "npm run build",
"prepublishOnly": "npm run build",
Expand Down
132 changes: 132 additions & 0 deletions scripts/presubmit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env node
/**
* Pre-submission verification command (issue #392).
*
* One local command contributors run before opening or updating an SDK PR.
* Mirrors the `npm run verify` CI-parity pipeline with clear step output and
* failure guidance.
*/
import { spawnSync } from 'child_process';
import path from 'path';

const ROOT = path.resolve(__dirname, '..');

interface CheckStep {
id: string;
label: string;
/** npm script name shown in logs (e.g. lint, test:coverage). */
npmScript: string;
command: string;
args: string[];
/** Short fix hint shown when this step fails. */
failureHint: string;
}

const STEPS: CheckStep[] = [
{
id: 'lint',
label: 'Lint / typecheck',
npmScript: 'lint',
command: 'npm',
args: ['run', 'lint'],
failureHint:
'Fix TypeScript errors reported by `tsc --noEmit`. Do not silence them with `@ts-ignore`.',
},
{
id: 'circular',
label: 'Circular dependency check',
npmScript: 'check:circular',
command: 'npm',
args: ['run', 'check:circular'],
failureHint:
'Break the import cycle (move shared types/helpers into a leaf module). See docs/dependency_direction_map.md.',
},
{
id: 'test',
label: 'Unit tests (offline)',
npmScript: 'test',
command: 'npm',
args: ['test'],
failureHint:
'Read the Vitest failure output and fix the cause (or the test if the assertion is wrong). Keep unit tests offline — see docs/testing.md.',
},
{
id: 'coverage',
label: 'Coverage report',
npmScript: 'test:coverage',
command: 'npm',
args: ['run', 'test:coverage'],
failureHint:
'Ensure `@vitest/coverage-v8` is installed (`npm install`). Thresholds are informational (0) unless raised in config.',
},
{
id: 'build',
label: 'Package build',
npmScript: 'build',
command: 'npm',
args: ['run', 'build'],
failureHint:
'Resolve `tsc` emit errors (usually the same root cause as lint). Confirm `dist/` is produced.',
},
];

function printHelp(): void {
console.log(`
PocketPay SDK — Pre-submission verification

Usage:
npm run presubmit
npm run verify:presubmit

Runs the same local CI-parity checks as \`npm run verify\`:
lint → check:circular → test → test:coverage → build

Stops at the first failure and prints fix guidance.

Documentation: docs/pre-submission-verification.md
`);
}

function runStep(step: CheckStep): { ok: boolean; durationMs: number } {
const started = Date.now();
const result = spawnSync(step.command, step.args, {
cwd: ROOT,
stdio: 'inherit',
shell: process.platform === 'win32',
});
return { ok: result.status === 0, durationMs: Date.now() - started };
}

function main(argv: string[]): number {
if (argv.includes('--help') || argv.includes('-h')) {
printHelp();
return 0;
}

console.log('PocketPay SDK — Pre-submission verification');
console.log('==========================================');
console.log('Run this before opening or updating a pull request.');
console.log('Pipeline: lint → circular → test → coverage → build\n');

for (let i = 0; i < STEPS.length; i++) {
const step = STEPS[i]!;
console.log(`→ [${i + 1}/${STEPS.length}] ${step.label} (\`npm run ${step.npmScript}\`)`);
const result = runStep(step);
if (!result.ok) {
console.error(`\n✗ Failed: ${step.label} (${result.durationMs}ms)`);
console.error(` Fix: ${step.failureHint}`);
console.error('\nSee docs/pre-submission-verification.md#failure-guidance for the full table.');
console.error('Re-run `npm run presubmit` after fixing.\n');
return 1;
}
console.log(`✓ ${step.label} (${result.durationMs}ms)\n`);
}

console.log('✓ Pre-submission verification passed.');
console.log(' You are ready to push and open/update your PR.');
console.log(' Optional next: `npm run verify:pr` for acceptance-criteria reminders.');
console.log(' See docs/pre-submission-verification.md\n');
return 0;
}

process.exit(main(process.argv.slice(2)));