203 lines
8.4 KiB
Bash
Executable File
203 lines
8.4 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
# Usage: deploy.sh <project-name> [dockerfile|nixpacks|static]
|
|
# Handles: Gitea repo creation, git push, Coolify app creation, deployment
|
|
# Returns: production URL
|
|
|
|
PROJECT_NAME="${1:?Usage: deploy.sh <project-name> [dockerfile|nixpacks|static]}"
|
|
BUILD_TYPE="${2:-nixpacks}"
|
|
|
|
GITEA_URL="${GITEA_URL:?GITEA_URL not set}"
|
|
GITEA_TOKEN="${GITEA_TOKEN:?GITEA_TOKEN not set}"
|
|
COOLIFY_BASE_URL="${COOLIFY_BASE_URL:?COOLIFY_BASE_URL not set}"
|
|
COOLIFY_ACCESS_TOKEN="${COOLIFY_ACCESS_TOKEN:?COOLIFY_ACCESS_TOKEN not set}"
|
|
|
|
GITEA_API="${GITEA_URL}/api/v1"
|
|
COOLIFY_API="${COOLIFY_BASE_URL}/api/v1"
|
|
GITEA_USER="pankaj"
|
|
|
|
echo "=== TenX Deploy: ${PROJECT_NAME} (build: ${BUILD_TYPE}) ==="
|
|
|
|
# ── Step 1: Git init + commit ────────────────────────────────────────
|
|
if [ ! -d .git ]; then
|
|
git init
|
|
git checkout -b main 2>/dev/null || true
|
|
fi
|
|
|
|
git add -A
|
|
git diff --cached --quiet 2>/dev/null || git commit -m "deploy: ${PROJECT_NAME}" --allow-empty
|
|
|
|
# ── Step 2: Create Gitea repo (ignore if exists) ─────────────────────
|
|
echo "[deploy] Creating Gitea repo..."
|
|
REPO_RESPONSE=$(curl -sk -w "\n%{http_code}" -X POST "${GITEA_API}/user/repos" \
|
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"name\":\"${PROJECT_NAME}\",\"private\":false,\"auto_init\":false}")
|
|
|
|
HTTP_CODE=$(echo "${REPO_RESPONSE}" | tail -1)
|
|
if [ "${HTTP_CODE}" = "201" ]; then
|
|
echo "[deploy] Gitea repo created: ${GITEA_URL}/${GITEA_USER}/${PROJECT_NAME}"
|
|
elif [ "${HTTP_CODE}" = "409" ]; then
|
|
echo "[deploy] Gitea repo already exists"
|
|
else
|
|
echo "[deploy] Gitea repo creation returned ${HTTP_CODE} (continuing anyway)"
|
|
fi
|
|
|
|
# ── Step 3: Push to Gitea ────────────────────────────────────────────
|
|
GITEA_HOST=$(echo "${GITEA_URL}" | sed 's|https://||;s|http://||')
|
|
REMOTE_URL="https://${GITEA_USER}:${GITEA_TOKEN}@${GITEA_HOST}/${GITEA_USER}/${PROJECT_NAME}.git"
|
|
|
|
git remote remove origin 2>/dev/null || true
|
|
git remote add origin "${REMOTE_URL}"
|
|
GIT_SSL_NO_VERIFY=true git push -u origin main --force
|
|
echo "[deploy] Code pushed to Gitea"
|
|
|
|
# ── Step 4: Get Coolify server UUID ──────────────────────────────────
|
|
echo "[deploy] Getting Coolify server..."
|
|
SERVER_UUID=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/servers" | python3 -c "import sys,json; servers=json.load(sys.stdin); print(servers[0]['uuid'])" 2>/dev/null)
|
|
|
|
if [ -z "${SERVER_UUID}" ]; then
|
|
echo "[deploy] ERROR: Could not get Coolify server UUID"
|
|
exit 1
|
|
fi
|
|
echo "[deploy] Server: ${SERVER_UUID}"
|
|
|
|
# ── Step 5: Get or create Coolify project ────────────────────────────
|
|
echo "[deploy] Getting Coolify project..."
|
|
PROJECT_UUID=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/projects" | python3 -c "
|
|
import sys,json
|
|
projects=json.load(sys.stdin)
|
|
for p in projects:
|
|
if p.get('name','').lower() == 'tenx':
|
|
print(p['uuid'])
|
|
sys.exit(0)
|
|
print('')
|
|
" 2>/dev/null)
|
|
|
|
if [ -z "${PROJECT_UUID}" ]; then
|
|
echo "[deploy] Creating TenX project on Coolify..."
|
|
PROJECT_UUID=$(curl -sk -X POST -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${COOLIFY_API}/projects" \
|
|
-d '{"name":"TenX","description":"TenX auto-deployed apps"}' | python3 -c "import sys,json; print(json.load(sys.stdin).get('uuid',''))" 2>/dev/null)
|
|
fi
|
|
echo "[deploy] Project: ${PROJECT_UUID}"
|
|
|
|
# ── Step 6: Get first environment UUID ───────────────────────────────
|
|
ENV_UUID=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/projects/${PROJECT_UUID}" | python3 -c "
|
|
import sys,json
|
|
data=json.load(sys.stdin)
|
|
envs=data.get('environments',[])
|
|
if envs: print(envs[0].get('id',''))
|
|
else: print('')
|
|
" 2>/dev/null)
|
|
|
|
if [ -z "${ENV_UUID}" ]; then
|
|
echo "[deploy] ERROR: No environment found in project"
|
|
exit 1
|
|
fi
|
|
echo "[deploy] Environment: ${ENV_UUID}"
|
|
|
|
# ── Step 7: Create Coolify application ───────────────────────────────
|
|
echo "[deploy] Creating Coolify application..."
|
|
REPO_FULL_URL="${GITEA_URL}/${GITEA_USER}/${PROJECT_NAME}.git"
|
|
|
|
APP_RESPONSE=$(curl -sk -X POST -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${COOLIFY_API}/applications/public" \
|
|
-d "{
|
|
\"project_uuid\": \"${PROJECT_UUID}\",
|
|
\"environment_name\": \"production\",
|
|
\"server_uuid\": \"${SERVER_UUID}\",
|
|
\"type\": \"public\",
|
|
\"name\": \"${PROJECT_NAME}\",
|
|
\"git_repository\": \"${REPO_FULL_URL}\",
|
|
\"git_branch\": \"main\",
|
|
\"build_pack\": \"${BUILD_TYPE}\",
|
|
\"ports_exposes\": \"3000\",
|
|
\"instant_deploy\": true
|
|
}")
|
|
|
|
APP_UUID=$(echo "${APP_RESPONSE}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('uuid',''))" 2>/dev/null)
|
|
|
|
if [ -z "${APP_UUID}" ]; then
|
|
echo "[deploy] App creation response: ${APP_RESPONSE}"
|
|
# Try to find existing app
|
|
APP_UUID=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/applications" | python3 -c "
|
|
import sys,json
|
|
apps=json.load(sys.stdin)
|
|
for a in apps:
|
|
if a.get('name','') == '${PROJECT_NAME}':
|
|
print(a['uuid'])
|
|
sys.exit(0)
|
|
print('')
|
|
" 2>/dev/null)
|
|
|
|
if [ -z "${APP_UUID}" ]; then
|
|
echo "[deploy] ERROR: Could not create or find app"
|
|
exit 1
|
|
fi
|
|
echo "[deploy] Found existing app: ${APP_UUID}, triggering redeploy..."
|
|
fi
|
|
|
|
echo "[deploy] App UUID: ${APP_UUID}"
|
|
|
|
# ── Step 7b: Fix git_repository URL (Coolify API strips base URL) ─────
|
|
curl -sk -X PATCH -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
"${COOLIFY_API}/applications/${APP_UUID}" \
|
|
-d "{\"git_repository\": \"${REPO_FULL_URL}\"}" > /dev/null
|
|
echo "[deploy] Git repository URL set: ${REPO_FULL_URL}"
|
|
|
|
# ── Step 8: Trigger deployment ────────────────────────────────────────
|
|
echo "[deploy] Triggering deployment..."
|
|
DEPLOY_RESPONSE=$(curl -sk -X POST -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
-H "Content-Type: application/json" \
|
|
-d "{\"uuid\":\"${APP_UUID}\"}" \
|
|
"${COOLIFY_API}/deploy")
|
|
DEPLOYMENT_UUID=$(echo "${DEPLOY_RESPONSE}" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('deployments',[{}])[0].get('deployment_uuid',''))" 2>/dev/null)
|
|
echo "[deploy] Deployment UUID: ${DEPLOYMENT_UUID}"
|
|
|
|
# ── Step 8b: Wait for deployment ─────────────────────────────────────
|
|
echo "[deploy] Waiting for deployment to complete..."
|
|
for i in $(seq 1 30); do
|
|
sleep 15
|
|
if [ -n "${DEPLOYMENT_UUID}" ]; then
|
|
DEP_STATUS=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/deployments/${DEPLOYMENT_UUID}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unknown'))" 2>/dev/null)
|
|
else
|
|
DEP_STATUS="unknown"
|
|
fi
|
|
APP_STATUS=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/applications/${APP_UUID}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unknown'))" 2>/dev/null)
|
|
echo "[deploy] Deploy: ${DEP_STATUS} | App: ${APP_STATUS} (attempt ${i}/30)"
|
|
if [ "${DEP_STATUS}" = "finished" ] || echo "${APP_STATUS}" | grep -q "running"; then
|
|
echo "[deploy] Deployment successful!"
|
|
break
|
|
fi
|
|
if [ "${DEP_STATUS}" = "failed" ]; then
|
|
echo "[deploy] Deployment FAILED. Check Coolify dashboard for logs."
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# ── Step 9: Get the URL ──────────────────────────────────────────────
|
|
FQDN=$(curl -sk -H "Authorization: Bearer ${COOLIFY_ACCESS_TOKEN}" \
|
|
"${COOLIFY_API}/applications/${APP_UUID}" | python3 -c "import sys,json; print(json.load(sys.stdin).get('fqdn',''))" 2>/dev/null)
|
|
|
|
if [ -z "${FQDN}" ]; then
|
|
echo "[deploy] WARNING: No FQDN set — app may be accessible via Coolify dashboard only"
|
|
echo "[deploy] App UUID: ${APP_UUID}"
|
|
else
|
|
echo ""
|
|
echo "=== DEPLOYED ==="
|
|
echo "URL: ${FQDN}"
|
|
echo "Gitea: ${GITEA_URL}/${GITEA_USER}/${PROJECT_NAME}"
|
|
echo "================"
|
|
fi
|