CI integration
stampede run needs no server, so it fits any CI system.
name: performanceon: [pull_request]jobs: smoke: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: { go-version: "1.27" } - run: go install github.com/Ivan825/Stampede/cmd/stampede@latest - name: start the app under test run: docker compose -f deploy/test.yml up -d --wait - name: load test run: | stampede run perf/checkout.yaml -e TARGET_URL=http://localhost:8080 \ --shape smoke --junit junit.xml --md summary.md -o report.html - if: always() run: cat summary.md >> "$GITHUB_STEP_SUMMARY" - if: always() uses: actions/upload-artifact@v4 with: { name: load-report, path: "report.html\njunit.xml" }| Exit code | Meaning |
|---|---|
| 0 | every target passed (or none set) |
| 3 | a target failed |
| 4 | stampede compare found a regression |
| 1 | any other error |
--junit writes one test case per target, which most CI systems display
natively. --md writes a summary suitable for a pull request comment.
To run against a shared Stampede server instead (for distributed load),
create an API token with stampede tokens create (role runner) and
use:
export STAMPEDE_SERVER=https://stampede.example.com STAMPEDE_TOKEN=stp_...stampede start --project shop --file perf/checkout.yaml --target staging --md summary.mdGitLab CI
Section titled “GitLab CI”The app under test runs as a service; its alias is its host name. A service on the job’s network has a private address, so no ownership check applies (see safety). GitLab reads the JUnit file into the merge request’s test report.
load-test: stage: test image: golang:1.27 services: - name: registry.example.com/shop:$CI_COMMIT_SHA alias: shop script: - go install github.com/Ivan825/Stampede/cmd/stampede@latest - stampede run perf/checkout.yaml -e TARGET_URL=http://shop:8080 --shape smoke --junit junit.xml --md summary.md -o report.html artifacts: when: always paths: [report.html, summary.md] reports: junit: junit.xmlExit code 3 fails the job when a target fails. To keep the job green and
only report, add allow_failure: { exit_codes: [3] }.
Jenkins
Section titled “Jenkins”A declarative pipeline in a Go container. The Go paths are moved into the
workspace because Jenkins runs the container as its own user, which cannot
write to the image’s /go.
// Jenkinsfilepipeline { agent { docker { image 'golang:1.27' } } environment { GOPATH = "${WORKSPACE}/.go" GOCACHE = "${WORKSPACE}/.cache/go-build" TARGET_URL = 'http://staging.internal:8080' } stages { stage('Install stampede') { steps { sh 'go install github.com/Ivan825/Stampede/cmd/stampede@latest' } } stage('Load test') { steps { sh '"$GOPATH/bin/stampede" run perf/checkout.yaml -e TARGET_URL="$TARGET_URL" --shape smoke --junit junit.xml --md summary.md -o report.html' } } } post { always { junit testResults: 'junit.xml', allowEmptyResults: true archiveArtifacts artifacts: 'report.html,summary.md', allowEmptyArchive: true } }}A failed target (exit code 3) fails the sh step and the build. To mark
the build unstable instead, wrap the step in
catchError(buildResult: 'UNSTABLE', stageResult: 'UNSTABLE') { ... }.
Both examples build the CLI with go install, which needs Go on the agent.
Without Go, use the one-line installer instead
(curl -fsSL .../install.sh | sh, see installation), which
downloads the released binary. These two examples are not run in this
repository’s CI; the GitHub Action below is.
GitHub Action
Section titled “GitHub Action”The repository ships a composite action in action/.
It installs stampede, runs a scenario, appends the Markdown summary to the
job summary, uploads the HTML, JSON, JUnit and Markdown reports as an
artifact, sets outputs and fails the step when a target fails (exit code 3).
name: performanceon: [pull_request]jobs: smoke: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: start the app under test run: docker compose -f deploy/test.yml up -d --wait - id: load uses: Ivan825/Stampede/action@v1 with: scenario: perf/checkout.yaml target-url: http://localhost:8080 shape: smoke - run: echo "p95 was ${{ steps.load.outputs.p95 }}s (${{ steps.load.outputs.verdict }})"@v1 follows the latest 1.x release; pin @v1.0.0 (or a commit SHA) to
stay on one version.
| Input | Default | Meaning |
|---|---|---|
scenario |
(required) | path to the scenario file |
target-url |
overrides target.baseURL (--base-url) |
|
shape, rate, vus, duration |
the matching stampede run overrides |
|
extra-args |
more stampede run arguments, split on spaces, e.g. -e TOKEN=abc |
|
version |
latest |
latest; a release tag such as v1.2.3 (downloads the release archive for the runner’s OS and architecture and checks it against the release checksums); any other git ref such as main or a SHA (go install ...@ref, with actions/setup-go); or local to build the Stampede repository checked out in the workspace. |
output-dir |
stampede-report |
where the reports are written |
artifact-name |
stampede-report |
name of the uploaded artifact; empty skips the upload |
fail-on-target-failure |
true |
fail the step when a target fails |
| Output | Meaning |
|---|---|
verdict |
pass, fail, generator-limited or no-targets |
p95 |
overall p95 latency in seconds |
error-rate |
share of failed requests, 0 to 1 |
exit-code |
exit code of stampede run |
report-dir |
directory holding report.html, report.json, junit.xml, summary.md |
The action is exercised in this repository’s CI (the action job) with
version: local against bench/echoserver: a passing run must set its
outputs and a failing target must fail the step. The same job runs it with
version: latest, which downloads the latest release and checks it against
the release checksums.