set up go gates in ci cd with leapwork go.md

Set Up Go Gates in CI/CD with Leapwork Go

This guide shows how to create threshold-based pass/fail gates for Leapwork Go in a CI/CD pipeline.

It assumes that your pipeline can already trigger a Leapwork Go run and poll for completion.

What this guide covers

Before you start

How performance gates work

A performance gate in CI/CD has two parts:

  1. You define acceptable response-time bands in Leapwork Go.

  2. Your pipeline evaluates the returned run metrics against those same numeric limits.

Leapwork Go exposes the run outcome and step-level metrics through the CI/CD integration API. The terminal response includes fields such as:

Use these values to decide whether the pipeline should continue or fail.

Leapwork Go stores and visualizes threshold bands in the product. In CI/CD, you enforce those thresholds by comparing the returned run metrics against the same numeric values in your pipeline logic.

Step 1: Define threshold bands in Leapwork Go

  1. Open the project that contains your timeline.
  2. Open the timeline you want to use as a release gate.
  3. Select the sequence on the timeline.
  4. In the right-side editor, locate Go level thresholds.
  5. Set the response-time limits for the sequence.
  6. Save the timeline.

Each sequence on a timeline has three performance bands:

Default thresholds for a new timeline sequence are:

Band Default range
Satisfactory 0 to 250 ms
Tolerable 250 ms to 1000 ms
Frustrating 1000 ms and above

A practical example:

Sequence type Satisfactory Tolerable Frustrating
Internal API 300 ms 800 ms > 800 ms
Customer-facing checkout API 500 ms 1500 ms > 1500 ms
Long-running partner API 1000 ms 3000 ms > 3000 ms

Step 2: Decide what should fail the pipeline

Leapwork Go returns several metrics. Not all of them need to be hard gates.

A good starting policy is:

Metric Recommended gate type Example rule
errors Hard fail Fail if any step returns more than 0 errors
p95 Hard fail Fail if p95 is above the Tolerable limit
average Soft fail or warning Investigate if average leaves the Satisfactory band
p99 Optional hard fail Use for strict gates on critical APIs
max Optional review signal Useful for investigation, but often too noisy for a release gate

For most teams, the safest first production gate is:

Step 3: Run the test from CI/CD

Use the CI/CD integration API to:

  1. Submit a run.
  2. Poll for completion.
  3. Evaluate the terminal response.

The terminal poll response includes a metadata array grouped by track item. Each step contains the values you need for gating.

Example terminal fields used for gates:

Field Meaning
title Step name or request label
errors Number of failed requests
average Average response time in milliseconds
median Median response time in milliseconds
p95 95th percentile response time in milliseconds
p99 99th percentile response time in milliseconds
max Maximum response time in milliseconds

Step 4: Add a gate evaluation step to your pipeline

The reference integration scripts already stop the pipeline if the run status is not Finished.

To turn the run into a threshold-based release gate, add one more step after polling completes. That step should:

  1. Fetch the terminal run response from pollResultUrl.
  2. Loop through the returned step metrics.
  3. Compare the metrics to your threshold values.
  4. Exit with a non-zero code when a rule is violated.

PowerShell example

Use this example in Azure DevOps, Jenkins on Windows, or any PowerShell-based runner.

param(
    [Parameter(Mandatory = $true)][string]$ApiKey,
    [Parameter(Mandatory = $true)][string]$PollResultUrl,
    [int]$SatisfactoryMs = 250,
    [int]$TolerableMs = 1000
)
$headers = @{ Authorization = "X-API-KEY $ApiKey" }
$result = Invoke-RestMethod -Uri $PollResultUrl -Headers $headers -Method Get
if ($result.status -ne 'Finished') {
    throw "Run did not finish successfully. Status: $($result.status)"
}
$failures = New-Object System.Collections.Generic.List[string]
$warnings = New-Object System.Collections.Generic.List[string]
foreach ($track in $result.metadata) {
    foreach ($step in $track.metadata) {
        $name = if ($step.title) { $step.title } else { $step.stepId }
        if (($step.errors | ForEach-Object { [int]$_ }) -gt 0) {
            $failures.Add("$name: errors=$($step.errors)")
        }
        if (($step.p95 | ForEach-Object { [int]$_ }) -gt $TolerableMs) {
            $failures.Add("$name: p95=$($step.p95) ms exceeded tolerable limit $TolerableMs ms")
        }
        if (($step.average | ForEach-Object { [int]$_ }) -gt $SatisfactoryMs) {
            $warnings.Add("$name: average=$($step.average) ms is above satisfactory limit $SatisfactoryMs ms")
        }
    }
}
if ($warnings.Count -gt 0) {
    Write-Host "Warnings:"
    $warnings | ForEach-Object { Write-Host "  $_" }
}
if ($failures.Count -gt 0) {
    Write-Host "Go gate failed:"
    $failures | ForEach-Object { Write-Host "  $_" }
    exit 1
}
Write-Host "Go gate passed."

Bash example

Use this example in Jenkins on Linux, GitHub Actions, or any Bash-based runner with jq installed.

#!/usr/bin/env bash
set -euo pipefail
: "

API_KEY is required
"
: "

POLL_RESULT_URL is required
"
SATISFACTORY_MS="${SATISFACTORY_MS:-250}"
TOLERABLE_MS="${TOLERABLE_MS:-1000}"
response="$(curl -sS -H "Authorization: X-API-KEY ${API_KEY}" "${POLL_RESULT_URL}")"
status="$(echo "${response}" | jq -r '.status')"
if [ "${status}" != "Finished" ]; then
  echo "Run did not finish successfully. Status: ${status}"
  exit 1
fi
warnings="$(echo "${response}" | jq -r --argjson satisfactory "${SATISFACTORY_MS}" '
  [
    .metadata[]?.metadata[]? as $step
    | ($step.title // $step.stepId) as $name
    | select(($step.average // 0) > $satisfactory)
    | "
     $(name): average=$(step.average) ms is above satisfactory limit 
    "
  ] | .[]')"
failures="$(echo "${response}" | jq -r --argjson tolerable "${TOLERABLE_MS}" '
  [
    .metadata[]?.metadata[]? as $step
    | ($step.title // $step.stepId) as $name
    | if ($step.errors // 0) > 0 then
        "
   $(name): errors=$(step.errors)"
      elif ($step.p95 // 0) > $tolerable then
        "
   $(name): p95=$(step.p95) ms exceeded tolerable limit 
        "
   else empty end
  ] | .[]')"
if [ -n "${warnings}" ]; then
  echo "Warnings:"
  printf '  %s\n' "${warnings}"
fi
if [ -n "${failures}" ]; then
  echo "Go gate failed:"
  printf '  %s\n' "${failures}"
  exit 1
fi
echo "Go gate passed."

Recommended implementation pattern

For a maintainable setup, store your threshold values as pipeline variables and keep them aligned with the values configured in Leapwork Go.

Example:

Variable Example value Purpose
SATISFACTORY_MS 500 Warning threshold
TOLERABLE_MS 1500 Hard fail threshold

This gives you a predictable gate model:

Example release policy

A typical release policy for a customer-facing API might be:

This gives teams a clear, automated release signal without overreacting to a single outlier.

Troubleshooting

Next step

If you have not yet connected Leapwork Go to your pipeline, start with the CI/CD integration reference. After that is in place, add a gate evaluation step using the examples above.