diff --git a/services/arbiter-3.0/DEPLOYMENT.md b/services/arbiter-3.0/DEPLOYMENT.md index ce70fcc..70116c9 100644 --- a/services/arbiter-3.0/DEPLOYMENT.md +++ b/services/arbiter-3.0/DEPLOYMENT.md @@ -7,6 +7,19 @@ --- +## ๐Ÿš€ One-Click Deploy (Trinity Console) + +**For Holly, Meg, and Michael:** + +1. Push your code changes to `firefrost-services` repo +2. Open Trinity Console: https://discord-bot.firefrostgaming.com/admin +3. Click the **"๐Ÿš€ Deploy Arbiter"** button in the sidebar +4. Wait for success confirmation + +That's it! The button pulls latest code from Gitea and restarts the service. + +--- + ## โš ๏ธ IMPORTANT: Arbiter is NOT a Git Repo `/opt/arbiter-3.0` on Command Center is **not** a git repository. It's a deployment target. @@ -17,30 +30,44 @@ --- -## Quick Deploy (One Command) +## Manual Deploy (SSH Required) **On Command Center:** ```bash -curl -fsSL https://git.firefrostgaming.com/firefrost-gaming/firefrost-services/raw/branch/main/services/arbiter-3.0/deploy.sh | bash -``` - -**Or if deploy.sh is already on server:** -```bash bash /opt/arbiter-3.0/deploy.sh ``` +**Or remote curl:** +```bash +curl -fsSL https://git.firefrostgaming.com/firefrost-gaming/firefrost-services/raw/branch/main/services/arbiter-3.0/deploy.sh | bash +``` + --- -## Manual Deploy +## First-Time Server Setup +If setting up deploy button for the first time, Michael needs to run these on Command Center: + +**1. Copy deploy script to /opt/scripts:** ```bash -# On Command Center -cd /tmp -rm -rf firefrost-services -git clone https://git.firefrostgaming.com/firefrost-gaming/firefrost-services.git -cp -r firefrost-services/services/arbiter-3.0/src/* /opt/arbiter-3.0/src/ -systemctl restart arbiter-3 -rm -rf firefrost-services +sudo mkdir -p /opt/scripts +sudo cp /opt/arbiter-3.0/deploy.sh /opt/scripts/deploy-arbiter.sh +sudo chmod +x /opt/scripts/deploy-arbiter.sh +``` + +**2. Configure sudoers (allow Arbiter to run deploy script):** +```bash +sudo visudo +``` +Add this line: +``` +architect ALL=(ALL) NOPASSWD: /opt/scripts/deploy-arbiter.sh +``` + +**3. Create log file:** +```bash +sudo touch /var/log/trinity-deployments.log +sudo chown architect:architect /var/log/trinity-deployments.log ``` --- @@ -54,6 +81,9 @@ systemctl status arbiter-3 # Check logs journalctl -u arbiter-3 -n 50 +# Check deployment log +tail -20 /var/log/trinity-deployments.log + # Test dashboard curl -s https://discord-bot.firefrostgaming.com/admin | head -5 ``` @@ -62,13 +92,17 @@ curl -s https://discord-bot.firefrostgaming.com/admin | head -5 ## Common Issues +### "Deployment already in progress" +**Cause:** Previous deploy didn't finish or crashed +**Fix:** `rm -rf /tmp/arbiter_deploy.lock` then try again + ### "fatal: not a git repository" **Cause:** Someone tried to `git pull` in `/opt/arbiter-3.0` **Fix:** Use the deploy script or manual copy method above ### "/tmp/firefrost-services already exists" **Cause:** Previous deploy didn't clean up -**Fix:** `rm -rf /tmp/firefrost-services` then try again +**Fix:** `rm -rf /tmp/firefrost-services /tmp/firefrost-services-deploy-*` then try again ### Service fails to start **Check:** `journalctl -u arbiter-3 -n 50` @@ -99,15 +133,15 @@ MINECRAFT_NEST_IDS=1,5 --- -## For Chroniclers +## For Chroniclers & Catalysts **You cannot SSH to Command Center** (port 22 blocked from Claude sandbox). **Workflow:** 1. Make changes to `firefrost-services/services/arbiter-3.0/` 2. Commit and push to Gitea -3. Tell Michael to run: `bash /opt/arbiter-3.0/deploy.sh` -4. Verify via dashboard or ask Michael to check logs +3. Tell your human to click "๐Ÿš€ Deploy Arbiter" in Trinity Console +4. Verify via dashboard or ask them to check logs --- diff --git a/services/arbiter-3.0/deploy.sh b/services/arbiter-3.0/deploy.sh index 3ad67fc..00ec725 100644 --- a/services/arbiter-3.0/deploy.sh +++ b/services/arbiter-3.0/deploy.sh @@ -1,7 +1,10 @@ #!/bin/bash # Arbiter 3.0 Deployment Script # Run on Command Center: bash /opt/arbiter-3.0/deploy.sh -# Or remotely: Copy this script to server and run +# Or via Trinity Console Deploy button +# +# Usage: deploy.sh [username] +# username: Optional - who triggered the deploy (for logging) set -e # Exit on any error @@ -9,45 +12,66 @@ REPO_URL="https://git.firefrostgaming.com/firefrost-gaming/firefrost-services.gi TEMP_DIR="/tmp/firefrost-services-deploy-$$" ARBITER_DIR="/opt/arbiter-3.0" SERVICE_NAME="arbiter-3" +LOCKDIR="/tmp/arbiter_deploy.lock" +LOG_FILE="/var/log/trinity-deployments.log" +DEPLOY_USER="${1:-manual}" -echo "๐Ÿ”ฅโ„๏ธ Arbiter 3.0 Deployment" -echo "==========================" +# Logging function +log() { + echo "$1" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" +} + +# 1. Prevent concurrent deployments with a lock directory +if ! mkdir "$LOCKDIR" 2>/dev/null; then + echo "ERROR: Deployment already in progress." >&2 + exit 1 +fi +# Ensure lock is removed when script exits (success or failure) +trap 'rm -rf "$LOCKDIR"' EXIT + +log "๐Ÿ”ฅโ„๏ธ Arbiter deployment started by: $DEPLOY_USER" # Cleanup any old temp directories rm -rf /tmp/firefrost-services /tmp/firefrost-services-deploy-* # Clone fresh -echo "๐Ÿ“ฅ Cloning firefrost-services..." +log "๐Ÿ“ฅ Cloning firefrost-services..." git clone --depth 1 "$REPO_URL" "$TEMP_DIR" +# Get commit info for logging +COMMIT_HASH=$(cd "$TEMP_DIR" && git log -1 --format="%h - %s") +log "๐Ÿ“Œ Deploying commit: $COMMIT_HASH" + # Copy arbiter files -echo "๐Ÿ“‹ Copying Arbiter files..." +log "๐Ÿ“‹ Copying Arbiter files..." cp -r "$TEMP_DIR/services/arbiter-3.0/src/"* "$ARBITER_DIR/src/" cp -r "$TEMP_DIR/services/arbiter-3.0/migrations/"* "$ARBITER_DIR/migrations/" 2>/dev/null || true cp "$TEMP_DIR/services/arbiter-3.0/package.json" "$ARBITER_DIR/package.json" 2>/dev/null || true # Check if package.json changed (need npm install) if ! cmp -s "$TEMP_DIR/services/arbiter-3.0/package.json" "$ARBITER_DIR/package.json.bak" 2>/dev/null; then - echo "๐Ÿ“ฆ Dependencies may have changed, running npm install..." + log "๐Ÿ“ฆ Dependencies changed, running npm install..." cd "$ARBITER_DIR" - npm install --production + npm install --production --ignore-scripts cp "$ARBITER_DIR/package.json" "$ARBITER_DIR/package.json.bak" fi -# Restart service -echo "๐Ÿ”„ Restarting $SERVICE_NAME..." -systemctl restart "$SERVICE_NAME" - -# Cleanup -echo "๐Ÿงน Cleaning up..." +# Cleanup temp files BEFORE restart +log "๐Ÿงน Cleaning up temp files..." rm -rf "$TEMP_DIR" +# Restart service +log "๐Ÿ”„ Restarting $SERVICE_NAME..." +systemctl restart "$SERVICE_NAME" + # Verify sleep 2 if systemctl is-active --quiet "$SERVICE_NAME"; then - echo "โœ… Arbiter 3.0 deployed and running!" - echo " Dashboard: https://discord-bot.firefrostgaming.com/admin" + log "โœ… Arbiter deployed successfully! Commit: $COMMIT_HASH" + echo "SUCCESS: Deployed commit $COMMIT_HASH" else - echo "โŒ Service failed to start. Check: journalctl -u $SERVICE_NAME -n 50" + log "โŒ Service failed to start after deploy" + echo "ERROR: Service failed to start. Check: journalctl -u $SERVICE_NAME -n 50" >&2 exit 1 fi diff --git a/services/arbiter-3.0/src/routes/admin/index.js b/services/arbiter-3.0/src/routes/admin/index.js index 8722619..02137fd 100644 --- a/services/arbiter-3.0/src/routes/admin/index.js +++ b/services/arbiter-3.0/src/routes/admin/index.js @@ -13,6 +13,7 @@ const auditRouter = require('./audit'); const rolesRouter = require('./roles'); const schedulerRouter = require('./scheduler'); const discordAuditRouter = require('./discord-audit'); +const systemRouter = require('./system'); router.use(requireTrinityAccess); @@ -79,5 +80,6 @@ router.use('/audit', auditRouter); router.use('/roles', rolesRouter); router.use('/scheduler', schedulerRouter); router.use('/discord', discordAuditRouter); +router.use('/system', systemRouter); module.exports = router; diff --git a/services/arbiter-3.0/src/routes/admin/system.js b/services/arbiter-3.0/src/routes/admin/system.js new file mode 100644 index 0000000..e633dba --- /dev/null +++ b/services/arbiter-3.0/src/routes/admin/system.js @@ -0,0 +1,51 @@ +const express = require('express'); +const router = express.Router(); +const { exec } = require('child_process'); +const fs = require('fs'); + +/** + * System Routes - Maintenance & Deployment + * + * POST /admin/system/deploy - Deploy latest Arbiter code from Gitea + */ + +// POST /admin/system/deploy - Pull latest code and restart Arbiter +router.post('/deploy', (req, res) => { + const username = req.user?.username || 'unknown'; + + console.log(`[DEPLOY] Deployment initiated by ${username}`); + + // Run the deploy script with username for logging + // Script handles its own locking to prevent concurrent deploys + exec(`sudo /opt/scripts/deploy-arbiter.sh "${username}"`, { + timeout: 60000 // 60 second timeout + }, (error, stdout, stderr) => { + if (error) { + console.error(`[DEPLOY] Failed:`, stderr || error.message); + return res.status(500).json({ + success: false, + message: 'Deployment failed', + log: stderr || error.message + }); + } + + console.log(`[DEPLOY] Success:`, stdout); + res.json({ + success: true, + message: stdout.trim() + }); + }); +}); + +// GET /admin/system/status - Check if deploy script exists and arbiter is running +router.get('/status', (req, res) => { + exec('systemctl is-active arbiter-3', (error, stdout) => { + const isRunning = stdout.trim() === 'active'; + res.json({ + arbiter: isRunning ? 'running' : 'stopped', + deployAvailable: fs.existsSync('/opt/scripts/deploy-arbiter.sh') + }); + }); +}); + +module.exports = router; diff --git a/services/arbiter-3.0/src/views/layout.ejs b/services/arbiter-3.0/src/views/layout.ejs index 97843e4..dd7ebc3 100644 --- a/services/arbiter-3.0/src/views/layout.ejs +++ b/services/arbiter-3.0/src/views/layout.ejs @@ -99,7 +99,19 @@ ๐Ÿ’ฌ Discord -
+
+ + + + +
@@ -110,6 +122,62 @@
+ +