Skip to content

model_testing with images #55

model_testing with images

model_testing with images #55

Workflow file for this run

name: CD
on:
push:
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 }}
steps:
- uses: actions/checkout@v4
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- 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
provenance: false
compression: gzip
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
provenance: false
compression: gzip
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
environment: production
concurrency:
group: prod-deploy
cancel-in-progress: false
steps:
- uses: actions/checkout@v4
- name: Verify required secrets are present
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
if [ -z "$SSH_HOST" ] || [ -z "$SSH_USER" ]; then
echo "Missing SSH_HOST or SSH_USER"; exit 1; fi
if [ -z "$SSH_PRIVATE_KEY" ]; then
echo "SSH_PRIVATE_KEY is required (password auth not supported)"; exit 1; fi
- 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 }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
source: "docker-compose.prod.yml"
target: "/tmp"
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 }}
passphrase: ${{ secrets.SSH_PASSPHRASE }}
script: |
set -euo pipefail
APP_DIR=/opt/edgeflow
sudo mkdir -p ${APP_DIR}
cd ${APP_DIR}
# Move compose file into place
if [ -d docker-compose.yml ]; then sudo rm -rf docker-compose.yml; fi
if [ -f /tmp/docker-compose.prod.yml ]; then mv /tmp/docker-compose.prod.yml docker-compose.yml; fi
# 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
export COMPOSE_PROJECT_NAME=edgeflow
# Stop any existing stack and containers to free ports (plugin only)
(docker compose -p ${COMPOSE_PROJECT_NAME} -f docker-compose.yml down -v || true)
(docker rm -f edgeflow-backend edgeflow-frontend || true)
(docker network rm ${COMPOSE_PROJECT_NAME}_edgeflow-net || true)
sleep 2
# Pull and run cleanly
docker compose -p ${COMPOSE_PROJECT_NAME} --env-file .env -f docker-compose.yml pull
docker compose -p ${COMPOSE_PROJECT_NAME} --env-file .env -f docker-compose.yml up -d --remove-orphans --force-recreate
docker image prune -f || true
# Basic health checks (backend on host port 18000)
curl -fsS http://localhost:18000/api/health || (echo 'Backend health failed' && exit 1)
curl -fsS http://localhost:13000/ || (echo 'Frontend health failed' && exit 1)