Skip to content
Draft
Show file tree
Hide file tree
Changes from 99 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
c8faa06
feat(engine): introduce gcx-driven execution package
zeitlinger Jun 12, 2026
fc5e7db
feat(assert): introduce assertion vocabulary
zeitlinger Jun 12, 2026
6176d54
feat(seed): introduce inline-OTLP seed mode
zeitlinger Jun 12, 2026
a7db5db
feat(v2case): case yaml schema, loader, and validator
zeitlinger Jun 12, 2026
d4e5779
feat(report): event-driven Reporter with compact text and NDJSON
zeitlinger Jun 12, 2026
15eadf0
chore: gofmt alignment on report and v2case structs
zeitlinger Jun 12, 2026
1ef29c1
feat(wait): generic polling primitive (replaces gomega.Eventually)
zeitlinger Jun 12, 2026
4df2734
feat(discovery): oats.toml root config and run planner
zeitlinger Jun 12, 2026
cac8145
feat(signalcmd): translate v2case assertions into gcx args
zeitlinger Jun 12, 2026
e55590a
chore: gofmt discovery struct alignment
zeitlinger Jun 12, 2026
760e464
feat(runner): orchestrate seed + poll-and-assert per case
zeitlinger Jun 12, 2026
b5244d0
feat(cmd/v2): oats-v2 binary entry point
zeitlinger Jun 12, 2026
f3a630a
test(cmd/v2): end-to-end integration with a fake gcx + OTLP stub
zeitlinger Jun 12, 2026
4f3dafb
feat(cache): skip-when-unchanged store
zeitlinger Jun 12, 2026
3918c6d
feat(runner): wire skip-when-unchanged cache into RunCase
zeitlinger Jun 12, 2026
b746e8d
feat(cmd/v2): wire cache into the CLI
zeitlinger Jun 12, 2026
7809e6d
docs: add V2.md describing the new architecture and CLI
zeitlinger Jun 12, 2026
2124436
chore: rumdl: add 'text' info string to architecture diagram fence
zeitlinger Jun 12, 2026
e379b6b
chore(renovate): track BurntSushi/toml in deps snapshot
zeitlinger Jun 12, 2026
92dc019
feat(v2): add collector-style match assertions
zeitlinger Jun 16, 2026
25736b3
test(v2): exercise match assertions end to end
zeitlinger Jun 16, 2026
3924924
feat(v2): parse OTLP traces and flamebearer matches
zeitlinger Jun 16, 2026
9d4798b
feat(v2): add best-effort legacy migration
zeitlinger Jun 16, 2026
1993391
feat(v2): support input-driven cases
zeitlinger Jun 16, 2026
d6abef0
feat(v2): add minimal compose fixture support
zeitlinger Jun 16, 2026
9412196
feat(v2): support multi-file compose fixtures
zeitlinger Jun 16, 2026
f6e6c1b
docs(v2): add sample config and routing note
zeitlinger Jun 16, 2026
626aa2d
feat(v2): add minimal k3d fixture support
zeitlinger Jun 16, 2026
63e6159
feat(v2): relax app seed and improve migrate hints
zeitlinger Jun 16, 2026
a0813cd
test(v2): cover k3d helper command planning
zeitlinger Jun 16, 2026
550c9c6
test(v2): cover fixture startup lifecycle
zeitlinger Jun 16, 2026
939dfd7
test(v2): cover app-backed remote case flow
zeitlinger Jun 16, 2026
b56eb91
feat(v2): improve matrix migration guidance
zeitlinger Jun 16, 2026
c895e6b
feat(v2): add custom check support
zeitlinger Jun 16, 2026
25bb20c
docs(v2): expand smoke examples
zeitlinger Jun 16, 2026
81c6295
test(v2): cover richer migration samples
zeitlinger Jun 16, 2026
7110994
test(v2): run migrated legacy case end to end
zeitlinger Jun 16, 2026
d075e25
test(v2): run migrated custom check end to end
zeitlinger Jun 16, 2026
df7b7c0
test(v2): run flattened matrix migration end to end
zeitlinger Jun 16, 2026
a4cdfc9
fix(v2): resolve custom check paths explicitly
zeitlinger Jun 16, 2026
1882623
docs(v2): add top-level quick pointer
zeitlinger Jun 16, 2026
b6f7592
docs(v2): add richer fixture examples
zeitlinger Jun 16, 2026
3fd20f2
test(v2): run migrated custom check path end to end
zeitlinger Jun 16, 2026
59809ba
feat(v2): emit fixture lifecycle events
zeitlinger Jun 16, 2026
bddfda3
fix(v2): emit teardown events on early close
zeitlinger Jun 16, 2026
c480d0a
test(v2): cover fixture start and ready helpers
zeitlinger Jun 16, 2026
49be0e4
docs(v2): add profile smoke example
zeitlinger Jun 16, 2026
0f846b7
test(v2): cover profile queries end to end
zeitlinger Jun 16, 2026
8d2eba9
test(v2): run migrated legacy profile end to end
zeitlinger Jun 16, 2026
97f7358
docs(v2): summarize implemented scope
zeitlinger Jun 16, 2026
ba9975a
Drop versioned naming from current CLI docs
zeitlinger Jun 16, 2026
54fbfe0
Use match_spans for trace structural assertions
zeitlinger Jun 17, 2026
307f863
fix(v2): handle empty gcx JSON output and script paths
zeitlinger Jun 17, 2026
c2c3ab7
Simplify consumer fixture wiring
zeitlinger Jun 19, 2026
28d7463
Polish docs after slimmer consumer wiring
zeitlinger Jun 19, 2026
f8a4e31
Fix CURRENT.md lint
zeitlinger Jun 19, 2026
9deed28
Support top-level cases lists in oats.toml
zeitlinger Jun 19, 2026
4a8e160
Own local gcx config for example assertions
zeitlinger Jun 19, 2026
424bad9
Ignore gcx table headers in empty result counts
zeitlinger Jun 19, 2026
6886479
Normalize k3d cluster names for suite tests
zeitlinger Jun 19, 2026
b5c0336
Fix gcx profile query argument mapping
zeitlinger Jun 19, 2026
dfaf749
feat: finish gcx rollout assertion cleanup
zeitlinger Jun 23, 2026
f78781a
test: normalize yaml fixtures after rebase
zeitlinger Jul 2, 2026
6eca67c
fix: make current docs and tests CI-safe
zeitlinger Jul 2, 2026
1e7ba71
refactor tests and remove legacy v2 naming
zeitlinger Jul 2, 2026
32cd857
Merge remote-tracking branch 'origin/main' into v2
zeitlinger Jul 2, 2026
fbb33d3
fix lint and k3d e2e failure case
zeitlinger Jul 2, 2026
6f510a4
fix ci test split and install k3d tools
zeitlinger Jul 2, 2026
59c18a1
track e2e tools in mise and renovate
zeitlinger Jul 2, 2026
f794531
split e2e matrix and address review comments
zeitlinger Jul 2, 2026
2066698
fix: finalize schema v3 and stabilize e2e
zeitlinger Jul 3, 2026
96201f1
test: clarify wait tight-deadline coverage
zeitlinger Jul 3, 2026
e5d0c50
test: make e2e fixture startup lazy and ready
zeitlinger Jul 3, 2026
6ba2d8c
test: use real lgtm for k3d smoke
zeitlinger Jul 3, 2026
d94ec5a
test: gate k3d smoke on grafana readiness
zeitlinger Jul 3, 2026
0c94f44
test: align k3d smoke readiness probe
zeitlinger Jul 3, 2026
828c58c
docs: fold current cli docs into readme
zeitlinger Jul 3, 2026
a8e3ea4
fix: list top-level cases in summary
zeitlinger Jul 3, 2026
af89fb9
feat: run safe suites in parallel
zeitlinger Jul 3, 2026
8700c68
ci: use catch-all non-k3d e2e shard
zeitlinger Jul 3, 2026
ec9694c
test: support excluding e2e case filters
zeitlinger Jul 3, 2026
37208eb
fix: address remaining review feedback
zeitlinger Jul 3, 2026
c3a02d1
ci: simplify e2e shard names
zeitlinger Jul 3, 2026
1db6c01
fix: polish remaining review nits
zeitlinger Jul 3, 2026
cbbc664
fix: use dynamic local ports for k3d fixtures
zeitlinger Jul 3, 2026
efacd28
docs: finish review follow-up cleanup
zeitlinger Jul 3, 2026
40d5a1b
fix: address final review comments
zeitlinger Jul 3, 2026
4883ded
ci: split core and fixture e2e shards
zeitlinger Jul 3, 2026
21f12b0
ci: use catch-all e2e shard filters
zeitlinger Jul 3, 2026
2427100
ci: split compose and remote e2e shards
zeitlinger Jul 7, 2026
9a4c742
Merge origin/main into v2 to resolve conflicts
zeitlinger Jul 7, 2026
171daed
ci: log e2e setup timings
zeitlinger Jul 7, 2026
19bd0e0
ci: run e2e tests in verbose mode
zeitlinger Jul 7, 2026
810ff3c
ci: reuse prebuilt e2e tools across shards
zeitlinger Jul 7, 2026
0311049
ci: use absolute path for prebuilt e2e tools
zeitlinger Jul 7, 2026
38a4df0
ci: restore e2e tool execute bits
zeitlinger Jul 7, 2026
c3021bd
fix: clean up local gcx config temp file and address review nits
zeitlinger Jul 7, 2026
d2265a6
feat: add --fail-fast, metrics/value e2e coverage, and v2 assertion docs
zeitlinger Jul 7, 2026
2f04f03
test(e2e): add profiles regression coverage; widen value timeout
zeitlinger Jul 7, 2026
6c1c56a
feat(cli): cobra subcommands, cache clear; drop inert hermetic field
zeitlinger Jul 7, 2026
fc36f5c
test(e2e): fail variants, ndjson, migrate, and cache-skip coverage
zeitlinger Jul 7, 2026
606fdd4
test(e2e): app-backed seed round-trip via telemetrygen
zeitlinger Jul 7, 2026
3a1c4cc
test(e2e): cover oats cache clear subcommand end-to-end
zeitlinger Jul 7, 2026
e40c00a
refactor(fixture): extract fixture lifecycle into its own package
zeitlinger Jul 7, 2026
427279d
fix: address Copilot review comments
zeitlinger Jul 7, 2026
217de8f
fix: bound waitForHTTP probes and close compose pipe on start failure
zeitlinger Jul 7, 2026
67e01cb
test(e2e): assert profile flamegraph on runtime. prefix, not runtime.…
zeitlinger Jul 7, 2026
ef0c0fb
fix: preserve original path in readTestCaseDefinition error
zeitlinger Jul 7, 2026
579f895
Merge branch 'main' into v2
zeitlinger Jul 8, 2026
c8afa64
remove deprecated files
zeitlinger Jul 8, 2026
008b321
remove deprecated files
zeitlinger Jul 8, 2026
d323aca
docs: restructure README, add case-reference and CI guides
zeitlinger Jul 8, 2026
8e0c072
feat(fixture): make app-seed compose suites parallel-safe
zeitlinger Jul 8, 2026
5f101fd
refactor(fixture): nested type-grouped fixture config
zeitlinger Jul 8, 2026
3e8571f
refactor(config): YAML config format, oats-config.yaml + oats-case.yaml
zeitlinger Jul 8, 2026
f2b95bc
feat(migrate): directory mode that generates a full v3 project
zeitlinger Jul 8, 2026
38d8ceb
refactor(schema): drop per-case oats-schema-version, single config ve…
zeitlinger Jul 8, 2026
e34023c
feat(cli): positional path scoping + config discovery from cwd
zeitlinger Jul 8, 2026
2231785
docs: clarify config file (what/where) and use default invocation
zeitlinger Jul 8, 2026
4c2ae26
docs: recommend per-dir oats-case.yaml layout; name config in --confi…
zeitlinger Jul 8, 2026
b31972b
docs: rewrite README getting-started, split CLI into docs/cli.md, ali…
zeitlinger Jul 8, 2026
77b26ba
docs(examples): comment the example configs and cases
zeitlinger Jul 8, 2026
8f12c7a
docs: explain suites vs cases (why the two layers exist)
zeitlinger Jul 8, 2026
fe5247b
feat(fixture): default the compose template to lgtm; add flagship pyt…
zeitlinger Jul 8, 2026
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
8 changes: 3 additions & 5 deletions .github/renovate-tracked-deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@
"mise"
]
},
".github/workflows/integration_test.yml": {
"regex": [
"mise"
]
},
".github/workflows/lint.yml": {
"regex": [
"mise"
Expand All @@ -33,6 +28,7 @@
},
"go.mod": {
"gomod": [
"github.com/BurntSushi/toml",
"github.com/cenkalti/backoff/v5",
"github.com/cespare/xxhash/v2",
"github.com/davecgh/go-spew",
Expand Down Expand Up @@ -83,6 +79,8 @@
"golangci-lint",
"goreleaser",
"hadolint",
"k3d",
"kubectl",
"lychee",
"node",
"npm:renovate",
Expand Down
69 changes: 64 additions & 5 deletions .github/workflows/e2e_test.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
---
name: End-to-end tests
name: E2E tests

on: [pull_request]

permissions: {}

jobs:
test:
build-e2e-tools:
runs-on: ubuntu-24.04
steps:
- name: Check out
Expand All @@ -17,5 +16,65 @@ jobs:
with:
version: v2026.7.0
sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68
- name: Run end-to-end test
run: mise run e2e-test
- name: Build e2e tools
run: ./scripts/build-local-tools.sh "$PWD/.e2e-tools/bin"
- name: Upload e2e tools
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.6.2
with:
name: e2e-tools
path: .e2e-tools/bin
if-no-files-found: error

test-e2e:
needs: build-e2e-tools
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
shard: [core, compose, remote, k3d-fail, k3d-smoke]
steps:
- name: Check out
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7
with:
persist-credentials: false
- uses: jdx/mise-action@e6a8b3978addb5a52f2b4cd9d91eafa7f0ab959d # v4.2.0
with:
version: v2026.7.0
sha256: 0744cb3c303baf0d308ff7b112ed41f22abb6029cb5644fd3a8ce74b29f16a68
- name: Download e2e tools
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: e2e-tools
path: .e2e-tools/bin
- name: Restore e2e tool permissions
run: chmod +x .e2e-tools/bin/oats .e2e-tools/bin/gcx
- name: Run ${{ matrix.shard }} e2e tests
# OATS_E2E_FILTER is not part of the matrix to avoid that it shows up in the gh action (too long)
run: |
start_ts="$(date +%s)"
case "${{ matrix.shard }}" in
core)
export OATS_E2E_FILTER="-fixture/"
;;
compose)
export OATS_E2E_FILTER="fixture/compose"
;;
remote)
export OATS_E2E_FILTER="fixture/remote"
;;
k3d-fail)
export OATS_E2E_FILTER="fixture/k3d-fail"
;;
k3d-smoke)
export OATS_E2E_FILTER="fixture/k3d-smoke"
;;
*)
echo "unknown e2e shard: ${{ matrix.shard }}" >&2
exit 1
;;
esac
export OATS_E2E_BIN_DIR="$PWD/.e2e-tools/bin"
echo "e2e timing: shard=${{ matrix.shard }} filter=${OATS_E2E_FILTER} bin_dir=${OATS_E2E_BIN_DIR}"
mise run e2e-test
end_ts="$(date +%s)"
echo "e2e timing: shard=${{ matrix.shard }} total=$((end_ts-start_ts))s"
21 changes: 0 additions & 21 deletions .github/workflows/integration_test.yml

This file was deleted.

40 changes: 14 additions & 26 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ OpenTelemetry written in Go. It enables full round-trip testing from
instrumented applications to the observability stack (LGTM: Loki, Grafana,
Tempo, Prometheus, Mimir, OpenTelemetry Collector).

Test cases are defined in YAML files with `oats-schema-version: 2` and can
Test cases are defined in YAML files with `oats-schema-version: 3` and can
validate traces (TraceQL), logs (LogQL), metrics (PromQL), and profiles
(Pyroscope queries) using Docker Compose or Kubernetes backends.

Expand All @@ -19,13 +19,10 @@ validate traces (TraceQL), logs (LogQL), metrics (PromQL), and profiles
# Build
mise run build

# Run unit tests
# Run non-e2e tests
mise run test

# Run integration tests (requires Docker)
mise run integration-test

# Run end-to-end tests
# Run e2e tests
mise run e2e-test
```

Expand All @@ -51,7 +48,8 @@ EditorConfig rules live in `.editorconfig`.

### Package Organization

- **`main.go`** — CLI entry point. Parses flags, discovers YAML test files, runs them sequentially
- **`main.go`** — Root `oats` CLI entry point
- **`internal/cli/`** — The gcx-driven CLI implementation used by the root binary
- **`model/`** — Core data models (`TestCaseDefinition`, expected signals)
- **`yaml/`** — Test case parsing, execution, signal-specific assertions
(`runner.go`, `traces.go`, `metrics.go`, `logs.go`, `profiles.go`)
Expand All @@ -61,31 +59,22 @@ EditorConfig rules live in `.editorconfig`.

### Test Case Schema

Required fields:

- `oats-schema-version: 2` (must be present in all test files)
- `oats-template: true` (for template files used in `include`)

Core sections: `include`, `docker-compose`, `kubernetes`, `matrix`, `input`, `interval`, `expected`

File discovery scans for `.yaml`/`.yml` files containing
`oats-schema-version`. Files with `oats-template: true` are skipped as entry
points. `.oatsignore` causes a directory to be ignored.
Current user-facing syntax is documented in `README.md`. Legacy yaml parsing
still exists in-package for migration support, but the repo's CLI surface is
the current `oats.toml` + case-yaml flow.

## CLI Usage

```bash
# Run specific test file
oats /path/to/test.yaml

# Scan directory for all tests
oats /path/to/tests/
# Print a plan
oats --config oats.toml --list

# With flags
oats -timeout 1m -lgtm-version latest /path/to/test.yaml
oats --config oats.toml --timeout 1m
```

Key flags: `-timeout` (default 30s), `-lgtm-version` (default "latest"), `-manual-debug` (keep containers running)
Key flags: `--config`, `--suite`, `--tags`, `--timeout`, `--interval`,
`--absent-timeout`, `--parallel`, `--gcx`, `--gcx-context`, `--version`
Comment on lines +78 to +79

## Code Conventions

Expand All @@ -98,11 +87,10 @@ Key flags: `-timeout` (default 30s), `-lgtm-version` (default "latest"), `-manua
## Testing

- Unit tests: `mise run test`
- Integration tests require `INTEGRATION_TESTS=true` env var
- Uses gomega for assertions, stretchr/testify for test utilities

## CI

- Lint on PRs (`mise run lint`), build on PRs (`mise run build`), tests on PRs (`mise run test`)
- Integration tests and e2e tests in separate workflows
- E2E tests in a separate workflow
- Linting via flint
1 change: 1 addition & 0 deletions CURRENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Current OATS docs now live in [README.md](README.md)
Loading
Loading