From 3d1e61b1607d66417b3a10112bee553e25ffcdbd Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 10:12:59 +0000 Subject: [PATCH 1/9] Run current OATS consumer suites Signed-off-by: Gregor Zeitlinger --- .github/renovate-tracked-deps.json | 7 +++++ ci/oats/docker-compose.lgtm.yml | 10 +++++++ ci/oats/gcx-wrapper.sh | 30 +++++++++++++++++++ .../oats-tests/agent/oats.yaml | 14 ++++----- .../oats-tests/http/oats.yaml | 14 ++++----- mise.toml | 19 +++++++++++- oats.toml | 28 +++++++++++++++++ 7 files changed, 105 insertions(+), 17 deletions(-) create mode 100644 ci/oats/docker-compose.lgtm.yml create mode 100755 ci/oats/gcx-wrapper.sh create mode 100644 oats.toml diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index eebbdf0d6..9a9b41979 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -103,6 +103,11 @@ "maven" ] }, + "ci/oats/docker-compose.lgtm.yml": { + "docker-compose": [ + "docker.io/grafana/otel-lgtm" + ] + }, "examples/example-custom-buckets/docker-compose.yaml": { "docker-compose": [ "eclipse-temurin", @@ -152,6 +157,7 @@ "aqua:owenlamont/ryl", "biome", "editorconfig-checker", + "go", "go:github.com/grafana/oats", "google-java-format", "hugo", @@ -169,6 +175,7 @@ "zizmor" ], "regex": [ + "gcx", "grafana/docker-otel-lgtm", "micrometer-metrics/micrometer", "prometheus/jmx_exporter" diff --git a/ci/oats/docker-compose.lgtm.yml b/ci/oats/docker-compose.lgtm.yml new file mode 100644 index 000000000..56d5237f4 --- /dev/null +++ b/ci/oats/docker-compose.lgtm.yml @@ -0,0 +1,10 @@ +services: + lgtm: + image: ${LGTM_IMAGE:-docker.io/grafana/otel-lgtm:latest} + ports: + - "3000:3000" + - "4317:4317" + - "4318:4318" + - "3200:3200" + - "4040:4040" + - "9090:9090" diff --git a/ci/oats/gcx-wrapper.sh b/ci/oats/gcx-wrapper.sh new file mode 100755 index 000000000..65c8adc57 --- /dev/null +++ b/ci/oats/gcx-wrapper.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +real_gcx="${REAL_GCX_BIN:-gcx}" +args=() +skip_next=false +for arg in "$@"; do + if [ "$skip_next" = true ]; then + skip_next=false + continue + fi + if [ "$arg" = "--context" ]; then + skip_next=true + continue + fi + args+=("$arg") +done + +for _ in $(seq 1 120); do + token="$(docker exec lgtm cat /tmp/grafana-sa-token 2>/dev/null || true)" + if [ -n "$token" ]; then + export GRAFANA_SERVER="${GRAFANA_SERVER:-http://localhost:3000}" + export GRAFANA_TOKEN="$token" + exec "$real_gcx" "${args[@]}" + fi + sleep 1 +done + +printf 'gcx-wrapper: timed out waiting for grafana service-account token\n' >&2 +exit 1 diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml index 899d1cd5d..7fd7d3945 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml @@ -1,12 +1,10 @@ -# OATS is an acceptance testing framework for OpenTelemetry - -# https://github.com/grafana/oats/tree/main/yaml -oats-schema-version: 2 -docker-compose: - files: - - ./docker-compose.yml +oats: 2 +name: java agent exporter preserves target_info identity +seed: + type: app expected: custom-checks: - script: ./service_instance_id_check.py metrics: - - promql: "uptime_seconds_total{}" - value: ">= 0" + - promql: 'uptime_seconds_total{}' + value: '>= 0' diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml index dbcfcf84f..a7bdc832c 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml @@ -1,10 +1,8 @@ -# OATS is an acceptance testing framework for OpenTelemetry - -# https://github.com/grafana/oats/tree/main/yaml -oats-schema-version: 2 -docker-compose: - files: - - ./docker-compose.yml +oats: 2 +name: http protobuf exporter emits uptime metric +seed: + type: app expected: metrics: - - promql: "uptime_seconds_total{}" - value: ">= 0" + - promql: 'uptime_seconds_total{}' + value: '>= 0' diff --git a/mise.toml b/mise.toml index 3e1a4b62c..0a2ba924f 100644 --- a/mise.toml +++ b/mise.toml @@ -1,4 +1,5 @@ [tools] +go = "1.25.4" "go:github.com/grafana/oats" = "0.7.0" hugo = "0.163.0" java = "temurin-25.0.3+9.0.LTS" @@ -93,7 +94,23 @@ run = "flint run --fix" [tasks.acceptance-test] description = "Run OATs acceptance tests" depends = "build" -run = "oats -lgtm-version $LGTM_VERSION -timeout 5m examples/" +run = """ +# renovate: datasource=github-releases depName=gcx packageName=grafana/gcx +export GCX_VERSION=v0.4.0 +go install "github.com/grafana/gcx/cmd/gcx@${GCX_VERSION}" + +workdir="$(mktemp -d)" +trap 'rm -rf "$workdir"' EXIT +git clone --depth 1 --branch v2 https://github.com/grafana/oats "$workdir/oats-src" +go build -o "$workdir/oats" "$workdir/oats-src/cmd/v2" + +REAL_GCX_BIN="$(go env GOPATH)/bin/gcx" \ + "$workdir/oats" \ + --config oats.toml \ + --gcx ./ci/oats/gcx-wrapper.sh \ + --no-cache \ + --timeout=5m +""" [tasks.javadoc] description = "Generate Javadoc" diff --git a/oats.toml b/oats.toml new file mode 100644 index 000000000..e02512ffb --- /dev/null +++ b/oats.toml @@ -0,0 +1,28 @@ +[meta] +version = 2 + +[[suite]] +name = "example-exporter-http" +cases = ["examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml"] +fixture = "example-exporter-http" +tags = ["metrics", "http-protobuf"] + +[[suite]] +name = "example-exporter-agent" +cases = ["examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml"] +fixture = "example-exporter-agent" +tags = ["metrics", "custom-check", "javaagent"] + +[fixture.example-exporter-http] +type = "compose" +compose_files = [ + "ci/oats/docker-compose.lgtm.yml", + "examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml", +] + +[fixture.example-exporter-agent] +type = "compose" +compose_files = [ + "ci/oats/docker-compose.lgtm.yml", + "examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml", +] From 2f6dfce49ddf6fcabedaf7fc3c8b40546f092d81 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 10:21:22 +0000 Subject: [PATCH 2/9] Fix current OATS CI bootstrap Signed-off-by: Gregor Zeitlinger --- .github/renovate-tracked-deps.json | 2 -- mise.toml | 22 ++++++++++++++++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index 9a9b41979..1e631ed77 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -157,8 +157,6 @@ "aqua:owenlamont/ryl", "biome", "editorconfig-checker", - "go", - "go:github.com/grafana/oats", "google-java-format", "hugo", "java", diff --git a/mise.toml b/mise.toml index 0a2ba924f..35fd2f2c7 100644 --- a/mise.toml +++ b/mise.toml @@ -1,6 +1,4 @@ [tools] -go = "1.25.4" -"go:github.com/grafana/oats" = "0.7.0" hugo = "0.163.0" java = "temurin-25.0.3+9.0.LTS" node = "24.16.0" @@ -97,12 +95,28 @@ depends = "build" run = """ # renovate: datasource=github-releases depName=gcx packageName=grafana/gcx export GCX_VERSION=v0.4.0 +gotmp="" + +if ! command -v go >/dev/null 2>&1; then + goversion="1.25.4" + arch="$(uname -m)" + case "$arch" in + x86_64|amd64) goarch="amd64" ;; + aarch64|arm64) goarch="arm64" ;; + *) echo "unsupported architecture: $arch" >&2; exit 1 ;; + esac + gotmp="$(mktemp -d)" + curl -fsSL "https://go.dev/dl/go${goversion}.linux-${goarch}.tar.gz" -o "$gotmp/go.tgz" + tar -C "$gotmp" -xzf "$gotmp/go.tgz" + export PATH="$gotmp/go/bin:$PATH" +fi + go install "github.com/grafana/gcx/cmd/gcx@${GCX_VERSION}" workdir="$(mktemp -d)" -trap 'rm -rf "$workdir"' EXIT +trap 'rm -rf "$workdir" ${gotmp:+"$gotmp"}' EXIT git clone --depth 1 --branch v2 https://github.com/grafana/oats "$workdir/oats-src" -go build -o "$workdir/oats" "$workdir/oats-src/cmd/v2" +GOWORK=off go build -o "$workdir/oats" "$workdir/oats-src/cmd/v2" REAL_GCX_BIN="$(go env GOPATH)/bin/gcx" \ "$workdir/oats" \ From 1a333c36c4e06db41d9cbf008643469aee52af0e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 10:27:29 +0000 Subject: [PATCH 3/9] Build current OATS from its module root Signed-off-by: Gregor Zeitlinger --- mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mise.toml b/mise.toml index 35fd2f2c7..d9be6b0f8 100644 --- a/mise.toml +++ b/mise.toml @@ -116,7 +116,7 @@ go install "github.com/grafana/gcx/cmd/gcx@${GCX_VERSION}" workdir="$(mktemp -d)" trap 'rm -rf "$workdir" ${gotmp:+"$gotmp"}' EXIT git clone --depth 1 --branch v2 https://github.com/grafana/oats "$workdir/oats-src" -GOWORK=off go build -o "$workdir/oats" "$workdir/oats-src/cmd/v2" +GOWORK=off go -C "$workdir/oats-src" build -o "$workdir/oats" ./cmd/v2 REAL_GCX_BIN="$(go env GOPATH)/bin/gcx" \ "$workdir/oats" \ From 1b25fb8b774c1647410f2d8a89659bdedeb7c62e Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 10:32:29 +0000 Subject: [PATCH 4/9] Trigger CI for current OATS validation Signed-off-by: Gregor Zeitlinger From fb5349d7a3e1da746c3eca5e45ba05f487bc75e7 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 11:24:15 +0000 Subject: [PATCH 5/9] Resolve merge with current main Signed-off-by: Gregor Zeitlinger --- mise.toml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/mise.toml b/mise.toml index d9be6b0f8..538da7f54 100644 --- a/mise.toml +++ b/mise.toml @@ -1,5 +1,6 @@ [tools] -hugo = "0.163.0" +"go:github.com/grafana/oats" = "0.7.0" +hugo = "0.163.2" java = "temurin-25.0.3+9.0.LTS" node = "24.16.0" protoc = "35" @@ -8,14 +9,14 @@ protoc = "35" actionlint = "1.7.12" "aqua:grafana/flint" = "0.22.5" "aqua:jonwiggins/xmloxide" = "v0.4.3" -"aqua:owenlamont/ryl" = "0.14.0" -biome = "2.4.16" +"aqua:owenlamont/ryl" = "0.18.1" +biome = "2.5.0" editorconfig-checker = "3.7.0" google-java-format = "1.35.0" lychee = "0.24.2" -"npm:renovate" = "43.212.4" -ruff = "0.15.16" -rumdl = "0.2.9" +"npm:renovate" = "43.220.0" +ruff = "0.15.17" +rumdl = "v0.2.17" shellcheck = "v0.11.0" shfmt = "3.13.1" taplo = "0.10.0" From 1d368e9690494e4b5a2d70193ed67caf55ffa211 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 11:31:59 +0000 Subject: [PATCH 6/9] Fix renovate dependency tracking Signed-off-by: Gregor Zeitlinger --- .github/renovate-tracked-deps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate-tracked-deps.json b/.github/renovate-tracked-deps.json index 1e631ed77..fba9d60bd 100644 --- a/.github/renovate-tracked-deps.json +++ b/.github/renovate-tracked-deps.json @@ -157,6 +157,7 @@ "aqua:owenlamont/ryl", "biome", "editorconfig-checker", + "go:github.com/grafana/oats", "google-java-format", "hugo", "java", From c21b152d1b76e13787e65aa514fa1bf475176a07 Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 17 Jun 2026 14:05:51 +0000 Subject: [PATCH 7/9] Fix OATS compose build paths Signed-off-by: Gregor Zeitlinger --- .../oats-tests/agent/docker-compose.yml | 2 +- .../oats-tests/http/docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml index 2b820bdea..46a541f54 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/docker-compose.yml @@ -4,7 +4,7 @@ version: "3.4" services: java: build: - context: ../.. + context: ../../examples/example-exporter-opentelemetry dockerfile: oats-tests/agent/Dockerfile environment: OTEL_SERVICE_NAME: "rolldice" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml index 889278010..2743dfef7 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml +++ b/examples/example-exporter-opentelemetry/oats-tests/http/docker-compose.yml @@ -4,7 +4,7 @@ version: "3.4" services: java: build: - context: ../.. + context: ../../examples/example-exporter-opentelemetry dockerfile: oats-tests/http/Dockerfile environment: OTEL_SERVICE_NAME: "rolldice" From 84259909e0a7c48bafa3faf25b81beb743b33e5b Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 18 Jun 2026 06:35:04 +0000 Subject: [PATCH 8/9] Use Prometheus custom checks for OATS acceptance Signed-off-by: Gregor Zeitlinger --- .../oats-tests/agent/check_uptime_metric.py | 11 +++++++++++ .../oats-tests/agent/oats.yaml | 4 +--- .../oats-tests/http/check_uptime_metric.py | 11 +++++++++++ .../oats-tests/http/oats.yaml | 5 ++--- 4 files changed, 25 insertions(+), 6 deletions(-) create mode 100755 examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py create mode 100755 examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py new file mode 100755 index 000000000..ffe1bfc8a --- /dev/null +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import json +from urllib.request import urlopen + +def get_json(url): + with urlopen(url) as response: + return json.loads(response.read().decode("utf-8")) + +res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") +results = res["data"]["result"] +assert results, "Expected uptime_seconds_total to be present" diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml index 7fd7d3945..1084b162c 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/oats.yaml @@ -4,7 +4,5 @@ seed: type: app expected: custom-checks: + - script: ./check_uptime_metric.py - script: ./service_instance_id_check.py - metrics: - - promql: 'uptime_seconds_total{}' - value: '>= 0' diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py new file mode 100755 index 000000000..ffe1bfc8a --- /dev/null +++ b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +import json +from urllib.request import urlopen + +def get_json(url): + with urlopen(url) as response: + return json.loads(response.read().decode("utf-8")) + +res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") +results = res["data"]["result"] +assert results, "Expected uptime_seconds_total to be present" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml index a7bdc832c..443471de4 100644 --- a/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml +++ b/examples/example-exporter-opentelemetry/oats-tests/http/oats.yaml @@ -3,6 +3,5 @@ name: http protobuf exporter emits uptime metric seed: type: app expected: - metrics: - - promql: 'uptime_seconds_total{}' - value: '>= 0' + custom-checks: + - script: ./check_uptime_metric.py From 929a9a497e44fcf5905b9273ec95230782ad71cd Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Thu, 18 Jun 2026 06:40:10 +0000 Subject: [PATCH 9/9] Format OATS custom check scripts Signed-off-by: Gregor Zeitlinger --- .../oats-tests/agent/check_uptime_metric.py | 2 ++ .../oats-tests/http/check_uptime_metric.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py index ffe1bfc8a..a04d66b0e 100755 --- a/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py +++ b/examples/example-exporter-opentelemetry/oats-tests/agent/check_uptime_metric.py @@ -2,10 +2,12 @@ import json from urllib.request import urlopen + def get_json(url): with urlopen(url) as response: return json.loads(response.read().decode("utf-8")) + res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") results = res["data"]["result"] assert results, "Expected uptime_seconds_total to be present" diff --git a/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py index ffe1bfc8a..a04d66b0e 100755 --- a/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py +++ b/examples/example-exporter-opentelemetry/oats-tests/http/check_uptime_metric.py @@ -2,10 +2,12 @@ import json from urllib.request import urlopen + def get_json(url): with urlopen(url) as response: return json.loads(response.read().decode("utf-8")) + res = get_json("http://localhost:9090/api/v1/query?query=uptime_seconds_total") results = res["data"]["result"] assert results, "Expected uptime_seconds_total to be present"