feat: Tekton-based integration testing (proper K8s CI/CD)
CI / CI (pull_request) Canceled after 41s

Replace ad-hoc K8s Job with proper Tekton TaskRun:

k8s/tekton/integration-test-task.yaml:
  - Tekton Task for integration testing
  - Two stages: migrate + test
  - Runs existing Rust integration tests:
    * it_phase3_phase4 (ingest + persistence)
    * it_unified_query_4_6 (query endpoint)
    * it_temporal_filtering_4_2_fixed (temporal)
    * mem_ingest (extraction pipeline)
    * mem_cli::query (query handler)
  - Reports results to /tekton/results/summary
  - Resource limits: 1Gi mem, 500m CPU

.gitea/workflows/build.yaml:
  - Integrated Tekton trigger after image push
  - Create TaskRun with image SHA
  - Wait for completion (5m timeout)
  - Gate image promotion on test passing
  - Only promote to :latest if tests pass

Pattern (from homelab-frontend):
  1. Build image → push with SHA
  2. Trigger Tekton TaskRun
  3. Wait for result
  4. Gate promotion
  5. Promote to :latest only if tests pass

Benefits:
  ✓ Proper K8s CI/CD framework
  ✓ Reusable Task
  ✓ Better logging/results
  ✓ Proper resource mgmt
  ✓ Matches homelab pattern

Requires:
  - Tekton Pipelines installed in cluster
  - KUBECONFIG_B64 secret in Forgejo
This commit is contained in:
2026-09-14 23:00:57 +09:00
parent ce6c93d3b5
commit a72719a68f
6 changed files with 244 additions and 328 deletions
+150
View File
@@ -0,0 +1,150 @@
---
# Tekton Task: Integration Tests for Poimen Memory Service
#
# Executes:
# 1. Database migrations
# 2. Integration test suites (cargo test)
# 3. Reports results
#
# Parameters:
# - image: Docker image with SHA to test
#
# Results:
# - summary: Test summary (pass/fail + count)
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: poimen-integration-test
namespace: poimen
spec:
params:
- name: image
type: string
description: "Docker image SHA to test (e.g., forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:abc123)"
results:
- name: summary
description: "Test summary: PASS or FAIL + test count"
steps:
# Step 1: Apply database migrations
- name: migrate
image: $(params.image)
env:
- name: DB_HOST
value: "memory-db-rw.poimen.svc.cluster.local"
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: "memory"
- name: DB_USER
value: "app"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: memory-db-app
key: password
script: |
#!/bin/bash
set -e
echo "=========================================="
echo "Step 1: Database Migrations"
echo "=========================================="
echo ""
# Run migrations
/app/migrations/run_migrations.sh
echo ""
echo "✓ Migrations complete"
# Step 2: Run integration tests
- name: test
image: $(params.image)
env:
- name: DATABASE_URL
value: "postgresql://[email protected]:5432/memory"
- name: RUST_LOG
value: "info,mem_cli=debug,mem_ingest=debug,mem_store=debug"
- name: MEM_AUTH_MODE
value: "none"
- name: SQLX_OFFLINE
value: "true"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: memory-db-app
key: password
script: |
#!/bin/bash
set -e
echo "=========================================="
echo "Step 2: Integration Tests"
echo "=========================================="
echo ""
TEST_SUITES=(
"it_phase3_phase4"
"it_unified_query_4_6"
"it_temporal_filtering_4_2_fixed"
)
PASSED=0
FAILED=0
for suite in "${TEST_SUITES[@]}"; do
echo "Running: $suite"
if cargo test --test "$suite" --lib 2>&1 | tail -50; then
((PASSED++))
echo "✓ $suite passed"
else
((FAILED++))
echo "✗ $suite failed"
fi
echo ""
done
# Run unit tests
echo "Running unit tests..."
if cargo test --lib mem_ingest 2>&1 | tail -100; then
echo "✓ mem_ingest passed"
else
((FAILED++))
echo "✗ mem_ingest failed"
fi
echo ""
if cargo test --lib mem_cli::query 2>&1 | tail -100; then
echo "✓ mem_cli::query passed"
else
((FAILED++))
echo "✗ mem_cli::query failed"
fi
echo ""
echo "=========================================="
echo "Test Summary: $PASSED passed, $FAILED failed"
echo "=========================================="
if [ $FAILED -eq 0 ]; then
echo "PASS: All integration tests passed"
echo "PASS: All integration tests passed" > /tekton/results/summary
exit 0
else
echo "FAIL: $FAILED test suite(s) failed"
echo "FAIL: $FAILED test suite(s) failed" > /tekton/results/summary
exit 1
fi
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
-23
View File
@@ -1,23 +0,0 @@
apiVersion: ENC[AES256_GCM,data:rSo=,iv:bdZ6ucHQdbMkAYckaHgPX1O37sNpRzemzgtZWnNvuyc=,tag:NnqNKDxkgVuMSJCjUz9d/A==,type:str]
kind: ENC[AES256_GCM,data:i8C5n+0g,iv:1hgoEM2lCfFJybqqu+LKLcPb0oDVBbZfaO4hNU2IHCM=,tag:DgArPgsw6T0CzbKVmkNFlQ==,type:str]
metadata:
name: ENC[AES256_GCM,data:hS5ed588kPm8qyKEk48JbnSAOA==,iv:Icy0jUqXw0kaeliFYReCrX/4CvJybWSALLt1vVOqDJ0=,tag:3eJJXmWynVA7ynRA7tIODw==,type:str]
namespace: ENC[AES256_GCM,data:TaDa/Qh4,iv:wQelDyrVDxNslhz7GBFA6LhziZ7jFUGMIzT4ymYolJI=,tag:rtZ755RHlseJvgWslzim1Q==,type:str]
type: ENC[AES256_GCM,data:FhwlDJfv,iv:5ne0JFyExRdmrhuG1A37FThKpFEhUhrJeFnFOvpgHcM=,tag:lQ/RbeQJ/x/3nnhKLcB20A==,type:str]
stringData:
DATABASE_URL: ENC[AES256_GCM,data:1OmlGtPPtpocOr1U9aW76+z20TKtGvC7M6IIEFmACjdhcascOoHuGAVWlUxjGDrqM6w5DF+zXvR43E49ZsSnTvorGH+abCIfn3SpsYo21YazgBKt3A/ewu2bnjIw/RPfJ6AB7FRPdg==,iv:A1eytAyxTH5u0Hy6kThxiuwweOozyE8fiXl1JdH6vD4=,tag:D5I5Eg2Zbivm12YCvgpPGw==,type:str]
sops:
age:
- enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLQXA5RWh3aEFCNDZGT3dR
L2FGckR3MGFodzRqUDRodDRHdTdUOWV0SGhVCk92bnl1SjdSQUl5QTFQanVRSzR1
SFp2MXhUbEdpUm1ES21mdHlPdHg2dlUKLS0tIFNjbXVHNHZONS9UZVNnU0IvQ1J5
clovQ0NRVytGcG1oaktWc25SVmhyK2cKZ11ZIXu3wEGUsuXkrwDG+jGjb6a9xrVc
1r8PWJYj5VwcT0HZO+le3A6wfmNZgCzZY6pIYE9rIHexUXcEUZiSug==
-----END AGE ENCRYPTED FILE-----
recipient: age1e5fq3hwxy78psus2nfvmtmua36g0u3suk78ephw6246l974d2utsvn0hla
lastmodified: "2026-09-14T13:48:10Z"
mac: ENC[AES256_GCM,data:aYO2ghlPJn5cq82i4hLBoAa4j5nxt4pekhoHB4OPAeZDbMXipgXa0Ha+HJtPreHh/w/6VaXnEGFtWujKHwvIoL8c5ffQK6Mqw9DSYVV0OnSFJ50/JgRvMLVFLqoqUBoiwQOyYopVjIEeqMFNslN7WvpsHCK9NRxgO1Klf97rE0w=,iv:gWlQ1VseNC/rxp7X/N8tTNRtTIckwMbrMNODQ1mHSj4=,tag:wxhucPCkXrhyvhfwwAgRbw==,type:str]
unencrypted_suffix: _unencrypted
version: 3.13.2
-171
View File
@@ -1,171 +0,0 @@
---
# Integration Test Job - Runs existing Rust integration tests in K8s
#
# Two-stage execution:
# 1. migrate: Apply database migrations
# 2. test: Run existing integration tests (cargo test)
#
# Tests executed:
# - it_phase3_phase4: Ingest + persistence tests
# - it_unified_query_4_6: Query endpoint tests
# - it_temporal_filtering_4_2_fixed: Temporal query tests
# - mem_ingest: Extraction pipeline tests
# - mem_cli::query: Query handler tests
apiVersion: batch/v1
kind: Job
metadata:
name: poimen-memory-integration-test
namespace: poimen
labels:
app: poimen-memory
test: integration
component: ci-cd
spec:
backoffLimit: 0
activeDeadlineSeconds: 600
ttlSecondsAfterFinished: 3600
template:
metadata:
labels:
app: poimen-memory
test: integration
spec:
serviceAccountName: memory-app
restartPolicy: Never
containers:
# Stage 1: Apply migrations
- name: migrate
image: forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:IMAGE_SHA
imagePullPolicy: IfNotPresent
command:
- /bin/bash
- -c
- |
set -e
echo "=========================================="
echo "Applying Database Migrations"
echo "=========================================="
echo ""
# Run migrations script
/app/migrations/run_migrations.sh
echo ""
echo "✓ Migrations complete"
env:
- name: DB_HOST
value: "memory-db-rw.poimen.svc.cluster.local"
- name: DB_PORT
value: "5432"
- name: DB_NAME
value: "memory"
- name: DB_USER
value: "app"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: memory-db-app
key: password
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
# Stage 2: Run integration tests
- name: test
image: forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:IMAGE_SHA
imagePullPolicy: IfNotPresent
command:
- /bin/bash
- -c
- |
set -e
echo "=========================================="
echo "Running Integration Tests"
echo "=========================================="
echo ""
# Run existing integration tests
echo "Test Suite 1: Ingest + Persistence (it_phase3_phase4)"
cargo test --test it_phase3_phase4 --lib 2>&1 | tail -50 || TEST_FAILED=1
echo ""
echo "Test Suite 2: Unified Query (it_unified_query_4_6)"
cargo test --test it_unified_query_4_6 --lib 2>&1 | tail -50 || TEST_FAILED=1
echo ""
echo "Test Suite 3: Temporal Filtering (it_temporal_filtering_4_2_fixed)"
cargo test --test it_temporal_filtering_4_2_fixed --lib 2>&1 | tail -50 || TEST_FAILED=1
echo ""
echo "Test Suite 4: Ingest Pipeline Unit Tests"
cargo test --lib mem_ingest 2>&1 | tail -100 || TEST_FAILED=1
echo ""
echo "Test Suite 5: Query Handler Tests"
cargo test --lib mem_cli::query 2>&1 | tail -100 || TEST_FAILED=1
echo ""
echo "=========================================="
echo "Integration Tests Complete"
echo "=========================================="
if [ -n "$TEST_FAILED" ]; then
echo "✗ Some tests failed"
exit 1
fi
echo "✓ All tests passed"
env:
- name: DATABASE_URL
value: "postgresql://[email protected]:5432/memory"
- name: RUST_LOG
value: "info,mem_cli=debug,mem_ingest=debug,mem_store=debug"
- name: MEM_AUTH_MODE
value: "none"
- name: SQLX_OFFLINE
value: "true"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: memory-db-app
key: password
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
livenessProbe:
exec:
command:
- /bin/sh
- -c
- test -f /proc/self/status
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: memory-app
namespace: poimen
labels:
app: poimen-memory