Add Core/bin/checl-wordpressversion, formerly wordpress-vercheck-all.sh, to be run regularly from cronjob to protect against WordPress version downgrades
This commit is contained in:
parent
dfe2aa1ffa
commit
a327a08783
361
bin/check-wordpressversion
Executable file
361
bin/check-wordpressversion
Executable file
@ -0,0 +1,361 @@
|
||||
#!/bin/bash
|
||||
|
||||
# WordPress Version Check and Update Script
|
||||
# Copyright 2024 A.D. Federated Computer, Inc.
|
||||
# saint@federated.computer
|
||||
# ---------------------------------------
|
||||
# This script checks the running WordPress version in a Docker container and updates
|
||||
# the IMAGE_VERSION in the .env file to match if needed.
|
||||
#
|
||||
# Version Detection Methods (in order):
|
||||
# 1. WP-CLI: Uses 'wp core version'
|
||||
# 2. PHP Direct: Uses wp_eval to get bloginfo('version')
|
||||
# 3. File Check: Reads version from /bitnami/wordpress/wp-includes/version.php
|
||||
# 4. Database Primary: Reads from wp_options._transient_wp_core_block_css_files
|
||||
# 5. Database Backup: Reads from wp_options._site_transient_update_core
|
||||
#
|
||||
# The script will:
|
||||
# - Use the highest valid version found from any method
|
||||
# - Check if that version is newer than the one in .env
|
||||
# - If newer, look for matching Docker image on Docker Hub
|
||||
# - If exact version not found, use next newer version or closest older version
|
||||
# - Update .env with the new version and add IMAGE_VERSION_HOLD=true if needed
|
||||
|
||||
# Enable debug output
|
||||
set -x
|
||||
|
||||
# Set your container name and .env file path
|
||||
CONTAINER_NAME="wordpress"
|
||||
APP_DIR="/federated/apps/$CONTAINER_NAME"
|
||||
ENV_FILE="$APP_DIR/.env"
|
||||
DOCKER_COMPOSE_FILE="$APP_DIR/docker-compose.yml"
|
||||
|
||||
# Function to validate version string
|
||||
is_valid_version() {
|
||||
local version=$1
|
||||
# Allow x, x.y, x.y.z, or x.y.z.a where all parts are integers
|
||||
[[ $version =~ ^[0-9]+(\.[0-9]+)*$ ]] || return 1
|
||||
# Count parts
|
||||
local parts
|
||||
IFS='.' read -ra parts <<< "$version"
|
||||
# Allow 1 to 4 parts
|
||||
[ ${#parts[@]} -le 4 ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
echo "Starting WordPress version check and update script..."
|
||||
|
||||
# Function to get version from different sources
|
||||
get_wp_version() {
|
||||
local wpcli_version php_version file_version db_version admin_version highest_version
|
||||
|
||||
# 1. Try wp-cli version
|
||||
wpcli_version=$(docker exec "$CONTAINER_NAME" wp core version --allow-root) || true
|
||||
if ! is_valid_version "$wpcli_version"; then wpcli_version=""; fi
|
||||
|
||||
# 2. Try version.php direct access
|
||||
php_version=$(docker exec "$CONTAINER_NAME" wp eval 'echo get_bloginfo("version");' --allow-root) || true
|
||||
if ! is_valid_version "$php_version"; then php_version=""; fi
|
||||
|
||||
# 3. Try direct file content check (fixed quotes)
|
||||
file_version=$(docker exec "$CONTAINER_NAME" bash -c "grep '\\\$wp_version = ' /bitnami/wordpress/wp-includes/version.php | sed -n 's/.*= .\\([0-9.]*\\).*/\\1/p'") || true
|
||||
if [ -z "$file_version" ]; then
|
||||
file_version=$(docker exec "$CONTAINER_NAME" bash -c "grep '\\\$wp_version = ' /opt/bitnami/wordpress/wp-includes/version.php | sed -n 's/.*= .\\([0-9.]*\\).*/\\1/p'") || true
|
||||
fi
|
||||
if ! is_valid_version "$file_version"; then file_version=""; fi
|
||||
|
||||
# 4. Try database version through wp-cli with socket path
|
||||
db_version=$(docker exec "$CONTAINER_NAME" bash -c '
|
||||
is_valid_version() {
|
||||
local version=$1
|
||||
# Allow x, x.y, x.y.z, or x.y.z.a formats
|
||||
[[ $version =~ ^[0-9]+(\.[0-9]+)*$ ]] || return 1
|
||||
# Count parts and ensure not more than 4
|
||||
local parts
|
||||
IFS='.' read -ra parts <<< "$version"
|
||||
[ ${#parts[@]} -le 4 ] || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
if [ -f /opt/bitnami/mysql/bin/mariadb ]; then
|
||||
MYSQL_CMD="/opt/bitnami/mysql/bin/mariadb"
|
||||
else
|
||||
MYSQL_CMD="/opt/bitnami/mysql/bin/mysql"
|
||||
fi
|
||||
export MYSQL_PWD="$WORDPRESS_DATABASE_PASSWORD"
|
||||
|
||||
# First try _transient_wp_core_block_css_files as it has simpler structure
|
||||
version=$($MYSQL_CMD -u "$WORDPRESS_DATABASE_USER" \
|
||||
-h "$WORDPRESS_DATABASE_HOST" \
|
||||
--skip-ssl \
|
||||
"$WORDPRESS_DATABASE_NAME" \
|
||||
-N -e "SELECT option_value FROM wp_options WHERE option_name = \"_transient_wp_core_block_css_files\";" | \
|
||||
sed -n "s/.*s:7:\"version\";s:[0-9]*:\"\([0-9][0-9.]*\)\".*/\1/p")
|
||||
|
||||
# Validate first version before accepting it
|
||||
if ! is_valid_version "$version"; then
|
||||
# If first attempt fails or gives invalid version, try _site_transient_update_core
|
||||
version=$($MYSQL_CMD -u "$WORDPRESS_DATABASE_USER" \
|
||||
-h "$WORDPRESS_DATABASE_HOST" \
|
||||
--skip-ssl \
|
||||
"$WORDPRESS_DATABASE_NAME" \
|
||||
-N -e "SELECT option_value FROM wp_options WHERE option_name = \"_site_transient_update_core\";" | \
|
||||
sed -n "s/.*\"version_checked\":\"\([0-9][0-9.]*\)\".*/\1/p")
|
||||
fi
|
||||
|
||||
# Only output version if it is valid
|
||||
if is_valid_version "$version"; then
|
||||
echo "$version"
|
||||
fi
|
||||
') || true
|
||||
if ! is_valid_version "$db_version"; then db_version=""; fi
|
||||
|
||||
# 5. Try reading version from version.php using PHP
|
||||
admin_version=$(docker exec "$CONTAINER_NAME" bash -c "php -r '
|
||||
\$files = array(\"/bitnami/wordpress/wp-includes/version.php\", \"/opt/bitnami/wordpress/wp-includes/version.php\");
|
||||
foreach (\$files as \$file) {
|
||||
if (file_exists(\$file)) {
|
||||
include \$file;
|
||||
echo \$wp_version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
'") || true
|
||||
if ! is_valid_version "$admin_version"; then admin_version=""; fi
|
||||
|
||||
# Log all found versions (to stderr for debugging)
|
||||
{
|
||||
echo "WP-CLI reports version: ${wpcli_version:-not found}" >&2
|
||||
echo "wp eval reports version: ${php_version:-not found}" >&2
|
||||
echo "File check reports version: ${file_version:-not found}" >&2
|
||||
echo "Database reports version: ${db_version:-not found}" >&2
|
||||
echo "Admin page reports version: ${admin_version:-not found}" >&2
|
||||
}
|
||||
|
||||
# Compare all versions and take the highest one
|
||||
local versions=()
|
||||
[ ! -z "$wpcli_version" ] && versions+=("$wpcli_version")
|
||||
[ ! -z "$php_version" ] && versions+=("$php_version")
|
||||
[ ! -z "$file_version" ] && versions+=("$file_version")
|
||||
[ ! -z "$db_version" ] && versions+=("$db_version")
|
||||
[ ! -z "$admin_version" ] && versions+=("$admin_version")
|
||||
|
||||
if [ ${#versions[@]} -eq 0 ]; then
|
||||
echo "Error: Could not determine WordPress version from any source" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Return just the version number
|
||||
printf '%s\n' "${versions[@]}" | sort -V | tail -n 1
|
||||
}
|
||||
|
||||
# Function to find closest available version on Docker Hub
|
||||
find_closest_version() {
|
||||
local target_version=$1
|
||||
local available_versions=""
|
||||
local page=1
|
||||
local page_size=100
|
||||
local next_url="https://hub.docker.com/v2/repositories/bitnami/wordpress/tags?page_size=$page_size"
|
||||
|
||||
echo "Retrieving available WordPress versions from Docker Hub..." >&2
|
||||
|
||||
# Keep fetching pages until we hit an empty page or no next URL
|
||||
while [ ! -z "$next_url" ]; do
|
||||
echo "Fetching page $page..." >&2
|
||||
|
||||
# Get the current page and extract versions and next URL
|
||||
local response=$(curl -s "$next_url")
|
||||
|
||||
# Extract versions from this page
|
||||
local page_versions=$(echo "$response" | \
|
||||
grep -o '"name":"[^"]*"' | \
|
||||
grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | \
|
||||
sort -V | uniq)
|
||||
|
||||
# If we got no versions, break
|
||||
if [ -z "$page_versions" ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
# Append to our list of versions
|
||||
available_versions="$available_versions"$'\n'"$page_versions"
|
||||
|
||||
# Get next page URL and decode \u0026 to &
|
||||
next_url=$(echo "$response" | \
|
||||
grep -o '"next":"[^"]*"' | \
|
||||
cut -d'"' -f4 | \
|
||||
sed 's/\\u0026/\&/g' )
|
||||
|
||||
# If no next URL or we've hit page limit, break
|
||||
if [ -z "$next_url" ] || [ $page -ge 10 ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
((page++))
|
||||
done
|
||||
|
||||
# Clean up and sort the final list
|
||||
available_versions=$(echo "$available_versions" | grep -v '^$' | sort -V | uniq)
|
||||
|
||||
if [ -z "$available_versions" ]; then
|
||||
echo "Failed to get versions from Docker Hub" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Print all versions for debugging
|
||||
echo "Available versions:" >&2
|
||||
echo "$available_versions" >&2
|
||||
|
||||
# First, check if target version exists
|
||||
if echo "$available_versions" | grep -Fxq "$target_version"; then
|
||||
printf '%s\n' "$target_version"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# If not, find next newer version
|
||||
local newer_version
|
||||
newer_version=$(echo "$available_versions" | awk -v ver="$target_version" '$1 > ver' | head -n1)
|
||||
|
||||
# If no newer version, find closest older version
|
||||
if [ -z "$newer_version" ]; then
|
||||
echo "$available_versions" | awk -v ver="$target_version" '$1 <= ver' | tail -n1
|
||||
else
|
||||
printf '%s\n' "$newer_version"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to compare version numbers
|
||||
version_greater_than() {
|
||||
local ver1=$1
|
||||
local ver2=$2
|
||||
|
||||
if ! is_valid_version "$ver1" || ! is_valid_version "$ver2"; then
|
||||
echo "Invalid version format" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Convert versions to arrays
|
||||
local v1_parts=() v2_parts=()
|
||||
IFS='.' read -ra v1_parts <<< "$ver1"
|
||||
IFS='.' read -ra v2_parts <<< "$ver2"
|
||||
|
||||
# Pad shorter version with zeros
|
||||
while [ ${#v1_parts[@]} -lt 4 ]; do
|
||||
v1_parts+=("0")
|
||||
done
|
||||
while [ ${#v2_parts[@]} -lt 4 ]; do
|
||||
v2_parts+=("0")
|
||||
done
|
||||
|
||||
# Compare each part numerically
|
||||
for i in {0..3}; do
|
||||
if [ "${v1_parts[i]:-0}" -gt "${v2_parts[i]:-0}" ]; then
|
||||
return 0 # ver1 is greater
|
||||
elif [ "${v1_parts[i]:-0}" -lt "${v2_parts[i]:-0}" ]; then
|
||||
return 1 # ver1 is not greater
|
||||
fi
|
||||
done
|
||||
return 1 # versions are equal
|
||||
}
|
||||
|
||||
# Test cases (can be commented out in production)
|
||||
test_versions() {
|
||||
local test_pairs=(
|
||||
"6.7 6.6.2" # should return 0 (true)
|
||||
"7 6.7" # should return 0 (true)
|
||||
"6.6.2 6.6.2" # should return 1 (false)
|
||||
"6.6.1 6.6.2" # should return 1 (false)
|
||||
"6.7.0 6.7" # should return 1 (false)
|
||||
"6.7.1 6.7" # should return 0 (true)
|
||||
"6.7.0.1 6.7" # should return 0 (true)
|
||||
)
|
||||
|
||||
echo "Running version comparison tests..."
|
||||
for pair in "${test_pairs[@]}"; do
|
||||
read -r v1 v2 <<< "$pair"
|
||||
if version_greater_than "$v1" "$v2"; then
|
||||
echo "$v1 > $v2 (OK)"
|
||||
else
|
||||
echo "$v1 <= $v2"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Running version validation tests..."
|
||||
local test_versions=(
|
||||
"6" # valid
|
||||
"6.7" # valid
|
||||
"6.7.2" # valid
|
||||
"6.7.2.1" # valid
|
||||
"6.7.2.1.5" # invalid
|
||||
"6.7.2a" # invalid
|
||||
"6.7." # invalid
|
||||
".6.7" # invalid
|
||||
"a.b.c" # invalid
|
||||
)
|
||||
|
||||
for ver in "${test_versions[@]}"; do
|
||||
if is_valid_version "$ver"; then
|
||||
echo "$ver is valid"
|
||||
else
|
||||
echo "$ver is invalid"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# Uncomment to run tests
|
||||
test_versions
|
||||
|
||||
# Get the current WordPress version
|
||||
current_wp_version=$(get_wp_version | tr -d '\r')
|
||||
if [ -z "$current_wp_version" ] || ! is_valid_version "$current_wp_version"; then
|
||||
echo "Failed to get valid WordPress version"
|
||||
exit 1
|
||||
fi
|
||||
echo "Using WordPress version: $current_wp_version"
|
||||
|
||||
## current_wp_version="6.7.0"
|
||||
|
||||
# Check the current IMAGE_VERSION from the .env file
|
||||
echo "Reading IMAGE_VERSION from .env file..."
|
||||
env_wp_version=$(grep '^IMAGE_VERSION=' "$ENV_FILE" | cut -d= -f2 | tr -d '"' | tr -d "'")
|
||||
if ! is_valid_version "$env_wp_version"; then
|
||||
echo "Invalid version in .env file"
|
||||
exit 1
|
||||
fi
|
||||
echo "WordPress version in .env file (IMAGE_VERSION): $env_wp_version"
|
||||
|
||||
# Check if current_wp_version is greater than env_wp_version
|
||||
if version_greater_than "$current_wp_version" "$env_wp_version"; then
|
||||
echo "Upgrade detected: WordPress ($current_wp_version) is newer than .env ($env_wp_version)"
|
||||
|
||||
# Find the best available version to use
|
||||
target_version=$(find_closest_version "$current_wp_version" | tr -d '\r')
|
||||
|
||||
if [ -n "$target_version" ]; then
|
||||
echo "Found appropriate Docker image version: $target_version"
|
||||
|
||||
# Backup current .env file
|
||||
echo "Backing up current .env file..."
|
||||
### cp "$ENV_FILE" "${ENV_FILE}.backup"
|
||||
|
||||
# Update the IMAGE_VERSION in the .env file
|
||||
echo "Updating IMAGE_VERSION in .env file to: $target_version"
|
||||
### sed -i "s/^IMAGE_VERSION=.*$/IMAGE_VERSION=\"$target_version\"/" "$ENV_FILE"
|
||||
|
||||
# Check if IMAGE_VERSION_HOLD exists, add it if it doesn't
|
||||
if ! grep -q "^IMAGE_VERSION_HOLD=" "$ENV_FILE"; then
|
||||
echo "Adding IMAGE_VERSION_HOLD=true after IMAGE_VERSION..."
|
||||
### sed -i "/^IMAGE_VERSION=.*/a IMAGE_VERSION_HOLD=true" "$ENV_FILE"
|
||||
fi
|
||||
|
||||
echo "Successfully updated .env to version $target_version"
|
||||
else
|
||||
echo "Failed to find an appropriate version on Docker Hub"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "No update required. WordPress version ($current_wp_version) is not newer than .env version ($env_wp_version)."
|
||||
fi
|
||||
|
||||
echo "WordPress version check and update script completed."
|
||||
|
Loading…
x
Reference in New Issue
Block a user