umbrel-apps/nextcloud/hooks/pre-start
2024-08-06 12:32:45 +10:00

162 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
APP_DATA_DIR="$(readlink -f $(dirname "${BASH_SOURCE[0]}")/..)"
UMBREL_ROOT="${APP_DATA_DIR}/../.."
CONFIG_PHP_FILE="${APP_DATA_DIR}/data/nextcloud/config/config.php"
APP_COMPOSE_FILE="${APP_DATA_DIR}/docker-compose.yml"
APP_COMPOSE_BACKUP_FILE="${APP_DATA_DIR}/docker-compose.yml.bak"
# TODO: When Nextcloud 30 is released, refactor this script to handle updates from all patch versions released to the umbrel app store.
# Supported list of Nextcloud migrations
VERSIONS=()
VERSIONS+=( "22.1.1.2" )
VERSIONS+=( "22.2.10.2" )
VERSIONS+=( "23.0.11.1" )
VERSIONS+=( "24.0.7.1" )
VERSIONS+=( "25.0.1.1" )
VERSIONS+=( "26.0.9.1" )
VERSIONS+=( "27.0.2.1" )
VERSIONS+=( "28.0.3.2" )
VERSIONS+=( "29.0.4.1" )
IMAGES=()
IMAGES+=( "nextcloud:22.1.1-apache@sha256:99d94124b2024c9f7f38dc12144a92bc0d68d110bcfd374169ebb7e8df0adf8e" )
IMAGES+=( "nextcloud:22.2.10-apache@sha256:71c4fb75d7c035ea2c840ebc1adf0da144b0c69e39ce925f4a2ea84b7c06db18" )
IMAGES+=( "nextcloud:23.0.11-apache@sha256:671ed70c7b204c63cb56d5c0d5dd624abec5eadeacd492191e65e834ddffef26" )
IMAGES+=( "nextcloud:24.0.7-apache@sha256:f95a21b598b7470b788251db5b0bbe9516992fdb865e7a8978980585e36eb715" )
IMAGES+=( "nextcloud:25.0.1-apache@sha256:a200319b132c01ec3486e0dcaf052092b560ec30ac9b78115607696dd201f704" )
IMAGES+=( "nextcloud:26.0.9-apache@sha256:23180fbe8169d428ce0058bfc8d47793628a16e00e40b495d82e4504a124b3fa" )
IMAGES+=( "nextcloud:27.0.2-apache@sha256:3c8040278bdc991cbc025278eaffc4978a9c2fd4ac34e95b10f646dcadb7c3fb" )
IMAGES+=( "nextcloud:28.0.3-apache@sha256:ed07f89119dcca2a3711897c48a8ac969542d96d69384445d8fcdc7804ca946f" )
IMAGES+=( "nextcloud:29.0.4-apache@sha256:12c7bb0da1d41a08583971d5ba9771c4f37592ddd0aae5f5ce6a306961caa674" )
find_index() {
local -r value="${1}"
shift
local -r array=("$@")
for i in "${!array[@]}"; do
if [[ "${array[$i]}" == "${value}" ]]; then
echo $i
exit
fi
done
echo -1
}
wait_for_value_in_file () {
local -r file="${1}"
local -r str="${2}"
local -r max_seconds="${3}"
echo "Searching for '${str}' inside: ${file}"
for i in $(seq 1 "${max_seconds}"); do
echo "Attempt: ${i}"
if cat "${file}" | grep --quiet "${str}"; then
return
fi
sleep 1
done
echo "Failed after ${max_seconds} seconds to find '${str}' inside: ${file}"
exit 1
}
check_compose_file () {
local -r image="${1}"
web_image=$(cat "${APP_COMPOSE_FILE}" 2> /dev/null | yq '.services.web.image' || true)
cron_image=$(cat "${APP_COMPOSE_FILE}" 2> /dev/null | yq '.services.cron.image' || true)
if [[ "${web_image}" != "${image}" ]] || [[ "${cron_image}" != "${image}" ]]; then
echo "The docker-compose.yml now looks bad. Restoring..."
mv "${APP_COMPOSE_BACKUP_FILE}" "${APP_COMPOSE_FILE}"
exit
fi
}
get_version() {
cat "${CONFIG_PHP_FILE}" | grep "'version'[[:space:]]=>[[:space:]]" | awk -F"'" '{print $4}'
}
# If a Nextcloud config file does not yet exist
# Then it's likely a new install
# Therefore there is nothing to do
if [[ ! -f "${CONFIG_PHP_FILE}" ]]; then
exit
fi
nextcloud_version=$(get_version)
echo "Active Nextcloud Version: ${nextcloud_version}"
# Check if active version is in migration list
active_version_idx=$(find_index "${nextcloud_version}" "${VERSIONS[@]}")
if [[ "${active_version_idx}" == "-1" ]]; then
echo "Active version is not supported in the list of migrations"
exit
fi
# Check if already up to date
if [[ "${VERSIONS[-1]}" == "${nextcloud_version}" ]]; then
echo "Nextcloud is up-to-date"
exit
fi
# Loop through versions, ignoring past versions
for i in "${!VERSIONS[@]}"; do
[[ "${i}" -le "${active_version_idx}" ]] && continue
version="${VERSIONS[$i]}"
image="${IMAGES[$i]}"
echo "Migrating to: ${version} (${image})"
echo
cp --archive "${APP_COMPOSE_FILE}" "${APP_COMPOSE_BACKUP_FILE}"
yq -i ".services.web.image = \"${image}\"" "${APP_COMPOSE_FILE}"
yq -i ".services.cron.image = \"${image}\"" "${APP_COMPOSE_FILE}"
check_compose_file "${image}"
nextcloud_version=$(get_version)
sed -i "s/${nextcloud_version}/${nextcloud_version}-patch/" "${CONFIG_PHP_FILE}"
"${UMBREL_ROOT}/scripts/app" start nextcloud
echo "Waiting for update to complete..."
# Wait for Nextcloud to enter maintenance mode
# Indicating their update process has started
wait_for_value_in_file "${CONFIG_PHP_FILE}" "'maintenance'[[:space:]]=>[[:space:]]true" 300
# Wait for Nextcloud to exit maintenance mode
# Indicating their update process has finished
wait_for_value_in_file "${CONFIG_PHP_FILE}" "'maintenance'[[:space:]]=>[[:space:]]false" 300
"${UMBREL_ROOT}/scripts/app" stop nextcloud
# Delete image of intermediate version
# Unless it's the latest image
# Otherwise it will have to be re-downloaded
if [[ "${version}" != "${VERSIONS[-1]}" ]]; then
echo "Deleting intermediary image: ${image}"
docker rmi "${image}" || true
fi
done
rm -rf "${APP_COMPOSE_BACKUP_FILE}"
echo "Migration completed successfully"