Modernize Smocker to a 2026 stack (mock format & API preserved)#320
Merged
Conversation
Backend/toolchain modernization with the mock format and HTTP/CLI API kept byte-identical (guarded by new golden serialization tests + the venom suite). - go 1.15 -> 1.26; io/ioutil -> io; rand.Seed -> math/rand/v2 - drop facebookgo/grace -> stdlib graceful shutdown (signal.NotifyContext + http.Server.Shutdown + errgroup), TLS preserved (SIGHUP restart dropped) - drop namsral/flag -> stdlib flag (flag names + SMOCKER_* env preserved) - drop logrus -> log/slog - drop teris-io/shortid -> zero-dep crypto/rand base62 id (server/types/id.go) - bump echo v4.15, sprig v3.3, objx v0.5, smarty/assertions v1.16, gopher-lua, gopher-luar, yaml.v3 v3.0.1 (goccy evaluated, rejected: alters output) - golangci-lint config v1 -> v2 (Makefile pin 2.12.2), lint clean - Dockerfile GO_VERSION 1.26 - add golden serialization tests locking the exact YAML/JSON mock format Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tack Full frontend overhaul with the HTTP API the client consumes kept identical. Build/tooling: - Parcel -> Vite 8 (Go index.html template + ./assets/ layout preserved) - yarn -> npm; TypeScript -> 7; ESLint -> oxlint (typescript-eslint is incompatible with the native TS compiler); Jest -> Vitest; Node 24 - pin exact dependency versions Libraries: - redux + redux-observable + rxjs + io-ts/fp-ts -> TanStack Query + zod - React 16 -> 19 (createRoot), react-router 5 -> 7, antd 4 -> 6, CodeMirror 5 -> 6, mermaid 8 -> 11, lodash -> es-toolkit - drop axios and react-hot-loader Verified: tsc --noEmit, vite build, vitest, oxlint all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion Move the serialization golden fixtures out of server/types/testdata/golden into tests/serialization (alongside the other test fixtures under tests/), and rename server/types/serialization_golden_test.go to serialization_test.go. The test stays in package types so it keeps running under `go test ./server/...` (make test). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
21 framework-agnostic specs (tests/e2e/smocker.spec.ts) locking the observable behaviour of the web UI: shell, routing, links, all pages, navigation, the mock editor (open/cancel, prefill, create via form and raw YAML), lock/unlock, autorefresh, session new/select/reset/rename, and file import. Assertions target stable text / hrefs / URLs / SVG (never framework DOM), so the same suite passes against the pre-migration and post-migration UIs. Output goes under build/e2e. Requires @playwright/test (in devDependencies) and a running server pointed at via SMOCKER_E2E_URL. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…/vitest - Makefile: coverage -> build/coverage, integration sessions -> build/sessions, integration test binary -> build/smocker.test, clean removes build/ only, and the release tarball packages only `smocker` + `client` (not test/runtime output). - Playwright output dir -> build/e2e (see playwright.config.ts). - sonar coverage report path -> build/coverage/cover.out. - CI: yarn -> npm (cache + `npm ci`), lint via `npm run lint` (oxlint), unit tests via `npm test` (vitest); ::set-output -> $GITHUB_OUTPUT. - .gitignore: everything generated now lives under build/, so ignore just build/ and node_modules/ (plus editor/OS files); drop the stale root-level entries. The repository root now stays clean: builds, coverage, e2e reports and runtime sessions all land under build/. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… use Two robustness fixes for the recurring persistence reports (#284, #292, #318): - Make LoadSessions best-effort per session. Previously a single missing or unreadable per-session file (e.g. a partial session directory after a mid-write restart or a K8s volume race) made the whole load fail and dropped EVERY persisted session. Now each session's history and mocks load independently: a missing/corrupt file is logged and skipped, other sessions and the session name/metadata still load. - Bound persistence concurrency with errgroup SetLimit(16) on both the load and the store paths, so a large number of sessions can no longer exhaust the process's file descriptors ("too many open files"). Tests (server/services/persistence_test.go, pass under -race): - TestLoadSessionsResilientToMissingFiles: a partial session dir no longer wipes the others. - TestStoreAndLoadManySessions: round-trips more sessions than the limit without deadlocking or losing data. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a `make test-e2e` target that builds the client and backend, serves the built client through smocker (seeded with tests/sessions), runs the Playwright suite against it, then stops the server. Wire it into CI as a dedicated `e2e` job (installs the Chromium browser via `npx playwright install --with-deps`) and make `deploy` depend on it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/mock.schema.json (draft 2020-12), derived from server/types. It is validated on the Go side by server/types/schema_test.go (santhosh-tekuri): every fixture under tests/data must match it, and clearly-invalid mocks are rejected. README documents it and the yaml-language-server $schema usage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
go get for installing binaries was removed in Go 1.17, so 'make start-caddy' could not install Caddy on Go 1.26. Use 'go install …/caddy@$(CADDYVERSION)' (v2.8.4), consistent with the venom/golangci-lint pinned installs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restore the antd 4 look lost in the antd 6 migration: base font/family, code line numbers in read-only previews, sidebar/navbar/page-header spacing, and the History filter rendered as an inline link. Theme the mermaid sequence diagram with the app palette and make the Visualize customize form a compact inline row. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rework mock creation and make the visual editor cover the whole mock format: - Extract the creation drawer to NewMock and mount it on both Mocks and History; History's 'Create a new mock from entry' now opens it in place (no navigation). - Toggle between the visual form and raw YAML: the YAML is the source of truth, and switching to the form is gated on it being a single mock valid against the schema (ajv). Validate before saving and keep the drawer open on error so the mock is never lost. Drop the now-redundant read-only preview. - Complete the form vs the schema: response/proxy delay (fixed or random), all 17 matchers, every HTTP method plus method-as-matcher, path and body matchers for all methods, multi-value query/header keys, numeric/bool values coerced to strings. Reverse conversion (mock -> form) with round-trip tests. - Keep pagination in the URL (?page/?page-size) so a page is shareable, with directional page scroll; the mock link preserves ?session and back returns to the list. - Only sync the ?session param on /pages/* routes so it no longer clobbers the '*' -> /pages/history redirect (which left the root on a blank page). Tests: vitest 64 (conversion, rendered component, YAML validation, utils) and the Playwright TNR grows to 22. New deps (pinned, audit-clean): ajv (runtime), and @testing-library/react + user-event (dev). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reducing crypto/rand bytes with % over a 62-char alphabet favored the first 8 characters (256 % 62 = 8). Reject bytes >= 248 (the largest multiple of 62 that fits in a byte) so every character is equally likely. IDs stay opaque and the persisted format is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Run the repo's prettier config over the client so the committed frontend matches 'npm run format' (no behavior change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The lint job installed golangci-lint via the install.sh from the master branch,
whose embedded checksums drifted from the v2.12.2 release tarball, so the download
failed checksum verification ("did not verify"). Fetch install.sh from the
matching v$(GOLANGCILINTVERSION) tag instead, so its checksums always match the
release being installed. golangci-lint run itself is clean (0 issues).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
gwleclerc
force-pushed
the
chore/modernize-2026
branch
from
July 18, 2026 03:43
93a695f to
5274d5e
Compare
This was referenced Jul 18, 2026
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.
Refreshes the whole toolchain and dependencies to a current, maintained stack while keeping two hard invariants: the mock format (YAML/JSON serialization, struct tags, matcher names, on-disk mocks.yml/history.yml/sessions.yml layout) and the HTTP/CLI API (routes, payloads, status codes, flag names, SMOCKER_* env vars) are unchanged. Guarded by byte-exact golden serialization tests, the venom API suite, and a Playwright UI non-regression suite.
✨ Features
🔧 Backend (Go)
🎨 Frontend
📦 Build / CI / Tests
Mock edit & delete (issues #299, #266, #303) lives in a separate branch (
feat/mock-edit-delete) stacked on top of this one.