Skip to content

Backend Release

Backend Release #108

Workflow file for this run

name: Backend Release
on:
workflow_run:
workflows: ["Backend CI"]
branches: [main]
types:
- completed
permissions:
contents: write
jobs:
release:
if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' }}
runs-on: ubuntu-latest
outputs:
version: ${{ steps.semantic.outputs.new_release_version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
ref: ${{ github.event.workflow_run.head_sha }}
# ---------------------------
# Setup Node
# ---------------------------
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install semantic-release
run: |
npm install -g semantic-release \
@semantic-release/commit-analyzer \
@semantic-release/release-notes-generator \
@semantic-release/github \
conventional-changelog-conventionalcommits
# ---------------------------
# Run semantic-release
# ---------------------------
- name: Semantic Release
id: semantic
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
npx semantic-release | tee release.log
VERSION=$(grep -oP 'Published release \K[0-9]+\.[0-9]+\.[0-9]+' release.log || true)
echo "Detected version: $VERSION"
echo "new_release_version=$VERSION" >> $GITHUB_OUTPUT
# ---------------------------
# Stop if no release
# ---------------------------
- name: Check release
if: steps.semantic.outputs.new_release_version == ''
run: |
echo "No release created. Skipping Docker build/deploy steps."
# ---------------------------
# Docker Login
# ---------------------------
- name: Login to Docker Hub
if: steps.semantic.outputs.new_release_version != ''
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# ---------------------------
# Build + Push
# ---------------------------
- name: Build and Push
if: steps.semantic.outputs.new_release_version != ''
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
tags: |
projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }}
projectbook07/projectbook-backend:sha-${{ github.sha }}
# ---------------------------
# Deploy via SSH
# ---------------------------
- name: Deploy to VPS
if: steps.semantic.outputs.new_release_version != ''
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
script: |
set -e
IMAGE="projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }}"
CONTAINER="projectbook-backend"
NEW_CONTAINER="projectbook-backend-new"
echo "Pulling image..."
docker pull $IMAGE
echo "Starting new container..."
docker run -d \
--name $NEW_CONTAINER \
--network projectbook-net \
--restart unless-stopped \
--env-file /opt/projectbook/backend.env \
-p 127.0.0.1:8081:8080 \
$IMAGE
echo "Waiting for health..."
for i in {1..30}; do
if curl -fsS http://127.0.0.1:8081/readyz; then
echo "New container healthy"
break
fi
sleep 2
done
if ! curl -fsS http://127.0.0.1:8081/readyz; then
echo "New container failed"
docker logs $NEW_CONTAINER
docker rm -f $NEW_CONTAINER
exit 1
fi
echo "Replacing old container..."
docker stop $CONTAINER || true
docker rm $CONTAINER || true
docker run -d \
--name $CONTAINER \
--network projectbook-net \
--restart unless-stopped \
--env-file /opt/projectbook/backend.env \
-p 127.0.0.1:8080:8080 \
$IMAGE
docker rm -f $NEW_CONTAINER
echo "Deployment complete"
# ---------------------------
# Promote to stable (ONLY if deploy succeeds)
# ---------------------------
- name: Tag stable
if: success() && steps.semantic.outputs.new_release_version != ''
run: |
docker pull projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }}
docker tag projectbook07/projectbook-backend:v${{ steps.semantic.outputs.new_release_version }} projectbook07/projectbook-backend:stable
docker push projectbook07/projectbook-backend:stable