Skip to content

Deploy Cloud

Deploy Cloud #92

Workflow file for this run

name: Deploy Cloud
on:
workflow_dispatch:
inputs:
tag:
description: "Docker image tag to deploy (default: latest)"
required: false
default: "latest"
type: string
jobs:
deploy:
name: Deploy to Cloud Droplet
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Copy config files to server
uses: appleboy/scp-action@v1.0.0
with:
host: ${{ secrets.CLOUD_HOST }}
username: root
key: ${{ secrets.CLOUD_SSH_KEY }}
source: "docker-compose.cloud.yml,deploy/cloud/Caddyfile,deploy/cloud/db-rest/Dockerfile"
target: /tmp/anythingmcp-deploy
overwrite: true
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
env:
CRON_SECRET: ${{ secrets.ONBOARDING_CRON_SECRET }}
with:
host: ${{ secrets.CLOUD_HOST }}
username: root
key: ${{ secrets.CLOUD_SSH_KEY }}
envs: CRON_SECRET
script: |
set -e
cd /opt/anythingmcp-cloud
# Pull the requested tag AND refresh :latest, since
# docker-compose.cloud.yml references :latest. Without this
# the local :latest tag can point to an older image.
docker pull helpcodeai/anythingmcp:${{ inputs.tag }}
docker pull helpcodeai/anythingmcp:latest
# Update compose, Caddyfile and the custom db-rest Dockerfile from
# checkout. The Dockerfile is the build context for the db-rest
# service; `docker compose up` builds it if the pinned image tag is
# missing (fresh droplet), otherwise the existing image is reused.
cp /tmp/anythingmcp-deploy/docker-compose.cloud.yml ./docker-compose.cloud.yml
cp /tmp/anythingmcp-deploy/deploy/cloud/Caddyfile ./Caddyfile
mkdir -p ./deploy/cloud/db-rest
cp /tmp/anythingmcp-deploy/deploy/cloud/db-rest/Dockerfile ./deploy/cloud/db-rest/Dockerfile
rm -rf /tmp/anythingmcp-deploy
# Keep CRON_SECRET in the server .env in sync with the repo
# secret so the onboarding-reminders cron can authenticate.
# Upsert (replace-or-append) without disturbing other vars.
touch .env
if grep -q '^CRON_SECRET=' .env; then
sed -i "s#^CRON_SECRET=.*#CRON_SECRET=${CRON_SECRET}#" .env
else
echo "CRON_SECRET=${CRON_SECRET}" >> .env
fi
# Recreate ONLY the app to pick up the new image/config (postgres,
# redis and db-rest keep running — no data churn, no needless
# downtime), and wait until it reports healthy. The old command
# force-recreated the whole stack with no health gate, so a
# crash-on-start went unnoticed and could take the DB down with it.
docker compose -f docker-compose.cloud.yml up -d \
--no-deps --force-recreate --wait --wait-timeout 300 app
# Ensure the proxy + any other services are up (caddy waits for the
# app to be healthy, which it now is).
docker compose -f docker-compose.cloud.yml up -d --remove-orphans
docker image prune -f
echo "Deployment complete"