Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions .github/workflows/functional-tests.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ node_modules/
.yarn/
.parcel-cache/
*.tsbuildinfo
**/.ui-build-hash

# IDE / Tooling
.idea/
Expand Down
53 changes: 53 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
SHELL := /usr/bin/env bash

.PHONY: all install build test lint fmt tidy clean control-plane sdk-go sdk-python
.PHONY: test-functional test-functional-local test-functional-postgres test-functional-cleanup test-functional-ci

all: build

Expand Down Expand Up @@ -38,3 +39,55 @@ tidy:
clean:
rm -rf control-plane/bin control-plane/dist
find . -type d -name "__pycache__" -exec rm -rf {} +

# ============================================================================
# Functional Testing with Docker
# ============================================================================

test-functional: test-functional-local test-functional-postgres
@echo "✅ All functional tests completed"

test-functional-local:
@echo "🧪 Running functional tests with SQLite storage..."
@if [ -z "$$OPENROUTER_API_KEY" ]; then \
echo "❌ Error: OPENROUTER_API_KEY environment variable is not set"; \
echo " Please set it with: export OPENROUTER_API_KEY=your-key"; \
echo " Or use: make test-functional-local OPENROUTER_API_KEY=your-key"; \
exit 1; \
fi
cd tests/functional && \
docker compose -f docker/docker-compose.local.yml up --build --abort-on-container-exit --exit-code-from test-runner
$(MAKE) test-functional-cleanup-local

test-functional-postgres:
@echo "🧪 Running functional tests with PostgreSQL storage..."
@if [ -z "$$OPENROUTER_API_KEY" ]; then \
echo "❌ Error: OPENROUTER_API_KEY environment variable is not set"; \
echo " Please set it with: export OPENROUTER_API_KEY=your-key"; \
echo " Or use: make test-functional-postgres OPENROUTER_API_KEY=your-key"; \
exit 1; \
fi
cd tests/functional && \
docker compose -f docker/docker-compose.postgres.yml up --build --abort-on-container-exit --exit-code-from test-runner
$(MAKE) test-functional-cleanup-postgres

test-functional-cleanup: test-functional-cleanup-local test-functional-cleanup-postgres

test-functional-cleanup-local:
@echo "🧹 Cleaning up local test environment..."
cd tests/functional && docker compose -f docker/docker-compose.local.yml down -v 2>/dev/null || true

test-functional-cleanup-postgres:
@echo "🧹 Cleaning up postgres test environment..."
cd tests/functional && docker compose -f docker/docker-compose.postgres.yml down -v 2>/dev/null || true

test-functional-ci:
@echo "🧪 Running functional tests in CI mode..."
@if [ -z "$$OPENROUTER_API_KEY" ]; then \
echo "❌ Error: OPENROUTER_API_KEY environment variable is not set"; \
exit 1; \
fi
@echo "Running tests with both storage modes..."
$(MAKE) test-functional-local || ($(MAKE) test-functional-cleanup-local && exit 1)
$(MAKE) test-functional-postgres || ($(MAKE) test-functional-cleanup-postgres && exit 1)
@echo "✅ CI functional tests completed successfully"
11 changes: 9 additions & 2 deletions control-plane/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ The AgentField control plane orchestrates agent workflows, manages verifiable cr

```bash
# From the repository root
cd control-plane
go mod download
npm --prefix web/client install
cd web/client
npm install
npm run build
cd ../..

# Run database migrations (requires AGENTFIELD_DATABASE_URL)
goose -dir ./migrations postgres "$AGENTFIELD_DATABASE_URL" up
Expand All @@ -38,9 +42,12 @@ Sample config files live in `config/`.
## Web UI Development

```bash
cd web/client
cd control-plane/web/client
npm install
npm run dev
# Build production assets embedded in Go binaries
cd ../..
npm run build
```

Run the Go server alongside the UI so API calls resolve locally. During production builds the UI is embedded via Go's `embed` package.
Expand Down
5 changes: 5 additions & 0 deletions deployments/docker/Dockerfile.control-plane
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,13 @@ RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/g
if [ "${TARGETARCH}" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc; else export CC=gcc; fi && \
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -tags "embedded sqlite_fts5" -o /app/bin/agentfield-server ./cmd/agentfield-server

# Pre-create writable data directory for distroless runtime. The nonroot user
# has UID/GID 65532 in the base image, so match that here.
RUN mkdir -p /tmp/agentfield-data && chown 65532:65532 /tmp/agentfield-data

FROM gcr.io/distroless/base-debian12
COPY --from=go-builder /app/bin/agentfield-server /usr/local/bin/agentfield-server
COPY --from=go-builder /app/control-plane/config /etc/agentfield/config
COPY --from=go-builder --chown=nonroot:nonroot /tmp/agentfield-data /data
USER nonroot:nonroot
ENTRYPOINT ["/usr/local/bin/agentfield-server"]
43 changes: 43 additions & 0 deletions tests/functional/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# AgentField Functional Test Environment Variables
# =================================================
# Copy this file to .env and fill in your actual values:
# cp .env.example .env

# Required: OpenRouter API Key for LLM integration tests
# Get your key from: https://openrouter.ai/keys
OPENROUTER_API_KEY=your_openrouter_api_key_here

# Required: OpenRouter Model to use for tests
# IMPORTANT: All tests MUST use this variable, DO NOT hardcode models
# Default uses a cost-effective model for testing
# Other options: openrouter/openai/gpt-4o-mini, openrouter/anthropic/claude-3-haiku, etc.
OPENROUTER_MODEL=openrouter/google/gemini-2.5-flash-lite

# Optional: Storage mode for testing
# Options: local (SQLite) or postgres
# Default: local
# STORAGE_MODE=local

# Optional: AgentField control plane port
# Default: 8080
# AGENTFIELD_PORT=8080

# Optional: Test timeout in seconds
# Default: 300 (5 minutes)
# TEST_TIMEOUT=300

# Optional: Additional pytest arguments
# Examples:
# -v Verbose output
# -x Stop on first failure
# -k test_name Run specific test
# --tb=short Short traceback format
# PYTEST_ARGS=-v --tb=short

# Optional: Maximum wait time for services to be ready (in seconds)
# Default: 120
# MAX_WAIT_TIME=120

# Optional: Sleep interval between health checks (in seconds)
# Default: 2
# SLEEP_INTERVAL=2
28 changes: 28 additions & 0 deletions tests/functional/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Environment variables
.env

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python

# Test artifacts
.pytest_cache/
htmlcov/
.coverage
*.cover
.hypothesis/
junit-*.xml

# IDE
.vscode/
.idea/
*.swp
*.swo

# Logs
*.log
logs/

Loading
Loading