#!/usr/bin/env bash set -euo pipefail readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" readonly PROJECT_PATH="${REPO_ROOT}/RpgRoller/RpgRoller.csproj" readonly REMOTE_HOST="myvserver" readonly REMOTE_ROOT="/root/docker/rpgroller" readonly REMOTE_RELEASES_DIR="${REMOTE_ROOT}/releases" readonly REMOTE_CURRENT_LINK="${REMOTE_ROOT}/current" readonly REMOTE_DATA_DIR="${REMOTE_ROOT}/data" readonly CONTAINER_NAME="rpgroller" readonly IMAGE_NAME="rpgroller" readonly CONTAINER_PORT="8080" readonly HOST_PORT="8082" readonly RELEASE_TIMESTAMP="$(date -u +%Y%m%d%H%M%S)" readonly LOCAL_STAGE_DIR="${REPO_ROOT}/artifacts/deploy/${RELEASE_TIMESTAMP}" readonly LOCAL_PUBLISH_DIR="${LOCAL_STAGE_DIR}/publish" readonly REMOTE_RELEASE_DIR="${REMOTE_RELEASES_DIR}/${RELEASE_TIMESTAMP}" cleanup() { rm -rf "${LOCAL_STAGE_DIR}" } trap cleanup EXIT require_tool() { local tool_name="$1" if ! command -v "${tool_name}" >/dev/null 2>&1; then printf 'Required tool not found: %s\n' "${tool_name}" >&2 exit 1 fi } printf 'Deploying release %s\n' "${RELEASE_TIMESTAMP}" require_tool dotnet require_tool rsync require_tool ssh mkdir -p "${LOCAL_PUBLISH_DIR}" printf '1) Publishing app locally...\n' dotnet publish "${PROJECT_PATH}" -c Release -o "${LOCAL_PUBLISH_DIR}" cat > "${LOCAL_STAGE_DIR}/Dockerfile" <<'EOF' FROM mcr.microsoft.com/dotnet/aspnet:10.0 WORKDIR /app ENV ASPNETCORE_URLS=http://+:8080 ENV DOTNET_EnableDiagnostics=0 EXPOSE 8080 COPY publish/ ./ RUN mkdir -p /app/data ENTRYPOINT ["dotnet", "RpgRoller.dll"] EOF printf '2) Preparing remote release directory...\n' ssh "${REMOTE_HOST}" "mkdir -p '${REMOTE_RELEASES_DIR}' '${REMOTE_DATA_DIR}' && test ! -e '${REMOTE_RELEASE_DIR}'" printf '3) Uploading release payload...\n' rsync -az --delete "${LOCAL_STAGE_DIR}/" "${REMOTE_HOST}:${REMOTE_RELEASE_DIR}/" printf '4) Building image and restarting container on remote host...\n' ssh "${REMOTE_HOST}" "bash -se" </dev/null fi if ! docker run -d \ --name "\${container_name}" \ --restart unless-stopped \ -p "127.0.0.1:\${host_port}:\${container_port}" \ -e ASPNETCORE_ENVIRONMENT=Production \ -e ASPNETCORE_URLS="http://+:\${container_port}" \ -e ConnectionStrings__RpgRoller="Data Source=/app/data/rpgroller.db" \ -v "\${remote_data_dir}:/app/data" \ "\${image_name}:\${release_timestamp}" >/dev/null; then if [ -n "\${previous_current_target}" ]; then ln -sfn "\${previous_current_target}" "\${remote_current_link}" fi exit 1 fi EOF printf '5) Deployment complete.\n'