Skip to content

updating sqllit to use pure go instead of c libraries, updating ci to… #10

updating sqllit to use pure go instead of c libraries, updating ci to…

updating sqllit to use pure go instead of c libraries, updating ci to… #10

Workflow file for this run

name: Build and Deploy
on:
push:
branches: ["main"]
workflow_dispatch: # Allow manual triggering
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
check-changes:
name: Check What Changed
runs-on: [self-hosted, home]
outputs:
backend-changed: ${{ steps.changes.outputs.backend }}
frontend-changed: ${{ steps.changes.outputs.frontend }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 2 # Need at least 2 commits to compare
- name: Check for changes
id: changes
run: |
# Check if this is the first commit (no previous commit to compare)
if git rev-parse HEAD~1 >/dev/null 2>&1; then
# Compare with previous commit
BACKEND_CHANGED=$(git diff --name-only HEAD~1 HEAD | grep -E '^(cmd/|internal/|pkg/|go\.|configs/|deployments/|\.github/workflows/deploy\.yml)' || echo '')
FRONTEND_CHANGED=$(git diff --name-only HEAD~1 HEAD | grep -E '^frontend/' || echo '')
else
# First commit - build everything
BACKEND_CHANGED="initial"
FRONTEND_CHANGED="initial"
fi
# Set outputs
if [ -n "$BACKEND_CHANGED" ]; then
echo "backend=true" >> $GITHUB_OUTPUT
echo "πŸ” Backend changes detected: $BACKEND_CHANGED"
else
echo "backend=false" >> $GITHUB_OUTPUT
echo "βœ… No backend changes detected"
fi
if [ -n "$FRONTEND_CHANGED" ]; then
echo "frontend=true" >> $GITHUB_OUTPUT
echo "πŸ” Frontend changes detected: $FRONTEND_CHANGED"
else
echo "frontend=false" >> $GITHUB_OUTPUT
echo "βœ… No frontend changes detected"
fi
build-and-push:
name: Build and Push Backend
runs-on: [self-hosted, home]
needs: check-changes
if: needs.check-changes.outputs.backend-changed == 'true'
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./deployments/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-frontend-image:
name: Build Frontend Container
runs-on: [self-hosted, home]
needs: check-changes
if: needs.check-changes.outputs.frontend-changed == 'true'
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for frontend
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-frontend
tags: |
type=ref,event=branch
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Frontend Docker image
uses: docker/build-push-action@v5
with:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
deploy-via-portainer:
name: Deploy via Portainer
runs-on: [self-hosted, home]
needs: [check-changes, build-and-push, build-frontend-image]
if: always() && github.ref == 'refs/heads/main' &&
(needs.build-and-push.result == 'success' || needs.build-and-push.result == 'skipped') &&
(needs.build-frontend-image.result == 'success' || needs.build-frontend-image.result == 'skipped') &&
(needs.check-changes.outputs.backend-changed == 'true' || needs.check-changes.outputs.frontend-changed == 'true')
steps:
- name: Deployment Info
run: |
echo "πŸ“‹ **Deployment Information**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Backend Changed**: ${{ needs.check-changes.outputs.backend-changed }}" >> $GITHUB_STEP_SUMMARY
echo "- **Frontend Changed**: ${{ needs.check-changes.outputs.frontend-changed }}" >> $GITHUB_STEP_SUMMARY
echo "- **Backend Build**: ${{ needs.build-and-push.result }}" >> $GITHUB_STEP_SUMMARY
echo "- **Frontend Build**: ${{ needs.build-frontend-image.result }}" >> $GITHUB_STEP_SUMMARY
- name: Verify Portainer Connection
run: |
echo "πŸ” Verifying connection to Portainer..."
# Test connection to Portainer
for i in {1..5}; do
if curl -f -s --connect-timeout 10 https://portainer.sankalpnarula.com/api/status > /dev/null; then
echo "βœ… Successfully connected to Portainer"
break
fi
echo "⏳ Attempt $i/5 - Waiting for Portainer connection..."
sleep 3
done
# Final connection test
if ! curl -f -s --connect-timeout 10 https://portainer.sankalpnarula.com/api/status > /dev/null; then
echo "❌ Failed to connect to Portainer"
exit 1
fi
- name: Trigger Portainer Stack Redeployment
env:
PORTAINER_URL: https://portainer.sankalpnarula.com
PORTAINER_TOKEN: ${{ secrets.PORTAINER_ACCESS_TOKEN }}
STACK_NAME: ocpp-chaos-sim
BACKEND_CHANGED: ${{ needs.check-changes.outputs.backend-changed }}
FRONTEND_CHANGED: ${{ needs.check-changes.outputs.frontend-changed }}
run: |
set -e
echo "πŸš€ Starting deployment process..."
echo "Backend changed: $BACKEND_CHANGED"
echo "Frontend changed: $FRONTEND_CHANGED"
# Get stack ID
echo "πŸ” Looking for stack: $STACK_NAME"
STACK_ID=$(curl -s -H "X-API-Key: $PORTAINER_TOKEN" \
"$PORTAINER_URL/api/stacks" | \
jq -r ".[] | select(.Name == \"$STACK_NAME\") | .Id")
if [ "$STACK_ID" = "null" ] || [ -z "$STACK_ID" ]; then
echo "❌ Stack '$STACK_NAME' not found. Available stacks:"
curl -s -H "X-API-Key: $PORTAINER_TOKEN" \
"$PORTAINER_URL/api/stacks" | jq -r '.[].Name'
exit 1
fi
echo "πŸ“‹ Found stack ID: $STACK_ID"
# Get endpoint ID
ENDPOINT_ID=$(curl -s -H "X-API-Key: $PORTAINER_TOKEN" \
"$PORTAINER_URL/api/stacks/$STACK_ID" | \
jq -r '.EndpointId')
echo "🎯 Using endpoint ID: $ENDPOINT_ID"
# Trigger stack update (always pull images, even if only one service changed)
echo "πŸ”„ Triggering stack redeployment with image pull..."
RESPONSE=$(curl -s -w "%{http_code}" -X PUT \
-H "X-API-Key: $PORTAINER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"pullImage": true,
"prune": true
}' \
"$PORTAINER_URL/api/stacks/$STACK_ID?endpointId=$ENDPOINT_ID")
HTTP_CODE="${RESPONSE: -3}"
RESPONSE_BODY="${RESPONSE%???}"
if [ "$HTTP_CODE" = "200" ]; then
echo "βœ… Stack redeployment triggered successfully!"
echo "πŸ“ Response: $RESPONSE_BODY"
else
echo "❌ Deployment failed with HTTP $HTTP_CODE"
echo "πŸ“ Response: $RESPONSE_BODY"
exit 1
fi
# Wait for deployment to process
echo "⏳ Waiting for deployment to complete..."
sleep 15
# Check deployment status
STACK_STATUS=$(curl -s -H "X-API-Key: $PORTAINER_TOKEN" \
"$PORTAINER_URL/api/stacks/$STACK_ID" | \
jq -r '.Status // "unknown"')
echo "πŸ“Š Stack status: $STACK_STATUS"
- name: Deployment Summary
if: always()
run: |
echo "🎯 **Portainer Deployment Summary**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ job.status }}" = "success" ]; then
echo "βœ… **Status**: Deployment successful" >> $GITHUB_STEP_SUMMARY
echo "πŸ”— **Portainer**: [View Stack](https://portainer.sankalpnarula.com)" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.check-changes.outputs.backend-changed }}" = "true" ]; then
echo "πŸ“¦ **Backend Image**: \`ghcr.io/${{ github.repository }}:latest\` (updated)" >> $GITHUB_STEP_SUMMARY
else
echo "πŸ“¦ **Backend Image**: \`ghcr.io/${{ github.repository }}:latest\` (unchanged)" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ needs.check-changes.outputs.frontend-changed }}" = "true" ]; then
echo "πŸ“¦ **Frontend Image**: \`ghcr.io/${{ github.repository }}-frontend:latest\` (updated)" >> $GITHUB_STEP_SUMMARY
else
echo "πŸ“¦ **Frontend Image**: \`ghcr.io/${{ github.repository }}-frontend:latest\` (unchanged)" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "**What was deployed:**" >> $GITHUB_STEP_SUMMARY
if [ "${{ needs.check-changes.outputs.backend-changed }}" = "true" ]; then
echo "- βœ… Backend: Built and deployed new image" >> $GITHUB_STEP_SUMMARY
else
echo "- ⏭️ Backend: No changes, using existing image" >> $GITHUB_STEP_SUMMARY
fi
if [ "${{ needs.check-changes.outputs.frontend-changed }}" = "true" ]; then
echo "- βœ… Frontend: Built and deployed new image" >> $GITHUB_STEP_SUMMARY
else
echo "- ⏭️ Frontend: No changes, using existing image" >> $GITHUB_STEP_SUMMARY
fi
else
echo "❌ **Status**: Deployment failed" >> $GITHUB_STEP_SUMMARY
echo "πŸ” **Check**: Review job logs for details" >> $GITHUB_STEP_SUMMARY
echo "πŸ”— **Portainer**: [Check Stack Status](https://portainer.sankalpnarula.com)" >> $GITHUB_STEP_SUMMARY
fi