From 541736a9a2006e314e4d41e6c972ad41c4252555 Mon Sep 17 00:00:00 2001 From: Md Bayazid Bostame Date: Tue, 31 Mar 2026 15:11:16 +0200 Subject: [PATCH] feat: add stack reset helper and setup runbook --- CONTRIBUTING.md | 6 ++ DEPLOYMENT.md | 37 +++++++++ .../workflows/developer_handbook.html | 16 ++++ scripts/reset_stack_from_mac.sh | 82 +++++++++++++++++++ 4 files changed, 141 insertions(+) create mode 100644 scripts/reset_stack_from_mac.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index afca45f..854b1ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -81,6 +81,12 @@ Standard test deployment command: ./scripts/deploy_test_from_mac.sh ``` +Destructive fresh reset command: + +```bash +RESET_CONFIRM=RESET EXPECTED_BRANCH=develop ./scripts/reset_stack_from_mac.sh +``` + Why: - GitHub-hosted runners cannot reliably reach the private LAN target at `192.168.2.55` diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index c9ef327..dcf714d 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -217,6 +217,43 @@ HEALTH_URL=http://192.168.2.55:8088/healthz/ \ ./scripts/deploy_test_from_mac.sh ``` +## Reset a stack from scratch +Use this only when you intentionally want a fresh environment with default bootstrap data. + +What it does: +1. syncs the current checkout to the target server +2. stops the stack +3. removes compose volumes with `down -v` +4. rebuilds and bootstraps the stack again +5. verifies the health endpoint + +Local test server reset: +```bash +git checkout develop +RESET_CONFIRM=RESET EXPECTED_BRANCH=develop ./scripts/reset_stack_from_mac.sh +``` + +Customer/TUBCO reset example: +```bash +git checkout release/tubco-v1 +RESET_CONFIRM=RESET \ +EXPECTED_BRANCH=release/tubco-v1 \ +DEPLOY_HOST=root@ \ +DEPLOY_PATH=/opt/workdock \ +REMOTE_ENV_FILE=.env.prod \ +HEALTH_URL=https://portal.tub.co/healthz/ \ +RUN_DJANGO_CHECK=1 \ +./scripts/reset_stack_from_mac.sh +``` + +This is destructive. It wipes: +- database state +- generated documents/media +- staticfiles volume +- backup volume + +It does not remove the server-local env file. That file must already exist. + ## Manual production deployment For production, use a dedicated helper instead of the test script. diff --git a/backend/workflows/templates/workflows/developer_handbook.html b/backend/workflows/templates/workflows/developer_handbook.html index 9a2e383..336bb75 100644 --- a/backend/workflows/templates/workflows/developer_handbook.html +++ b/backend/workflows/templates/workflows/developer_handbook.html @@ -684,6 +684,22 @@ docker compose restart worker
./scripts/deploy_test_from_mac.sh

Sync the current develop checkout to the LAN test server and deploy it.

+
+

Reset a stack from scratch

+
git checkout develop
+RESET_CONFIRM=RESET EXPECTED_BRANCH=develop ./scripts/reset_stack_from_mac.sh
+

Wipe the current test stack state and rebuild it with default bootstrap data.

+
git checkout release/tubco-v1
+RESET_CONFIRM=RESET \
+EXPECTED_BRANCH=release/tubco-v1 \
+DEPLOY_HOST=root@<customer-host> \
+DEPLOY_PATH=/opt/workdock \
+REMOTE_ENV_FILE=.env.prod \
+HEALTH_URL=https://portal.tub.co/healthz/ \
+RUN_DJANGO_CHECK=1 \
+./scripts/reset_stack_from_mac.sh
+

Use the second form for a customer setup from scratch. This is destructive and removes database/media/static/backups before bootstrapping again.

+

Production deployment

./scripts/deploy_prod_from_mac.sh
diff --git a/scripts/reset_stack_from_mac.sh b/scripts/reset_stack_from_mac.sh new file mode 100644 index 0000000..87e1736 --- /dev/null +++ b/scripts/reset_stack_from_mac.sh @@ -0,0 +1,82 @@ +#!/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:-http://192.168.2.55:8088/healthz/}" +REMOTE_ENV_FILE="${REMOTE_ENV_FILE:-.env.test}" +COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.prod.yml}" +RUN_DJANGO_CHECK="${RUN_DJANGO_CHECK:-0}" +SSH_CMD="${SSH_CMD:-ssh -4}" +RSYNC_SSH="${RSYNC_SSH:-ssh -4}" +EXPECTED_BRANCH="${EXPECTED_BRANCH:-}" +RESET_CONFIRM="${RESET_CONFIRM:-}" + +cd "$REPO_ROOT" + +current_branch="$(git branch --show-current)" + +if [[ -n "$EXPECTED_BRANCH" && "$current_branch" != "$EXPECTED_BRANCH" ]]; then + echo "Expected branch '$EXPECTED_BRANCH' for this reset, got '$current_branch'." >&2 + exit 1 +fi + +if [[ "$RESET_CONFIRM" != "RESET" ]]; then + cat >&2 <&2 + echo "Create or restore the server env file before resetting." >&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 "Resetting remote stack state..." +$SSH_CMD "$DEPLOY_HOST" "cd '$DEPLOY_PATH' && export APP_ENV_FILE='$REMOTE_ENV_FILE' && docker compose --env-file '$REMOTE_ENV_FILE' -f '$COMPOSE_FILE' down -v" + +echo "Rebuilding and bootstrapping fresh stack..." +$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 "Reset deployment healthy: $HEALTH_URL" +echo "Deployed commit: $commit_sha" +echo "Branch: $current_branch"