Skip to content

Commit 4c136e4

Browse files
authored
Merge pull request #4 from constructive-io/d/function-testing-foundation
functions testing harness
2 parents 6b6fe47 + eb5a904 commit 4c136e4

69 files changed

Lines changed: 22415 additions & 113 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
packages
3+
dist
4+
.git
5+
.env

Makefile

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
.PHONY: build clean lint docker-build docker-build-simple-email docker-build-send-email-link docker-push docker-push-simple-email docker-push-send-email-link
1+
.PHONY: build clean lint test test-all build-test-runner docker-build docker-build-simple-email docker-build-send-email-link docker-push docker-push-simple-email docker-push-send-email-link
22

33
REGISTRY := ghcr.io/constructive-io/constructive-functions
4+
KIND_BIN ?= /opt/homebrew/bin/kind
5+
6+
SUBDIRS := functions/hello-world functions/simple-email functions/send-email-link functions/runtime-script
47

58
build:
6-
pnpm run build
9+
pnpm -r build
710

811
clean:
9-
pnpm run clean
12+
pnpm -r clean
1013

1114
lint:
12-
pnpm run lint
15+
pnpm -r lint
16+
17+
test:
18+
pnpm -r test
1319

20+
# Docker Build & Push (Restored)
1421
docker-build:
1522
@echo "Building Docker images for functions..."
1623
@for fn in functions/*; do \
@@ -40,3 +47,14 @@ docker-push-simple-email:
4047

4148
docker-push-send-email-link:
4249
docker push $(REGISTRY)/send-email-link:latest
50+
51+
# Kubernetes Test Runner
52+
test-k8s-all: build-test-runner
53+
@echo "Running All K8s Tests (Centralized Runner)..."
54+
# Run the centralized TS test runner
55+
npx ts-node scripts/test-runner.ts
56+
57+
build-test-runner:
58+
@echo "Building Shared Test Runner Image..."
59+
docker build -f functions/_runtimes/node/Dockerfile.test -t constructive/function-test-runner:v2 .
60+
$(KIND_BIN) load docker-image constructive/function-test-runner:v2 --name interweb-local
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Python runtime for LLM API inference (OpenAI & Claude)
2+
# This module makes API calls to OpenAI and Anthropic for LLM inference
3+
# For the full fat container with Ollama & local models, see Dockerfile.ollama
4+
# Based on: /Users/0xj0/Documents/projects/LQL/CONSTRUCTIVE/agentic-foundation
5+
6+
##################### heres what is had inside of (/Users/0xj0/Documents/projects/LQL/CONSTRUCTIVE/agentic-foundation) -- GO VERIFY YOURSELF
7+
8+
# Builder Stage
9+
FROM rust:latest as builder
10+
WORKDIR /app
11+
COPY . .
12+
# Build agent_core
13+
RUN cargo build --release --bin agent_core
14+
15+
# Runtime Stage - "Fat Container"
16+
FROM ubuntu:22.04
17+
WORKDIR /app
18+
19+
# Set non-interactive install
20+
ENV DEBIAN_FRONTEND=noninteractive
21+
22+
# 1. Install Basic Tools & Runtimes (Python, Node, System Utils)
23+
RUN apt-get update && apt-get install -y \
24+
curl wget git build-essential \
25+
python3 python3-pip python3-venv \
26+
nodejs npm \
27+
postgresql-14 postgresql-client-14 \
28+
sudo \
29+
libnss3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 \
30+
libxcomposite1 libxdamage1 libxfixes3 libxrandr2 libgbm1 libasound2 \
31+
chromium-browser \
32+
&& rm -rf /var/lib/apt/lists/*
33+
34+
# 2. Install Rust in Runtime (for the agent to use `cargo`)
35+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
36+
ENV PATH="/root/.cargo/bin:${PATH}"
37+
38+
# 3. Install PostGraphile
39+
RUN npm install -g postgraphile @graphile-contrib/pg-simplify-inflector
40+
41+
# 4. Install Ollama & Bake Models
42+
# We install Ollama, then start it in the background to pull models into the image layers.
43+
RUN curl -fsSL https://ollama.com/install.sh | sh
44+
45+
# Pre-pull Models (Using available equivalents for the '2025' spec models)
46+
# GPT-OSS -> llama3.2 (Small, open, robust)
47+
# Qwen3-VL -> llava (Vision model standard in Ollama)
48+
# Devstral -> qwen2.5-coder (Excellent coding model)
49+
# Nemotron -> mistral (Strong reasoning)
50+
RUN nohup bash -c "ollama serve" & \
51+
sleep 10 && \
52+
ollama pull llama3.2 && \
53+
ollama pull llava && \
54+
ollama pull qwen2.5-coder && \
55+
ollama pull mistral && \
56+
pkill ollama
57+
58+
# 5. Setup Data & Permissions
59+
RUN mkdir -p /var/lib/postgresql/data && chown -R postgres:postgres /var/lib/postgresql/data
60+
61+
# 6. Copy Binaries & Scripts
62+
COPY --from=builder /app/target/release/agent_core /app/agent_core
63+
COPY scripts/entrypoint.sh /app/entrypoint.sh
64+
RUN chmod +x /app/entrypoint.sh
65+
66+
# 7. Config
67+
ENV DATABASE_URL=postgres://agent:agent@localhost:5432/agentic
68+
ENV OLLAMA_HOST=0.0.0.0:11434
69+
70+
EXPOSE 3000 5432 11434 5000
71+
72+
ENTRYPOINT ["/app/entrypoint.sh"]
73+
CMD ["./agent_core"]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM node:22-alpine
2+
3+
WORKDIR /usr/src/app
4+
5+
COPY package.json ./
6+
7+
RUN npm install -g pnpm@10.12.2 && pnpm install --prod
8+
9+
COPY dist ./dist
10+
11+
ENV NODE_ENV=production
12+
ENV PORT=8080
13+
14+
USER node
15+
16+
CMD ["node", "dist/index.js"]
17+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
FROM node:20-alpine
2+
3+
# Install Postgres Client and Build Tools
4+
RUN apk add --no-cache postgresql-client bash make g++ python3 kubectl
5+
6+
COPY . /app
7+
WORKDIR /app
8+
9+
# Ensure clean slate
10+
RUN rm -rf node_modules
11+
12+
# 3. Install Dependencies from NPM
13+
RUN npm install -g pnpm@9 && pnpm install --no-frozen-lockfile
14+
15+
# 4. Build
16+
# 5. Install PGPM from NPM
17+
RUN npm install -g pgpm
18+
19+
# Run as postgres user to avoid 'role root does not exist' in pgsql-test
20+
# handle existing user/group if created by apk
21+
RUN (getent group postgres || addgroup -S postgres) && (getent passwd postgres || adduser -S postgres -G postgres)
22+
RUN chown -R postgres:postgres /app
23+
USER postgres
24+
ENV USER=postgres
25+
ENV PGUSER=postgres
26+
27+
# 6. Setup Entrypoint (Inlined for Minimalism)
28+
ENV NODE_ENV=test
29+
CMD ["/bin/bash", "-c", "set -e; \
30+
echo \"Waiting for Postgres at $PGHOST:$PGPORT...\"; \
31+
until pg_isready -h \"$PGHOST\" -p \"$PGPORT\" -U \"$PGUSER\"; do echo \"Waiting...\"; sleep 2; done; \
32+
echo \"Deploying Schema...\"; \
33+
pgpm deploy --package pgpm-database-jobs --database template1 --yes 2>/dev/null || echo \"Deploy continued...\"; \
34+
unset PGDATABASE; \
35+
pnpm test"]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# TODO: create a standard python function here that can run pytorch for me
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Multi-stage build for Rust functions
2+
FROM rust:1.83-alpine AS builder
3+
4+
WORKDIR /build
5+
6+
# Install build dependencies
7+
RUN apk add --no-cache musl-dev
8+
9+
# Copy dependency manifests first (for layer caching)
10+
COPY Cargo.toml Cargo.lock ./
11+
12+
# Create dummy src to build dependencies
13+
RUN mkdir src && echo "fn main() {}" > src/main.rs
14+
RUN cargo build --release --target x86_64-unknown-linux-musl
15+
RUN rm -rf src
16+
17+
# Copy actual source code
18+
COPY src ./src
19+
20+
# Build the actual binary
21+
RUN touch src/main.rs && cargo build --release --target x86_64-unknown-linux-musl
22+
23+
# Runtime stage - minimal Alpine image
24+
FROM alpine:3.19
25+
26+
WORKDIR /usr/src/app
27+
28+
# Copy the compiled binary from builder
29+
COPY --from=builder /build/target/x86_64-unknown-linux-musl/release/app ./app
30+
31+
# Create non-root user
32+
RUN addgroup -g 1000 appuser && \
33+
adduser -D -u 1000 -G appuser appuser && \
34+
chown -R appuser:appuser /usr/src/app
35+
36+
ENV PORT=8080
37+
38+
USER appuser
39+
40+
EXPOSE 8080
41+
42+
CMD ["./app"]

functions/hello-world/Makefile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
IMAGE_NAME ?= constructive/hello-world-test:v1
3+
KIND_CLUSTER_NAME ?= interweb-local
4+
KIND_BIN ?= $(shell which kind 2>/dev/null || echo "/opt/homebrew/bin/kind")
5+
6+
# Define Secrets and Env
7+
TEST_PGHOST ?= postgres
8+
TEST_PGPASSWORD ?= $(shell kubectl get secret --namespace default pg-credentials -o jsonpath="{.data.PGPASSWORD}" | base64 --decode)
9+
10+
.PHONY: vendor test clean test-k8s
11+
12+
test:
13+
pnpm test
14+
15+
clean:
16+
pnpm clean
17+
18+
# Test in K8s (In-Cluster)
19+
test-k8s:
20+
@echo "Running Generic Test Pattern for Hello World..."
21+
kubectl proxy --port=8001 > proxy.log 2>&1 & PID=$$!; \
22+
echo "Starting Proxy (PID: $$PID)..."; \
23+
sleep 2; \
24+
TEST_PGPASSWORD=$$(kubectl get secret pg-credentials -o jsonpath="{.data.PGPASSWORD}" | base64 --decode) \
25+
IMAGE_NAME="constructive/function-test-runner:v1" \
26+
IS_IN_POD="false" \
27+
PGHOST=$(TEST_PGHOST) \
28+
PGUSER=postgres \
29+
PGPASSWORD=$$TEST_PGPASSWORD \
30+
TEST_GRAPHQL_URL=$(TEST_GRAPHQL_URL) \
31+
npm test -- __tests__/index.test.ts || (echo "=== Proxy Logs ===" && cat proxy.log && kill $$PID && exit 1); \
32+
kill $$PID; \
33+
rm proxy.log

0 commit comments

Comments
 (0)