CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
deploy.sh
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| 8ade77b | 1 | #!/bin/bash |
| 2 | set -euo pipefail | |
| 3 | ||
| 4 | # ============================================ | |
| 5 | # Gluecron Deploy Script | |
| 6 | # One command to deploy to production. | |
| 7 | # ============================================ | |
| 8 | ||
| 9 | APP_NAME="gluecron" | |
| 10 | APP_DIR="/opt/gluecron" | |
| 11 | REPO_URL="https://github.com/ccantynz-alt/Gluecron.com.git" | |
| 12 | BRANCH="claude/ship-fixes-and-tests-Jvz1c" | |
| 13 | ||
| 14 | echo "==========================================" | |
| 15 | echo " Deploying $APP_NAME" | |
| 16 | echo "==========================================" | |
| 17 | ||
| 18 | # 1. Check prerequisites | |
| 19 | command -v git >/dev/null 2>&1 || { echo "git required"; exit 1; } | |
| 20 | command -v bun >/dev/null 2>&1 || { | |
| 21 | echo "Installing Bun..." | |
| ea52715 | 22 | curl -fsSL --output /tmp/bun-install.sh https://bun.sh/install |
| 23 | bash /tmp/bun-install.sh | |
| 24 | rm -f /tmp/bun-install.sh | |
| 8ade77b | 25 | export PATH="$HOME/.bun/bin:$PATH" |
| 26 | } | |
| 27 | ||
| 28 | # 2. Check for DATABASE_URL | |
| 29 | if [ -z "${DATABASE_URL:-}" ]; then | |
| 30 | if [ -f "$APP_DIR/.env" ]; then | |
| 31 | export $(grep -v '^#' "$APP_DIR/.env" | xargs) | |
| 32 | fi | |
| 33 | fi | |
| 34 | ||
| 35 | if [ -z "${DATABASE_URL:-}" ]; then | |
| 36 | echo "ERROR: DATABASE_URL not set." | |
| 37 | echo "Set it in $APP_DIR/.env or export it." | |
| 38 | echo "" | |
| 39 | echo "Get a free database at https://neon.tech" | |
| 40 | echo "Then: echo 'DATABASE_URL=postgresql://...' > $APP_DIR/.env" | |
| 41 | exit 1 | |
| 42 | fi | |
| 43 | ||
| 44 | # 3. Clone or update repo | |
| 45 | if [ -d "$APP_DIR" ]; then | |
| 46 | echo "Updating existing installation..." | |
| 47 | cd "$APP_DIR" | |
| 48 | git fetch origin "$BRANCH" | |
| 49 | git reset --hard "origin/$BRANCH" | |
| 50 | else | |
| 51 | echo "Fresh install..." | |
| 52 | sudo mkdir -p "$APP_DIR" | |
| 53 | sudo chown "$(whoami)" "$APP_DIR" | |
| 54 | git clone --branch "$BRANCH" "$REPO_URL" "$APP_DIR" | |
| 55 | cd "$APP_DIR" | |
| 56 | fi | |
| 57 | ||
| 58 | # 4. Install dependencies | |
| 59 | echo "Installing dependencies..." | |
| 60 | bun install --frozen-lockfile --production | |
| 61 | ||
| 62 | # 5. Run database migration | |
| 63 | echo "Running database migration..." | |
| 64 | psql "$DATABASE_URL" -f drizzle/0000_init.sql 2>/dev/null || { | |
| 65 | echo "psql not found or migration failed — trying via bun..." | |
| 66 | bun run -e " | |
| 67 | const { neon } = require('@neondatabase/serverless'); | |
| 68 | const sql = neon(process.env.DATABASE_URL); | |
| 69 | const fs = require('fs'); | |
| 70 | const migration = fs.readFileSync('drizzle/0000_init.sql', 'utf-8'); | |
| 71 | // Split by semicolons and execute each statement | |
| 72 | const statements = migration.split(';').filter(s => s.trim()); | |
| 73 | (async () => { | |
| 74 | for (const stmt of statements) { | |
| 75 | try { await sql(stmt); } catch(e) { /* table may already exist */ } | |
| 76 | } | |
| 77 | console.log('Migration complete'); | |
| 78 | })(); | |
| 79 | " | |
| 80 | } | |
| 81 | ||
| 82 | # 6. Create repos directory | |
| 83 | mkdir -p /data/repos 2>/dev/null || mkdir -p "$APP_DIR/repos" | |
| 84 | export GIT_REPOS_PATH="${GIT_REPOS_PATH:-/data/repos}" | |
| 85 | ||
| 86 | # 7. Set up systemd service | |
| 87 | echo "Setting up systemd service..." | |
| 88 | sudo tee /etc/systemd/system/gluecron.service > /dev/null << UNIT | |
| 89 | [Unit] | |
| 90 | Description=Gluecron - AI-native code intelligence | |
| 91 | After=network.target | |
| 92 | ||
| 93 | [Service] | |
| 94 | Type=simple | |
| 95 | User=$(whoami) | |
| 96 | WorkingDirectory=$APP_DIR | |
| 97 | EnvironmentFile=$APP_DIR/.env | |
| 98 | ExecStart=$(which bun) run src/index.ts | |
| 99 | Restart=always | |
| 100 | RestartSec=5 | |
| 101 | StandardOutput=journal | |
| 102 | StandardError=journal | |
| 103 | ||
| 104 | [Install] | |
| 105 | WantedBy=multi-user.target | |
| 106 | UNIT | |
| 107 | ||
| 108 | sudo systemctl daemon-reload | |
| 109 | sudo systemctl enable gluecron | |
| 110 | sudo systemctl restart gluecron | |
| 111 | ||
| 112 | echo "" | |
| 113 | echo "==========================================" | |
| 114 | echo " $APP_NAME is now running!" | |
| 115 | echo "==========================================" | |
| 116 | echo "" | |
| 117 | echo " URL: http://$(hostname -I | awk '{print $1}'):3000" | |
| 118 | echo " Logs: journalctl -u gluecron -f" | |
| 119 | echo " Status: systemctl status gluecron" | |
| 120 | echo "" | |
| 121 | echo " Next steps:" | |
| 122 | echo " 1. Set up reverse proxy (nginx/caddy) for HTTPS" | |
| 123 | echo " 2. Point gluecron.com DNS to this server" | |
| 124 | echo " 3. Register your admin account at /register" | |
| 125 | echo "" |