CI / CI (pull_request) Failing after 3m38s
Implement Kubernetes-native CI/CD with Tekton Pipelines: ARCHITECTURE: - Tekton Task: Runs integration tests in container - Tekton Pipeline: Orchestrates test execution - ArgoCD Application: Manages Tekton installation - CI: Triggers PipelineRun, reads results, promotes image FLOW: 1. CI builds image:sha 2. CI creates PipelineRun with new image 3. Tekton controller watches PipelineRun 4. Task executes integration tests 5. Results written to PipelineRun status 6. CI reads status, promotes to :latest if pass 7. ArgoCD detects :latest change and deploys BENEFITS: ✓ Kubernetes-native (CRDs, no external dependencies) ✓ DRY (parameterized Task/Pipeline) ✓ SOLID (single responsibility, clean interfaces) ✓ GitOps (Tekton managed by ArgoCD) ✓ Observable (logs, status, results) ✓ Secure (non-root, resource limits) FILES: - k8s/tekton/task-integration-test.yaml: Task definition - k8s/tekton/pipeline-integration-test.yaml: Pipeline definition - k8s/tekton/kustomization.yaml: Kustomize management - k8s/tekton/README.md: Documentation - k8s/argocd-apps/tekton.yaml: ArgoCD Application - .gitea/workflows/ci.yaml: Updated CI to use Tekton NEXT: 1. Merge PR 2. ArgoCD syncs and installs Tekton 3. First git push triggers PipelineRun 4. Integration tests run in cluster 5. Results feedback to CI
138 lines
4.6 KiB
YAML
138 lines
4.6 KiB
YAML
name: CI
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
REGISTRY: forgejo.riotpiao.com
|
|
IMAGE: forgejo.riotpiao.com/rock/api-gateway
|
|
DOCKER_HOST: tcp://localhost:2375
|
|
|
|
jobs:
|
|
ci:
|
|
name: CI
|
|
runs-on: golang
|
|
steps:
|
|
- name: Install Node.js and Docker
|
|
run: |
|
|
apt-get update
|
|
apt-get install -y nodejs docker.io
|
|
|
|
- name: Checkout code
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Go vet
|
|
run: go vet ./...
|
|
|
|
- name: Go test
|
|
run: go test ./...
|
|
|
|
- name: Get short SHA
|
|
id: sha
|
|
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
|
|
|
- name: Registry login
|
|
run: |
|
|
echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY}" \
|
|
--username "${REGISTRY_USER}" --password-stdin
|
|
env:
|
|
REGISTRY_USER: ${{ secrets.FORGEJO_REGISTRY_USER }}
|
|
REGISTRY_TOKEN: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
|
|
|
|
- name: Build Docker image
|
|
run: |
|
|
docker build --no-cache \
|
|
-t "${IMAGE}:${{ steps.sha.outputs.short_sha }}" \
|
|
-f Dockerfile .
|
|
echo "Built image: ${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
|
|
|
- name: Push test image (SHA tag only, not latest yet)
|
|
run: |
|
|
docker push "${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
|
echo "✓ Pushed test image: ${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
|
|
|
- name: Setup kubeconfig for Tekton trigger
|
|
run: |
|
|
mkdir -p ~/.kube
|
|
echo "${KUBECONFIG_B64}" | base64 -d > ~/.kube/config
|
|
env:
|
|
KUBECONFIG_B64: ${{ secrets.KUBECONFIG_B64 }}
|
|
continue-on-error: true
|
|
|
|
- name: Trigger integration tests via Tekton PipelineRun
|
|
run: |
|
|
echo "Triggering integration tests via Tekton..."
|
|
|
|
# Create PipelineRun to run integration tests
|
|
kubectl create -f - << 'YAML'
|
|
apiVersion: tekton.dev/v1
|
|
kind: PipelineRun
|
|
metadata:
|
|
name: integration-test-${{ steps.sha.outputs.short_sha }}
|
|
namespace: api
|
|
labels:
|
|
pr-id: "${{ github.event.pull_request.number || 'main' }}"
|
|
commit-sha: "${{ steps.sha.outputs.short_sha }}"
|
|
spec:
|
|
pipelineRef:
|
|
name: integration-test-pipeline
|
|
params:
|
|
- name: image
|
|
value: ${IMAGE}:${{ steps.sha.outputs.short_sha }}
|
|
- name: test-timeout
|
|
value: "5m"
|
|
YAML
|
|
|
|
echo "✓ PipelineRun created: integration-test-${{ steps.sha.outputs.short_sha }}"
|
|
|
|
# Wait for PipelineRun completion
|
|
echo "Waiting for tests to complete (max 10 minutes)..."
|
|
kubectl wait --for=condition=Succeeded \
|
|
pipelineruns/integration-test-${{ steps.sha.outputs.short_sha }} \
|
|
-n api --timeout=10m 2>/dev/null || \
|
|
kubectl wait --for=condition=Failed \
|
|
pipelineruns/integration-test-${{ steps.sha.outputs.short_sha }} \
|
|
-n api --timeout=1s 2>/dev/null || true
|
|
|
|
# Get test results
|
|
echo ""
|
|
echo "=== Test Results ==="
|
|
RESULT=$(kubectl get pipelinerun integration-test-${{ steps.sha.outputs.short_sha }} \
|
|
-n api -o jsonpath='{.status.conditions[0].reason}')
|
|
TEST_MESSAGE=$(kubectl get pipelinerun integration-test-${{ steps.sha.outputs.short_sha }} \
|
|
-n api -o jsonpath='{.status.taskRuns[*].status.taskResults[?(@.name=="result")].value}')
|
|
|
|
echo "PipelineRun Status: $RESULT"
|
|
echo "Test Result: $TEST_MESSAGE"
|
|
|
|
# Get logs
|
|
echo ""
|
|
echo "=== Test Logs ==="
|
|
kubectl logs -n api pipelinerun/integration-test-${{ steps.sha.outputs.short_sha }} || true
|
|
|
|
# Determine if tests passed
|
|
if [ "$RESULT" = "Succeeded" ]; then
|
|
echo "✓ Integration tests PASSED"
|
|
exit 0
|
|
else
|
|
echo "✗ Integration tests FAILED"
|
|
exit 1
|
|
fi
|
|
continue-on-error: false
|
|
|
|
- name: Promote image to latest (only if tests passed)
|
|
if: success()
|
|
run: |
|
|
docker pull "${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
|
docker tag "${IMAGE}:${{ steps.sha.outputs.short_sha }}" "${IMAGE}:latest"
|
|
docker push "${IMAGE}:latest"
|
|
echo "✓ Promoted ${IMAGE}:${{ steps.sha.outputs.short_sha }} to latest"
|
|
|
|
- name: Cleanup
|
|
if: always()
|
|
run: docker image prune -a --force 2>&1 | tail -3 || true
|