name: Build & Deploy to K3s on: push: branches: [main] env: REGISTRY: git.arthurbarre.fr WEB_IMAGE: git.arthurbarre.fr/ordinarthur/rebours-web REGISTRY_USER: ordinarthur jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Login to Gitea Container Registry run: | echo "${{ secrets.REGISTRY_PASSWORD }}" | \ docker login ${{ env.REGISTRY }} -u ${{ env.REGISTRY_USER }} --password-stdin - name: Build web image run: | docker build \ -f nextjs/Dockerfile \ -t ${{ env.WEB_IMAGE }}:${{ github.sha }} \ -t ${{ env.WEB_IMAGE }}:latest \ ./nextjs - name: Push web image run: | docker push ${{ env.WEB_IMAGE }}:${{ github.sha }} docker push ${{ env.WEB_IMAGE }}:latest - name: Install kubectl run: | curl -LO "https://dl.k8s.io/release/$(curl -Ls https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x kubectl mv kubectl /usr/local/bin/kubectl - name: Configure kubeconfig run: | mkdir -p ~/.kube echo "${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config - name: Apply namespace run: | kubectl apply -f k8s/namespace.yml - name: Tear down legacy workloads run: | # Old split-service topology (Astro SSR + Fastify API + nginx proxy). # Must run before applying new service.yml — old rebours-proxy used NodePort 30083. kubectl -n rebours delete deployment rebours-ssr rebours-api rebours-proxy --ignore-not-found kubectl -n rebours delete service rebours-ssr rebours-api rebours-proxy --ignore-not-found - name: Apply configmap + service run: | kubectl apply -f k8s/configmap.yml kubectl apply -f k8s/service.yml - name: Create image pull secret run: | kubectl -n rebours create secret docker-registry gitea-registry-secret \ --docker-server=${{ env.REGISTRY }} \ --docker-username=${{ env.REGISTRY_USER }} \ --docker-password="${{ secrets.REGISTRY_PASSWORD }}" \ --dry-run=client -o yaml | kubectl apply -f - - name: Create database secret run: | kubectl -n rebours create secret generic rebours-db-secret \ --from-literal=POSTGRES_DB="rebours" \ --from-literal=POSTGRES_USER="rebours" \ --from-literal=POSTGRES_PASSWORD="${{ secrets.POSTGRES_PASSWORD }}" \ --dry-run=client -o yaml | kubectl apply -f - - name: Create app secrets run: | kubectl -n rebours create secret generic rebours-secrets \ --from-literal=PAYLOAD_SECRET="${{ secrets.PAYLOAD_SECRET }}" \ --from-literal=DATABASE_URL="postgres://rebours:${{ secrets.POSTGRES_PASSWORD }}@rebours-postgres:5432/rebours" \ --from-literal=STRIPE_SECRET_KEY="${{ secrets.STRIPE_SECRET_KEY }}" \ --from-literal=STRIPE_WEBHOOK_SECRET="${{ secrets.STRIPE_WEBHOOK_SECRET }}" \ --dry-run=client -o yaml | kubectl apply -f - - name: Deploy Postgres run: | kubectl apply -f k8s/postgres.yml kubectl -n rebours rollout status statefulset/rebours-postgres --timeout=180s - name: Deploy web run: | kubectl apply -f k8s/deployment.yml kubectl -n rebours set image deployment/rebours-web \ rebours-web=${{ env.WEB_IMAGE }}:${{ github.sha }} kubectl -n rebours rollout status deployment/rebours-web --timeout=300s - name: Cleanup old images run: | docker image prune -f