Pushing stage runs CI and deploys to stage.transcribe.z00.nu with its own data, Reverb credentials, and Caddy network.
174 lines
6.3 KiB
Bash
Executable File
174 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# One-time bootstrap for the AndyTranscribe staging instance on z00.
|
|
# Creates ~/andyTranscibe-stage, a unique .env, the stage Caddy Docker network,
|
|
# and the Gitea STAGE_DEPLOY_PATHS secret.
|
|
set -euo pipefail
|
|
|
|
GITEA_DIR="${GITEA_DIR:-${HOME}/gitea}"
|
|
REPO_OWNER="${REPO_OWNER:-ben}"
|
|
REPO_NAME="${REPO_NAME:-AndyTranscribe}"
|
|
REGISTRY_HOST="${REGISTRY_HOST:-gitea.z00.nu}"
|
|
PROD_PATH="${PROD_PATH:-${HOME}/andyTranscibe}"
|
|
STAGE_PATH="${STAGE_PATH:-${HOME}/andyTranscibe-stage}"
|
|
STAGE_URL="${STAGE_URL:-https://stage.transcribe.z00.nu}"
|
|
REVERB_PUBLIC_HOST="${REVERB_PUBLIC_HOST:-reverb.stage.transcribe.z00.nu}"
|
|
CONTAINER_PREFIX="${CONTAINER_PREFIX:-andytranscribe-stage}"
|
|
CADDY_NETWORK="${CADDY_NETWORK:-andytranscribe-stage-caddy}"
|
|
PROD_CADDY_NETWORK="${PROD_CADDY_NETWORK:-caddy-proxy-manager-test_caddy-test-network}"
|
|
CADDY_CONTAINER="${CADDY_CONTAINER:-}"
|
|
CREDENTIALS_FILE="${GITEA_DIR}/.credentials"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
|
|
upsert_env() {
|
|
local file="$1"
|
|
local key="$2"
|
|
local value="$3"
|
|
python3 - "$file" "$key" "$value" <<'PY'
|
|
import re
|
|
import sys
|
|
|
|
path, key, value = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
text = open(path).read()
|
|
pattern = re.compile(r"^" + re.escape(key) + r"=.*$", re.M)
|
|
replacement = f"{key}={value}"
|
|
if pattern.search(text):
|
|
text = pattern.sub(replacement, text, count=1)
|
|
else:
|
|
text = text.rstrip("\n") + "\n" + replacement + "\n"
|
|
open(path, "w").write(text)
|
|
PY
|
|
}
|
|
|
|
if [[ ! -f "${CREDENTIALS_FILE}" ]]; then
|
|
echo "Missing ${CREDENTIALS_FILE}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# shellcheck disable=SC1090
|
|
source "${CREDENTIALS_FILE}"
|
|
|
|
API="https://${REGISTRY_HOST}/api/v1"
|
|
AUTH=(-u "${ADMIN_USERNAME}:${ADMIN_PASSWORD}")
|
|
|
|
if ! curl -fsS "${AUTH[@]}" "${API}/repos/${REPO_OWNER}/${REPO_NAME}" >/dev/null 2>&1; then
|
|
echo "Repository ${REPO_OWNER}/${REPO_NAME} not found on ${REGISTRY_HOST}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ! -d "${STAGE_PATH}/.git" ]]; then
|
|
mkdir -p "$(dirname "${STAGE_PATH}")"
|
|
if [[ -d "${PROD_PATH}/.git" ]]; then
|
|
git clone "${PROD_PATH}" "${STAGE_PATH}"
|
|
else
|
|
git clone "https://${REGISTRY_HOST}/${REPO_OWNER}/${REPO_NAME}.git" "${STAGE_PATH}"
|
|
fi
|
|
fi
|
|
|
|
(
|
|
cd "${STAGE_PATH}"
|
|
git fetch origin || true
|
|
if git rev-parse --verify origin/stage >/dev/null 2>&1; then
|
|
git checkout stage
|
|
git pull --ff-only origin stage || true
|
|
else
|
|
echo "Remote branch origin/stage not found yet; leaving $(git branch --show-current)."
|
|
fi
|
|
)
|
|
|
|
mkdir -p \
|
|
"${STAGE_PATH}/database" \
|
|
"${STAGE_PATH}/storage/app/private/recordings" \
|
|
"${STAGE_PATH}/storage/app/public" \
|
|
"${STAGE_PATH}/storage/framework/cache" \
|
|
"${STAGE_PATH}/storage/framework/sessions" \
|
|
"${STAGE_PATH}/storage/framework/views" \
|
|
"${STAGE_PATH}/storage/logs" \
|
|
"${STAGE_PATH}/bootstrap/cache"
|
|
|
|
if [[ ! -f "${STAGE_PATH}/database/database.sqlite" ]]; then
|
|
touch "${STAGE_PATH}/database/database.sqlite"
|
|
fi
|
|
|
|
ENV_SRC="${STAGE_PATH}/.env.example"
|
|
if [[ ! -f "${ENV_SRC}" ]]; then
|
|
ENV_SRC="${REPO_ROOT}/.env.example"
|
|
fi
|
|
|
|
if [[ ! -f "${STAGE_PATH}/.env" ]]; then
|
|
cp "${ENV_SRC}" "${STAGE_PATH}/.env"
|
|
upsert_env "${STAGE_PATH}/.env" "APP_ENV" "production"
|
|
upsert_env "${STAGE_PATH}/.env" "APP_DEBUG" "false"
|
|
upsert_env "${STAGE_PATH}/.env" "APP_KEY" "base64:$(openssl rand -base64 32)"
|
|
upsert_env "${STAGE_PATH}/.env" "APP_URL" "${STAGE_URL}"
|
|
upsert_env "${STAGE_PATH}/.env" "PUBLIC_APP_URL" "${STAGE_URL}"
|
|
upsert_env "${STAGE_PATH}/.env" "APP_HOST_PORT" "18180"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_HOST_PORT" "18181"
|
|
upsert_env "${STAGE_PATH}/.env" "WHISPER_HOST_PORT" "18190"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_APP_ID" "$(openssl rand -hex 8)"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_APP_KEY" "$(openssl rand -hex 16)"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_APP_SECRET" "$(openssl rand -hex 20)"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_PUBLIC_HOST" "${REVERB_PUBLIC_HOST}"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_PUBLIC_PORT" "443"
|
|
upsert_env "${STAGE_PATH}/.env" "REVERB_PUBLIC_SCHEME" "https"
|
|
upsert_env "${STAGE_PATH}/.env" "CONTAINER_PREFIX" "${CONTAINER_PREFIX}"
|
|
upsert_env "${STAGE_PATH}/.env" "CADDY_NETWORK" "${CADDY_NETWORK}"
|
|
echo "Wrote ${STAGE_PATH}/.env"
|
|
else
|
|
echo "Keeping existing ${STAGE_PATH}/.env"
|
|
fi
|
|
|
|
if ! docker network inspect "${CADDY_NETWORK}" >/dev/null 2>&1; then
|
|
docker network create "${CADDY_NETWORK}"
|
|
echo "Created Docker network ${CADDY_NETWORK}"
|
|
fi
|
|
|
|
if [[ -z "${CADDY_CONTAINER}" ]]; then
|
|
CADDY_CONTAINER="$(
|
|
docker network inspect "${PROD_CADDY_NETWORK}" \
|
|
--format '{{range .Containers}}{{.Name}}{{"\n"}}{{end}}' \
|
|
| grep -i caddy \
|
|
| head -1 || true
|
|
)"
|
|
fi
|
|
|
|
if [[ -z "${CADDY_CONTAINER}" ]]; then
|
|
echo "Could not find a Caddy container on ${PROD_CADDY_NETWORK}." >&2
|
|
echo "Set CADDY_CONTAINER and re-run: docker network connect ${CADDY_NETWORK} <caddy-container>" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if docker network inspect "${CADDY_NETWORK}" --format '{{range .Containers}}{{.Name}}{{"\n"}}{{end}}' | grep -qx "${CADDY_CONTAINER}"; then
|
|
echo "Caddy container ${CADDY_CONTAINER} already on ${CADDY_NETWORK}"
|
|
else
|
|
docker network connect "${CADDY_NETWORK}" "${CADDY_CONTAINER}"
|
|
echo "Attached ${CADDY_CONTAINER} to ${CADDY_NETWORK}"
|
|
fi
|
|
|
|
set_secret() {
|
|
local name="$1"
|
|
local value="$2"
|
|
local tmp
|
|
tmp="$(mktemp)"
|
|
python3 -c 'import json,sys; json.dump({"data": sys.argv[1]}, open(sys.argv[2], "w"))' "${value}" "${tmp}"
|
|
curl -fsS "${AUTH[@]}" -X PUT \
|
|
"${API}/repos/${REPO_OWNER}/${REPO_NAME}/actions/secrets/${name}" \
|
|
-H "Content-Type: application/json" \
|
|
--data-binary @"${tmp}" >/dev/null
|
|
rm -f "${tmp}"
|
|
}
|
|
|
|
set_secret "STAGE_DEPLOY_PATHS" "${STAGE_PATH}"
|
|
|
|
echo "Stage instance ready at ${STAGE_PATH}"
|
|
echo "Public URL: ${STAGE_URL}"
|
|
echo "Reverb host: ${REVERB_PUBLIC_HOST}"
|
|
echo "Caddy network: ${CADDY_NETWORK} (container ${CADDY_CONTAINER})"
|
|
echo "Gitea secret STAGE_DEPLOY_PATHS=${STAGE_PATH}"
|
|
echo
|
|
echo "Still required: DNS for stage.transcribe.z00.nu and ${REVERB_PUBLIC_HOST},"
|
|
echo "plus Caddy Proxy Manager hosts pointing at ${CONTAINER_PREFIX}-app:80"
|
|
echo "and ${CONTAINER_PREFIX}-reverb:8080."
|
|
echo "Then: git checkout -b stage && git push -u origin stage"
|