> ## Documentation Index
> Fetch the complete documentation index at: https://qodex.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Run tests in Jenkins

> Trigger Qodex from a Jenkins pipeline, poll for completion, and fail the build on a failed Qodex run.

# Run tests in Jenkins

Use a Jenkins pipeline stage to trigger Qodex and block the build when scenarios fail.

## Before you start

You need:

* A Qodex project with runnable scenarios.
* A project API key from **Settings > Platform > API keys**.
* A Jenkins agent that can run `curl` and `jq`, or a Docker agent.

## Store the API key

In Jenkins, open **Manage Jenkins > Credentials**, then add a credential:

* Kind: **Secret text**
* Secret: your `qk_...` key
* ID: `qodex-api-key`

Expose `QODEX_PROJECT` as a job or global environment variable with your Qodex project slug.

## Add the Jenkinsfile

Save this file as `Jenkinsfile`.

```groovy theme={null}
pipeline {
  agent {
    docker {
      image 'alpine:3.20'
      args '-u root'
    }
  }
  options {
    timeout(time: 30, unit: 'MINUTES')
    timestamps()
  }
  environment {
    QODEX_HOST = 'https://agents.qodex.ai'
  }
  stages {
    stage('Qodex smoke') {
      steps {
        withCredentials([string(credentialsId: 'qodex-api-key', variable: 'QODEX_API_KEY')]) {
          sh '''
            set -euo pipefail
            apk add --no-cache curl jq >/dev/null

            ENV_NAME=staging
            if [ "${BRANCH_NAME:-}" = "main" ]; then ENV_NAME=prod; fi

            RESPONSE=$(curl -fsS -X POST \
              "$QODEX_HOST/api/projects/$QODEX_PROJECT/webhooks/trigger" \
              -H "Authorization: Bearer $QODEX_API_KEY" \
              -H "Content-Type: application/json" \
              -d "{\\"environment\\":\\"$ENV_NAME\\",\\"tags\\":[\\"smoke\\"]}")

            RUN_ID=$(echo "$RESPONSE" | jq -r .testRunId)
            if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
              echo "Failed to start run. Response: $RESPONSE"
              exit 1
            fi

            DEADLINE=$(( $(date +%s) + 1500 ))
            while [ "$(date +%s)" -lt "$DEADLINE" ]; do
              STATUS=$(curl -fsS \
                "$QODEX_HOST/api/projects/$QODEX_PROJECT/test-runs/$RUN_ID" \
                -H "Authorization: Bearer $QODEX_API_KEY" | jq -r .status)
              echo "status=$STATUS"
              case "$STATUS" in
                completed) exit 0 ;;
                failed) exit 1 ;;
                *) sleep 10 ;;
              esac
            done
            echo "Timed out waiting for Qodex run $RUN_ID"
            exit 1
          '''
        }
      }
    }
  }
}
```

The `withCredentials` block keeps the API key out of logs. The Docker agent keeps the runtime predictable.

## Make it required

If Jenkins reports build status back to GitHub or GitLab, mark the Jenkins check as required in your branch protection or merge settings.

## Related

<CardGroup cols={2}>
  <Card title="Generic shell recipe" icon="terminal" href="/run-tests-ci-generic-shell" />

  <Card title="GitHub Actions recipe" icon="git-branch" href="/run-tests-ci-github-actions" />
</CardGroup>
