Record app deployments in database
This commit is contained in:
+158
-47
@@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
|
||||||
|
source "$CONFIG_FILE"
|
||||||
|
|
||||||
APP_ID="${1:-}"
|
APP_ID="${1:-}"
|
||||||
|
|
||||||
if [ -z "$APP_ID" ]; then
|
if [ -z "$APP_ID" ]; then
|
||||||
@@ -8,14 +11,11 @@ if [ -z "$APP_ID" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CONFIG_FILE="/opt/appfactory/config/appfactory.env"
|
|
||||||
source "$CONFIG_FILE"
|
|
||||||
|
|
||||||
export DOCKER_CONFIG="/tmp/.docker"
|
export DOCKER_CONFIG="/tmp/.docker"
|
||||||
mkdir -p "$DOCKER_CONFIG"
|
mkdir -p "$DOCKER_CONFIG"
|
||||||
|
|
||||||
|
DB_FILE="/opt/appfactory/data/appfactory/appfactory.db"
|
||||||
APP_SOURCE_DIR="$WORKSPACE_DIR/$APP_ID"
|
APP_SOURCE_DIR="$WORKSPACE_DIR/$APP_ID"
|
||||||
CATALOG_FILE="$APPFACTORY_DIR/apps/catalog.yml"
|
|
||||||
TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools"
|
TOOLS_DIR="$WORKSPACE_DIR/appfactory-tools"
|
||||||
|
|
||||||
if [ ! -d "$APP_SOURCE_DIR" ]; then
|
if [ ! -d "$APP_SOURCE_DIR" ]; then
|
||||||
@@ -28,55 +28,166 @@ if [ ! -f "$APP_SOURCE_DIR/Dockerfile" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Updating source code..."
|
DEPLOY_ID="$(python3 - "$DB_FILE" "$APP_ID" <<'PY'
|
||||||
cd "$APP_SOURCE_DIR"
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
|
||||||
if [ -d ".git" ]; then
|
db_file = sys.argv[1]
|
||||||
git \
|
app_id = sys.argv[2]
|
||||||
-c safe.directory="$APP_SOURCE_DIR" \
|
|
||||||
fetch origin main
|
|
||||||
|
|
||||||
git \
|
con = sqlite3.connect(db_file)
|
||||||
-c safe.directory="$APP_SOURCE_DIR" \
|
|
||||||
reset --hard origin/main
|
cur = con.execute(
|
||||||
|
"""
|
||||||
|
INSERT INTO deployments (
|
||||||
|
app_id,
|
||||||
|
kind,
|
||||||
|
status,
|
||||||
|
started_at
|
||||||
|
)
|
||||||
|
VALUES (?, ?, ?, CURRENT_TIMESTAMP)
|
||||||
|
""",
|
||||||
|
(app_id, "app", "running"),
|
||||||
|
)
|
||||||
|
|
||||||
|
con.execute(
|
||||||
|
"""
|
||||||
|
UPDATE apps
|
||||||
|
SET status = 'deploying',
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = ?
|
||||||
|
""",
|
||||||
|
(app_id,),
|
||||||
|
)
|
||||||
|
|
||||||
|
con.commit()
|
||||||
|
print(cur.lastrowid)
|
||||||
|
con.close()
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
STDOUT_FILE="$TMP_DIR/stdout.log"
|
||||||
|
STDERR_FILE="$TMP_DIR/stderr.log"
|
||||||
|
|
||||||
|
finish_deploy() {
|
||||||
|
local status="$1"
|
||||||
|
local returncode="$2"
|
||||||
|
|
||||||
|
python3 - "$DB_FILE" "$DEPLOY_ID" "$APP_ID" "$status" "$returncode" "$STDOUT_FILE" "$STDERR_FILE" <<'PY'
|
||||||
|
import sqlite3
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
db_file = sys.argv[1]
|
||||||
|
deploy_id = sys.argv[2]
|
||||||
|
app_id = sys.argv[3]
|
||||||
|
status = sys.argv[4]
|
||||||
|
returncode = int(sys.argv[5])
|
||||||
|
stdout_file = Path(sys.argv[6])
|
||||||
|
stderr_file = Path(sys.argv[7])
|
||||||
|
|
||||||
|
stdout = stdout_file.read_text(errors="replace") if stdout_file.exists() else ""
|
||||||
|
stderr = stderr_file.read_text(errors="replace") if stderr_file.exists() else ""
|
||||||
|
|
||||||
|
app_status = "deployed" if status == "success" else "failed"
|
||||||
|
|
||||||
|
con = sqlite3.connect(db_file)
|
||||||
|
|
||||||
|
con.execute(
|
||||||
|
"""
|
||||||
|
UPDATE deployments
|
||||||
|
SET status = ?,
|
||||||
|
finished_at = CURRENT_TIMESTAMP,
|
||||||
|
stdout = ?,
|
||||||
|
stderr = ?,
|
||||||
|
returncode = ?
|
||||||
|
WHERE id = ?
|
||||||
|
""",
|
||||||
|
(status, stdout, stderr, returncode, deploy_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
con.execute(
|
||||||
|
"""
|
||||||
|
UPDATE apps
|
||||||
|
SET status = ?,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = ?
|
||||||
|
""",
|
||||||
|
(app_status, app_id),
|
||||||
|
)
|
||||||
|
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
|
PY
|
||||||
|
|
||||||
|
rm -rf "$TMP_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_step() {
|
||||||
|
local title="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "=================================================="
|
||||||
|
echo "$title"
|
||||||
|
echo "=================================================="
|
||||||
|
"$@"
|
||||||
|
} >>"$STDOUT_FILE" 2>>"$STDERR_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
set +e
|
||||||
|
|
||||||
|
run_step "Updating source code" bash -c "
|
||||||
|
cd '$APP_SOURCE_DIR'
|
||||||
|
if [ -d '.git' ]; then
|
||||||
|
git -c safe.directory='$APP_SOURCE_DIR' fetch origin main
|
||||||
|
git -c safe.directory='$APP_SOURCE_DIR' reset --hard origin/main
|
||||||
|
fi
|
||||||
|
"
|
||||||
|
|
||||||
|
RESULT=$?
|
||||||
|
|
||||||
|
if [ "$RESULT" -eq 0 ]; then
|
||||||
|
run_step "Building Docker image" docker build --pull --no-cache -t "$APP_ID:latest" "$APP_SOURCE_DIR"
|
||||||
|
RESULT=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Building Docker image..."
|
if [ "$RESULT" -eq 0 ]; then
|
||||||
docker build --pull --no-cache -t "$APP_ID:latest" "$APP_SOURCE_DIR"
|
run_step "Regenerating generated files" bash -c "
|
||||||
|
'$TOOLS_DIR/scripts/generate-catalog.sh'
|
||||||
if [ ! -f "$CATALOG_FILE" ]; then
|
'$TOOLS_DIR/scripts/generate-apps-compose.sh'
|
||||||
echo "apps:" > "$CATALOG_FILE"
|
'$TOOLS_DIR/scripts/generate-caddyfile.sh'
|
||||||
|
'$TOOLS_DIR/scripts/generate-apps-page.sh'
|
||||||
|
"
|
||||||
|
RESULT=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! grep -q "id: $APP_ID" "$CATALOG_FILE"; then
|
if [ "$RESULT" -eq 0 ]; then
|
||||||
cat >> "$CATALOG_FILE" <<EOF_APP
|
run_step "Starting app container" bash -c "
|
||||||
|
cd '$APPFACTORY_DIR/deploy'
|
||||||
- id: $APP_ID
|
docker compose -f docker-compose.yml -f apps-compose.yml up -d --force-recreate '$APP_ID'
|
||||||
name: $APP_ID
|
"
|
||||||
language: python
|
RESULT=$?
|
||||||
version: 1.0.0
|
|
||||||
base_path: /apps/$APP_ID
|
|
||||||
docs: /apps/$APP_ID/docs
|
|
||||||
health: /apps/$APP_ID/health
|
|
||||||
status: deployed
|
|
||||||
EOF_APP
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Regenerating generated files..."
|
set -e
|
||||||
|
|
||||||
"$TOOLS_DIR/scripts/generate-apps-compose.sh"
|
if [ "$RESULT" -eq 0 ]; then
|
||||||
"$TOOLS_DIR/scripts/generate-caddyfile.sh"
|
finish_deploy "success" 0
|
||||||
"$TOOLS_DIR/scripts/generate-apps-page.sh"
|
cat "$STDOUT_FILE"
|
||||||
|
cat "$STDERR_FILE" >&2
|
||||||
echo "Starting app container..."
|
echo ""
|
||||||
cd "$APPFACTORY_DIR/deploy"
|
echo "DONE"
|
||||||
|
echo "Open:"
|
||||||
docker compose \
|
echo "$APPFACTORY_PUBLIC_URL/apps/$APP_ID/docs"
|
||||||
-f docker-compose.yml \
|
else
|
||||||
-f apps-compose.yml \
|
finish_deploy "failed" "$RESULT"
|
||||||
up -d --force-recreate "$APP_ID"
|
cat "$STDOUT_FILE"
|
||||||
|
cat "$STDERR_FILE" >&2
|
||||||
echo ""
|
echo ""
|
||||||
echo "DONE"
|
echo "FAILED"
|
||||||
echo "Open:"
|
echo "Deployment ID: $DEPLOY_ID"
|
||||||
echo "$APPFACTORY_PUBLIC_URL/apps/$APP_ID/docs"
|
exit "$RESULT"
|
||||||
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user