chore(devops): tighten deployment scripts
This commit is contained in:
parent
85f21ae9f6
commit
1deb832b1a
105
deploy-clock.sh
105
deploy-clock.sh
@ -4,17 +4,21 @@ set -euo pipefail
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# ByteLyst ChronoMind - Production Deployment Script
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Usage: ./deploy-clock.sh [--force] [--skip-health-check]
|
||||
# Usage: ./deploy-clock.sh [option]
|
||||
#
|
||||
# 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 (interactive menu when no arguments):
|
||||
# 1 - Normal deployment (with cache, with health checks)
|
||||
# 2 - Force deployment (skip dirty checks, with cache)
|
||||
# 3 - Skip health checks (with cache)
|
||||
# 4 - No-cache build (force rebuild, with health checks)
|
||||
# 5 - Force + No-cache (skip checks, force rebuild)
|
||||
# 6 - Force + Skip health checks (skip both)
|
||||
# 7 - All options: Force + Skip health + No-cache
|
||||
#
|
||||
# Options:
|
||||
# Command-line options:
|
||||
# --force Skip dirty checks and force deployment
|
||||
# --skip-health-check Skip endpoint health verification
|
||||
# --no-cache Force rebuild without cache
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
@ -31,15 +35,47 @@ cd "$SCRIPT_DIR"
|
||||
|
||||
FORCE=false
|
||||
SKIP_HEALTH_CHECK=false
|
||||
NO_CACHE=false
|
||||
|
||||
# Parse command-line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) FORCE=true; shift ;;
|
||||
--skip-health-check) SKIP_HEALTH_CHECK=true; shift ;;
|
||||
--no-cache) NO_CACHE=true; shift ;;
|
||||
*) fail "Unknown option: $1";;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Interactive Menu ─────────────────────────────────────────────────
|
||||
if [ "$FORCE" = false ] && [ "$SKIP_HEALTH_CHECK" = false ] && [ "$NO_CACHE" = false ]; then
|
||||
echo ""
|
||||
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║${NC} ByteLyst ChronoMind - Deployment Options ${CYAN}║${NC}"
|
||||
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e " ${GREEN}1${NC} - Normal deployment (with cache, with health checks)"
|
||||
echo -e " ${GREEN}2${NC} - Force deployment (skip dirty checks, with cache)"
|
||||
echo -e " ${GREEN}3${NC} - Skip health checks (with cache)"
|
||||
echo -e " ${GREEN}4${NC} - No-cache build (force rebuild, with health checks)"
|
||||
echo -e " ${GREEN}5${NC} - Force + No-cache (skip checks, force rebuild)"
|
||||
echo -e " ${GREEN}6${NC} - Force + Skip health checks (skip both)"
|
||||
echo -e " ${GREEN}7${NC} - All options: Force + Skip health + No-cache"
|
||||
echo ""
|
||||
read -r -p "Select option (1-7): " choice
|
||||
|
||||
case $choice in
|
||||
1) ;;
|
||||
2) FORCE=true ;;
|
||||
3) SKIP_HEALTH_CHECK=true ;;
|
||||
4) NO_CACHE=true ;;
|
||||
5) FORCE=true; NO_CACHE=true ;;
|
||||
6) FORCE=true; SKIP_HEALTH_CHECK=true ;;
|
||||
7) FORCE=true; SKIP_HEALTH_CHECK=true; NO_CACHE=true ;;
|
||||
*) fail "Invalid option. Please select 1-7." ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# ── Prerequisites ────────────────────────────────────────────────────
|
||||
if [ ! -d "$REPO_DIR" ]; then
|
||||
fail "Repo directory not found: $REPO_DIR"
|
||||
@ -105,6 +141,48 @@ if [ "$SKIP_HEALTH_CHECK" = false ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Package Publication Check ───────────────────────────────────────────
|
||||
log "Checking @bytelyst package publication status..."
|
||||
|
||||
# Read Gitea token from file
|
||||
unset GITEA_NPM_TOKEN
|
||||
if [ -f "/opt/bytelyst/.gitea_token" ]; then
|
||||
GITEA_NPM_TOKEN="$(< /opt/bytelyst/.gitea_token)"
|
||||
elif [ -f "$HOME/.gitea_npm_token" ]; then
|
||||
GITEA_NPM_TOKEN="$(< "$HOME/.gitea_npm_token")"
|
||||
fi
|
||||
|
||||
if [ -z "$GITEA_NPM_TOKEN" ]; then
|
||||
warn "Gitea token not found, skipping package publication check"
|
||||
else
|
||||
GITEA_REGISTRY="http://localhost:3300/api/packages/ByteLyst/npm/"
|
||||
CRITICAL_PACKAGES=(
|
||||
"@bytelyst/config|@bytelyst%2fconfig"
|
||||
"@bytelyst/cosmos|@bytelyst%2fcosmos"
|
||||
"@bytelyst/errors|@bytelyst%2ferrors"
|
||||
"@bytelyst/fastify-core|@bytelyst%2ffastify-core"
|
||||
)
|
||||
MISSING_PACKAGES=()
|
||||
|
||||
for entry in "${CRITICAL_PACKAGES[@]}"; do
|
||||
package="${entry%%|*}"
|
||||
encoded="${entry##*|}"
|
||||
if ! curl -sf -H "Authorization: token ${GITEA_NPM_TOKEN}" "${GITEA_REGISTRY}${encoded}" > /dev/null 2>&1; then
|
||||
MISSING_PACKAGES+=("$package")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#MISSING_PACKAGES[@]}" -eq 0 ]; then
|
||||
ok "All critical @bytelyst packages are published"
|
||||
else
|
||||
warn "Some @bytelyst packages may not be published: ${MISSING_PACKAGES[*]}"
|
||||
read -r -p "Continue anyway? (y/N): " continue_anyway
|
||||
if [[ ! "$continue_anyway" =~ ^[Yy]$ ]]; then
|
||||
fail "Deployment cancelled"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Build and Deploy ──────────────────────────────────────────────────
|
||||
log "Building and deploying Docker containers..."
|
||||
|
||||
@ -114,8 +192,15 @@ if [ ! -f "docker-compose.yml" ]; then
|
||||
fi
|
||||
|
||||
# Build and start services
|
||||
BUILD_ARGS=()
|
||||
if [ "$NO_CACHE" = true ]; then
|
||||
BUILD_ARGS+=(--no-cache)
|
||||
log "Building Docker images without cache..."
|
||||
else
|
||||
log "Building Docker images..."
|
||||
docker compose build || fail "Docker build failed"
|
||||
fi
|
||||
|
||||
docker compose build "${BUILD_ARGS[@]}" || fail "Docker build failed"
|
||||
|
||||
log "Starting services..."
|
||||
docker compose up -d || fail "Docker compose up failed"
|
||||
@ -171,7 +256,7 @@ fi
|
||||
log "Verifying production endpoints..."
|
||||
|
||||
API_ENDPOINT="https://api.bytelyst.com/chronomind"
|
||||
WEB_ENDPOINT="http://localhost:3030"
|
||||
WEB_ENDPOINT="https://clock.bytelyst.com"
|
||||
|
||||
# Check API endpoint
|
||||
if curl -sf "$API_ENDPOINT/health" > /dev/null 2>&1; then
|
||||
@ -219,5 +304,5 @@ fi
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
ok "Deployment completed successfully!"
|
||||
log "Backend: http://localhost:4011 → $API_ENDPOINT"
|
||||
log "Web: http://localhost:3030"
|
||||
log "Web: http://localhost:3030 → $WEB_ENDPOINT"
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
|
||||
111
deploy-notes.sh
111
deploy-notes.sh
@ -4,17 +4,21 @@ set -euo pipefail
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# ByteLyst NoteLett - Production Deployment Script
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# Usage: ./deploy-notes.sh [--force] [--skip-health-check]
|
||||
# Usage: ./deploy-notes.sh [option]
|
||||
#
|
||||
# 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 (interactive menu when no arguments):
|
||||
# 1 - Normal deployment (with cache, with health checks)
|
||||
# 2 - Force deployment (skip dirty checks, with cache)
|
||||
# 3 - Skip health checks (with cache)
|
||||
# 4 - No-cache build (force rebuild, with health checks)
|
||||
# 5 - Force + No-cache (skip checks, force rebuild)
|
||||
# 6 - Force + Skip health checks (skip both)
|
||||
# 7 - All options: Force + Skip health + No-cache
|
||||
#
|
||||
# Options:
|
||||
# Command-line options:
|
||||
# --force Skip dirty checks and force deployment
|
||||
# --skip-health-check Skip endpoint health verification
|
||||
# --no-cache Force rebuild without cache
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||
@ -31,15 +35,47 @@ cd "$SCRIPT_DIR"
|
||||
|
||||
FORCE=false
|
||||
SKIP_HEALTH_CHECK=false
|
||||
NO_CACHE=false
|
||||
|
||||
# Parse command-line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--force) FORCE=true; shift ;;
|
||||
--skip-health-check) SKIP_HEALTH_CHECK=true; shift ;;
|
||||
--no-cache) NO_CACHE=true; shift ;;
|
||||
*) fail "Unknown option: $1";;
|
||||
esac
|
||||
done
|
||||
|
||||
# ── Interactive Menu ─────────────────────────────────────────────────
|
||||
if [ "$FORCE" = false ] && [ "$SKIP_HEALTH_CHECK" = false ] && [ "$NO_CACHE" = false ]; then
|
||||
echo ""
|
||||
echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}"
|
||||
echo -e "${CYAN}║${NC} ByteLyst NoteLett - Deployment Options ${CYAN}║${NC}"
|
||||
echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}"
|
||||
echo ""
|
||||
echo -e " ${GREEN}1${NC} - Normal deployment (with cache, with health checks)"
|
||||
echo -e " ${GREEN}2${NC} - Force deployment (skip dirty checks, with cache)"
|
||||
echo -e " ${GREEN}3${NC} - Skip health checks (with cache)"
|
||||
echo -e " ${GREEN}4${NC} - No-cache build (force rebuild, with health checks)"
|
||||
echo -e " ${GREEN}5${NC} - Force + No-cache (skip checks, force rebuild)"
|
||||
echo -e " ${GREEN}6${NC} - Force + Skip health checks (skip both)"
|
||||
echo -e " ${GREEN}7${NC} - All options: Force + Skip health + No-cache"
|
||||
echo ""
|
||||
read -r -p "Select option (1-7): " choice
|
||||
|
||||
case $choice in
|
||||
1) ;;
|
||||
2) FORCE=true ;;
|
||||
3) SKIP_HEALTH_CHECK=true ;;
|
||||
4) NO_CACHE=true ;;
|
||||
5) FORCE=true; NO_CACHE=true ;;
|
||||
6) FORCE=true; SKIP_HEALTH_CHECK=true ;;
|
||||
7) FORCE=true; SKIP_HEALTH_CHECK=true; NO_CACHE=true ;;
|
||||
*) fail "Invalid option. Please select 1-7." ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# ── Prerequisites ────────────────────────────────────────────────────
|
||||
if [ ! -d "$REPO_DIR" ]; then
|
||||
fail "Repo directory not found: $REPO_DIR"
|
||||
@ -105,6 +141,48 @@ if [ "$SKIP_HEALTH_CHECK" = false ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Package Publication Check ───────────────────────────────────────────
|
||||
log "Checking @bytelyst package publication status..."
|
||||
|
||||
# Read Gitea token from file
|
||||
unset GITEA_NPM_TOKEN
|
||||
if [ -f "/opt/bytelyst/.gitea_token" ]; then
|
||||
GITEA_NPM_TOKEN="$(< /opt/bytelyst/.gitea_token)"
|
||||
elif [ -f "$HOME/.gitea_npm_token" ]; then
|
||||
GITEA_NPM_TOKEN="$(< "$HOME/.gitea_npm_token")"
|
||||
fi
|
||||
|
||||
if [ -z "$GITEA_NPM_TOKEN" ]; then
|
||||
warn "Gitea token not found, skipping package publication check"
|
||||
else
|
||||
GITEA_REGISTRY="http://localhost:3300/api/packages/ByteLyst/npm/"
|
||||
CRITICAL_PACKAGES=(
|
||||
"@bytelyst/config|@bytelyst%2fconfig"
|
||||
"@bytelyst/cosmos|@bytelyst%2fcosmos"
|
||||
"@bytelyst/errors|@bytelyst%2ferrors"
|
||||
"@bytelyst/fastify-core|@bytelyst%2ffastify-core"
|
||||
)
|
||||
MISSING_PACKAGES=()
|
||||
|
||||
for entry in "${CRITICAL_PACKAGES[@]}"; do
|
||||
package="${entry%%|*}"
|
||||
encoded="${entry##*|}"
|
||||
if ! curl -sf -H "Authorization: token ${GITEA_NPM_TOKEN}" "${GITEA_REGISTRY}${encoded}" > /dev/null 2>&1; then
|
||||
MISSING_PACKAGES+=("$package")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#MISSING_PACKAGES[@]}" -eq 0 ]; then
|
||||
ok "All critical @bytelyst packages are published"
|
||||
else
|
||||
warn "Some @bytelyst packages may not be published: ${MISSING_PACKAGES[*]}"
|
||||
read -r -p "Continue anyway? (y/N): " continue_anyway
|
||||
if [[ ! "$continue_anyway" =~ ^[Yy]$ ]]; then
|
||||
fail "Deployment cancelled"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── Build and Deploy ──────────────────────────────────────────────────
|
||||
log "Building and deploying Docker containers..."
|
||||
|
||||
@ -114,8 +192,15 @@ if [ ! -f "docker-compose.yml" ]; then
|
||||
fi
|
||||
|
||||
# Build and start services
|
||||
BUILD_ARGS=()
|
||||
if [ "$NO_CACHE" = true ]; then
|
||||
BUILD_ARGS+=(--no-cache)
|
||||
log "Building Docker images without cache..."
|
||||
else
|
||||
log "Building Docker images..."
|
||||
docker compose build || fail "Docker build failed"
|
||||
fi
|
||||
|
||||
docker compose build "${BUILD_ARGS[@]}" || fail "Docker build failed"
|
||||
|
||||
log "Starting services..."
|
||||
docker compose up -d || fail "Docker compose up failed"
|
||||
@ -152,7 +237,7 @@ fi
|
||||
# Check web health
|
||||
WEB_HEALTH=false
|
||||
for _ in {1..30}; do
|
||||
if curl -sf http://localhost:3000 > /dev/null 2>&1; then
|
||||
if curl -sf http://localhost:3045 > /dev/null 2>&1; then
|
||||
WEB_HEALTH=true
|
||||
break
|
||||
fi
|
||||
@ -162,7 +247,7 @@ done
|
||||
echo ""
|
||||
|
||||
if [ "$WEB_HEALTH" = true ]; then
|
||||
ok "Web health check passed (http://localhost:3000)"
|
||||
ok "Web health check passed (http://localhost:3045)"
|
||||
else
|
||||
warn "Web health check failed (may be starting up)"
|
||||
fi
|
||||
@ -171,7 +256,7 @@ fi
|
||||
log "Verifying production endpoints..."
|
||||
|
||||
API_ENDPOINT="https://api.bytelyst.com/notelett"
|
||||
WEB_ENDPOINT="http://localhost:3000"
|
||||
WEB_ENDPOINT="https://notes.bytelyst.com"
|
||||
|
||||
# Check API endpoint
|
||||
if curl -sf "$API_ENDPOINT/health" > /dev/null 2>&1; then
|
||||
@ -202,7 +287,7 @@ else
|
||||
fi
|
||||
|
||||
# Test web is serving content
|
||||
WEB_URL="http://localhost:3000"
|
||||
WEB_URL="http://localhost:3045"
|
||||
if curl -sf "$WEB_URL" > /dev/null 2>&1; then
|
||||
ok "Web frontend is serving content"
|
||||
# Check if it's actually HTML
|
||||
@ -219,5 +304,5 @@ fi
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
ok "Deployment completed successfully!"
|
||||
log "Backend: http://localhost:4016 → $API_ENDPOINT"
|
||||
log "Web: http://localhost:3000"
|
||||
log "Web: http://localhost:3045 → $WEB_ENDPOINT"
|
||||
log "══════════════════════════════════════════════════════════════════════"
|
||||
|
||||
78
scripts/monitor-lucky25-execution.sh
Executable file
78
scripts/monitor-lucky25-execution.sh
Executable file
@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# Lucky25 Execution Monitoring Script
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# Runs every 15 minutes to monitor lucky25 test plan execution
|
||||
# Logs status to /var/log/lucky25-monitoring.log
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
|
||||
LOG_FILE="/var/log/lucky25-monitoring.log"
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
BACKEND_DIR="${SCRIPT_DIR}/../learning_ai_invt_trdg/backend"
|
||||
|
||||
log() {
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
|
||||
}
|
||||
|
||||
log "════════════════════════════════════════════════════════════════"
|
||||
log "Starting Lucky25 Execution Monitoring"
|
||||
log "════════════════════════════════════════════════════════════════"
|
||||
|
||||
# Create log file if it doesn't exist
|
||||
touch "$LOG_FILE"
|
||||
|
||||
cd "$BACKEND_DIR"
|
||||
|
||||
# Run the status check using node with the compiled JS
|
||||
node -e "
|
||||
const { config } = require('./dist/src/config/index.js');
|
||||
const { MANUAL_ENTRY_CONTAINER, queryDocuments } = require('./dist/src/services/tradingRecordStore.js');
|
||||
|
||||
async function main() {
|
||||
const query = 'SELECT * FROM c WHERE c.productId = @productId AND c.type = @type ORDER BY c.created_at DESC';
|
||||
const rows = await queryDocuments(MANUAL_ENTRY_CONTAINER, query, [
|
||||
{ name: '@productId', value: config.PRODUCT_ID },
|
||||
{ name: '@type', value: 'manual_entry' },
|
||||
]);
|
||||
|
||||
const lucky25Plans = rows.filter(row =>
|
||||
row.hashtags && Array.isArray(row.hashtags) && row.hashtags.includes('lucky25') && row.active === true
|
||||
);
|
||||
|
||||
const byStatus = {};
|
||||
for (const plan of lucky25Plans) {
|
||||
const status = plan.status || 'unknown';
|
||||
byStatus[status] = (byStatus[status] || 0) + 1;
|
||||
}
|
||||
|
||||
console.log('Lucky25 Plans Status:');
|
||||
console.log('Total: ' + lucky25Plans.length);
|
||||
console.log('Status breakdown:');
|
||||
for (const [status, count] of Object.entries(byStatus)) {
|
||||
console.log(' ' + status + ': ' + count);
|
||||
}
|
||||
|
||||
const executedPlans = lucky25Plans.filter(p =>
|
||||
p.status !== 'simple_armed_buy' && p.status !== 'deleted'
|
||||
);
|
||||
|
||||
console.log('Execution Progress:');
|
||||
console.log('Executed: ' + executedPlans.length + '/' + lucky25Plans.length);
|
||||
console.log('Rate: ' + ((executedPlans.length / lucky25Plans.length) * 100).toFixed(1) + '%');
|
||||
|
||||
if (executedPlans.length > 0) {
|
||||
console.log('Recent executions:');
|
||||
const recent = executedPlans.slice(0, 3);
|
||||
for (const plan of recent) {
|
||||
console.log(' ' + plan.symbol + ' - ' + plan.status + ' - ' + plan.label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
"
|
||||
|
||||
log "Monitoring check completed"
|
||||
log "════════════════════════════════════════════════════════════════"
|
||||
Loading…
Reference in New Issue
Block a user