Files
appstore/apps/dootask/latest/scripts/dootask-entrypoint.sh
T
2026-07-06 12:46:02 +08:00

235 lines
7.0 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
APP_ROOT="/var/www"
SCRIPT_ROOT="/opt/dootask-scripts"
EXPECTED_RELEASE="1.8.64"
SOURCE_URL="https://github.com/kuaifan/dootask/archive/refs/tags/v1.8.64.tar.gz"
SOURCE_SHA256="934b422f0917c8fd55b8a65fcdb476c9158d72a20c1d0a6fe62cd88c0fa0b13b"
VENDOR_URL="https://github.com/kuaifan/dootask/releases/download/v1.8.64/vendor.tar.gz"
VENDOR_SHA256="136430ac28ee38820c37167c0eae4c29e8b64d287ea0224a2c4320ff0873596d"
MARKER_FILE="${APP_ROOT}/.1panel-release-version"
log() {
echo "[dootask-entrypoint] $*"
}
escape_sed_replacement() {
printf '%s' "$1" | sed -e 's/[&|]/\\&/g'
}
set_env_value() {
local key="$1"
local value="$2"
local file="${APP_ROOT}/.env"
local escaped
escaped="$(escape_sed_replacement "$value")"
if grep -qE "^${key}=" "$file"; then
sed -i "s|^${key}=.*|${key}=${escaped}|" "$file"
else
printf '%s=%s\n' "$key" "$value" >>"$file"
fi
}
get_env_value() {
local key="$1"
local file="${APP_ROOT}/.env"
local line
line="$(grep -E "^${key}=" "$file" 2>/dev/null | tail -n 1 || true)"
if [[ -z "$line" ]]; then
return 1
fi
printf '%s' "${line#*=}"
}
download_with_sha() {
local url="$1"
local target="$2"
local sha="$3"
curl -fsSL "$url" -o "$target"
echo "${sha} ${target}" | sha256sum -c -
}
bootstrap_source() {
mkdir -p "${APP_ROOT}" "${APP_ROOT}/storage" "${APP_ROOT}/bootstrap/cache" "${APP_ROOT}/public/uploads"
if [[ -f "${MARKER_FILE}" ]]; then
local current_release
current_release="$(cat "${MARKER_FILE}")"
if [[ "${current_release}" != "${EXPECTED_RELEASE}" ]]; then
log "detected existing source release ${current_release}, expected ${EXPECTED_RELEASE}; refusing automatic in-place source replacement"
exit 1
fi
fi
if [[ ! -f "${APP_ROOT}/artisan" ]]; then
log "bootstrapping upstream source ${EXPECTED_RELEASE}"
local tmpdir archive srcdir
tmpdir="$(mktemp -d)"
archive="${tmpdir}/dootask-source.tar.gz"
download_with_sha "${SOURCE_URL}" "${archive}" "${SOURCE_SHA256}"
tar -xzf "${archive}" -C "${tmpdir}"
srcdir="$(find "${tmpdir}" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
cp -a "${srcdir}/." "${APP_ROOT}/"
echo "${EXPECTED_RELEASE}" >"${MARKER_FILE}"
rm -rf "${tmpdir}"
fi
if [[ ! -f "${APP_ROOT}/vendor/autoload.php" ]]; then
log "restoring vendor bundle for ${EXPECTED_RELEASE}"
local tmpdir archive
tmpdir="$(mktemp -d)"
archive="${tmpdir}/vendor.tar.gz"
download_with_sha "${VENDOR_URL}" "${archive}" "${VENDOR_SHA256}"
rm -rf "${APP_ROOT}/vendor"
tar -xzf "${archive}" -C "${APP_ROOT}"
rm -rf "${tmpdir}"
fi
mkdir -p "${APP_ROOT}/docker/crontab" "${APP_ROOT}/docker/nginx/site" "${APP_ROOT}/docker/nginx/conf.d"
cp -f "${SCRIPT_ROOT}/dootask-crontab.sh" "${APP_ROOT}/docker/crontab/crontab.sh"
chmod +x "${APP_ROOT}/docker/crontab/crontab.sh"
}
apply_source_compat_patches() {
php "${SCRIPT_ROOT}/dootask-source-patch.php"
}
ensure_env_file() {
if [[ ! -f "${APP_ROOT}/.env" ]]; then
cp "${APP_ROOT}/.env.docker" "${APP_ROOT}/.env"
fi
local current_app_url derived_app_url
current_app_url="$(get_env_value APP_URL || true)"
derived_app_url="http://127.0.0.1:${PANEL_APP_PORT_HTTP}"
set_env_value "APP_NAME" "DooTask"
set_env_value "APP_ENV" "production"
set_env_value "APP_DEBUG" "false"
set_env_value "APP_SCHEME" "auto"
set_env_value "TIMEZONE" "${TIMEZONE}"
if [[ -z "${current_app_url}" || "${current_app_url}" == "http://localhost" || "${current_app_url}" == http://127.0.0.1* ]]; then
set_env_value "APP_URL" "${derived_app_url}"
fi
set_env_value "APP_PORT" "${PANEL_APP_PORT_HTTP}"
set_env_value "APP_ID" "${CONTAINER_NAME:-dootask}"
set_env_value "APP_IPPR" ""
set_env_value "APP_DEV_PORT" ""
set_env_value "DB_CONNECTION" "mysql"
set_env_value "DB_HOST" "${PANEL_DB_HOST}"
set_env_value "DB_PORT" "${DB_PORT}"
set_env_value "DB_DATABASE" "${PANEL_DB_NAME}"
set_env_value "DB_USERNAME" "${PANEL_DB_USER}"
set_env_value "DB_PASSWORD" "${PANEL_DB_USER_PASSWORD}"
set_env_value "DB_PREFIX" "${DB_PREFIX}"
set_env_value "CACHE_DRIVER" "redis"
set_env_value "QUEUE_CONNECTION" "redis"
set_env_value "SESSION_DRIVER" "redis"
set_env_value "REDIS_HOST" "${REDIS_HOST}"
set_env_value "REDIS_PORT" "${REDIS_PORT}"
if [[ -z "${PANEL_REDIS_ROOT_PASSWORD}" || "${PANEL_REDIS_ROOT_PASSWORD}" == "null" ]]; then
set_env_value "REDIS_PASSWORD" "null"
else
set_env_value "REDIS_PASSWORD" "${PANEL_REDIS_ROOT_PASSWORD}"
fi
set_env_value "REDIS_DB" "${REDIS_DB}"
set_env_value "REDIS_CACHE_DB" "1"
set_env_value "LARAVELS_LISTEN_IP" "0.0.0.0"
set_env_value "LARAVELS_LISTEN_PORT" "20000"
}
ensure_app_key() {
local app_key
app_key="$(get_env_value APP_KEY || true)"
if [[ -n "${app_key}" ]]; then
return 0
fi
app_key="$(php artisan key:generate --show --no-interaction)"
set_env_value "APP_KEY" "${app_key}"
}
ensure_vendor_fallback() {
if [[ -f "${APP_ROOT}/vendor/autoload.php" ]]; then
return 0
fi
log "vendor bundle missing after restore, running composer install fallback"
COMPOSER_ALLOW_SUPERUSER=1 composer install --no-dev --prefer-dist --no-interaction --optimize-autoloader
}
wait_for_mysql() {
log "waiting for MySQL ${PANEL_DB_HOST}:${DB_PORT}"
for _ in $(seq 1 90); do
if php -r '
try {
$pdo = new PDO(
"mysql:host=" . getenv("PANEL_DB_HOST") . ";port=" . getenv("DB_PORT") . ";dbname=" . getenv("PANEL_DB_NAME") . ";charset=utf8mb4",
getenv("PANEL_DB_USER"),
getenv("PANEL_DB_USER_PASSWORD"),
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
);
exit(0);
} catch (Throwable $e) {
fwrite(STDERR, $e->getMessage());
exit(1);
}
' >/dev/null 2>&1; then
return 0
fi
sleep 2
done
log "MySQL did not become ready in time"
return 1
}
wait_for_redis() {
log "waiting for Redis ${REDIS_HOST}:${REDIS_PORT}"
for _ in $(seq 1 90); do
if php -r '
try {
$redis = new Redis();
$redis->connect(getenv("REDIS_HOST"), (int) getenv("REDIS_PORT"), 2.5);
$password = getenv("PANEL_REDIS_ROOT_PASSWORD");
if ($password !== false && $password !== "" && strtolower($password) !== "null") {
$redis->auth($password);
}
$redis->select((int) getenv("REDIS_DB"));
if ($redis->ping() === false) {
exit(1);
}
exit(0);
} catch (Throwable $e) {
fwrite(STDERR, $e->getMessage());
exit(1);
}
' >/dev/null 2>&1; then
return 0
fi
sleep 2
done
log "Redis did not become ready in time"
return 1
}
run_app_setup() {
php artisan config:clear >/dev/null 2>&1 || true
php artisan cache:clear >/dev/null 2>&1 || true
php artisan migrate --force
php "${SCRIPT_ROOT}/dootask-bootstrap.php"
}
main() {
cd "${APP_ROOT}"
bootstrap_source
apply_source_compat_patches
ensure_env_file
ensure_vendor_fallback
ensure_app_key
wait_for_mysql
wait_for_redis
run_app_setup
exec /usr/bin/supervisord -n
}
main "$@"