chore: import upstream snapshot with attribution
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
---
|
||||
sidebar_label: Jenkins
|
||||
description: Integrate Promptfoo's LLM testing into Jenkins pipelines with automated evaluation, credential management, and CI/CD workflows for production AI deployments
|
||||
---
|
||||
|
||||
# Setting up Promptfoo with Jenkins
|
||||
|
||||
This guide demonstrates how to integrate Promptfoo's LLM evaluation into your Jenkins pipeline. This setup enables automatic testing of your prompts and models whenever changes are made to your repository.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Jenkins server with pipeline support
|
||||
- Node.js installed on the Jenkins agent
|
||||
- Your LLM provider's API keys (e.g., OpenAI API key)
|
||||
- Basic familiarity with Jenkins Pipeline syntax
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
### 1. Create Jenkinsfile
|
||||
|
||||
Create a `Jenkinsfile` in your repository root. Here's a basic configuration that installs Promptfoo and runs evaluations:
|
||||
|
||||
```groovy:Jenkinsfile
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
OPENAI_API_KEY = credentials('openai-api-key')
|
||||
PROMPTFOO_CACHE_PATH = '~/.promptfoo/cache'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Setup') {
|
||||
steps {
|
||||
sh 'npm install -g promptfoo'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Evaluate Prompts') {
|
||||
steps {
|
||||
script {
|
||||
try {
|
||||
sh 'promptfoo eval -c promptfooconfig.yaml --prompts prompts/**/*.json --share -o output.json'
|
||||
} catch (Exception e) {
|
||||
currentBuild.result = 'FAILURE'
|
||||
error("Prompt evaluation failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Process Results') {
|
||||
steps {
|
||||
script {
|
||||
def output = readJSON file: 'output.json'
|
||||
echo "Evaluation Results:"
|
||||
echo "Successes: ${output.results.stats.successes}"
|
||||
echo "Failures: ${output.results.stats.failures}"
|
||||
|
||||
if (output.shareableUrl) {
|
||||
echo "View detailed results at: ${output.shareableUrl}"
|
||||
}
|
||||
|
||||
if (output.results.stats.failures > 0) {
|
||||
currentBuild.result = 'UNSTABLE'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
archiveArtifacts artifacts: 'output.json', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Configure Jenkins Credentials
|
||||
|
||||
You'll need to add the API keys for any LLM providers you're using. For example, if you're using OpenAI, you'll need to add the OpenAI API key.
|
||||
|
||||
1. Navigate to Jenkins Dashboard → Manage Jenkins → Credentials
|
||||
2. Add a new credential:
|
||||
- Kind: Secret text
|
||||
- Scope: Global
|
||||
- ID: openai-api-key
|
||||
- Description: OpenAI API Key
|
||||
- Secret: Your API key value
|
||||
|
||||
### 3. Set Up Caching
|
||||
|
||||
To implement caching for better performance and reduced API costs:
|
||||
|
||||
1. Create a cache directory on your Jenkins agent:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.promptfoo/cache
|
||||
```
|
||||
|
||||
2. Ensure the Jenkins user has write permissions:
|
||||
|
||||
```bash
|
||||
chown -R jenkins:jenkins ~/.promptfoo/cache
|
||||
```
|
||||
|
||||
### 4. Advanced Pipeline Configuration
|
||||
|
||||
Here's an example of a more advanced pipeline with additional features:
|
||||
|
||||
The advanced configuration includes several important improvements:
|
||||
|
||||
- **Build timeouts**: The `timeout` option ensures builds don't run indefinitely (1 hour limit)
|
||||
- **Timestamps**: Adds timestamps to console output for better debugging
|
||||
- **SCM polling**: Automatically checks for changes every 15 minutes using `pollSCM`
|
||||
- **Conditional execution**: Only runs evaluations when files in `prompts/` directory change
|
||||
- **Email notifications**: Sends emails to developers on pipeline failures
|
||||
- **Workspace cleanup**: Automatically cleans up workspace after each run
|
||||
- **Artifact management**: Archives both JSON and HTML reports with fingerprinting
|
||||
- **Better error handling**: More robust error catching and build status management
|
||||
|
||||
```groovy:Jenkinsfile
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
OPENAI_API_KEY = credentials('openai-api-key')
|
||||
PROMPTFOO_CACHE_PATH = '~/.promptfoo/cache'
|
||||
}
|
||||
|
||||
options {
|
||||
timeout(time: 1, unit: 'HOURS')
|
||||
timestamps()
|
||||
}
|
||||
|
||||
triggers {
|
||||
pollSCM('H/15 * * * *')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Setup') {
|
||||
steps {
|
||||
sh 'npm install -g promptfoo'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Evaluate Prompts') {
|
||||
when {
|
||||
changeset 'prompts/**'
|
||||
}
|
||||
steps {
|
||||
script {
|
||||
try {
|
||||
sh '''
|
||||
promptfoo eval \
|
||||
-c promptfooconfig.yaml \
|
||||
--prompts prompts/**/*.json \
|
||||
--share \
|
||||
-o output.json
|
||||
'''
|
||||
} catch (Exception e) {
|
||||
currentBuild.result = 'FAILURE'
|
||||
error("Prompt evaluation failed: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Process Results') {
|
||||
steps {
|
||||
script {
|
||||
def output = readJSON file: 'output.json'
|
||||
|
||||
// Create HTML report
|
||||
writeFile file: 'evaluation-report.html', text: """
|
||||
<html>
|
||||
<body>
|
||||
<h1>Prompt Evaluation Results</h1>
|
||||
<p>Successes: ${output.results.stats.successes}</p>
|
||||
<p>Failures: ${output.results.stats.failures}</p>
|
||||
<p>View detailed results: <a href="${output.shareableUrl}">${output.shareableUrl}</a></p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
// Publish HTML report
|
||||
publishHTML([
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: '.',
|
||||
reportFiles: 'evaluation-report.html',
|
||||
reportName: 'Prompt Evaluation Report'
|
||||
])
|
||||
|
||||
if (output.results.stats.failures > 0) {
|
||||
currentBuild.result = 'UNSTABLE'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
archiveArtifacts artifacts: 'output.json,evaluation-report.html', fingerprint: true
|
||||
cleanWs()
|
||||
}
|
||||
failure {
|
||||
emailext (
|
||||
subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
|
||||
body: "Prompt evaluation failed. Check console output at ${env.BUILD_URL}",
|
||||
recipientProviders: [[$class: 'DevelopersRecipientProvider']]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Common issues and solutions:
|
||||
|
||||
1. **Permission issues:**
|
||||
- Ensure Jenkins has appropriate permissions to install global npm packages
|
||||
- Verify cache directory permissions
|
||||
- Check API key credential permissions
|
||||
|
||||
2. **Pipeline timeout:**
|
||||
- Adjust the timeout in pipeline options
|
||||
- Consider splitting evaluations into smaller batches
|
||||
- Monitor API rate limits
|
||||
|
||||
3. **Cache problems:**
|
||||
- Verify cache path exists and is writable
|
||||
- Check disk space availability
|
||||
- Clear cache if needed: `rm -rf ~/.promptfoo/cache/*`
|
||||
|
||||
4. **Node.js issues:**
|
||||
- Ensure Node.js is installed on the Jenkins agent
|
||||
- Verify npm is available in PATH
|
||||
- Consider using `nodejs` tool installer in Jenkins
|
||||
|
||||
For more information on Promptfoo configuration and usage, refer to the [configuration reference](/docs/configuration/guide/).
|
||||
Reference in New Issue
Block a user