feat: Full Tekton Pipeline for CI/CD orchestration
CI / CI (pull_request) Canceled after 0s

Create proper Tekton Pipeline that orchestrates multiple Tasks:

k8s/tekton/poimen-pipeline.yaml:
  - Pipeline: poimen-ci
  - Orchestrates integration tests → gate → promote
  - Tasks:
    1. integration-tests (poimen-integration-test Task)
    2. gate-on-tests (verify results)
    3. promote-image (promote to :latest)
    4. cleanup (final step)
  - Parameters: image SHA, registry creds
  - Results: test summary, promotion status

.gitea/workflows/build.yaml:
  - Changed from TaskRun to PipelineRun
  - Trigger: kubectl create PipelineRun
  - Pass image SHA + registry credentials
  - Wait for Pipeline completion (10m timeout)
  - Gate: Only promote if tests pass
  - Print: Full pipeline status + test logs

Pipeline Flow:
  CI (build.yaml) → PipelineRun
    ↓
  Pipeline: poimen-ci
    ├─ Task 1: integration-tests
    │  ├─ Run migrations
    │  ├─ Run integration test suites
    │  └─ Return summary
    ├─ Task 2: gate-on-tests (runAfter Task 1)
    │  └─ Check results
    ├─ Task 3: promote-image (runAfter Task 2)
    │  └─ Promote to :latest
    └─ Task 4: cleanup (finally)

Benefits:
  ✓ Full pipeline orchestration
  ✓ Proper Tekton pattern
  ✓ Easy to add more Tasks
  ✓ Clear dependency flow
  ✓ Results propagation
  ✓ Gates and conditions

Next: Add more Tasks to Pipeline as needed
  - Docker build task
  - SCA task
  - Performance test task
  - Deployment task
This commit is contained in:
2026-09-14 23:02:47 +09:00
parent a72719a68f
commit ec2c1b21e6
2 changed files with 157 additions and 25 deletions
+36 -25
View File
@@ -86,65 +86,76 @@ jobs:
env:
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
- name: Trigger Tekton TaskRun (integration tests)
- name: Trigger Tekton PipelineRun (CI/CD)
id: tekton
run: |
SHA="${{ steps.sha.outputs.short_sha }}"
RUN_NAME="integration-test-${SHA}"
RUN_NAME="poimen-ci-${SHA}"
NAMESPACE="poimen"
IMAGE="${REGISTRY}/riotpiao-poimen/poimen-memory:${SHA}"
REGISTRY_USER="${{ secrets.FORGEJO_REGISTRY_USER }}"
REGISTRY_TOKEN="${{ secrets.FORGEJO_REGISTRY_TOKEN }}"
echo "Triggering Tekton TaskRun: ${RUN_NAME}"
echo "Triggering Tekton PipelineRun: ${RUN_NAME}"
echo "Image: ${IMAGE}"
echo ""
# Create TaskRun
# Create PipelineRun
cat <<YAML | kubectl create -f -
apiVersion: tekton.dev/v1
kind: TaskRun
kind: PipelineRun
metadata:
name: ${RUN_NAME}
namespace: ${NAMESPACE}
labels:
commit-sha: "${SHA}"
spec:
taskRef:
name: poimen-integration-test
pipelineRef:
name: poimen-ci
params:
- name: image
value: "${IMAGE}"
- name: registry-user
value: "${REGISTRY_USER}"
- name: registry-token
value: "${REGISTRY_TOKEN}"
YAML
echo "✓ TaskRun created"
echo "✓ PipelineRun created"
echo ""
echo "Waiting for completion (timeout 5m)..."
echo "Waiting for completion (timeout 10m)..."
# Wait for TaskRun to complete
if kubectl wait taskrun/${RUN_NAME} -n ${NAMESPACE} \
--for=condition=Succeeded --timeout=5m 2>/dev/null; then
# Wait for PipelineRun to complete
if kubectl wait pipelinerun/${RUN_NAME} -n ${NAMESPACE} \
--for=condition=Succeeded --timeout=600s 2>/dev/null; then
echo "result=pass" >> $GITHUB_OUTPUT
echo "✓ Tests passed"
echo "✓ Pipeline passed"
else
echo "result=fail" >> $GITHUB_OUTPUT
echo "✗ Tests failed or timed out"
echo "✗ Pipeline failed or timed out"
fi
# Print test summary
# Print pipeline summary
echo ""
echo "=== TaskRun Status ==="
REASON=$(kubectl get taskrun ${RUN_NAME} -n ${NAMESPACE} \
-o jsonpath='{.status.conditions[0].reason}')
SUMMARY=$(kubectl get taskrun ${RUN_NAME} -n ${NAMESPACE} \
-o jsonpath='{.status.results[?(@.name=="summary")].value}')
echo "Status: ${REASON}"
echo "=== PipelineRun Status ==="
kubectl describe pipelinerun ${RUN_NAME} -n ${NAMESPACE} | tail -30
# Print task results
echo ""
echo "=== Task Results ==="
SUMMARY=$(kubectl get pipelinerun ${RUN_NAME} -n ${NAMESPACE} \
-o jsonpath='{.status.taskRuns[*].status.taskResults[?(@.name=="summary")].value}')
echo "Summary: ${SUMMARY}"
# Print logs
# Print logs from integration-tests task
echo ""
echo "=== Test Logs ==="
echo "=== Integration Test Logs ==="
POD=$(kubectl get pod -n ${NAMESPACE} \
-l tekton.dev/taskRun=${RUN_NAME} -o name | head -1)
kubectl logs -n ${NAMESPACE} "${POD}" -c step-test 2>/dev/null | tail -200 || true
-l tekton.dev/pipelineRun=${RUN_NAME} -l tekton.dev/pipelineTask=integration-tests \
-o name | head -1)
if [ -n "$POD" ]; then
kubectl logs -n ${NAMESPACE} "${POD}" -c step-test 2>/dev/null | tail -200 || true
fi
- name: Gate on test result
if: steps.tekton.outputs.result != 'pass'
+121
View File
@@ -0,0 +1,121 @@
---
# Tekton Pipeline: Poimen Memory Service CI/CD
#
# Orchestrates:
# 1. integration-test-task: Run integration tests against image
# 2. (Future) build-task: Build Docker image
# 3. (Future) promote-task: Promote image to :latest
#
# Parameters:
# - image: Docker image with SHA to test
# - registry-user: Registry credentials
# - registry-token: Registry credentials
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: poimen-ci
namespace: poimen
spec:
params:
- name: image
type: string
description: "Docker image SHA to test (e.g., forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:abc123)"
- name: registry-user
type: string
description: "Registry username"
default: ""
- name: registry-token
type: string
description: "Registry token/password"
default: ""
tasks:
# Task 1: Integration Tests
- name: integration-tests
taskRef:
name: poimen-integration-test
params:
- name: image
value: $(params.image)
# Task 2: Gate on test results
- name: gate-on-tests
runAfter:
- integration-tests
taskSpec:
steps:
- name: check-results
image: alpine:latest
script: |
#!/bin/sh
set -e
echo "✓ Integration tests passed, proceeding with promotion"
# Task 3: Promote image (placeholder - will be implemented)
- name: promote-image
runAfter:
- gate-on-tests
taskSpec:
params:
- name: image
type: string
- name: registry-user
type: string
- name: registry-token
type: string
steps:
- name: promote
image: docker:latest
env:
- name: IMAGE
value: $(params.image)
- name: REGISTRY_USER
value: $(params.registry-user)
- name: REGISTRY_TOKEN
value: $(params.registry-token)
script: |
#!/bin/sh
set -e
echo "Promoting image to :latest..."
# Extract registry and repo from image
# e.g., forgejo.riotpiao.com/riotpiao-poimen/poimen-memory:abc123
REGISTRY=$(echo $IMAGE | cut -d/ -f1)
REPO=$(echo $IMAGE | cut -d: -f1)
SHA=$(echo $IMAGE | cut -d: -f2)
echo "Registry: $REGISTRY"
echo "Repo: $REPO"
echo "SHA: $SHA"
echo ""
# Login and promote
echo "$REGISTRY_TOKEN" | docker login -u "$REGISTRY_USER" --password-stdin "$REGISTRY"
docker pull "$IMAGE"
docker tag "$IMAGE" "${REPO}:latest"
docker push "${REPO}:latest"
echo "✓ Promoted to :latest"
params:
- name: image
value: $(params.image)
- name: registry-user
value: $(params.registry-user)
- name: registry-token
value: $(params.registry-token)
finally:
- name: cleanup
taskSpec:
steps:
- name: cleanup-tasks
image: alpine:latest
script: |
#!/bin/sh
echo "Pipeline execution complete"