feat(deploy): add deployment scripts for clock and notes repos
- Add deploy-clock.sh for ChronoMind deployment (backend:4011, web:3030) - Add deploy-notes.sh for NoteLett deployment (backend:4016, web:3000) - Both scripts follow same pattern as deploy-invttrdg.sh - Include dirty checks, pull/rebase, smoke tests, Docker deployment, health checks Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
bdf0fba468
commit
0f61684397
223
deploy-clock.sh
Executable file
223
deploy-clock.sh
Executable file
@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# ByteLyst ChronoMind - Production Deployment Script
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Usage: ./deploy-clock.sh [--force] [--skip-health-check]
|
||||
#
|
||||
# What it does:
|
||||
# 1. Dirty check: uncommitted changes, unpushed commits
|
||||
# 2. Pull and rebase origin/main
|
||||
# 3. Build and deploy Docker containers
|
||||
# 4. Verify endpoints: https://api.bytelyst.com/chronomind, http://localhost:3030
|
||||
#
|
||||
# Options:
|
||||
# --force Skip dirty checks and force deployment
|
||||
# --skip-health-check Skip endpoint health verification
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
|
||||
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[$(date +%H:%M:%S)] ✓${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[$(date +%H:%M:%S)] ⚠${NC} $*"; }
|
||||
fail() { echo -e "${RED}[$(date +%H:%M:%S)] ✗${NC} $*"; exit 1; }
|
||||
|
||||
# ── Configuration ────────────────────────────────────────────────────
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_DIR="${SCRIPT_DIR}/../learning_ai_clock"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
FORCE=false
|
||||
SKIP_HEALTH_CHECK=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) FORCE=true; shift ;;
|
||||
--skip-health-check) SKIP_HEALTH_CHECK=true; shift ;;
|
||||
*) fail "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Prerequisites ────────────────────────────────────────────────────
|
||||
if [ ! -d "$REPO_DIR" ]; then
|
||||
fail "Repo directory not found: $REPO_DIR"
|
||||
fi
|
||||
|
||||
cd "$REPO_DIR"
|
||||
|
||||
# ── Dirty Check ───────────────────────────────────────────────────────
|
||||
if [ "$FORCE" = false ]; then
|
||||
log "Running dirty checks..."
|
||||
|
||||
# Check for uncommitted changes
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
fail "Uncommitted changes detected. Commit or stash first, or use --force"
|
||||
fi
|
||||
|
||||
# Check for untracked files
|
||||
if [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
||||
fail "Untracked files detected. Commit or remove them, or use --force"
|
||||
fi
|
||||
|
||||
# Check for unpushed commits
|
||||
LOCAL_COMMIT=$(git rev-parse @)
|
||||
REMOTE_COMMIT=$(git rev-parse '@{u}' 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$REMOTE_COMMIT" ] && [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then
|
||||
fail "Unpushed commits detected. Push first or use --force"
|
||||
fi
|
||||
|
||||
ok "Dirty checks passed"
|
||||
else
|
||||
warn "Skipping dirty checks (--force enabled)"
|
||||
fi
|
||||
|
||||
# ── Pull and Rebase ───────────────────────────────────────────────────
|
||||
log "Pulling latest changes from origin/main..."
|
||||
git fetch origin
|
||||
|
||||
LOCAL_MAIN=$(git rev-parse main)
|
||||
REMOTE_MAIN=$(git rev-parse origin/main)
|
||||
|
||||
if [ "$LOCAL_MAIN" != "$REMOTE_MAIN" ]; then
|
||||
log "Local main is behind origin/main, rebasing..."
|
||||
git rebase origin/main || {
|
||||
fail "Rebase failed. Resolve conflicts and run: git rebase --continue"
|
||||
}
|
||||
ok "Rebase completed successfully"
|
||||
else
|
||||
ok "Already up to date with origin/main"
|
||||
fi
|
||||
|
||||
# ── Run Smoke Tests ─────────────────────────────────────────────────────
|
||||
if [ "$SKIP_HEALTH_CHECK" = false ]; then
|
||||
log "Running smoke tests before deployment..."
|
||||
if [ -f "scripts/smoke-release.sh" ]; then
|
||||
chmod +x scripts/smoke-release.sh
|
||||
./scripts/smoke-release.sh || {
|
||||
fail "Smoke tests failed. Fix issues before deploying or use --skip-health-check"
|
||||
}
|
||||
ok "Smoke tests passed"
|
||||
else
|
||||
warn "Smoke test script not found, skipping pre-deployment tests"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Build and Deploy ──────────────────────────────────────────────────
|
||||
log "Building and deploying Docker containers..."
|
||||
|
||||
# Check if docker-compose files exist
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
fail "docker-compose.yml not found in $REPO_DIR"
|
||||
fi
|
||||
|
||||
# Build and start services
|
||||
log "Building Docker images..."
|
||||
docker compose build || fail "Docker build failed"
|
||||
|
||||
log "Starting services..."
|
||||
docker compose up -d || fail "Docker compose up failed"
|
||||
|
||||
ok "Deployment completed"
|
||||
|
||||
# ── Health Check ──────────────────────────────────────────────────────
|
||||
if [ "$SKIP_HEALTH_CHECK" = true ]; then
|
||||
warn "Skipping health checks (--skip-health-check enabled)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Waiting for services to be healthy..."
|
||||
sleep 10
|
||||
|
||||
# Check backend health
|
||||
BACKEND_HEALTH=false
|
||||
for _ in {1..30}; do
|
||||
if curl -sf http://localhost:4011/health > /dev/null 2>&1; then
|
||||
BACKEND_HEALTH=true
|
||||
break
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 2
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ "$BACKEND_HEALTH" = true ]; then
|
||||
ok "Backend health check passed (http://localhost:4011)"
|
||||
else
|
||||
fail "Backend health check failed"
|
||||
fi
|
||||
|
||||
# Check web health
|
||||
WEB_HEALTH=false
|
||||
for _ in {1..30}; do
|
||||
if curl -sf http://localhost:3030 > /dev/null 2>&1; then
|
||||
WEB_HEALTH=true
|
||||
break
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 2
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ "$WEB_HEALTH" = true ]; then
|
||||
ok "Web health check passed (http://localhost:3030)"
|
||||
else
|
||||
warn "Web health check failed (may be starting up)"
|
||||
fi
|
||||
|
||||
# ── Endpoint Verification ─────────────────────────────────────────────
|
||||
log "Verifying production endpoints..."
|
||||
|
||||
API_ENDPOINT="https://api.bytelyst.com/chronomind"
|
||||
WEB_ENDPOINT="http://localhost:3030"
|
||||
|
||||
# Check API endpoint
|
||||
if curl -sf "$API_ENDPOINT/health" > /dev/null 2>&1; then
|
||||
ok "API endpoint accessible: $API_ENDPOINT"
|
||||
else
|
||||
warn "API endpoint not accessible: $API_ENDPOINT (may need DNS propagation or routing)"
|
||||
fi
|
||||
|
||||
# Check web endpoint
|
||||
if curl -sf "$WEB_ENDPOINT" > /dev/null 2>&1; then
|
||||
ok "Web endpoint accessible: $WEB_ENDPOINT"
|
||||
else
|
||||
warn "Web endpoint not accessible: $WEB_ENDPOINT (may be starting up)"
|
||||
fi
|
||||
|
||||
# ── API Smoke Tests (Post-Deployment) ───────────────────────────────────
|
||||
log "Running post-deployment API smoke tests..."
|
||||
|
||||
# Test backend health endpoint
|
||||
BACKEND_URL="http://localhost:4011"
|
||||
if curl -sf "$BACKEND_URL/health" > /dev/null 2>&1; then
|
||||
ok "Backend health endpoint responding"
|
||||
# Try to get health details
|
||||
HEALTH_RESPONSE=$(curl -s "$BACKEND_URL/health" 2>/dev/null || echo "{}")
|
||||
log "Health response: $HEALTH_RESPONSE"
|
||||
else
|
||||
fail "Backend health endpoint not responding"
|
||||
fi
|
||||
|
||||
# Test web is serving content
|
||||
WEB_URL="http://localhost:3030"
|
||||
if curl -sf "$WEB_URL" > /dev/null 2>&1; then
|
||||
ok "Web frontend is serving content"
|
||||
# Check if it's actually HTML
|
||||
CONTENT_TYPE=$(curl -sI "$WEB_URL" | grep -i content-type || echo "")
|
||||
if echo "$CONTENT_TYPE" | grep -qi "text/html"; then
|
||||
ok "Web frontend is serving HTML content"
|
||||
else
|
||||
warn "Web frontend content type unexpected: $CONTENT_TYPE"
|
||||
fi
|
||||
else
|
||||
fail "Web frontend not responding"
|
||||
fi
|
||||
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
ok "Deployment completed successfully!"
|
||||
log "Backend: http://localhost:4011 → $API_ENDPOINT"
|
||||
log "Web: http://localhost:3030"
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
223
deploy-notes.sh
Executable file
223
deploy-notes.sh
Executable file
@ -0,0 +1,223 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# ByteLyst NoteLett - Production Deployment Script
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Usage: ./deploy-notes.sh [--force] [--skip-health-check]
|
||||
#
|
||||
# What it does:
|
||||
# 1. Dirty check: uncommitted changes, unpushed commits
|
||||
# 2. Pull and rebase origin/main
|
||||
# 3. Build and deploy Docker containers
|
||||
# 4. Verify endpoints: https://api.bytelyst.com/notelett, http://localhost:3000
|
||||
#
|
||||
# Options:
|
||||
# --force Skip dirty checks and force deployment
|
||||
# --skip-health-check Skip endpoint health verification
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
|
||||
log() { echo -e "${CYAN}[$(date +%H:%M:%S)]${NC} $*"; }
|
||||
ok() { echo -e "${GREEN}[$(date +%H:%M:%S)] ✓${NC} $*"; }
|
||||
warn() { echo -e "${YELLOW}[$(date +%H:%M:%S)] ⚠${NC} $*"; }
|
||||
fail() { echo -e "${RED}[$(date +%H:%M:%S)] ✗${NC} $*"; exit 1; }
|
||||
|
||||
# ── Configuration ────────────────────────────────────────────────────
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
REPO_DIR="${SCRIPT_DIR}/../learning_ai_notes"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
FORCE=false
|
||||
SKIP_HEALTH_CHECK=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) FORCE=true; shift ;;
|
||||
--skip-health-check) SKIP_HEALTH_CHECK=true; shift ;;
|
||||
*) fail "Unknown option: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Prerequisites ────────────────────────────────────────────────────
|
||||
if [ ! -d "$REPO_DIR" ]; then
|
||||
fail "Repo directory not found: $REPO_DIR"
|
||||
fi
|
||||
|
||||
cd "$REPO_DIR"
|
||||
|
||||
# ── Dirty Check ───────────────────────────────────────────────────────
|
||||
if [ "$FORCE" = false ]; then
|
||||
log "Running dirty checks..."
|
||||
|
||||
# Check for uncommitted changes
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
fail "Uncommitted changes detected. Commit or stash first, or use --force"
|
||||
fi
|
||||
|
||||
# Check for untracked files
|
||||
if [ -n "$(git ls-files --others --exclude-standard)" ]; then
|
||||
fail "Untracked files detected. Commit or remove them, or use --force"
|
||||
fi
|
||||
|
||||
# Check for unpushed commits
|
||||
LOCAL_COMMIT=$(git rev-parse @)
|
||||
REMOTE_COMMIT=$(git rev-parse '@{u}' 2>/dev/null || echo "")
|
||||
|
||||
if [ -n "$REMOTE_COMMIT" ] && [ "$LOCAL_COMMIT" != "$REMOTE_COMMIT" ]; then
|
||||
fail "Unpushed commits detected. Push first or use --force"
|
||||
fi
|
||||
|
||||
ok "Dirty checks passed"
|
||||
else
|
||||
warn "Skipping dirty checks (--force enabled)"
|
||||
fi
|
||||
|
||||
# ── Pull and Rebase ───────────────────────────────────────────────────
|
||||
log "Pulling latest changes from origin/main..."
|
||||
git fetch origin
|
||||
|
||||
LOCAL_MAIN=$(git rev-parse main)
|
||||
REMOTE_MAIN=$(git rev-parse origin/main)
|
||||
|
||||
if [ "$LOCAL_MAIN" != "$REMOTE_MAIN" ]; then
|
||||
log "Local main is behind origin/main, rebasing..."
|
||||
git rebase origin/main || {
|
||||
fail "Rebase failed. Resolve conflicts and run: git rebase --continue"
|
||||
}
|
||||
ok "Rebase completed successfully"
|
||||
else
|
||||
ok "Already up to date with origin/main"
|
||||
fi
|
||||
|
||||
# ── Run Smoke Tests ─────────────────────────────────────────────────────
|
||||
if [ "$SKIP_HEALTH_CHECK" = false ]; then
|
||||
log "Running smoke tests before deployment..."
|
||||
if [ -f "scripts/smoke-release.sh" ]; then
|
||||
chmod +x scripts/smoke-release.sh
|
||||
./scripts/smoke-release.sh || {
|
||||
fail "Smoke tests failed. Fix issues before deploying or use --skip-health-check"
|
||||
}
|
||||
ok "Smoke tests passed"
|
||||
else
|
||||
warn "Smoke test script not found, skipping pre-deployment tests"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Build and Deploy ──────────────────────────────────────────────────
|
||||
log "Building and deploying Docker containers..."
|
||||
|
||||
# Check if docker-compose files exist
|
||||
if [ ! -f "docker-compose.yml" ]; then
|
||||
fail "docker-compose.yml not found in $REPO_DIR"
|
||||
fi
|
||||
|
||||
# Build and start services
|
||||
log "Building Docker images..."
|
||||
docker compose build || fail "Docker build failed"
|
||||
|
||||
log "Starting services..."
|
||||
docker compose up -d || fail "Docker compose up failed"
|
||||
|
||||
ok "Deployment completed"
|
||||
|
||||
# ── Health Check ──────────────────────────────────────────────────────
|
||||
if [ "$SKIP_HEALTH_CHECK" = true ]; then
|
||||
warn "Skipping health checks (--skip-health-check enabled)"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Waiting for services to be healthy..."
|
||||
sleep 10
|
||||
|
||||
# Check backend health
|
||||
BACKEND_HEALTH=false
|
||||
for _ in {1..30}; do
|
||||
if curl -sf http://localhost:4016/health > /dev/null 2>&1; then
|
||||
BACKEND_HEALTH=true
|
||||
break
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 2
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ "$BACKEND_HEALTH" = true ]; then
|
||||
ok "Backend health check passed (http://localhost:4016)"
|
||||
else
|
||||
fail "Backend health check failed"
|
||||
fi
|
||||
|
||||
# Check web health
|
||||
WEB_HEALTH=false
|
||||
for _ in {1..30}; do
|
||||
if curl -sf http://localhost:3000 > /dev/null 2>&1; then
|
||||
WEB_HEALTH=true
|
||||
break
|
||||
fi
|
||||
echo -n "."
|
||||
sleep 2
|
||||
done
|
||||
echo ""
|
||||
|
||||
if [ "$WEB_HEALTH" = true ]; then
|
||||
ok "Web health check passed (http://localhost:3000)"
|
||||
else
|
||||
warn "Web health check failed (may be starting up)"
|
||||
fi
|
||||
|
||||
# ── Endpoint Verification ─────────────────────────────────────────────
|
||||
log "Verifying production endpoints..."
|
||||
|
||||
API_ENDPOINT="https://api.bytelyst.com/notelett"
|
||||
WEB_ENDPOINT="http://localhost:3000"
|
||||
|
||||
# Check API endpoint
|
||||
if curl -sf "$API_ENDPOINT/health" > /dev/null 2>&1; then
|
||||
ok "API endpoint accessible: $API_ENDPOINT"
|
||||
else
|
||||
warn "API endpoint not accessible: $API_ENDPOINT (may need DNS propagation or routing)"
|
||||
fi
|
||||
|
||||
# Check web endpoint
|
||||
if curl -sf "$WEB_ENDPOINT" > /dev/null 2>&1; then
|
||||
ok "Web endpoint accessible: $WEB_ENDPOINT"
|
||||
else
|
||||
warn "Web endpoint not accessible: $WEB_ENDPOINT (may be starting up)"
|
||||
fi
|
||||
|
||||
# ── API Smoke Tests (Post-Deployment) ───────────────────────────────────
|
||||
log "Running post-deployment API smoke tests..."
|
||||
|
||||
# Test backend health endpoint
|
||||
BACKEND_URL="http://localhost:4016"
|
||||
if curl -sf "$BACKEND_URL/health" > /dev/null 2>&1; then
|
||||
ok "Backend health endpoint responding"
|
||||
# Try to get health details
|
||||
HEALTH_RESPONSE=$(curl -s "$BACKEND_URL/health" 2>/dev/null || echo "{}")
|
||||
log "Health response: $HEALTH_RESPONSE"
|
||||
else
|
||||
fail "Backend health endpoint not responding"
|
||||
fi
|
||||
|
||||
# Test web is serving content
|
||||
WEB_URL="http://localhost:3000"
|
||||
if curl -sf "$WEB_URL" > /dev/null 2>&1; then
|
||||
ok "Web frontend is serving content"
|
||||
# Check if it's actually HTML
|
||||
CONTENT_TYPE=$(curl -sI "$WEB_URL" | grep -i content-type || echo "")
|
||||
if echo "$CONTENT_TYPE" | grep -qi "text/html"; then
|
||||
ok "Web frontend is serving HTML content"
|
||||
else
|
||||
warn "Web frontend content type unexpected: $CONTENT_TYPE"
|
||||
fi
|
||||
else
|
||||
fail "Web frontend not responding"
|
||||
fi
|
||||
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
ok "Deployment completed successfully!"
|
||||
log "Backend: http://localhost:4016 → $API_ENDPOINT"
|
||||
log "Web: http://localhost:3000"
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
Loading…
Reference in New Issue
Block a user