feat: TypeScript test harness + Eval functions + behavioral fixtures#3
feat: TypeScript test harness + Eval functions + behavioral fixtures#3JacobPEvans-personal wants to merge 2 commits into
Conversation
Pilot pivot mirroring dryvist/cc-edge-pack-template#3 (TS port). All Cribl pack content (default/, data/) carries over from VisiCore unchanged; the test/build tooling switches to TypeScript + Vitest + Biome + nix-devenv. Pack changes (the user-visible behavior): - default/pipelines/claude-code-otel/conf.yml — added Eval function setting sourcetype='claude:code:otel', index='claude-code', datatype='claude-code-otel' - default/pipelines/claude-code-session-logs/conf.yml — added Eval function setting sourcetype='claude:code:session_logs', index='claude-code', datatype='claude-code-session-logs' Test harness (synced from cc-edge-pack-template@feature/ts-pivot): - tests/cribl-client.ts — TS client (CriblClient, runRouteFlow, assertRequiredFields, capture primitives) - tests/parse-filter.ts, global-setup.ts, test-helpers.ts, routes.test.ts, pipelines.test.ts, vitest.config.ts, tsconfig.json - tests/package.json + pnpm-lock.yaml (vitest 2.1, typescript 5.6, biome 2, tar 7, yaml 2, tsx 4) - tests/generate-fixtures.ts — committed helper for regenerating expected fixtures via live Cribl (run via `pnpm exec tsx generate-fixtures.ts ...`) Fixtures (the actual proof the pack works): - tests/fixtures/claude-code-otel/sample.json — sourced from data/samples/sanitized_event_api_request.json (5 OTLP events) - tests/fixtures/claude-code-otel/sample.expected.json — generated by running through live Cribl, trimmed to {sourcetype, index, datatype, _raw, _time} - tests/fixtures/claude-code-session-logs/sample.json — sourced from data/samples/sanitized_assistant.log (1 assistant turn) - tests/fixtures/claude-code-session-logs/sample.expected.json — same flow Tooling (mirrors template): - biome.jsonc, flake.nix, .envrc, .gitignore, Makefile (npm/pnpm scripts) - .release-please-manifest.json + release-please-config.json (initial 0.0.0) Workflows: - .github/workflows/test.yml — caller for cc-edge-pack-template's reusable workflow, pinned to @feature/ts-pivot until that PR merges - .github/workflows/release.yml — caller for the template release workflow (pinned to @main since release isn't exercised in this PR) - .github/workflows/release-please.yml — caller for JacobPEvans inherited workflow Docs: - CLAUDE.md — rewritten for pilot scope (was a stale copy of the template's CLAUDE.md from Python era) - README.md — added Installation + Usage anchors at top to satisfy readme validator; documented Eval pipeline tagging (sourcetype/index/datatype); removed the misleading 1.0.0 release notes line (no release exists yet, and per user direction the agent does NOT tag versions — release-please proposes them via PR for human approval) Verification (locally, with `nix develop github:JacobPEvans/nix-devenv?dir=shells/typescript`): - pnpm run typecheck: tsc --noEmit returns 0 - biome check: 14 files, 0 errors - pnpm run test (vitest run): 11/11 passed - 7 structural route tests - 2 dynamic route flow tests (one per route — both produce non-empty output) - 2 fixture-driven pipeline tests (partial-match + required-fields assertion) Sequencing note: the test caller workflow is temporarily pinned to `cc-edge-pack-template@feature/ts-pivot` so this PR's CI can run before the template PR merges. Flip to `@main` immediately after dryvist/cc-edge-pack-template#3 lands. (claude)
There was a problem hiding this comment.
Pull request overview
Ports the pack repo’s build/test tooling to a TypeScript + Vitest + Biome + nix-devenv harness, and updates the pack pipelines/routes to set Splunk-canonical fields (sourcetype, index, datatype) with fixture-backed behavioral verification.
Changes:
- Replaces the Python-based test harness with a TypeScript/Vitest harness (client, global setup, route/pipeline suites, fixture generator).
- Adds two pipelines + routes/inputs that tag events via Eval and route by
datatype. - Introduces repo tooling for formatting/linting (Biome), dev shell (Nix flake/direnv), and release automation (release-please), plus updated docs.
Reviewed changes
Copilot reviewed 57 out of 59 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/vitest.config.ts | Adds Vitest configuration (single-worker + global setup). |
| tests/tsconfig.json | Adds strict TypeScript compiler settings for test harness. |
| tests/test_routes.py | Removes legacy Python route tests. |
| tests/test_pipelines.py | Removes legacy Python pipeline fixture tests. |
| tests/test-helpers.ts | Adds per-test-file Cribl client helper + pack id accessor. |
| tests/routes.test.ts | Adds TS route structure tests + dynamic route-flow tests. |
| tests/requirements.txt | Removes Python test dependency list. |
| tests/pipelines.test.ts | Adds TS fixture-driven pipeline tests (optional required-fields skip). |
| tests/parse-filter.ts | Adds simple filter parser for dynamic route-flow testing. |
| tests/package.json | Adds Node/TS dev dependencies and scripts for tests. |
| tests/global-setup.ts | Adds Vitest global setup/teardown to install pack into Cribl once per run. |
| tests/generate-fixtures.ts | Adds committed helper to generate .expected.json fixtures via live Cribl. |
| tests/fixtures/claude-code-session-logs/sample.json | Adds session-logs input fixture. |
| tests/fixtures/claude-code-session-logs/sample.expected.json | Adds expected output fixture asserting canonical field tagging. |
| tests/fixtures/claude-code-otel/sample.json | Adds OTEL input fixture (5 events). |
| tests/fixtures/claude-code-otel/sample.expected.json | Adds expected output fixture asserting canonical field tagging. |
| tests/cribl_client.py | Removes legacy Python Cribl API client. |
| tests/cribl-client.ts | Adds TypeScript Cribl management API client + tarball builder + assertions. |
| tests/conftest.py | Removes pytest fixtures used by the legacy harness. |
| tests/README.md | Removes legacy Python test harness documentation. |
| release-please-config.json | Adds release-please configuration. |
| .release-please-manifest.json | Adds release-please manifest with initial version state. |
| package.json | Updates pack metadata (name/tags/etc.) and version. |
| flake.nix | Adds Nix flake delegating to shared TypeScript dev shell. |
| .envrc | Enables direnv flake usage. |
| default/samples.yml | Populates Cribl UI sample catalog entries for included sample files. |
| default/pipelines/route.yml | Replaces placeholder routes with datatype-based routing to the two pipelines. |
| default/pipelines/claude-code-session-logs/conf.yml | Adds Eval tagging for session logs pipeline. |
| default/pipelines/claude-code-otel/conf.yml | Adds Eval tagging for OTEL pipeline. |
| default/pack.yml | Adds embedded base64 logo. |
| default/inputs.yml | Adds file monitor + OTLP source definitions with datatype metadata. |
| data/samples/viOToM.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/smpLil.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/nuJv6j.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/mSfzuP.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/lCrlnQ.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/kkcx4D.json | Adds session-log sample payload for Cribl UI samples. |
| data/samples/k0h8NP.json | Adds session-log sample payload for Cribl UI samples. |
| data/samples/hO8QQb.json | Adds session-log sample payload for Cribl UI samples. |
| data/samples/go9A8j.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/bw3bbR.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/bCOM2K.json | Adds session-log sample payload for Cribl UI samples. |
| data/samples/aukWzL.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/QtXzUr.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/QS0mDG.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/OsXDpa.json | Adds session-log sample payload for Cribl UI samples. |
| data/samples/Io4OFW.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/DBvKLd.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/CBxGTZ.json | Adds OTEL sample payload for Cribl UI samples. |
| data/samples/36cP1M.json | Adds session-log sample payload for Cribl UI samples. |
| biome.jsonc | Adds Biome formatter/linter configuration. |
| README.md | Rewrites docs for this specific pack (install/usage/setup/reference). |
| Makefile | Updates developer commands to use pnpm/Vitest/Biome + keeps pack build/validate targets. |
| CLAUDE.md | Updates AI assistant guidance for this specific pack and new TS harness. |
| .gitignore | Switches ignores from Python venv/pytest to Node/direnv artifacts. |
| .github/workflows/test.yml | Updates CI to call TS-pivot reusable workflow (pinned to feature branch). |
| .github/workflows/release.yml | Updates CI to call release workflow from template repo. |
| .github/workflows/release-please.yml | Adds release-please workflow caller. |
Files not reviewed (1)
- tests/pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - **Auth:** None | ||
| - **OTLP Version:** 1.3.1 | ||
| - **Max active connections:** 1000 | ||
| - **Metadata:** `datatype == ''claude-code-otel'` |
There was a problem hiding this comment.
The OTLP input metadata line has mismatched quoting: datatype == ''claude-code-otel'. This looks like a typo and may confuse readers; it should be a single-quoted value like datatype == 'claude-code-otel' (or match the exact route filter syntax used elsewhere).
| - **Metadata:** `datatype == ''claude-code-otel'` | |
| - **Metadata:** `datatype == 'claude-code-otel'` |
|
|
||
| ## License | ||
| --- | ||
| This Pack uses the following license: [`Apache 2.0`](https://github.com/criblio/appscope/blob/master/LICENSE) No newline at end of file |
There was a problem hiding this comment.
The License section links to an unrelated repository (criblio/appscope). Since this pack includes its own LICENSE file, the README should link to that (or to the correct canonical license reference for this repository) to avoid misrepresenting the licensing terms.
| This Pack uses the following license: [`Apache 2.0`](https://github.com/criblio/appscope/blob/master/LICENSE) | |
| This Pack uses the following license: [`Apache 2.0`](LICENSE) |
| const response = await fetch(url, init); | ||
| const text = await response.text(); | ||
|
|
||
| // Try JSON first; fall back to NDJSON; fall back to raw text. | ||
| if (text.length === 0) return null; | ||
| try { |
There was a problem hiding this comment.
CriblClient.call() doesn’t check response.ok before attempting to parse the response body. For non-2xx responses, callers will treat error payloads (or HTML/text) as successful results, which can hide failures and make tests flaky/hard to debug. Please fail fast when !response.ok (include status + response text), similar to login().
| const REQUIRED_FIELDS: Record<PackType, readonly string[]> = { | ||
| edge: ['sourcetype', 'index'], | ||
| stream: ['host', 'source', '_time'], | ||
| }; |
There was a problem hiding this comment.
assertRequiredFields() documents that Edge packs should have Splunk-canonical routing fields, but REQUIRED_FIELDS.edge only checks sourcetype and index. This PR’s pipelines also set datatype and routes depend on it, so fixture cases without an .expected.json won’t assert datatype is present. Consider adding datatype to the Edge required-fields list to make the smoke-test path enforce the intended contract.
| const absInput = resolve(inputPath); | ||
| const filename = absInput.split('/').pop(); | ||
| if (filename === undefined) { | ||
| throw new Error(`Could not derive filename from path '${absInput}'`); | ||
| } | ||
| const expectedPath = join(dirname(absInput), `${filename.replace(/\.json$/, '')}.expected.json`); |
There was a problem hiding this comment.
generate-fixtures.ts derives filename by splitting on '/', which breaks on Windows paths (and is generally less robust). Use path.basename(absInput) instead so fixture generation works cross-platform.
| const events = JSON.parse(await readFile(absInput, 'utf-8')) as CriblEvent[]; | ||
| console.log(`Loaded ${events.length} input event(s) from ${absInput}`); |
There was a problem hiding this comment.
generate-fixtures.ts assumes the input fixture JSON parses to CriblEvent[]. Elsewhere (e.g. pipelines.test.ts) fixtures can be a single object or an array; this script will log events.length and pass a non-array to saveSample() if given a single-object fixture. Consider normalizing to an array (and validating the parsed type) before continuing.
| ".": { | ||
| "package-name": "cc-edge-pack-template", | ||
| "changelog-path": "CHANGELOG.md", | ||
| "extra-files": ["package.json"] | ||
| } |
There was a problem hiding this comment.
release-please-config.json still uses package-name: "cc-edge-pack-template", which doesn’t match this pack’s actual package.json name (cc-edge-claude-code-io). This will produce incorrect release metadata (and can confuse downstream automation). Update the configured package name to match the pack.
| "name": "cc-edge-claude-code-io", | ||
| "version": "1.0.0", | ||
| "minLogStreamVersion": "4.17.0", |
There was a problem hiding this comment.
package.json sets version to 1.0.0, but this PR also introduces a release-please manifest at 0.0.0 and the PR description states this is an initial pre-release with no releases cut yet. This mismatch will cause release-please/changelog state to be inconsistent. Align package.json version with .release-please-manifest.json (or update the manifest/config if 1.0.0 is intended).
…amed input dryvist exposes only the generic GH_APP_ID + GH_APP_PRIVATE_KEY org secrets; the wrap pattern aliases them to whatever the inherited workflow expects at the boundary. Anyone reading the dryvist repos sees only the generic name. (claude)
|
Recreating on |
Summary
Pilot TS pivot mirroring dryvist/cc-edge-pack-template#3 (TS port). All Cribl pack content (`default/`, `data/`) carries over from VisiCore unchanged; the test/build tooling switches to TypeScript + Vitest + Biome + nix-devenv.
What changed
Pack behavior (the user-visible part)
(Index value follows the vendor/software convention you specified.)
Test harness (synced from cc-edge-pack-template@feature/ts-pivot)
Fixtures (the actual proof)
Tooling
Workflows
Docs
Verification
Locally via `nix develop github:JacobPEvans/nix-devenv?dir=shells/typescript`:
Sequencing
After CI green:
No version tag in this PR. Release timing is yours to decide.