CI / CI (pull_request) Failing after 2m56s
RATIONALE: Gitea CI runner is running IN-CLUSTER, so we should use Kubernetes' built-in in-cluster authentication mechanism instead of storing kubeconfig secrets. IN-CLUSTER AUTHENTICATION: - Kubernetes automatically mounts service account token - Location: /var/run/secrets/kubernetes.io/serviceaccount/token - Location: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - kubectl automatically detects and uses these - No need to pass credentials via secrets CHANGES: 1. Remove KUBECONFIG_B64 secret requirement 2. Add in-cluster auth detection step 3. Update Job to use actual built image (not golang base) 4. Job uses imagePullSecrets for registry auth (can be encrypted with SOPS) 5. Add regcred image pull secret reference CI FLOW: 1. Detect in-cluster authentication is available 2. kubectl commands automatically use mounted service account 3. No secrets needed in CI env vars 4. Job applies with RBAC service account 5. Registry credentials via imagePullSecrets (encrypted with SOPS) SECURITY: ✓ In-cluster auth is more secure (bound to service account) ✓ No kubeconfig stored in secrets ✓ Sensitive data encrypted with SOPS ✓ Principle of least privilege (service account RBAC)
127 lines
4.4 KiB
YAML
127 lines
4.4 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: Detect in-cluster Kubernetes authentication
|
|
run: |
|
|
# When running inside K8s cluster, kubectl auto-detects service account
|
|
# Mounted at: /var/run/secrets/kubernetes.io/serviceaccount/
|
|
if [ -f /var/run/secrets/kubernetes.io/serviceaccount/token ]; then
|
|
echo "✓ In-cluster authentication detected"
|
|
export KUBECONFIG=/dev/null # kubectl will auto-use in-cluster auth
|
|
else
|
|
echo "⚠ Not running in-cluster, kubectl may fail"
|
|
fi
|
|
|
|
- name: Run integration tests via Kubernetes Job
|
|
run: |
|
|
echo "Running integration tests via Kubernetes Job..."
|
|
echo "Test image: ${IMAGE}:${{ steps.sha.outputs.short_sha }}"
|
|
|
|
# Apply job template from repo (uses in-cluster auth automatically)
|
|
kubectl apply -f k8s/integration-test-job.yaml
|
|
|
|
# Update job to use new image
|
|
kubectl set image job/api-gateway-integration-test \
|
|
integration-tester="${IMAGE}:${{ steps.sha.outputs.short_sha }}" \
|
|
-n api --record
|
|
|
|
# Wait for job to complete (max 10 minutes)
|
|
echo "Waiting for job to complete (this may take a few minutes)..."
|
|
kubectl wait --for=condition=complete job/api-gateway-integration-test \
|
|
-n api --timeout=10m 2>/dev/null || true
|
|
|
|
# Stream logs
|
|
echo ""
|
|
echo "=== Job Logs ==="
|
|
kubectl logs -n api job/api-gateway-integration-test --all-containers=true --timestamps=true || echo "No logs available"
|
|
echo "================"
|
|
echo ""
|
|
|
|
# Check if job succeeded
|
|
SUCCEEDED=$(kubectl get job api-gateway-integration-test -n api -o jsonpath='{.status.succeeded}' 2>/dev/null || echo "0")
|
|
FAILED=$(kubectl get job api-gateway-integration-test -n api -o jsonpath='{.status.failed}' 2>/dev/null || echo "0")
|
|
|
|
echo "Job Status: Succeeded=$SUCCEEDED, Failed=$FAILED"
|
|
|
|
if [ "$SUCCEEDED" = "1" ]; 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 integration test job
|
|
if: always()
|
|
run: |
|
|
echo "Cleaning up test job..."
|
|
kubectl delete job api-gateway-integration-test -n api --ignore-not-found=true
|
|
continue-on-error: true
|
|
|
|
- name: Cleanup docker
|
|
if: always()
|
|
run: docker image prune -a --force 2>&1 | tail -3 || true
|