Newman CI Workflow
Newman CI Workflow
The Newman integration test suite runs the full Postman collection against a live or staging API using Newman, Postman’s CLI runner. This document covers the workflow definition, required secrets, how to trigger runs manually, how to interpret the HTML report, and the current state of the x402 end-to-end test stub.
Changes introduced in: PRs #1711, #1712, #1713
See also: Postman Collection README — collection structure, variable naming, admin routes
See also: Postman Testing Guide — complete testing reference
Overview
The Newman integration test suite validates the Bloqr Compiler Worker API end-to-end on every deployment and on demand. It runs the full Postman collection (docs/postman/postman-collection.json) against a live environment — either the production Cloudflare Worker or a staging instance — using Newman, Postman’s command-line collection runner.
The workflow is defined in .github/workflows/newman.yml. It is designed to be:
- Triggered manually from the GitHub Actions UI or the
ghCLI. - Called automatically by the deployment pipeline after a successful deploy via
workflow_call. - Self-contained — all credentials are injected as environment variables from GitHub Actions secrets; no Postman account is required on the local developer machine.
Artifacts — an interactive HTML report and a machine-readable JSON results file — are uploaded with 30-day retention after every run.
Workflow Triggers
The workflow responds to two triggers:
on: workflow_dispatch: # Manual trigger from the Actions UI inputs: environment: description: "Target environment" required: true default: "cloudflare" type: choice options: - cloudflare - local workflow_call: # Called by the deployment pipeline after a successful deploy inputs: environment: description: "Target environment" required: false default: "cloudflare" type: stringworkflow_dispatch accepts an environment input (cloudflare or local, defaulting to cloudflare) that selects which Postman environment file is loaded. workflow_call is used by the deployment pipeline with the same environment input so Newman always runs against the environment that was just deployed rather than a hard-coded default.
Required Secrets
The following secrets must be configured in Settings → Secrets and variables → Actions before the workflow can authenticate with the API under test.
| Secret | Injected as | Description |
|---|---|---|
NEWMAN_USER_API_KEY | bearerToken | A valid API key for a test user; used to authenticate compile/queue endpoints |
NEWMAN_POSTMAN_EMAIL | postmanEmail | Email address of the Postman account that owns the synced collection |
NEWMAN_POSTMAN_PASSWORD | postmanPassword | Password for the Postman account (used to export collection via API) |
Note: The API key in
NEWMAN_USER_API_KEYmust be pre-created. It is not provisioned by the workflow itself. Create it via the dashboard or with a session-authenticated request:Terminal window curl -X POST https://api.bloqr.dev/api/keys \-H "Cookie: better_auth.session_token=<your-session>" \-H "Content-Type: application/json" \-d '{"name": "newman-ci"}'
To set secrets from the CLI:
gh secret set NEWMAN_USER_API_KEY --body "blq_xxxxxxxxxxxxxxxxxxxx"gh secret set NEWMAN_POSTMAN_EMAIL --body "newman@test.bloqr.io"gh secret set NEWMAN_POSTMAN_PASSWORD --body "<password>"Workflow Steps
The workflow performs the following steps in order:
-
Checkout — checks out the repository at the deployment SHA so the collection and environment files match exactly what was deployed.
-
Install Newman — installs the Newman runner and the
htmlextrareporter globally:Terminal window npm install -g newman newman-reporter-htmlextra -
Export Postman collection — downloads the latest synced collection from the Postman API using
NEWMAN_POSTMAN_EMAILandNEWMAN_POSTMAN_PASSWORD. This ensures the collection used in CI always matches the latest saved version in Postman Cloud, even if local JSON files are slightly stale. -
Run Newman — executes the full collection against the target environment, injecting secrets as
--env-varoverrides:Terminal window newman run docs/postman/postman-collection.json \-e docs/postman/postman-environment-prod.json \--env-var "bearerToken=$NEWMAN_USER_API_KEY" \--env-var "postmanEmail=$NEWMAN_POSTMAN_EMAIL" \--env-var "postmanPassword=$NEWMAN_POSTMAN_PASSWORD" \--reporters cli,htmlextra,json \--reporter-htmlextra-export newman-report.html \--reporter-json-export newman-results.json -
Upload HTML report — saves
newman-report.htmlas thenewman-reportartifact (30-day retention). -
Upload JSON results — saves
newman-results.jsonas thenewman-resultsartifact for downstream processing or dashboards.
Calling from another workflow
To call this workflow from a deployment pipeline:
jobs: integration-tests: uses: ./.github/workflows/newman.yml with: environment: cloudflare secrets: inheritsecrets: inherit forwards all repository secrets automatically, satisfying the workflow_call secret requirements.
How to Trigger Manually
From the GitHub Actions UI
- Go to Actions → Newman Integration Tests.
- Click Run workflow (top right of the workflow list).
- Select the branch (typically
main). - Set
environmenttocloudflare(production) orlocal(requires a locally running Worker on:8787). - Click the green Run workflow button.
From the CLI
Using the gh CLI (requires gh auth login first):
# Run against production on the main branchgh workflow run newman.yml \ --ref main \ -f environment=cloudflare
# Run against production on a feature branchgh workflow run newman.yml \ --ref feat/my-feature \ -f environment=cloudflareTo watch the run in real time:
gh run watch $(gh run list --workflow newman.yml --limit 1 --json databaseId -q '.[0].databaseId')How to Read the HTML Report
The HTML report artifact is uploaded as newman-report after every workflow run.
Download via the CLI
# Replace <run-id> with the numeric run ID from `gh run list`gh run download <run-id> --name newman-report --dir /tmp/newman-reportopen /tmp/newman-report/newman-report.htmlTo find the latest run ID:
gh run list --workflow newman.yml --limit 5What the report shows
The htmlextra reporter produces a self-contained HTML file with:
- Summary bar — total requests, passed assertions, failed assertions, skipped requests, average response time.
- Folder-level breakdown — collapsible sections per Postman folder (e.g.,
Auth,Compile,Admin/Users,x402 Contract Tests) showing pass/fail counts. - Per-request detail — for each request: HTTP method, URL, status code, response time in milliseconds, and the full list of test assertions with pass/fail status.
- Failed assertion detail — for any failing assertion: the assertion script, the actual value received, and the expected value. This is the primary debugging surface when a test regresses.
- Request/response bodies — expandable panels for request headers, request body, response headers, and response body. Useful for diagnosing auth failures or unexpected response shapes.
- Timeline — a Gantt-style view of request execution order and duration.
Common failure patterns
| Symptom | Likely cause |
|---|---|
| All requests fail with 401 | NEWMAN_USER_API_KEY is expired, revoked, or incorrect |
| Admin folder fails with 403 | CF_ACCESS_CLIENT_ID/CF_ACCESS_CLIENT_SECRET missing or expired |
x402 Contract Tests fail with 200 | The compile endpoint accepted a request that should have returned 402 |
| Intermittent timeouts | Worker cold-start on first request; re-run the workflow |
Running Newman Locally
Running Newman locally is the fastest way to iterate on collection changes or debug a failing CI test without waiting for a full workflow run.
Prerequisites
npm install -g newman newman-reporter-htmlextraRun the full collection against the local Worker
Start the Worker first (deno task worker:dev or wrangler dev), then:
newman run docs/postman/postman-collection.json \ -e docs/postman/postman-environment-local.json \ --env-var "bearerToken=$NEWMAN_USER_API_KEY" \ --reporters cli,htmlextra \ --reporter-htmlextra-export /tmp/newman-report.htmlOpen /tmp/newman-report.html in a browser to inspect results.
Run the full collection against production
newman run docs/postman/postman-collection.json \ -e docs/postman/postman-environment-prod.json \ --env-var "bearerToken=$NEWMAN_USER_API_KEY" \ --reporters cli,htmlextra \ --reporter-htmlextra-export /tmp/newman-report-prod.htmlRun only a specific folder
# x402 contract tests onlynewman run docs/postman/postman-collection.json \ -e docs/postman/postman-environment-local.json \ --folder "x402 Contract Tests" \ --env-var "bearerToken=$NEWMAN_USER_API_KEY"Run with JSON output for scripting
newman run docs/postman/postman-collection.json \ -e docs/postman/postman-environment-local.json \ --env-var "bearerToken=$NEWMAN_USER_API_KEY" \ --reporters json \ --reporter-json-export /tmp/newman-results.json
# Count failuresjq '.run.stats.assertions.failed' /tmp/newman-results.jsonCloudflare Access and Admin Routes
Admin route tests (/api/admin/*) require a valid Cloudflare Access service token. Newman injects these via custom headers sourced from CI secrets:
| Secret | Newman --env-var | Header sent to API |
|---|---|---|
CF_ACCESS_CLIENT_ID | cfAccessClientId | CF-Access-Client-Id |
CF_ACCESS_CLIENT_SECRET | cfAccessClientSecret | CF-Access-Client-Secret |
These are set in the Postman collection’s pre-request script for the admin/ folder. If the secrets are absent or the service token has expired, the admin folder fails with 403 and the rest of the collection continues unaffected.
To rotate or create a new service token:
- Go to Cloudflare Zero Trust → Access → Service Tokens.
- Create a new token or rotate the existing
newman-citoken. - Update
CF_ACCESS_CLIENT_IDandCF_ACCESS_CLIENT_SECRETin GitHub Actions secrets.
x402 E2E Stub and Roadmap
.github/workflows/x402-e2e.yml exists in the repository as a stub for a future full end-to-end x402 payment test. It is not currently active — the workflow has no trigger that fires automatically and will not run until the prerequisites below are satisfied. It serves as both a placeholder and documentation for what is needed to complete the implementation.
What the x402 e2e workflow would test (when fully implemented)
- 402 response shape —
POST /api/compilewith an exhausted PAYG balance returns a402 Payment Requiredresponse whose body conforms exactly to the x402 payment-required schema. - Payment acceptance — a valid
X-Paymentheader constructed with a Stripe test-mode payment intent is sent on retry, and the compile proceeds to a200 OKresponse. - Idempotency — the same payment header cannot be replayed.
What is needed before the stub can be activated
- Stripe test mode keys —
STRIPE_TEST_SECRET_KEYandSTRIPE_TEST_PUBLISHABLE_KEYadded to GitHub Actions secrets. - x402 CLI payment listener — a lightweight process that listens for payment requests on a known port, auto-pays using the Stripe test key, and outputs the resulting
X-Paymentheader value. - Two-phase test structure:
- Phase 1: verify 402 response shape (already covered by the x402 Contract Tests folder in the main Newman workflow — this is already active).
- Phase 2: send a valid payment header and verify the compile proceeds to 200.
- Cleanup step — cancel or void the Stripe payment intent after the test to avoid accumulating test charges.
Until these prerequisites are in place, x402 contract testing (response shape validation only) is handled by the x402 Contract Tests folder in the main Newman workflow (newman.yml). This folder runs on every Newman invocation and provides meaningful signal without requiring a live payment stack.
Related Documentation
- Postman README — collection structure, variable naming, admin routes
- Postman Testing Guide — complete testing reference including local setup and assertion authoring
- Error Passing Architecture — error logging endpoints tested by Newman