Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 31 additions & 3 deletions .github/workflows/packages-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
build-push-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: read
contents: write
packages: write
attestations: write
id-token: write
Expand All @@ -32,6 +32,19 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v4

- name: Compute next release version
id: version
run: |
LATEST=$(gh release list --limit 1 --json tagName --jq '.[0].tagName // "v0.9.9"')
LATEST=${LATEST#v}
IFS='.' read -r MAJOR MINOR PATCH <<< "$LATEST"
PATCH=$((PATCH + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
echo "NEW_VERSION=${NEW_VERSION}" >> $GITHUB_ENV
echo "Computed version: ${NEW_VERSION}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
Expand All @@ -44,6 +57,9 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend
tags: |
type=raw,value=${{ env.NEW_VERSION }}
type=raw,value=latest

- name: Build and push Frontend image
id: push-frontend
Expand All @@ -59,6 +75,9 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend
tags: |
type=raw,value=${{ env.NEW_VERSION }}
type=raw,value=latest

- name: Build and push Backend image
id: push-backend
Expand All @@ -83,6 +102,15 @@ jobs:
subject-digest: ${{ steps.push-backend.outputs.digest }}
push-to-registry: true

- name: Create GitHub Release
run: |
gh release create "v${{ env.NEW_VERSION }}" \
--title "Release v${{ env.NEW_VERSION }}" \
--generate-notes \
--target main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# --- VPS DEPLOY ---
- name: Setup SSH key
uses: webfactory/ssh-agent@v0.9.1
Expand All @@ -107,7 +135,7 @@ jobs:
cat > docker-compose.prod.yaml << 'EOF'
services:
frontend:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend:main
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend:${{ env.NEW_VERSION }}
container_name: portfolio-frontend
# ports:
# - "8080:8080"
Expand Down Expand Up @@ -139,7 +167,7 @@ jobs:


backend:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend:main
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend:${{ env.NEW_VERSION }}
container_name: portfolio-backend
# ports:
# - "8090:8090"
Expand Down
138 changes: 138 additions & 0 deletions .github/workflows/rollback.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
name: Rollback Deployment

on:
workflow_dispatch:
inputs:
version:
description: 'Version to rollback to (e.g., 1.0.3). Leave empty to auto-detect previous release.'
required: false
type: string

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
rollback:
runs-on: ubuntu-latest
permissions:
contents: read
packages: read

steps:
- name: Determine rollback version
run: |
if [ -n "${{ github.event.inputs.version }}" ]; then
ROLLBACK_VERSION="${{ github.event.inputs.version }}"
else
# Releases are ordered newest-first; .[1] is the one before the current
ROLLBACK_VERSION=$(gh release list --limit 2 --json tagName --jq '.[1].tagName')
ROLLBACK_VERSION=${ROLLBACK_VERSION#v}
fi
if [ -z "$ROLLBACK_VERSION" ]; then
echo "ERROR: Could not determine rollback version. No previous release found."
exit 1
fi
echo "ROLLBACK_VERSION=${ROLLBACK_VERSION}" >> $GITHUB_ENV
echo "Rolling back to version: ${ROLLBACK_VERSION}"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Setup SSH key
uses: webfactory/ssh-agent@v0.9.1
with:
ssh-private-key: ${{ secrets.VPS_SSH_PRIVATE_KEY }}

- name: Add host to known hosts
run: |
mkdir -p ~/.ssh
ssh-keyscan -H ${{ secrets.VPS_SSH_HOST }} >> ~/.ssh/known_hosts

- name: Create rollback docker-compose
run: |
cat > docker-compose.rollback.yaml << 'EOF'
services:
frontend:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/frontend:${{ env.ROLLBACK_VERSION }}
container_name: portfolio-frontend
environment:
- DD_SERVICE=ivanildobarauna.dev
- DD_ENV=production
- DD_VERSION=${{ env.ROLLBACK_VERSION }}
- DD_TRACE_SAMPLE_RATE=1.0
- DD_AGENT_HOST=localhost
- DD_PROCESS_AGENT_ENABLED=true
- DD_TAGS="app:portfolio,tech:nextjs,role:frontend"
labels:
com.datadoghq.ad.logs: '[{"source": "nodejs", "service": "ivanildobarauna.dev"}]'
tags.env: "production"
tags.service: "ivanildobarauna.dev"
tags.tech: "nextjs"
tags.app: "portfolio"
tags.role: "frontend"
depends_on:
- backend
restart: unless-stopped
network_mode: host
healthcheck:
test: ["CMD", "node", "-e", "require('http').get('http://localhost:8080', res => process.exit(res.statusCode === 200 ? 0 : 1)).on('error', () => process.exit(1))"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s

backend:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}/backend:${{ env.ROLLBACK_VERSION }}
container_name: portfolio-backend
environment:
- POSTGRES_HOST=localhost
- DD_SERVICE=api.ivanildobarauna.dev
- DD_ENV=production
- DD_VERSION=${{ env.ROLLBACK_VERSION }}
- DD_TRACE_SAMPLE_RATE=1.0
- DD_AGENT_HOST=localhost
- DD_PROCESS_AGENT_ENABLED=true
- DD_TAGS="app:portfolio,tech:python,role:backend"
- DD_RUNTIME_METRICS_ENABLED=true
labels:
com.datadoghq.ad.logs: '[{"source": "python", "service": "api.ivanildobarauna.dev"}]'
tags.env: "production"
tags.service: "api.ivanildobarauna.dev"
tags.tech: "python"
tags.app: "portfolio"
tags.role: "backend"
restart: unless-stopped
network_mode: host
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8090/api/v1/ping"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
EOF

- name: Sync rollback compose to VPS
run: |
rsync -avz \
docker-compose.rollback.yaml \
${{ secrets.VPS_SSH_USER }}@${{ secrets.VPS_SSH_HOST }}:/home/ubuntu/app/site/

- name: Deploy rollback version on VPS
run: |
ssh ${{ secrets.VPS_SSH_USER }}@${{ secrets.VPS_SSH_HOST }} << 'EOF'
cd /home/ubuntu/app/site
docker compose -f docker-compose.rollback.yaml pull
docker compose -f docker-compose.rollback.yaml up -d --remove-orphans
docker system prune -f
EOF

environment:
name: Production
url: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
Loading