feat: add production deploy helper
This commit is contained in:
@@ -24,8 +24,9 @@ This is intentional. For a private repository, server-side `git clone` adds unne
|
||||
|
||||
### Production
|
||||
- same deployment mechanism
|
||||
- different server
|
||||
- usually a different server
|
||||
- env file on server: `.env.prod`
|
||||
- branch: `main`
|
||||
- should run behind real HTTPS
|
||||
- should keep `DEBUG=0`
|
||||
|
||||
@@ -198,6 +199,44 @@ HEALTH_URL=http://192.168.2.55:8088/healthz/ \
|
||||
./scripts/deploy_test_from_mac.sh
|
||||
```
|
||||
|
||||
## Manual production deployment
|
||||
For production, use a dedicated helper instead of the test script.
|
||||
|
||||
### One-command production deployment from your Mac
|
||||
Use:
|
||||
```bash
|
||||
./scripts/deploy_prod_from_mac.sh
|
||||
```
|
||||
|
||||
What it does:
|
||||
1. requires the current branch to be `main`
|
||||
2. fast-forwards from `origin/main`
|
||||
3. verifies that the server env file exists before syncing
|
||||
4. syncs the repo to the production path via `rsync`
|
||||
5. runs the remote deployment script with `RUN_DJANGO_CHECK=1`
|
||||
6. verifies the production health endpoint
|
||||
7. prints the deployed commit and branch
|
||||
|
||||
Important:
|
||||
- the production helper preserves server-local env files:
|
||||
- `.env.test`
|
||||
- `.env.prod`
|
||||
- do not use the test helper for production
|
||||
|
||||
Default assumptions:
|
||||
- target host: `root@192.168.2.55`
|
||||
- target path: `/opt/workdock`
|
||||
- env file: `.env.prod`
|
||||
- health URL: `https://workdock.bostame.de/healthz/`
|
||||
|
||||
Optional overrides:
|
||||
```bash
|
||||
DEPLOY_HOST=root@192.168.2.55 \
|
||||
DEPLOY_PATH=/opt/workdock \
|
||||
HEALTH_URL=https://workdock.bostame.de/healthz/ \
|
||||
./scripts/deploy_prod_from_mac.sh
|
||||
```
|
||||
|
||||
### Manual server-side deploy only
|
||||
If the latest code is already on the server:
|
||||
```bash
|
||||
@@ -208,7 +247,7 @@ RUN_DJANGO_CHECK=0 DEPLOY_HEALTH_URL="http://127.0.0.1:8088/healthz/" ./scripts/
|
||||
Manual production deployment:
|
||||
```bash
|
||||
cd /opt/workdock
|
||||
RUN_DJANGO_CHECK=1 ./scripts/deploy_stack.sh .env.prod docker-compose.prod.yml
|
||||
RUN_DJANGO_CHECK=1 DEPLOY_HEALTH_URL="https://workdock.bostame.de/healthz/" ./scripts/deploy_stack.sh .env.prod docker-compose.prod.yml
|
||||
```
|
||||
|
||||
## Runtime config sync
|
||||
|
||||
@@ -362,6 +362,7 @@ make backup-verify BACKUP_DIR=backups/backup_YYYYmmdd_HHMMSS</code></pre>
|
||||
<li>Stable branch: <code>main</code>.</li>
|
||||
<li>GitHub Actions is used for CI.</li>
|
||||
<li>Test deployment is done manually from a LAN-connected machine, not from GitHub-hosted runners.</li>
|
||||
<li>Production deployment is also manual from the Mac today, but it uses <code>main</code> and a separate helper.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -386,6 +387,7 @@ make backup-verify BACKUP_DIR=backups/backup_YYYYmmdd_HHMMSS</code></pre>
|
||||
<li>Run the local test deployment helper from the Mac.</li>
|
||||
<li>Verify the updated version in the browser.</li>
|
||||
<li>When the integration line is stable, merge <code>develop</code> into <code>main</code>.</li>
|
||||
<li>Deploy production from the Mac only from <code>main</code>.</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@@ -407,6 +409,24 @@ make backup-verify BACKUP_DIR=backups/backup_YYYYmmdd_HHMMSS</code></pre>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>One-command production deployment</h3>
|
||||
<p>From the Mac, only after the change has been promoted into <code>main</code>:</p>
|
||||
<pre><code>git checkout main
|
||||
./scripts/deploy_prod_from_mac.sh</code></pre>
|
||||
<p>This helper script does all of the following:</p>
|
||||
<ol>
|
||||
<li>checks that the current branch is <code>main</code></li>
|
||||
<li>fast-forwards from <code>origin/main</code></li>
|
||||
<li>checks that the server env file exists</li>
|
||||
<li>syncs the repository to <code>/opt/workdock</code> with <code>rsync</code></li>
|
||||
<li>preserves server-local env files like <code>.env.test</code> and <code>.env.prod</code></li>
|
||||
<li>runs the remote deployment script with <code>RUN_DJANGO_CHECK=1</code></li>
|
||||
<li>waits for the public health endpoint</li>
|
||||
<li>prints the deployed commit and branch</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<h3>Test server values</h3>
|
||||
<ul>
|
||||
@@ -478,10 +498,17 @@ make backup-verify BACKUP_DIR=backups/backup_YYYYmmdd_HHMMSS</code></pre>
|
||||
<p>The preferred test-deployment path is the local helper script from a Mac or another LAN-connected workstation:</p>
|
||||
<pre><code>./scripts/deploy_test_from_mac.sh</code></pre>
|
||||
<p>This script fast-forwards <code>develop</code>, checks that the remote env file exists, syncs the repo to the server with <code>rsync</code>, runs the remote deployment, verifies the health endpoint, and prints the deployed commit hash.</p>
|
||||
<p>The script explicitly preserves server-local env files such as <code>.env.test</code> and <code>.env.prod</code> so deployment does not wipe machine-specific secrets.</p>
|
||||
<p>The helper scripts explicitly preserve server-local env files such as <code>.env.test</code> and <code>.env.prod</code> so deployment does not wipe machine-specific secrets.</p>
|
||||
<h3>Manual production deploy from the Mac</h3>
|
||||
<p>Use the production helper only from <code>main</code>:</p>
|
||||
<pre><code>git checkout main
|
||||
./scripts/deploy_prod_from_mac.sh</code></pre>
|
||||
<p>This script fast-forwards <code>main</code>, checks that <code>.env.prod</code> exists on the target server, syncs the repo, runs the production deployment with <code>RUN_DJANGO_CHECK=1</code>, verifies <code>https://workdock.bostame.de/healthz/</code>, and prints the deployed commit hash.</p>
|
||||
<p>Direct server-side deploy is still available if the code is already on the server:</p>
|
||||
<pre><code>cd /opt/workdock
|
||||
RUN_DJANGO_CHECK=0 DEPLOY_HEALTH_URL="http://127.0.0.1:8088/healthz/" ./scripts/deploy_stack.sh .env.test docker-compose.prod.yml</code></pre>
|
||||
<pre><code>cd /opt/workdock
|
||||
RUN_DJANGO_CHECK=1 DEPLOY_HEALTH_URL="https://workdock.bostame.de/healthz/" ./scripts/deploy_stack.sh .env.prod docker-compose.prod.yml</code></pre>
|
||||
<h3>Validation after deploy</h3>
|
||||
<pre><code>curl -I http://192.168.2.55:8088/healthz/
|
||||
ssh root@192.168.2.55 "cd /opt/workdock && docker compose --env-file .env.test -f docker-compose.prod.yml ps"</code></pre>
|
||||
@@ -566,11 +593,19 @@ docker compose restart worker</code></pre>
|
||||
<pre><code>./scripts/deploy_test_from_mac.sh</code></pre>
|
||||
<p>Sync the current <code>develop</code> checkout to the LAN test server and deploy it.</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Production deployment</h3>
|
||||
<pre><code>./scripts/deploy_prod_from_mac.sh</code></pre>
|
||||
<p>Sync the current <code>main</code> checkout to the production target and deploy it with production checks enabled.</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Direct server deployment</h3>
|
||||
<pre><code>cd /opt/workdock
|
||||
RUN_DJANGO_CHECK=0 DEPLOY_HEALTH_URL="http://127.0.0.1:8088/healthz/" ./scripts/deploy_stack.sh .env.test docker-compose.prod.yml</code></pre>
|
||||
<p>Deploy when code is already present on the server.</p>
|
||||
<pre><code>cd /opt/workdock
|
||||
RUN_DJANGO_CHECK=1 DEPLOY_HEALTH_URL="https://workdock.bostame.de/healthz/" ./scripts/deploy_stack.sh .env.prod docker-compose.prod.yml</code></pre>
|
||||
<p>Production deploy when code is already present on the server.</p>
|
||||
</div>
|
||||
<div class="box">
|
||||
<h3>Config sync</h3>
|
||||
|
||||
57
scripts/deploy_prod_from_mac.sh
Executable file
57
scripts/deploy_prod_from_mac.sh
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
DEPLOY_HOST="${DEPLOY_HOST:-root@192.168.2.55}"
|
||||
DEPLOY_PATH="${DEPLOY_PATH:-/opt/workdock}"
|
||||
HEALTH_URL="${HEALTH_URL:-https://workdock.bostame.de/healthz/}"
|
||||
REMOTE_ENV_FILE="${REMOTE_ENV_FILE:-.env.prod}"
|
||||
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}"
|
||||
RUN_DJANGO_CHECK="${RUN_DJANGO_CHECK:-1}"
|
||||
SSH_CMD="${SSH_CMD:-ssh -4}"
|
||||
RSYNC_SSH="${RSYNC_SSH:-ssh -4}"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
current_branch="$(git branch --show-current)"
|
||||
if [[ "$current_branch" != "main" ]]; then
|
||||
echo "Expected branch 'main' for production deployment, got '$current_branch'." >&2
|
||||
echo "Switch to main or override intentionally before deploying." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Updating local branch from origin/main..."
|
||||
git pull --ff-only origin main
|
||||
|
||||
echo "Checking remote env file..."
|
||||
$SSH_CMD "$DEPLOY_HOST" "test -f '$DEPLOY_PATH/$REMOTE_ENV_FILE'" || {
|
||||
echo "Missing remote env file: $DEPLOY_PATH/$REMOTE_ENV_FILE" >&2
|
||||
echo "Create or restore the server env file before deploying." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "Syncing repository to ${DEPLOY_HOST}:${DEPLOY_PATH} ..."
|
||||
rsync -az --delete \
|
||||
--filter 'P .env.test' \
|
||||
--filter 'P .env.prod' \
|
||||
--exclude '.git' \
|
||||
--exclude '.github' \
|
||||
--exclude '.venv' \
|
||||
--exclude '__pycache__' \
|
||||
--exclude 'node_modules' \
|
||||
--exclude 'backend/media' \
|
||||
--exclude 'backend/staticfiles' \
|
||||
-e "$RSYNC_SSH" \
|
||||
"$REPO_ROOT"/ \
|
||||
"${DEPLOY_HOST}:${DEPLOY_PATH}/"
|
||||
|
||||
echo "Running remote deployment..."
|
||||
$SSH_CMD "$DEPLOY_HOST" \
|
||||
"cd '$DEPLOY_PATH' && RUN_DJANGO_CHECK='$RUN_DJANGO_CHECK' DEPLOY_HEALTH_URL='$HEALTH_URL' ./scripts/deploy_stack.sh '$REMOTE_ENV_FILE' '$COMPOSE_FILE'"
|
||||
|
||||
echo "Verifying health endpoint..."
|
||||
curl --fail --silent --show-error --max-time 10 "$HEALTH_URL" >/dev/null
|
||||
commit_sha="$(git rev-parse --short HEAD)"
|
||||
echo "Production deployment healthy: $HEALTH_URL"
|
||||
echo "Deployed commit: $commit_sha"
|
||||
echo "Branch: $current_branch"
|
||||
Reference in New Issue
Block a user