name: CI/CD Pipeline on: push: branches: - development - main jobs: build-app: name: Build and Push App Docker Image runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set environment variables run: | if [ "${{ github.ref }}" == "refs/heads/main" ]; then echo "DOCKER_TAG=latest" >> $GITHUB_ENV echo "ENVIRONMENT=prod" >> $GITHUB_ENV else echo "DOCKER_TAG=dev" >> $GITHUB_ENV echo "ENVIRONMENT=dev" >> $GITHUB_ENV fi - name: Build and push app Docker image run: | docker login git.yohler.net -u ${{ github.actor }} -p ${{ secrets.PACKAGES_TOKEN }} docker build \ -f Dockerfile \ -t git.yohler.net/kyle/flxn-app:${{ env.DOCKER_TAG }} \ -t git.yohler.net/kyle/flxn-app:${{ github.sha }} \ . docker push git.yohler.net/kyle/flxn-app:${{ env.DOCKER_TAG }} docker push git.yohler.net/kyle/flxn-app:${{ github.sha }} build-pocketbase: name: Build and Push PocketBase Docker Image runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Check if PocketBase Dockerfile or migrations changed id: check_changes run: | if [ "${{ github.event.before }}" == "0000000000000000000000000000000000000000" ] || ! git cat-file -e ${{ github.event.before }} 2>/dev/null; then echo "changed=true" >> $GITHUB_OUTPUT elif git diff --name-only ${{ github.event.before }} ${{ github.sha }} | grep -qE "(Dockerfile.pocketbase|pb_migrations/)"; then echo "changed=true" >> $GITHUB_OUTPUT else echo "changed=false" >> $GITHUB_OUTPUT fi - name: Build and push PocketBase Docker image if: steps.check_changes.outputs.changed == 'true' || github.event.before == '0000000000000000000000000000000000000000' run: | docker login git.yohler.net -u ${{ github.actor }} -p ${{ secrets.PACKAGES_TOKEN }} docker build \ -f Dockerfile.pocketbase \ -t git.yohler.net/kyle/flxn-pocketbase:latest \ -t git.yohler.net/kyle/flxn-pocketbase:${{ github.sha }} \ . docker push git.yohler.net/kyle/flxn-pocketbase:latest docker push git.yohler.net/kyle/flxn-pocketbase:${{ github.sha }} deploy: name: Deploy to Kubernetes needs: [build-app, build-pocketbase] runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set environment variables run: | if [ "${{ github.ref }}" == "refs/heads/main" ]; then echo "ENVIRONMENT=prod" >> $GITHUB_ENV echo "NAMESPACE=flxn-prod" >> $GITHUB_ENV else echo "ENVIRONMENT=dev" >> $GITHUB_ENV echo "NAMESPACE=flxn-dev" >> $GITHUB_ENV fi - name: Install kubectl run: | curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" chmod +x kubectl mv kubectl /usr/local/bin/ - name: Configure kubectl run: | mkdir -p $HOME/.kube echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config chmod 600 $HOME/.kube/config kubectl config set-cluster local --insecure-skip-tls-verify=true - name: Verify kubectl access run: | kubectl version --client kubectl get nodes - name: Deploy shared services (SuperTokens) run: | kubectl apply -k k8s/overlays/shared/ - name: Deploy to ${{ env.ENVIRONMENT }} run: | kubectl apply -k k8s/overlays/${{ env.ENVIRONMENT }}/ - name: Force rollout to pull latest image run: | kubectl rollout restart deployment/flxn-app -n ${{ env.NAMESPACE }} kubectl rollout restart deployment/flxn-pocketbase -n ${{ env.NAMESPACE }} - name: Wait for rollout run: | kubectl rollout status deployment/flxn-app -n ${{ env.NAMESPACE }} --timeout=5m kubectl rollout status deployment/flxn-pocketbase -n ${{ env.NAMESPACE }} --timeout=5m - name: Verify deployment run: | kubectl get pods -n ${{ env.NAMESPACE }} -l app=flxn kubectl get svc -n ${{ env.NAMESPACE }} -l app=flxn kubectl get ingress -n ${{ env.NAMESPACE }} - name: Check app health run: | sleep 15 APP_POD=$(kubectl get pod -n ${{ env.NAMESPACE }} -l component=app -o jsonpath='{.items[0].metadata.name}') kubectl exec -n ${{ env.NAMESPACE }} $APP_POD -- wget -O- http://localhost:3000/api/health || echo "Health check failed (endpoint may not exist yet)" - name: Check PocketBase health run: | PB_POD=$(kubectl get pod -n ${{ env.NAMESPACE }} -l component=pocketbase -o jsonpath='{.items[0].metadata.name}') kubectl exec -n ${{ env.NAMESPACE }} $PB_POD -- wget -O- http://localhost:8090/api/health || echo "PocketBase health check completed"