Skip to content

chore(deps): bump devalue (#11) #20

chore(deps): bump devalue (#11)

chore(deps): bump devalue (#11) #20

Workflow file for this run

name: Deploy to Droplet
on:
push:
branches: [main]
workflow_dispatch:
env:
REGISTRY: ghcr.io
# GHCR requires lowercase image names
IMAGE_PREFIX: ghcr.io/layerdynamics
jobs:
build-and-push:
name: Build & Push Docker Images
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push browserx-api image
uses: docker/build-push-action@v6
with:
context: .
file: services/browserx-api/Dockerfile
push: true
tags: |
${{ env.IMAGE_PREFIX }}/browserx-api:latest
${{ env.IMAGE_PREFIX }}/browserx-api:${{ github.sha }}
cache-from: type=gha,scope=browserx-api
cache-to: type=gha,mode=max,scope=browserx-api
- name: Build and push doc-site image
uses: docker/build-push-action@v6
with:
context: .
file: doc-site/Dockerfile
push: true
tags: |
${{ env.IMAGE_PREFIX }}/browserx-doc-site:latest
${{ env.IMAGE_PREFIX }}/browserx-doc-site:${{ github.sha }}
cache-from: type=gha,scope=doc-site
cache-to: type=gha,mode=max,scope=doc-site
deploy:
name: Deploy to Droplet
needs: build-and-push
runs-on: ubuntu-latest
steps:
- name: Checkout (for compose + nginx files)
uses: actions/checkout@v4
- name: Copy deployment files to Droplet
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.DROPLET_IP }}
username: root
key: ${{ secrets.DROPLET_SSH_KEY }}
source: "docker-compose.yml,nginx/browserx.conf"
target: "/opt/browserx/"
strip_components: 0
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.2.0
env:
IMAGE_PREFIX: ${{ env.IMAGE_PREFIX }}
SHA: ${{ github.sha }}
with:
host: ${{ secrets.DROPLET_IP }}
username: root
key: ${{ secrets.DROPLET_SSH_KEY }}
envs: IMAGE_PREFIX,SHA
script: |
set -e
cd /opt/browserx
mkdir -p nginx
cat > docker-compose.override.yml <<EOF
services:
browserx-api:
image: ${IMAGE_PREFIX}/browserx-api:${SHA}
build: ~
doc-site:
image: ${IMAGE_PREFIX}/browserx-doc-site:${SHA}
build: ~
EOF
docker compose -f docker-compose.yml -f docker-compose.override.yml pull
docker compose -f docker-compose.yml -f docker-compose.override.yml \
up -d --no-deps browserx-api
for i in $(seq 1 24); do
API_ID=$(docker compose -f docker-compose.yml -f docker-compose.override.yml \
ps -q browserx-api 2>/dev/null)
STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$API_ID" 2>/dev/null || echo "unknown")
if [ "$STATUS" = "healthy" ]; then
echo "browserx-api healthy"
break
fi
echo "Waiting for browserx-api (${i}/24) — status: ${STATUS}..."
sleep 5
done
docker compose -f docker-compose.yml -f docker-compose.override.yml \
up -d --no-deps doc-site
# Stop any container (from any compose project or standalone) that has
# port 80 published — prevents "port is already allocated" on redeploy
docker ps -q --filter "publish=80" | xargs -r docker stop 2>/dev/null || true
# Explicitly remove the tracked nginx container so Docker releases the port
# binding before we try to allocate it again
docker compose -f docker-compose.yml -f docker-compose.override.yml \
rm -sf nginx 2>/dev/null || true
docker compose -f docker-compose.yml -f docker-compose.override.yml \
up -d --no-deps nginx
docker system prune -f
echo "Deploy complete!"
docker compose ps