Skip to content

jac-gpt-fullstack Integration Test #710

jac-gpt-fullstack Integration Test

jac-gpt-fullstack Integration Test #710

name: jac-gpt-fullstack Integration Test
on:
schedule:
- cron: '0 0,6,12,18 * * *'
push:
branches:
- main
paths:
- 'jac-gpt-fullstack/**'
- '.github/workflows/jac-gpt-integration-test.yml'
pull_request:
branches:
- main
paths:
- 'jac-gpt-fullstack/**'
- '.github/workflows/jac-gpt-integration-test.yml'
workflow_dispatch:
inputs:
jac_release:
description: 'jaseci release tag to test against (dev = rolling build of main)'
required: false
default: 'dev'
permissions:
contents: read
jobs:
integration-test:
name: Server Start Test (jaseci dev/main)
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout Agentic-AI
uses: actions/checkout@v4
- name: Set up Node.js 20
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Set up Bun
uses: oven-sh/setup-bun@v2
# jaclang ships as a self-contained native binary (bundled CPython + bun),
# not a pip package, so there is nothing to `pip install`. The `dev` release
# is a prebuilt rolling build of main -- download it directly (seconds)
# instead of compiling from source with Zig (~34 min cold on every run,
# since a cross-repo cache goes cold whenever jaseci touches jaclang).
- name: Install jac binary (prebuilt dev build of main)
env:
JAC_RELEASE: ${{ github.event.inputs.jac_release || 'dev' }}
run: |
set -euo pipefail
ASSET="jac-${JAC_RELEASE}-linux-x86_64"
BASE="https://github.com/jaseci-labs/jaseci/releases/download/${JAC_RELEASE}"
mkdir -p "$HOME/.jacbin"
cd "$HOME/.jacbin"
echo "Downloading ${ASSET} from ${BASE}..."
curl -fsSL -o "${ASSET}" "${BASE}/${ASSET}"
curl -fsSL -o "${ASSET}.sha256" "${BASE}/${ASSET}.sha256"
sha256sum -c "${ASSET}.sha256"
mv "${ASSET}" jac
chmod +x jac
echo "$HOME/.jacbin" >> "$GITHUB_PATH"
# The binary bundles jaclang (incl. the folded-in client + byllm + scale),
# but the heavy runtime capability closures install separately, exactly as
# jaseci's own CI does. Pins mirror jac/jaclang/project/capabilities.jac.
- name: Install serve capability deps (for `jac start`)
run: |
jac install \
"fastapi>=0.121.3,<0.122.0" "uvicorn[standard]>=0.38.0,<0.39.0" \
"pyjwt>=2.10.1,<2.11.0" "fastapi-sso>=0.21.0,<1.0.0" \
"python-multipart>=0.0.21,<1.0.0" "bcrypt>=4.0.0,<5.0.0" \
"aiohttp>=3.9.0,<4.0.0" "sqlalchemy>=2.0.0,<3.0.0" \
"email-validator>=2.3.0,<3.0.0" "python-dotenv>=1.2.1,<2.0.0" \
"requests>=2.32.0,<3.0.0" \
--global
- name: Install byllm capability deps (for `by llm()`)
run: |
jac install \
"litellm>=1.70.0,<=1.82.6" "pillow>=12.0.0,<13.0.0" \
"httpx>=0.27.0" "loguru>=0.7.2,<0.8.0" \
--global
- name: Install app dependencies
working-directory: jac-gpt-fullstack
run: jac install
- name: Restore FAISS index cache
uses: actions/cache@v4
with:
path: jac-gpt-fullstack/services/faiss_index
key: jac-gpt-faiss-v1
- name: Install Playwright dependencies
# --global puts playwright in the binary's own site so the e2e (run from
# the project dir) can import it; a plain install would land in the
# project venv instead.
run: |
jac install playwright --global
jac -m playwright install chromium --with-deps
- name: Verify installation
run: |
echo "=== Jac Version ==="
jac --version
echo "=== Plugins ==="
jac plugins list
JAC_VERSION="$(jac --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
echo "JAC_VERSION=${JAC_VERSION:-unknown}" >> "$GITHUB_ENV"
- name: Run jac check
working-directory: jac-gpt-fullstack
run: jac check main.jac
- name: Start server in background
working-directory: jac-gpt-fullstack
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
MODEL: gemini/gemini-2.0-flash
run: |
timeout 600 jac start main.jac > /tmp/jac-server.log 2>&1 &
SERVER_PID=$!
echo "SERVER_PID=$SERVER_PID" >> $GITHUB_ENV
echo "Server starting with PID $SERVER_PID..."
sleep 10
if ! kill -0 $SERVER_PID 2>/dev/null; then
echo "Server process died during startup"
cat /tmp/jac-server.log
exit 1
fi
- name: Wait for server to be ready
run: |
echo "Waiting for server on port 8000..."
for i in $(seq 1 24); do
if ! kill -0 ${{ env.SERVER_PID }} 2>/dev/null; then
echo "Server process exited unexpectedly"
cat /tmp/jac-server.log
exit 1
fi
if curl -sf --max-time 10 http://localhost:8000 -o /dev/null 2>/dev/null; then
echo "Server is ready (attempt $i)"
exit 0
fi
echo "Attempt $i/24: not ready, waiting 15s..."
sleep 15
done
echo "Server failed to respond after 24 attempts"
tail -100 /tmp/jac-server.log
exit 1
- name: Verify HTTP response
run: |
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 15 http://localhost:8000)
echo "Root endpoint: HTTP $HTTP_CODE"
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 500 ]; then
echo "Server responding correctly"
else
echo "Unexpected HTTP $HTTP_CODE"
exit 1
fi
- name: Run E2E tests
working-directory: jac-gpt-fullstack
env:
SERVER_URL: http://localhost:8000
# Run from the project dir so the binary loads jac-gpt's deps; the binary
# provides jaclang + pytest (system pytest has neither).
run: jac test tests/test_e2e.jac -vv
- name: Stop server
if: always()
run: |
if [ -n "${{ env.SERVER_PID }}" ]; then
kill ${{ env.SERVER_PID }} 2>/dev/null || true
sleep 3
kill -9 ${{ env.SERVER_PID }} 2>/dev/null || true
fi
- name: Upload server logs
if: always()
uses: actions/upload-artifact@v4
with:
name: jac-server-logs
path: /tmp/jac-server.log
retention-days: 7
- name: Upload E2E screenshots
if: always()
uses: actions/upload-artifact@v4
with:
name: e2e-screenshots
path: jac-gpt-fullstack/tests/screenshots/
retention-days: 7
- name: Job summary
if: always()
run: |
echo "## jac-gpt-fullstack Integration Test" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "| Detail | Value |" >> $GITHUB_STEP_SUMMARY
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| **Jac version** | \`${{ env.JAC_VERSION }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| **jac release** | \`${{ github.event.inputs.jac_release || 'dev' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| **Status** | \`${{ job.status }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| **Trigger** | \`${{ github.event_name }}\` |" >> $GITHUB_STEP_SUMMARY