Skip to content

Merge pull request #5 from SkySingh04/feature/cd-pipeline #10

Merge pull request #5 from SkySingh04/feature/cd-pipeline

Merge pull request #5 from SkySingh04/feature/cd-pipeline #10

Workflow file for this run

name: CD

Check failure on line 1 in .github/workflows/cd.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/cd.yml

Invalid workflow file

(Line: 87, Col: 9): Unrecognized named-value: 'secrets'. Located at position 1 within expression: secrets.SSH_HOST != '' && secrets.SSH_USER != '' && secrets.SSH_PRIVATE_KEY != '' && (github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository)
on:
push:
branches: [ main ]
pull_request_target:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
jobs:
build-and-push:
runs-on: ubuntu-latest
outputs:
backend_image: ${{ steps.tags.outputs.backend }}
frontend_image: ${{ steps.tags.outputs.frontend }}
# Only run on PRs originating from this repo to avoid exposing secrets to forks
if: ${{ github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository }}
steps:
- name: Select ref
run: |
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
echo "REF=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
else
echo "REF=${GITHUB_SHA}" >> $GITHUB_ENV
fi
- uses: actions/checkout@v4
with:
ref: ${{ env.REF }}
- name: Derive lowercase image repo
run: |
echo "IMAGE_REPO=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set image tags
id: tags
run: |
SHA_TAG=sha-${GITHUB_SHA::7}
echo "backend=${{ env.REGISTRY }}/${IMAGE_REPO}-backend:${SHA_TAG}" >> $GITHUB_OUTPUT
echo "backend_latest=${{ env.REGISTRY }}/${IMAGE_REPO}-backend:latest" >> $GITHUB_OUTPUT
echo "frontend=${{ env.REGISTRY }}/${IMAGE_REPO}-frontend:${SHA_TAG}" >> $GITHUB_OUTPUT
echo "frontend_latest=${{ env.REGISTRY }}/${IMAGE_REPO}-frontend:latest" >> $GITHUB_OUTPUT
- name: Build and push backend
uses: docker/build-push-action@v6
with:
context: .
file: backend/Dockerfile
push: true
tags: |
${{ steps.tags.outputs.backend }}
${{ steps.tags.outputs.backend_latest }}
- name: Build and push frontend
uses: docker/build-push-action@v6
with:
context: frontend
file: frontend/Dockerfile
push: true
tags: |
${{ steps.tags.outputs.frontend }}
${{ steps.tags.outputs.frontend_latest }}
- name: Show image tags
run: |
echo "Backend: ${{ steps.tags.outputs.backend }}"
echo "Frontend: ${{ steps.tags.outputs.frontend }}"
deploy-compose:
runs-on: ubuntu-latest
needs: build-and-push
if: ${{ secrets.SSH_HOST != '' && secrets.SSH_USER != '' && secrets.SSH_PRIVATE_KEY != '' && (github.event_name != 'pull_request_target' || github.event.pull_request.head.repo.full_name == github.repository) }}
environment: production
concurrency:
group: prod-deploy
cancel-in-progress: false
steps:
- name: Select ref
run: |
if [ "${{ github.event_name }}" = "pull_request_target" ]; then
echo "REF=${{ github.event.pull_request.head.sha }}" >> $GITHUB_ENV
else
echo "REF=${GITHUB_SHA}" >> $GITHUB_ENV
fi
- uses: actions/checkout@v4
with:
ref: ${{ env.REF }}
- name: Upload docker-compose file
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "docker-compose.prod.yml"
target: "/opt/edgeflow/docker-compose.yml"
strip_components: 0
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
set -euo pipefail
APP_DIR=/opt/edgeflow
sudo mkdir -p ${APP_DIR}
cd ${APP_DIR}
# Write .env with image tags
cat > .env << 'EOF'
BACKEND_IMAGE=${{ needs.build-and-push.outputs.backend_image }}
FRONTEND_IMAGE=${{ needs.build-and-push.outputs.frontend_image }}
EOF
# Login to GHCR if credentials provided
if [ -n "${{ secrets.GHCR_USERNAME }}" ] && [ -n "${{ secrets.GHCR_TOKEN }}" ]; then
echo "${{ secrets.GHCR_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin
fi
# Ensure docker compose is available
(docker compose version || docker-compose version)
# Pull and run
(docker compose --env-file .env -f docker-compose.yml pull || docker-compose --env-file .env -f docker-compose.yml pull)
(docker compose --env-file .env -f docker-compose.yml up -d || docker-compose --env-file .env -f docker-compose.yml up -d)
docker image prune -f || true
# Basic health checks
curl -fsS http://localhost:8000/api/health || (echo 'Backend health failed' && exit 1)
curl -fsS http://localhost:3000/ || (echo 'Frontend health failed' && exit 1)