#!/usr/bin/env bash # Builds and brings up an environment, then makes sure WordPress/WooCommerce # are installed and configured to match design doc §01/§03/§07. Safe to run # repeatedly — every step is idempotent. set -euo pipefail ENVIRONMENT="${1:?Usage: deploy.sh }" export ENVIRONMENT REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$REPO_ROOT" case "$ENVIRONMENT" in dev|staging|production) ;; *) echo "environment must be 'dev', 'staging', or 'production'" >&2; exit 1 ;; esac ENV_FILE=".env.${ENVIRONMENT}" if [[ ! -f "$ENV_FILE" ]]; then echo "missing $ENV_FILE — copy .env.example to $ENV_FILE and fill it in" >&2 exit 1 fi # shellcheck source=lib/env.sh source "$REPO_ROOT/deploy/lib/env.sh" SITE_URL="$(env_get "$ENV_FILE" SITE_URL)" SITE_TITLE="$(env_get "$ENV_FILE" SITE_TITLE)" WP_ADMIN_USER="$(env_get "$ENV_FILE" WP_ADMIN_USER)" WP_ADMIN_PASSWORD="$(env_get "$ENV_FILE" WP_ADMIN_PASSWORD)" WP_ADMIN_EMAIL="$(env_get "$ENV_FILE" WP_ADMIN_EMAIL)" # -p pins the Compose project name to the environment (default is the # directory name, which every environment shares — that made staging quietly # reuse dev's db_data volume/credentials the first time this ran). COMPOSE="docker compose -p bookstore-${ENVIRONMENT} -f docker-compose.yml -f docker-compose.${ENVIRONMENT}.yml --env-file ${ENV_FILE}" echo "==> writing DB secret files (bypasses compose's \${VAR} interpolation entirely)" SECRETS_DIR="secrets/${ENVIRONMENT}" mkdir -p "$SECRETS_DIR" chmod 700 "secrets" "$SECRETS_DIR" 2>/dev/null || true DB_PASSWORD_VALUE="$(env_get "$ENV_FILE" DB_PASSWORD)" DB_ROOT_PASSWORD_VALUE="$(env_get "$ENV_FILE" DB_ROOT_PASSWORD)" : "${DB_PASSWORD_VALUE:?set DB_PASSWORD in ${ENV_FILE}}" : "${DB_ROOT_PASSWORD_VALUE:?set DB_ROOT_PASSWORD in ${ENV_FILE}}" printf '%s' "$DB_PASSWORD_VALUE" > "$SECRETS_DIR/db_password" printf '%s' "$DB_ROOT_PASSWORD_VALUE" > "$SECRETS_DIR/db_root_password" # 644, not 600: the db/wordpress/cron containers read this as their own # (non-host-matching) container UID, e.g. www-data — chmod 600 made it # unreadable to them. The containing directory (700, above) is what # actually keeps other host users out; these just need to be world-readable # within that already-restricted directory. chmod 644 "$SECRETS_DIR/db_password" "$SECRETS_DIR/db_root_password" echo "==> building and starting ${ENVIRONMENT}" $COMPOSE up -d --build echo "==> waiting for the wordpress container to come up" for i in $(seq 1 30); do if $COMPOSE exec -T wordpress php -v >/dev/null 2>&1; then break fi if [[ "$i" -eq 30 ]]; then echo "wordpress container did not become ready in time" >&2 exit 1 fi sleep 2 done echo "==> ensuring WordPress is installed" if ! $COMPOSE exec -T wordpress wp core is-installed --allow-root; then $COMPOSE exec -T wordpress wp core install \ --url="${SITE_URL:?set SITE_URL in ${ENV_FILE}}" \ --title="${SITE_TITLE:-Bookstore}" \ --admin_user="${WP_ADMIN_USER:?set WP_ADMIN_USER in ${ENV_FILE}}" \ --admin_password="${WP_ADMIN_PASSWORD:?set WP_ADMIN_PASSWORD in ${ENV_FILE}}" \ --admin_email="${WP_ADMIN_EMAIL:?set WP_ADMIN_EMAIL in ${ENV_FILE}}" \ --skip-email \ --allow-root fi echo "==> installing/activating theme (Blocksy — free; Book Store starter site needs a manual license + import, see README)" $COMPOSE exec -T wordpress wp theme install blocksy --activate --allow-root echo "==> installing/activating required plugins" $COMPOSE exec -T wordpress wp plugin install woocommerce redis-cache blocksy-companion --activate --allow-root $COMPOSE exec -T wordpress wp plugin activate bookstore-core --allow-root $COMPOSE exec -T wordpress wp redis enable --allow-root || true echo "==> enabling WooCommerce HPOS (custom order tables)" $COMPOSE exec -T wordpress wp option update woocommerce_custom_orders_table_enabled yes --allow-root $COMPOSE exec -T wordpress wp option update woocommerce_custom_orders_table_data_sync_enabled yes --allow-root if [[ "$ENVIRONMENT" != "production" ]]; then echo "==> discouraging search engines (non-production)" $COMPOSE exec -T wordpress wp option update blog_public 0 --allow-root fi echo "==> flushing caches and rewrite rules" $COMPOSE exec -T wordpress wp cache flush --allow-root $COMPOSE exec -T wordpress wp rewrite flush --allow-root echo "==> deploy complete: ${ENVIRONMENT}"