AI-Development-Server/install/phases/50-plotdirector-dev.sh

219 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
REPO_ROOT="$(cd "${INSTALL_DIR}/.." && pwd)"
# shellcheck source=install/lib/common.sh
source "${INSTALL_DIR}/lib/common.sh"
# shellcheck source=install/lib/logging.sh
source "${INSTALL_DIR}/lib/logging.sh"
# shellcheck source=install/lib/files.sh
source "${INSTALL_DIR}/lib/files.sh"
atlas_set_script_name "50-plotdirector-dev.sh"
atlas_install_error_trap
APP_REPO="/srv/repos/PlotDirector"
APP_BRANCH="onboarding"
APP_PROJECT="${APP_REPO}/PlotLine/PlotLine.csproj"
PUBLISH_DIR="/srv/apps/plotdirector-dev/current"
UPLOADS_DIR="/srv/apps/plotdirector-dev/uploads"
ENV_FILE="/etc/plotdirector/plotdirector.env"
SERVICE_USER="plotdirector"
SERVICE_NAME="plotdirector-dev"
SYSTEMD_SOURCE="${REPO_ROOT}/config/systemd/plotdirector-dev.service"
SYSTEMD_DEST="/etc/systemd/system/plotdirector-dev.service"
NGINX_SOURCE="${REPO_ROOT}/config/nginx/plotdirector-dev.conf"
NGINX_DEST="/etc/nginx/sites-available/plotdirector-dev.conf"
NGINX_LINK="/etc/nginx/sites-enabled/plotdirector-dev.conf"
NGINX_BACKUP_DIR="/etc/nginx/atlas-backups"
ALLOW_DIRTY=0
usage() {
cat <<'USAGE'
Usage: install/phases/50-plotdirector-dev.sh [options]
Publish and run the PlotDirector onboarding branch as the Atlas development
instance behind nginx. This script does not modify PlotDirector source,
create Git commits, or store secrets.
Prerequisites:
- /srv/repos/PlotDirector exists on branch onboarding.
- /etc/plotdirector/plotdirector.env exists and contains runtime settings.
- The PlotDirector development database has already been initialised.
Options:
--help Show this help text.
--version Show script/framework version.
--dry-run Show intended actions without making changes.
--verbose Print additional diagnostic output.
--allow-dirty Permit deployment from a dirty PlotDirector working tree.
USAGE
}
while [[ "$#" -gt 0 ]]; do
case "$1" in
--help)
usage
exit "${ATLAS_EXIT_OK}"
;;
--version)
atlas_print_version
exit "${ATLAS_EXIT_OK}"
;;
--dry-run)
atlas_enable_dry_run
;;
--verbose)
atlas_enable_verbose
;;
--allow-dirty)
ALLOW_DIRTY=1
;;
*)
atlas_usage_error "Unknown option: $1"
exit "${ATLAS_EXIT_USAGE}"
;;
esac
shift
done
require_prerequisites() {
atlas_require_command git
atlas_require_command dotnet
atlas_require_command curl
atlas_require_sudo_noninteractive || {
atlas_log_error "Passwordless non-interactive sudo is required"
exit "${ATLAS_EXIT_PREREQ}"
}
if [[ ! -d "${APP_REPO}/.git" ]]; then
atlas_log_error "PlotDirector repository not found at ${APP_REPO}"
exit "${ATLAS_EXIT_PREREQ}"
fi
local current_branch
current_branch="$(git -C "$APP_REPO" branch --show-current)"
if [[ "$current_branch" != "$APP_BRANCH" ]]; then
atlas_log_error "Expected ${APP_REPO} to be on ${APP_BRANCH}; found ${current_branch}"
exit "${ATLAS_EXIT_UNSAFE}"
fi
if [[ "$ALLOW_DIRTY" != "1" ]] && [[ -n "$(git -C "$APP_REPO" status --porcelain)" ]]; then
atlas_log_error "PlotDirector working tree is dirty. Use --allow-dirty only for deliberate local deployments."
exit "${ATLAS_EXIT_UNSAFE}"
fi
if ! sudo -n test -f "$ENV_FILE"; then
atlas_log_error "Runtime environment file is missing: ${ENV_FILE}"
exit "${ATLAS_EXIT_PREREQ}"
fi
}
ensure_runtime_user_and_dirs() {
if atlas_is_dry_run; then
atlas_log_info "Dry-run mode: would ensure ${SERVICE_USER} user and deployment directories"
return 0
fi
if ! id "$SERVICE_USER" >/dev/null 2>&1; then
sudo -n useradd --system --home-dir /srv/apps/plotdirector-dev --shell /usr/sbin/nologin --create-home "$SERVICE_USER"
fi
sudo -n install -d -m 0750 -o "$SERVICE_USER" -g "$SERVICE_USER" /srv/apps/plotdirector-dev "$PUBLISH_DIR" "$UPLOADS_DIR"
local srv_mode
srv_mode="$(stat -c '%a' /srv)"
if (( (8#$srv_mode & 0001) == 0 )); then
sudo -n chmod o+x /srv
fi
sudo -n chown root:"$SERVICE_USER" /etc/plotdirector
sudo -n chmod 0750 /etc/plotdirector
sudo -n chown root:"$SERVICE_USER" "$ENV_FILE"
sudo -n chmod 0640 "$ENV_FILE"
}
publish_application() {
if atlas_is_dry_run; then
atlas_log_info "Dry-run mode: would restore and publish ${APP_PROJECT} to ${PUBLISH_DIR}"
return 0
fi
local publish_tmp
publish_tmp="$(mktemp -d)"
dotnet restore "$APP_PROJECT"
dotnet publish "$APP_PROJECT" --configuration Release --output "$publish_tmp"
sudo -n rsync -a --delete "${publish_tmp}/" "${PUBLISH_DIR}/"
sudo -n chown -R "${SERVICE_USER}:${SERVICE_USER}" "$PUBLISH_DIR" "$UPLOADS_DIR"
sudo -n find "$PUBLISH_DIR" -type d -exec chmod 0750 {} +
sudo -n find "$PUBLISH_DIR" -type f -exec chmod 0640 {} +
rm -rf "$publish_tmp"
}
deploy_systemd_unit() {
if atlas_is_dry_run; then
atlas_log_info "Dry-run mode: would deploy ${SYSTEMD_DEST}"
atlas_log_info "Dry-run mode: would enable ${SERVICE_NAME}"
return 0
fi
if [[ -f "$SYSTEMD_DEST" ]] && cmp -s "$SYSTEMD_SOURCE" "$SYSTEMD_DEST"; then
atlas_log_ok "No change required for ${SYSTEMD_DEST}"
else
sudo -n install -m 0644 -o root -g root "$SYSTEMD_SOURCE" "$SYSTEMD_DEST"
atlas_log_ok "Updated ${SYSTEMD_DEST}"
fi
sudo -n systemctl daemon-reload
sudo -n systemctl enable "$SERVICE_NAME"
}
deploy_nginx_site() {
if atlas_is_dry_run; then
atlas_log_info "Dry-run mode: would deploy nginx site ${NGINX_DEST}"
return 0
fi
sudo -n install -d -m 0755 /etc/nginx/sites-available /etc/nginx/sites-enabled
sudo -n install -d -m 0750 "$NGINX_BACKUP_DIR"
sudo -n nginx -t
sudo -n install -m 0644 "$NGINX_SOURCE" "$NGINX_DEST"
sudo -n ln -sfn "$NGINX_DEST" "$NGINX_LINK"
sudo -n nginx -t
}
restart_and_verify() {
if atlas_is_dry_run; then
atlas_log_info "Dry-run mode: would restart ${SERVICE_NAME}, reload nginx, and verify HTTP responses"
return 0
fi
sudo -n systemctl restart "$SERVICE_NAME"
local attempt
for attempt in {1..30}; do
if curl -fsS http://127.0.0.1:5050/ >/dev/null 2>&1; then
break
fi
sleep 2
done
curl -fsS http://127.0.0.1:5050/ >/dev/null
sudo -n nginx -t
sudo -n systemctl reload nginx
curl -fsS -H "Host: dev.plotdirector.com" http://127.0.0.1/health >/dev/null
atlas_log_ok "PlotDirector development deployment verified"
}
main() {
require_prerequisites
ensure_runtime_user_and_dirs
publish_application
deploy_systemd_unit
deploy_nginx_site
restart_and_verify
}
main