update deployment instructions

This commit is contained in:
Forbes
2026-01-26 21:31:49 -06:00
parent f9324686c5
commit f37052c2f0
6 changed files with 923 additions and 1 deletions

372
scripts/deploy.sh Executable file
View File

@@ -0,0 +1,372 @@
#!/usr/bin/env bash
#
# Silo Deployment Script
# Deploys silod to silo.kindred.internal via systemd
#
# Usage:
# ./scripts/deploy.sh [options]
#
# Options:
# --build-only Only build the binary, don't deploy
# --no-build Skip build, deploy existing binary
# --restart-only Only restart the service
# --dry-run Show what would be done without doing it
# --help Show this help message
#
# Environment variables:
# SILO_HOST Target host (default: silo.kindred.internal)
# SILO_USER SSH user (default: deploy)
# SILO_SSH_KEY Path to SSH private key (optional)
# BUILD_VERSION Version string for build (default: git describe)
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Configuration
SILO_HOST="${SILO_HOST:-silo.kindred.internal}"
SILO_USER="${SILO_USER:-deploy}"
SILO_SSH_KEY="${SILO_SSH_KEY:-}"
BUILD_VERSION="${BUILD_VERSION:-$(git describe --tags --always --dirty 2>/dev/null || echo "dev")}"
# Paths
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
BUILD_DIR="${PROJECT_ROOT}/build/out"
BINARY_NAME="silod"
# Remote paths
REMOTE_BIN_DIR="/opt/silo/bin"
REMOTE_CONFIG_DIR="/etc/silo"
REMOTE_SCHEMAS_DIR="/etc/silo/schemas"
REMOTE_SERVICE="silod"
# Flags
BUILD=true
DEPLOY=true
DRY_RUN=false
# Functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $*"
}
log_success() {
echo -e "${GREEN}[OK]${NC} $*"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
die() {
log_error "$*"
exit 1
}
show_help() {
head -20 "$0" | grep -E '^#' | sed 's/^# *//'
exit 0
}
ssh_cmd() {
local ssh_opts=(-o StrictHostKeyChecking=accept-new -o ConnectTimeout=10)
if [[ -n "${SILO_SSH_KEY}" ]]; then
ssh_opts+=(-i "${SILO_SSH_KEY}")
fi
if [[ "${DRY_RUN}" == "true" ]]; then
echo "[DRY-RUN] ssh ${ssh_opts[*]} ${SILO_USER}@${SILO_HOST} $*"
else
ssh "${ssh_opts[@]}" "${SILO_USER}@${SILO_HOST}" "$@"
fi
}
scp_cmd() {
local scp_opts=(-o StrictHostKeyChecking=accept-new -o ConnectTimeout=10)
if [[ -n "${SILO_SSH_KEY}" ]]; then
scp_opts+=(-i "${SILO_SSH_KEY}")
fi
if [[ "${DRY_RUN}" == "true" ]]; then
echo "[DRY-RUN] scp ${scp_opts[*]} $*"
else
scp "${scp_opts[@]}" "$@"
fi
}
check_dependencies() {
log_info "Checking dependencies..."
local missing=()
command -v go >/dev/null 2>&1 || missing+=("go")
command -v ssh >/dev/null 2>&1 || missing+=("ssh")
command -v scp >/dev/null 2>&1 || missing+=("scp")
command -v git >/dev/null 2>&1 || missing+=("git")
if [[ ${#missing[@]} -gt 0 ]]; then
die "Missing required commands: ${missing[*]}"
fi
log_success "All dependencies available"
}
check_connectivity() {
log_info "Checking connectivity to ${SILO_HOST}..."
if [[ "${DRY_RUN}" == "true" ]]; then
log_info "[DRY-RUN] Would check SSH connectivity"
return 0
fi
if ! ssh_cmd "echo 'Connection successful'" >/dev/null 2>&1; then
die "Cannot connect to ${SILO_HOST} as ${SILO_USER}"
fi
log_success "SSH connection verified"
}
build_binary() {
log_info "Building ${BINARY_NAME} (version: ${BUILD_VERSION})..."
mkdir -p "${BUILD_DIR}"
local ldflags="-w -s -X main.Version=${BUILD_VERSION}"
if [[ "${DRY_RUN}" == "true" ]]; then
echo "[DRY-RUN] CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags=\"${ldflags}\" -o ${BUILD_DIR}/${BINARY_NAME} ./cmd/silod"
return 0
fi
cd "${PROJECT_ROOT}"
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="${ldflags}" \
-o "${BUILD_DIR}/${BINARY_NAME}" \
./cmd/silod
if [[ ! -f "${BUILD_DIR}/${BINARY_NAME}" ]]; then
die "Build failed: binary not found"
fi
local size
size=$(du -h "${BUILD_DIR}/${BINARY_NAME}" | cut -f1)
log_success "Built ${BINARY_NAME} (${size})"
}
deploy_binary() {
log_info "Deploying binary to ${SILO_HOST}..."
local binary="${BUILD_DIR}/${BINARY_NAME}"
if [[ ! -f "${binary}" ]] && [[ "${DRY_RUN}" != "true" ]]; then
die "Binary not found: ${binary}"
fi
# Upload to temp location first
scp_cmd "${binary}" "${SILO_USER}@${SILO_HOST}:/tmp/${BINARY_NAME}.new"
# Move to final location with sudo
ssh_cmd "sudo mv /tmp/${BINARY_NAME}.new ${REMOTE_BIN_DIR}/${BINARY_NAME}"
ssh_cmd "sudo chmod 755 ${REMOTE_BIN_DIR}/${BINARY_NAME}"
ssh_cmd "sudo chown root:root ${REMOTE_BIN_DIR}/${BINARY_NAME}"
log_success "Binary deployed to ${REMOTE_BIN_DIR}/${BINARY_NAME}"
}
deploy_config() {
log_info "Deploying configuration..."
local config_file="${PROJECT_ROOT}/deployments/config.prod.yaml"
if [[ ! -f "${config_file}" ]] && [[ "${DRY_RUN}" != "true" ]]; then
die "Config file not found: ${config_file}"
fi
scp_cmd "${config_file}" "${SILO_USER}@${SILO_HOST}:/tmp/config.yaml"
ssh_cmd "sudo mv /tmp/config.yaml ${REMOTE_CONFIG_DIR}/config.yaml"
ssh_cmd "sudo chmod 644 ${REMOTE_CONFIG_DIR}/config.yaml"
ssh_cmd "sudo chown root:silo ${REMOTE_CONFIG_DIR}/config.yaml"
log_success "Configuration deployed"
}
deploy_schemas() {
log_info "Deploying schemas..."
local schemas_dir="${PROJECT_ROOT}/schemas"
if [[ ! -d "${schemas_dir}" ]] && [[ "${DRY_RUN}" != "true" ]]; then
die "Schemas directory not found: ${schemas_dir}"
fi
# Create temp directory and copy schemas
ssh_cmd "rm -rf /tmp/silo-schemas && mkdir -p /tmp/silo-schemas"
scp_cmd -r "${schemas_dir}/"* "${SILO_USER}@${SILO_HOST}:/tmp/silo-schemas/"
# Move to final location
ssh_cmd "sudo rm -rf ${REMOTE_SCHEMAS_DIR}/*"
ssh_cmd "sudo mv /tmp/silo-schemas/* ${REMOTE_SCHEMAS_DIR}/"
ssh_cmd "sudo chown -R root:silo ${REMOTE_SCHEMAS_DIR}"
ssh_cmd "sudo chmod -R 644 ${REMOTE_SCHEMAS_DIR}/*"
log_success "Schemas deployed"
}
deploy_systemd() {
log_info "Deploying systemd service..."
local service_file="${PROJECT_ROOT}/deployments/systemd/silod.service"
if [[ ! -f "${service_file}" ]] && [[ "${DRY_RUN}" != "true" ]]; then
die "Service file not found: ${service_file}"
fi
scp_cmd "${service_file}" "${SILO_USER}@${SILO_HOST}:/tmp/silod.service"
ssh_cmd "sudo mv /tmp/silod.service /etc/systemd/system/silod.service"
ssh_cmd "sudo chmod 644 /etc/systemd/system/silod.service"
ssh_cmd "sudo systemctl daemon-reload"
log_success "Systemd service deployed"
}
restart_service() {
log_info "Restarting ${REMOTE_SERVICE} service..."
ssh_cmd "sudo systemctl restart ${REMOTE_SERVICE}"
# Wait for service to start
sleep 2
if [[ "${DRY_RUN}" != "true" ]]; then
if ssh_cmd "sudo systemctl is-active --quiet ${REMOTE_SERVICE}"; then
log_success "Service restarted successfully"
else
log_error "Service failed to start"
ssh_cmd "sudo journalctl -u ${REMOTE_SERVICE} -n 20 --no-pager" || true
die "Deployment failed: service not running"
fi
else
log_info "[DRY-RUN] Would verify service is running"
fi
}
verify_deployment() {
log_info "Verifying deployment..."
if [[ "${DRY_RUN}" == "true" ]]; then
log_info "[DRY-RUN] Would verify health endpoints"
return 0
fi
# Wait a moment for service to fully start
sleep 3
# Check health endpoint
local health_status
health_status=$(ssh_cmd "curl -sf http://localhost:8080/health" 2>/dev/null || echo "FAILED")
if [[ "${health_status}" == *"ok"* ]] || [[ "${health_status}" == *"healthy"* ]]; then
log_success "Health check passed"
else
log_warn "Health check returned: ${health_status}"
fi
# Check ready endpoint (includes DB and MinIO)
local ready_status
ready_status=$(ssh_cmd "curl -sf http://localhost:8080/ready" 2>/dev/null || echo "FAILED")
if [[ "${ready_status}" == *"ok"* ]] || [[ "${ready_status}" == *"ready"* ]]; then
log_success "Readiness check passed (DB and MinIO connected)"
else
log_warn "Readiness check returned: ${ready_status}"
log_warn "Service may still be starting or external services unavailable"
fi
# Show deployed version
local deployed_version
deployed_version=$(ssh_cmd "${REMOTE_BIN_DIR}/${BINARY_NAME} --version" 2>/dev/null || echo "unknown")
log_info "Deployed version: ${deployed_version}"
}
enable_service() {
log_info "Enabling ${REMOTE_SERVICE} service..."
ssh_cmd "sudo systemctl enable ${REMOTE_SERVICE}"
log_success "Service enabled for auto-start"
}
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
--build-only)
DEPLOY=false
shift
;;
--no-build)
BUILD=false
shift
;;
--restart-only)
BUILD=false
DEPLOY=false
restart_service
exit 0
;;
--dry-run)
DRY_RUN=true
shift
;;
--help|-h)
show_help
;;
*)
die "Unknown option: $1"
;;
esac
done
# Main execution
main() {
log_info "Silo Deployment Script"
log_info "======================"
log_info "Target: ${SILO_USER}@${SILO_HOST}"
log_info "Version: ${BUILD_VERSION}"
if [[ "${DRY_RUN}" == "true" ]]; then
log_warn "DRY-RUN MODE: No changes will be made"
fi
echo ""
check_dependencies
if [[ "${BUILD}" == "true" ]]; then
build_binary
fi
if [[ "${DEPLOY}" == "true" ]]; then
check_connectivity
deploy_binary
deploy_config
deploy_schemas
deploy_systemd
enable_service
restart_service
verify_deployment
fi
echo ""
log_success "Deployment complete!"
}
main "$@"