Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 9 additions & 0 deletions .trivyignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,12 @@
# ships a base image built with Go >= 1.26.5. Remove this entry then (and
# consider bumping the grafana/k6 base tag in runner/Dockerfile).
CVE-2026-39822

# GHSA-hrxh-6v49-42gf — gRPC-Go: xDS RBAC and HTTP/2 vulnerabilities (HIGH).
# Lives in the upstream grafana/k6 base image's usr/bin/k6 binary, which
# bundles google.golang.org/grpc < 1.82.1. No k6 release fixes it: 2.1.0 (the
# version we pin) and even k6 master still use grpc 1.81.1, and we do not build
# k6 from source. The affected paths (gRPC xDS/RBAC server authorization) are
# not exercised — this suite benchmarks JSON-RPC over HTTP and never uses k6's
# gRPC module. Remove this entry once k6 bumps grpc to >= 1.82.1.
GHSA-hrxh-6v49-42gf
6 changes: 3 additions & 3 deletions runner/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ COPY runner/ ./runner/
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o jsonrpc-bench-runner ./runner

# Final stage - minimal runtime image with k6 (base is alpine)
FROM grafana/k6:1.8.0
FROM grafana/k6:2.1.0

# Use root user for dependencies installation
USER root

# Refresh base image packages so the pinned grafana/k6:1.4.0 picks up
# patched libcrypto3/libssl3 from Alpine 3.22's update channel.
# Refresh base image packages so the pinned grafana/k6:2.1.0 picks up
# patched libcrypto3/libssl3 from Alpine's update channel.
RUN apk --no-cache upgrade && \
apk --no-cache add ca-certificates tzdata curl postgresql-client

Expand Down
20 changes: 20 additions & 0 deletions runner/generator/k6_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ func GenerateK6Config(cfg *config.Config, outputDir string) (string, error) {
}
}

// Register always-true per-client x per-method submetric thresholds so k6's
// --summary-export emits a per-scenario (client) breakdown for each method:
// k6 only includes a tag-filtered submetric in summary.json when a threshold
// is defined on it. These conditions can never fail, so they never affect the
// k6 exit code. Keys are UNQUOTED and use {scenario:C,req_name:M} ordering
// because k6 stores the submetric name verbatim and metrics/summary_fallback.go
// (lookupSubmetric) matches that exact string. Grows as clients x methods x 3.
for _, client := range cfg.ResolvedClients {
for _, call := range cfg.Calls {
identifier := call.Name
if identifier == "" {
identifier = call.Method
}
selector := fmt.Sprintf("{scenario:%s,req_name:%s}", client.Name, identifier)
config.Options.Thresholds["http_req_duration"+selector] = []string{"max>=0"}
config.Options.Thresholds["http_reqs"+selector] = []string{"count>=0"}
config.Options.Thresholds["http_req_failed"+selector] = []string{"rate>=0"}
}
}

// Add scenario to config for each client
for _, client := range cfg.ResolvedClients {
tags := make(map[string]string)
Expand Down