Add K8s app deployment, Dockerfile, and CI workflow (Option A)

This commit is contained in:
Story Crater Bot
2026-08-23 00:01:30 -07:00
parent 9ca988aeb3
commit eaed7fc42a
8 changed files with 272 additions and 1 deletions
+28
View File
@@ -0,0 +1,28 @@
# Build artifacts
target/
*.rs.bk
# Version control
.git/
.gitignore
# IDE
.idea/
.vscode/
*.swp
# CI
.github/
.forgejo/
# Documentation
*.md
!README.md
# Tests (keep for build cache, exclude from runtime)
tests/
fixtures/
# Logs
log/
*.log
+61
View File
@@ -0,0 +1,61 @@
name: Build and Push
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: forgejo.riotpiao.com
IMAGE_NAME: rock/poimen-memory
jobs:
test:
name: Test
runs-on: rust
steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --workspace
- name: Test
run: cargo test --all
build:
name: Build Image
runs-on: rust
needs: test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=raw,value=latest
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
+50
View File
@@ -0,0 +1,50 @@
# Build stage
FROM rust:1.82-slim-bookworm AS builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY crates ./crates
# Build release binary
RUN cargo build --release --bin mem
# Runtime stage
FROM debian:bookworm-slim
WORKDIR /app
# Install runtime dependencies
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
# Copy binary from builder
COPY --from=builder /app/target/release/mem /usr/local/bin/mem
# Copy templates and queries
COPY templates ./templates
COPY queries ./queries
# Create non-root user
RUN useradd -r -u 1000 memuser
USER memuser
# Default port
EXPOSE 8080
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
# Default command: start HTTP server
ENTRYPOINT ["mem"]
CMD ["serve", "--port", "8080"]
+1 -1
View File
@@ -48,7 +48,7 @@ pub async fn start_server(port: u16, api_key: String) -> Result<()> {
.route("/memory/projects", web::get().to(projects_handler))
.route("/memory/projects/{id}/status", web::get().to(project_status))
})
.bind(("127.0.0.1", port))?
.bind(("0.0.0.0", port))?
.run()
.await?;
+95
View File
@@ -0,0 +1,95 @@
# Poimen Memory API Server
# Serves 7 HTTP endpoints for memory ingest, query, and management.
# Connects to memory-db (pgvector) for persistent storage.
apiVersion: apps/v1
kind: Deployment
metadata:
name: poimen-memory
namespace: poimen
labels:
app.kubernetes.io/name: poimen-memory
app.kubernetes.io/component: api-server
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: poimen-memory
template:
metadata:
labels:
app.kubernetes.io/name: poimen-memory
spec:
containers:
- name: memory
image: forgejo.riotpiao.com/rock/poimen-memory:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
name: http
env:
# Database connection (from CNPG auto-generated secret)
- name: DATABASE_HOST
value: "memory-db-rw.poimen.svc.cluster.local"
- name: DATABASE_PORT
value: "5432"
- name: DATABASE_NAME
value: "memory"
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: memory-db-app
key: username
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: memory-db-app
key: password
- name: DATABASE_URL
value: "postgresql://$(DATABASE_USER):$(DATABASE_PASSWORD)@$(DATABASE_HOST):$(DATABASE_PORT)/$(DATABASE_NAME)?sslmode=disable"
# LLM Gateway API key
- name: MEM_API_KEY
valueFrom:
secretKeyRef:
name: poimen-memory-secrets
key: llm-api-key
# Server config
- name: MEM_PORT
value: "8080"
- name: MEM_HOME
value: "/data"
args:
- serve
- --port
- "8080"
- --api-key
- "$(MEM_API_KEY)"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 10
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
emptyDir: {}
# Tolerate control-plane nodes
tolerations:
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
+8
View File
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: poimen
resources:
- deployment.yaml
- service.yaml
# Secret managed separately (SealedSecret in homelab)
# - secrets.yaml
+12
View File
@@ -0,0 +1,12 @@
# Poimen Memory Secrets
# NOTE: In production, use SealedSecrets or ExternalSecrets.
# This is a placeholder - actual secret should be in homelab/k8s/argocd/secrets/
apiVersion: v1
kind: Secret
metadata:
name: poimen-memory-secrets
namespace: poimen
type: Opaque
stringData:
# LLM Gateway API key (Kong gateway)
llm-api-key: "REPLACE_WITH_ACTUAL_KEY"
+17
View File
@@ -0,0 +1,17 @@
# Poimen Memory API Service
apiVersion: v1
kind: Service
metadata:
name: poimen-memory
namespace: poimen
labels:
app.kubernetes.io/name: poimen-memory
spec:
type: ClusterIP
ports:
- port: 8080
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: poimen-memory