name: Docker Build & Test
on:
push:
branches:
- main
- develop
- 'feature/**'
pull_request:
branches:
- main
- develop
env:
REGISTRY: docker.io
IMAGE_NAME: promptheus-web
jobs:
build-and-test:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64
push: false
load: true
tags: ${{ env.IMAGE_NAME }}:test
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test CLI version - Basic prompt
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GOOGLE_MODEL: ${{ secrets.GOOGLE_MODEL }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
ZHIPUAI_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
PROMPTHEUS_PROVIDER: ${{ secrets.PROMPTHEUS_PROVIDER }}
PROMPTHEUS_MODEL: ${{ secrets.PROMPTHEUS_MODEL }}
PROMPTHEUS_ENABLE_HISTORY: ${{ secrets.PROMPTHEUS_ENABLE_HISTORY }}
run: |
docker run --rm \
-e ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \
-e GOOGLE_API_KEY="${GOOGLE_API_KEY}" \
-e GOOGLE_MODEL="${GOOGLE_MODEL:-gemini-1.5-flash}" \
-e OPENAI_API_KEY="${OPENAI_API_KEY}" \
-e GROQ_API_KEY="${GROQ_API_KEY}" \
-e ZHIPUAI_API_KEY="${ZHIPUAI_API_KEY}" \
-e DASHSCOPE_API_KEY="${DASHSCOPE_API_KEY}" \
-e PROMPTHEUS_PROVIDER="${PROMPTHEUS_PROVIDER:-anthropic}" \
-e PROMPTHEUS_MODEL="${PROMPTHEUS_MODEL:-claude-haiku-4-5}" \
-e PROMPTHEUS_ENABLE_HISTORY="${PROMPTHEUS_ENABLE_HISTORY:-true}" \
${{ env.IMAGE_NAME }}:test \
python -m promptheus.main --skip-questions -o json "What is artificial intelligence?" \
2>&1 | tee /tmp/cli_test_1_full.txt | grep -E '^\{"refined_prompt"' > /tmp/cli_test_1.json
# Check for structured refined prompt output
if jq -e '.refined_prompt and (.refined_prompt | type == "string") and (.refined_prompt | length > 10)' /tmp/cli_test_1.json >/dev/null 2>&1; then
echo "✓ CLI test 1 passed: Basic prompt refinement works"
jq -r '.refined_prompt' /tmp/cli_test_1.json | head -c 160 && echo ""
else
echo "✗ CLI test 1 failed: Expected output not found"
echo "=== Full output ==="
cat /tmp/cli_test_1_full.txt
echo "=== Extracted JSON ==="
cat /tmp/cli_test_1.json
exit 1
fi
- name: Test CLI version - Complex prompt
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GOOGLE_MODEL: ${{ secrets.GOOGLE_MODEL }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
ZHIPUAI_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
PROMPTHEUS_PROVIDER: ${{ secrets.PROMPTHEUS_PROVIDER }}
PROMPTHEUS_MODEL: ${{ secrets.PROMPTHEUS_MODEL }}
PROMPTHEUS_ENABLE_HISTORY: ${{ secrets.PROMPTHEUS_ENABLE_HISTORY }}
run: |
docker run --rm \
-e ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \
-e GOOGLE_API_KEY="${GOOGLE_API_KEY}" \
-e GOOGLE_MODEL="${GOOGLE_MODEL:-gemini-1.5-flash}" \
-e OPENAI_API_KEY="${OPENAI_API_KEY}" \
-e GROQ_API_KEY="${GROQ_API_KEY}" \
-e ZHIPUAI_API_KEY="${ZHIPUAI_API_KEY}" \
-e DASHSCOPE_API_KEY="${DASHSCOPE_API_KEY}" \
-e PROMPTHEUS_PROVIDER="${PROMPTHEUS_PROVIDER:-anthropic}" \
-e PROMPTHEUS_MODEL="${PROMPTHEUS_MODEL:-claude-haiku-4-5}" \
-e PROMPTHEUS_ENABLE_HISTORY="${PROMPTHEUS_ENABLE_HISTORY:-true}" \
${{ env.IMAGE_NAME }}:test \
python -m promptheus.main --skip-questions -o json "Create a comprehensive guide on machine learning algorithms" \
2>&1 | tee /tmp/cli_test_2_full.txt | grep -E '^\{"refined_prompt"' > /tmp/cli_test_2.json
if jq -e '.refined_prompt and (.refined_prompt | type == "string") and (.refined_prompt | test("guide|algorithm"; "i"))' /tmp/cli_test_2.json >/dev/null 2>&1; then
echo "✓ CLI test 2 passed: Complex prompt refinement works"
jq -r '.refined_prompt' /tmp/cli_test_2.json | head -c 200 && echo ""
else
echo "✗ CLI test 2 failed"
echo "=== Full output ==="
cat /tmp/cli_test_2_full.txt
echo "=== Extracted JSON ==="
cat /tmp/cli_test_2.json
exit 1
fi
- name: Start web server
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
GOOGLE_MODEL: ${{ secrets.GOOGLE_MODEL }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GROQ_API_KEY: ${{ secrets.GROQ_API_KEY }}
ZHIPUAI_API_KEY: ${{ secrets.ZHIPUAI_API_KEY }}
DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }}
PROMPTHEUS_PROVIDER: ${{ secrets.PROMPTHEUS_PROVIDER }}
PROMPTHEUS_MODEL: ${{ secrets.PROMPTHEUS_MODEL }}
PROMPTHEUS_ENABLE_HISTORY: ${{ secrets.PROMPTHEUS_ENABLE_HISTORY }}
run: |
docker run -d \
--name promptheus-test \
-e ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY}" \
-e GOOGLE_API_KEY="${GOOGLE_API_KEY}" \
-e GOOGLE_MODEL="${GOOGLE_MODEL:-gemini-1.5-flash}" \
-e OPENAI_API_KEY="${OPENAI_API_KEY}" \
-e GROQ_API_KEY="${GROQ_API_KEY}" \
-e ZHIPUAI_API_KEY="${ZHIPUAI_API_KEY}" \
-e DASHSCOPE_API_KEY="${DASHSCOPE_API_KEY}" \
-e PROMPTHEUS_PROVIDER="${PROMPTHEUS_PROVIDER:-anthropic}" \
-e PROMPTHEUS_MODEL="${PROMPTHEUS_MODEL:-claude-haiku-4-5}" \
-e PROMPTHEUS_ENABLE_HISTORY="${PROMPTHEUS_ENABLE_HISTORY:-true}" \
-p 8000:8000 \
${{ env.IMAGE_NAME }}:test
# Wait for server to be ready
echo "Waiting for web server to start..."
for i in {1..30}; do
if curl -s http://localhost:8000/ > /dev/null 2>&1; then
echo "✓ Web server is ready"
break
fi
echo "Attempt $i: Server not ready yet, waiting..."
sleep 2
done
# Final check
if ! curl -s http://localhost:8000/ > /dev/null 2>&1; then
echo "✗ Web server failed to start"
docker logs promptheus-test
exit 1
fi
- name: Test web API - Get providers
run: |
RESPONSE=$(curl -s http://localhost:8000/api/providers)
if echo "$RESPONSE" | grep -q "anthropic\|openai\|google"; then
echo "✓ Providers endpoint works"
echo "$RESPONSE" | grep -o '"id":"[^"]*"' | head -6
else
echo "✗ Providers endpoint failed"
echo "$RESPONSE"
exit 1
fi
- name: Test web API - Submit prompt
run: |
# Use hardcoded test defaults (works with both act and GitHub Actions)
PROVIDER="anthropic"
MODEL="claude-haiku-4-5"
RESPONSE=$(curl -s -X POST http://localhost:8000/api/prompt/submit \
-H "Content-Type: application/json" \
-d "$(jq -nc --arg p "Explain quantum computing" --arg prov "$PROVIDER" --arg m "$MODEL" '{
prompt: $p,
skip_questions: true,
provider: ($prov // empty | select(. != "")),
model: ($m // empty | select(. != ""))
}')")
if echo "$RESPONSE" | grep -q '"success":true'; then
echo "✓ Prompt submission works"
echo "$RESPONSE" | grep -o '"refined_prompt":"[^"]*"' | head -c 100
echo ""
else
echo "✗ Prompt submission failed"
echo "$RESPONSE"
exit 1
fi
- name: Test web API - Get history
run: |
RESPONSE=$(curl -s http://localhost:8000/api/history)
if echo "$RESPONSE" | grep -q '"entries"'; then
TOTAL=$(echo "$RESPONSE" | grep -o '"total":[0-9]*' | grep -o '[0-9]*')
echo "✓ History endpoint works (found $TOTAL entries)"
else
echo "✗ History endpoint failed"
echo "$RESPONSE"
exit 1
fi
- name: Test web API - Stream endpoint
run: |
# Use hardcoded test defaults (works with both act and GitHub Actions)
PROVIDER="anthropic"
MODEL_Q="&model=claude-haiku-4-5"
# Test streaming endpoint with retry logic (up to 3 attempts)
MAX_ATTEMPTS=3
ATTEMPT=1
SUCCESS=false
while [ $ATTEMPT -le $MAX_ATTEMPTS ] && [ "$SUCCESS" = "false" ]; do
echo "Attempt $ATTEMPT of $MAX_ATTEMPTS: Testing stream endpoint..."
# Increase timeout to 20 seconds for more reliability
RESPONSE=$(curl -s --max-time 20 -N "http://localhost:8000/api/prompt/stream?prompt=Explain%20Python&skip_questions=true&provider=${PROVIDER}${MODEL_Q}" | head -c 1000 || true)
# Check if we got any streaming data
if [ -n "$RESPONSE" ] && (echo "$RESPONSE" | grep -q '"type".*"token"\|data:'); then
echo "✓ Stream endpoint works"
echo "$RESPONSE" | head -c 200
echo ""
SUCCESS=true
else
echo "⚠ Attempt $ATTEMPT failed (response length: ${#RESPONSE})"
if [ $ATTEMPT -lt $MAX_ATTEMPTS ]; then
echo " Retrying in 2 seconds..."
sleep 2
fi
ATTEMPT=$((ATTEMPT + 1))
fi
done
if [ "$SUCCESS" = "false" ]; then
echo "✗ Stream endpoint failed after $MAX_ATTEMPTS attempts"
echo "Last response: $RESPONSE" | head -c 500
exit 1
fi
- name: Test web UI - Homepage
run: |
RESPONSE=$(curl -s http://localhost:8000/)
if echo "$RESPONSE" | grep -q "Promptheus\|alchemical\|prompt"; then
echo "✓ Web UI loads correctly"
echo "$RESPONSE" | grep -o '<title>[^<]*</title>'
else
echo "✗ Web UI failed to load"
echo "$RESPONSE" | head -20
exit 1
fi
- name: Test web API - Error handling
run: |
# Test with invalid prompt (empty)
RESPONSE=$(curl -s -X POST http://localhost:8000/api/prompt/submit \
-H "Content-Type: application/json" \
-d '{"prompt": "", "skip_questions": true}')
# Should either succeed with empty or fail gracefully
if echo "$RESPONSE" | grep -q '"success"'; then
echo "✓ Error handling works (gracefully handled empty prompt)"
else
echo "⚠ Warning: Unexpected response for empty prompt (this may be expected)"
echo "$RESPONSE" | head -c 200
fi
- name: Check container logs
if: failure()
run: |
echo "=== Container Logs ==="
docker logs promptheus-test || echo "No container logs available"
- name: Cleanup
if: always()
run: |
docker stop promptheus-test 2>/dev/null || true
docker rm promptheus-test 2>/dev/null || true
- name: Summary
if: success()
run: |
echo "=== All Tests Passed ✓ ==="
echo ""
echo "Tests completed:"
echo " ✓ Docker image builds successfully"
echo " ✓ CLI version works with multiple prompts"
echo " ✓ Web server starts and responds"
echo " ✓ All API endpoints functional"
echo " ✓ Web UI loads correctly"
echo " ✓ Error handling works properly"