Skip to content

feat(load-generator): replace Locust with k6 #724

feat(load-generator): replace Locust with k6

feat(load-generator): replace Locust with k6 #724

# Copyright The OpenTelemetry Authors
# SPDX-License-Identifier: Apache-2.0
name: Telemetry Tests
on:
# Run on every approved PR review (covers human-reviewed PRs).
pull_request_review:
types: [submitted]
# Run on dependabot PRs without requiring approval. The `gate` job below
# restricts this to dependabot only; other PRs are tested via review approval.
pull_request:
branches: [main]
paths:
- 'src/**'
- 'test/telemetry/**'
- 'compose.yaml'
- 'compose.full.yaml'
- 'compose.observability.yaml'
- 'compose.extras.yaml'
- '.env'
- '.github/workflows/run-telemetry-tests.yml'
# Post-merge validation on main.
push:
branches: [main]
paths:
- 'src/**'
- 'test/telemetry/**'
- 'compose.yaml'
- 'compose.full.yaml'
- 'compose.observability.yaml'
- 'compose.extras.yaml'
- '.env'
- '.github/workflows/run-telemetry-tests.yml'
workflow_dispatch:
permissions:
contents: read
# Coalesce concurrent runs on the same PR or branch so an approval right
# after a push doesn't fire two builds in parallel.
concurrency:
group: telemetry-tests-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# Single source of truth for when the telemetry test jobs should run:
# - approved PR reviews on open non-dependabot PRs, OR
# - dependabot PRs (tested on open/sync, not on approval), OR
# - push to main / manual dispatch
gate:
name: "Telemetry Test Gate"
runs-on: ubuntu-latest
outputs:
should_run: ${{ steps.check.outputs.should_run }}
steps:
- id: check
# Pass GitHub-context values through env: rather than expanding them
# directly into the shell command, so a hostile fork can't sneak shell
# metacharacters into a context field and break out of the comparison.
env:
EVENT_NAME: ${{ github.event_name }}
REVIEW_STATE: ${{ github.event.review.state }}
PR_STATE: ${{ github.event.pull_request.state }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
run: |
if [[ "$EVENT_NAME" == "workflow_dispatch" || "$EVENT_NAME" == "push" ]] \
|| [[ "$EVENT_NAME" == "pull_request_review" && "$REVIEW_STATE" == "approved" && "$PR_STATE" == "open" && "$PR_AUTHOR" != "dependabot[bot]" ]] \
|| [[ "$EVENT_NAME" == "pull_request" && "$PR_AUTHOR" == "dependabot[bot]" ]]; then
echo "should_run=true" >> "$GITHUB_OUTPUT"
else
echo "should_run=false" >> "$GITHUB_OUTPUT"
fi
# Build the demo images from the PR's source ONCE, then hand them to the test
# jobs as an artifact. Without this the test jobs ran `docker compose up`,
# which pulls the released `ghcr.io/open-telemetry/demo:latest-*` images from
# the registry — so a PR's own changes were never actually exercised.
build-images:
name: "Build demo images"
needs: gate
if: ${{ needs.gate.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: check out code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
# On pull_request_review the default ref is the base branch; check out
# the PR head so we build the proposed changes. Falls back to the
# default ref for push and workflow_dispatch events.
ref: ${{ github.event.pull_request.head.sha || github.ref }}
persist-credentials: false
- name: Free disk space
run: |
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc
docker system prune -af
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
- name: Create .env.override if missing
run: touch .env.override
- name: Build demo images
run: make build
- name: Save demo images to an artifact tarball
run: |
# Only the images we build (demo:latest-*) need shipping; third-party
# images (jaeger, prometheus, grafana, ...) are pulled from their own
# registries by each test job, so leave them out to keep the tarball small.
IMAGES=$(docker images 'ghcr.io/open-telemetry/demo:latest-*' --format '{{.Repository}}:{{.Tag}}')
echo "Saving images:"; echo "$IMAGES"
docker save $IMAGES | zstd -3 -T0 -o demo-images.tar.zst
ls -lh demo-images.tar.zst
- name: Upload demo images artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: demo-images-${{ github.run_id }}
path: demo-images.tar.zst
retention-days: 1
compression-level: 0 # already zstd-compressed
telemetry-tests-full:
needs: [gate, build-images]
if: ${{ needs.gate.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
name: "Telemetry Tests (full)"
steps:
- name: check out code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
persist-credentials: false
- name: Free disk space
run: |
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc
docker system prune -af
- name: Download demo images artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: demo-images-${{ github.run_id }}
- name: Load demo images
run: zstd -d -c demo-images.tar.zst | docker load
- name: Create .env.override if missing
run: touch .env.override
- name: Run telemetry tests
timeout-minutes: 15
env:
# Give backends more headroom on slow shared runners before the
# per-test polls begin; the warmup gate waits for all three backends.
WARMUP_SECONDS: "300"
POLL_TIMEOUT: "240"
WARMUP_PROBE_TIMEOUT: "180"
PYTEST_ADDOPTS: "--capture=tee-sys --maxfail=1"
run: make run-telemetry-tests
- name: Print service logs on failure
if: failure()
run: docker compose logs --tail=50
- name: Stop demo
if: always()
run: make stop
telemetry-tests-minimal:
needs: [gate, build-images]
if: ${{ needs.gate.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
timeout-minutes: 30
name: "Telemetry Tests (minimal)"
steps:
- name: check out code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}
persist-credentials: false
- name: Free disk space
run: |
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc
docker system prune -af
- name: Download demo images artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: demo-images-${{ github.run_id }}
- name: Load demo images
run: zstd -d -c demo-images.tar.zst | docker load
- name: Create .env.override if missing
run: touch .env.override
- name: Run telemetry tests (minimal)
timeout-minutes: 15
env:
WARMUP_SECONDS: "300"
POLL_TIMEOUT: "240"
WARMUP_PROBE_TIMEOUT: "180"
PYTEST_ADDOPTS: "--capture=tee-sys --maxfail=1"
run: make run-telemetry-tests-minimal
- name: Print service logs on failure
if: failure()
run: docker compose logs --tail=50
- name: Stop demo
if: always()
run: make stop