feat(parse-server-mongo): compat-lane-ready sample + JS line coverage gate#97
Open
AkashKumar7902 wants to merge 6 commits intomainfrom
Open
feat(parse-server-mongo): compat-lane-ready sample + JS line coverage gate#97AkashKumar7902 wants to merge 6 commits intomainfrom
AkashKumar7902 wants to merge 6 commits intomainfrom
Conversation
…e template
Make the parse-server-mongo sample directly consumable as a keploy compat-lane
sample, on par with samples-typescript/umami-postgres and samples-python/
doccano-django.
- flow.sh refactored to subcommand form: bootstrap | record-traffic |
coverage | list-routes. bootstrap is idempotent (4xx during signup is
treated as already-exists), persists the session token to
/tmp/parse-token-${PARSE_PHASE}, and preserves the 3-second post-/health
pause that the boot-phase _SCHEMA divergence reproducer needs.
- record-traffic ports the broad parse-server REST + GraphQL surface
(51 fire calls across users/sessions/classes/roles/files/cloud-functions/
schemas/hooks/graphql/aggregate). Every curl is preceded by log_fired so
PARSE_FIRED_ROUTES_FILE captures (method,route) for coverage. The
multi-class _SCHEMA mutation (GameScore, PlayerStats, Achievement) is
retained so the boot-phase tiebreaker reproducer still triggers.
- coverage subcommand reports (method,route) coverage with numerator from
keploy/test-set-*/tests/*.yaml when present, else from the fired-routes
log. Denominator from a curated 35-route table in parse_list_routes.
- docker-compose.yml takes ${VAR:-default} for project name, network name,
network subnet, IPs, container names, host:container port, and the
internal PORT env. Defaults preserve standalone `docker compose up`;
overrides let concurrent matrix cells share a single docker daemon.
- keploy.yml.template carries the parse-server noise filter (header.Date,
body.objectId, body.sessionToken, body.createdAt, body.updatedAt) so a
lane consumer can apply it to keploy.yml after `keploy config --generate`.
- README rewritten to document the four subcommands, all env vars, the
route surface covered, the boot-phase divergence rationale, and a
concurrent-cell run recipe.
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
There was a problem hiding this comment.
Pull request overview
Promotes parse-server-mongo/ from a minimal boot-phase reproducer into a keploy compat-lane sample by adding a subcommand-driven traffic/coverage driver, making compose configuration override-friendly for CI matrix concurrency, and providing a Keploy noise-filter template + updated docs.
Changes:
- Reworked
flow.shintobootstrap | record-traffic | coverage | list-routes, broadened the fired API surface, and added a coverage report mode. - Parameterized
docker-compose.ymlusing${VAR:-default}for project/network/container naming, IPs, and ports to support concurrent runs on a shared daemon. - Added
keploy.yml.templatefor Parse Server noise filtering and expandedREADME.mdto document usage and overrides.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| parse-server-mongo/flow.sh | Introduces subcommands, broader traffic generation, fired-route logging, and coverage reporting. |
| parse-server-mongo/docker-compose.yml | Makes compose names/network/IPs/ports/env configurable via environment variable defaults. |
| parse-server-mongo/keploy.yml.template | Adds a noise filter template for volatile Parse Server fields. |
| parse-server-mongo/README.md | Updates documentation for new flow/compose knobs and lane usage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+120
to
+125
| case "${signup_status}" in | ||
| 2*) echo "[flow] signup ok (HTTP ${signup_status})" ;; | ||
| 4*) | ||
| # 4xx during bootstrap is treated as already-exists; re-run case. | ||
| echo "[flow] signup returned HTTP ${signup_status} — treating as already-exists" | ||
| ;; |
Comment on lines
+137
to
+142
| token="$(printf '%s' "${login_resp}" | jq -r '.sessionToken // empty' 2>/dev/null || true)" | ||
| if [ -z "${token}" ]; then | ||
| echo "[flow] no sessionToken in login response — bootstrap will continue but session-bound calls will be skipped" | ||
| : > "${PARSE_TOKEN_FILE}" | ||
| else | ||
| printf '%s' "${token}" > "${PARSE_TOKEN_FILE}" |
Comment on lines
+78
to
+81
| # urlenc — minimal URL-encoder for query payloads. | ||
| urlenc() { | ||
| jq -rn --arg v "$1" '$v|@uri' | ||
| } |
| PARSE_SERVER_MASTER_KEY: ${PARSE_MASTER_KEY:-keploy-parse-master} | ||
| PARSE_SERVER_MASTER_KEY_IPS: ${PARSE_MASTER_KEY_IPS:-0.0.0.0/0,::0} | ||
| PARSE_SERVER_SERVER_URL: ${PARSE_SERVER_URL:-http://localhost:6100/parse} | ||
| PARSE_SERVER_DATABASE_URI: ${PARSE_DATABASE_URI:-mongodb://172.30.0.10:27017/parse} |
| # parse-server-mongo | ||
|
|
||
| Minimal Parse Server + MongoDB sample. Exists primarily as a falsifying e2e reproducer for the mongo/v2 boot-phase candidate-selection bug — a class of bug where an application issues the same query repeatedly during recording while DB state mutates, and the matcher's score-tied tiebreaker at replay picks the wrong same-shape mock. | ||
| Parse Server (`parseplatform/parse-server` 9.x via `parse-server` npm 8.2.x) backed by MongoDB 7. Packaged as a complete keploy compat-lane sample: subcommand-driven traffic, env-driven docker-compose so concurrent matrix cells share a daemon, a noise-filter template that masks the parse-server identifiers that change every run, and a curated route list for coverage reporting. |
Comment on lines
+69
to
+75
| # fire METHOD URL [curl args...] — log then send a tolerant curl. | ||
| fire() { | ||
| local method="$1" | ||
| local url="$2" | ||
| shift 2 | ||
| log_fired "${method}" "${url}" | ||
| curl -sS -X "${method}" "${url}" "$@" >/dev/null 2>&1 || true |
Comment on lines
+360
to
+361
| method="$(awk '/^ method:/{print $2; exit}' "${f}")" | ||
| route="$(awk '/^ url:/{print $2; exit}' "${f}")" |
Introduce a GitHub Actions workflow scoped to the parse-server-mongo
sample that runs the same end-to-end record/coverage shape as the
doccano-django and umami-postgres lanes. The workflow is path-filtered
to `parse-server-mongo/**` (plus the workflow file and its helper
script) so it does NOT trigger on changes to other samples in this
repo or on changes elsewhere.
Three jobs:
* build-coverage — runs the sample end-to-end against the PR's
HEAD ref; emits a coverage percentage.
* release-coverage — same, against the PR's base ref; first-PR
bootstrap escape hatch returns 0% if the
sample doesn't exist on the base ref yet.
* coverage-gate — fails the PR if HEAD coverage drops more
than COVERAGE_THRESHOLD percentage points
below base. Default 1.0pp; override via the
repo variable PARSE_COVERAGE_THRESHOLD.
A sticky PR comment surfaces the base-vs-PR coverage diff with a
prose explanation of which parse-server REST + GraphQL routes the
sample's flow.sh::parse_record_traffic exercises.
Helper script .github/workflows/scripts/run-and-measure-parse-server.sh
is per-sample (sibling samples will land their own
run-and-measure-<sample>.sh on parallel branches). It does docker
compose up -d --build, polls /parse/health, runs flow.sh bootstrap →
record-traffic → coverage with PARSE_FIRED_ROUTES_FILE as the
standalone numerator, parses the report, and emits coverage=PCT to
GITHUB_OUTPUT.
This gate runs ONLY on PRs touching parse-server-mongo/. The
enterprise PR pipeline (.woodpecker/parse-server-linux.yml) calls
flow.sh coverage informationally and does NOT gate; the gate lives
here on the sample repo, isolated from the enterprise lane.
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
…se ref parse-server-mongo/ already exists on main (PRs #94/#95), so the prior detect step returned true on every PR's release-coverage job and the measure step then tried to invoke a helper script that didn't exist on the base ref. Extending detect to require the helper script too lets the first-PR escape hatch fire when the workflow itself is the change being introduced. Signed-off-by: Akash Kumar <meakash7902@gmail.com>
parse-server-mongo sample coverage
Threshold: PR may not drop coverage by more than 1.0pp. Override per-repo via the |
Replaces the prior API-route-surface "coverage" (counting fired
routes / curated route table) with actual V8 line coverage of the
parse-server library code under node_modules/parse-server/lib.
Architecture:
- `Dockerfile.coverage` extends the base image with a graceful-
shutdown shim (coverage-entrypoint.js installs SIGTERM/SIGINT
handlers calling process.exit(0)) so V8 actually flushes its
coverage data on `compose stop`. Without that shim, express's
app.listen pins the loop and the kernel signal-kills node
(exit 143) before NODE_V8_COVERAGE writes anything.
- `docker-compose.coverage.yml` is an OVERLAY: applied via
`-f docker-compose.yml -f docker-compose.coverage.yml`. It
sets NODE_V8_COVERAGE=/coverage and bind-mounts the host
./coverage dir. The base `Dockerfile` and `docker-compose.yml`
are untouched, so keploy/integrations and keploy/enterprise
CI lanes consume the base compose and pay zero coverage cost.
- `coverage-report.js` reads V8's per-process JSON dumps and
produces a `Covered N/M (XX.X%)` summary plus a c8-shaped
coverage-summary.json. We don't use `c8 report` because c8
filters node_modules even when --include is set, and
parse-server lives entirely under node_modules/parse-server.
The custom tool walks V8's nested ranges (block coverage)
and resolves per-line execution count to the deepest range.
- `flow.sh::parse_coverage` shells into the coverage image to
run coverage-report.js against the dumped V8 data; when called
against the base image (no overlay) it prints
"INFO: ... uninstrumented" and exits 0 so enterprise lanes'
`flow.sh coverage || true` informational calls keep working.
Removed:
- `parse_list_routes` (curated route table denominator).
- `parse_collect_recorded_routes` (keploy-tests / fired-routes
reader).
- The legacy route-surface `parse_coverage` body.
- `list-routes` subcommand.
Validated locally: helper produced `coverage=38.7` to GITHUB_OUTPUT
against a fresh stack (signup + record-traffic + clean stop).
38.7% reflects coverage of node_modules/parse-server/lib —
mongo paths ~46%, REST ~52%, Auth ~40%, schema ~58%; postgres
adapter ~7% (mongo storage selected) and LiveQuery ~3% (not
exercised), which is the expected distribution.
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
officialasishkumar
approved these changes
May 1, 2026
Signed-off-by: Akash Kumar <meakash7902@gmail.com>
…/FIRED_ROUTES refs Signed-off-by: Akash Kumar <meakash7902@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the
parse-server-mongo/sample (originally introduced as a focused boot-phase mongo tiebreaker reproducer in #94 / #95) up to the keploy compat-lane shape used bysamples-python/doccano-djangoandsamples-java/restheart-mongo:flow.shrefactored into thebootstrap | record-traffic | coveragesubcommand contract.docker-compose.ymlnow uses${VAR:-default}substitutions throughout so concurrent matrix cells can share a docker daemon.keploy.yml.templateships parse-server's noise filter (objectId,sessionToken,createdAt,updatedAt,Dateheader).parse_record_traffic(51 distinct fires across users, sessions, classes, roles, files, cloud-functions, schemas, hooks, GraphQL, aggregate).node_modules/parse-server/libviaNODE_V8_COVERAGE+ a custom report tool — see "Coverage architecture" below.The boot-phase divergence behaviour for the mongo/v2 tiebreaker test is preserved (
bootstrapstill sleeps 3s after/healthso pre-mutationfind _SCHEMAsnapshots land first;record-trafficstill issues the three-class_SCHEMAmutation pattern).Layout
Coverage architecture
Real JS line coverage via Node-native
NODE_V8_COVERAGE+ a customcoverage-report.js, validated locally end-to-end at 38.7% (9605/24851 lines) on the existing record-traffic surface. Distribution sanity-checks: PostgresStorageAdapter 7.7% (mongo selected, postgres unused), MongoStorageAdapter 46%, RestQuery 52.8%, RestWrite 45.4%, Auth 40.5%, LiveQuery 3% (not exercised) — the numbers reflect what traffic actually executes.Critical: the base
Dockerfileanddocker-compose.ymlare untouched. Coverage instrumentation lives in a separate overlay applied only by the standalone GH Actions coverage workflow. The keploy/enterprise compat lane consumes the base compose unchanged.How it works:
Dockerfile.coverageinstalls c8 and drops acoverage-entrypoint.jsshim that registersprocess.on('SIGTERM', () => process.exit(0)). Without that, express'sapp.listenpins the event loop andcompose stopwould signal-kill node (exit 143) before V8'sNODE_V8_COVERAGEwriter ran.NODE_V8_COVERAGE=/coverage. Each Node process writes acoverage-<pid>-<ts>.jsondump on clean exit.coverage-report.jsreads V8's nested block-coverage ranges, resolves per-line execution count against the deepest enclosing range, and emits aCovered N/M (XX.X%)summary plus a c8-shaped json-summary. We don't usec8 reportbecause c8 filtersnode_modules/**even with--includeoverrides, and parse-server lives entirely undernode_modules/parse-server.flow.sh coverageagainst the base compose (no overlay) is a graceful no-op.Coverage gate
.github/workflows/parse-server-mongo.ymltriggers ONLY on changes underparse-server-mongo/**. Build (PR HEAD) + release (base ref) coverage compared; PR fails if drop exceeds 1.0pp. Threshold overridable viavars.PARSE_COVERAGE_THRESHOLD. The first-PR escape hatch detects a missing helper script on the base ref and treats baseline as 0%.Run modes
docker compose up -d && bash flow.sh bootstrap 240 && bash flow.sh record-traffic— exactly what the keploy enterprise lane wraps.compose stop -t 30 parse-server+flow.sh coverage.PARSE_PROJECT,PARSE_HOST_PORT,PARSE_NETWORK_SUBNET, …) all${VAR:-default}-substituted so multiple cells can run in parallel.See README for full commands.
Consumers
keploy/enterprise.woodpecker/parse-server-linux.yml— three-cell record/replay matrix that delegates compose + bootstrap + traffic to this sample.Test plan
docker compose up -dboots mongo + parse-server cleanly with no env varsflow.sh bootstrap 240signs up the fixed user, persists session tokenflow.sh record-trafficexercises 51 fires across the surface aboveflow.sh coverageagainst base compose exits 0 cleanly with INFO message