/root/bin/deploy-mediawiki.sh (1)

From RaySoft
#!/bin/bash -
# ------------------------------------------------------------------------------
# deploy-mediawiki.sh
# ===================
#
# Project   RaySoft
# Scope     Native
# Copyright (C) 2024 by RaySoft, Zurich, Switzerland
# License   GNU General Public License (GPL) 2.0
#           https://www.gnu.org/licenses/gpl2.txt
#
# This script installs, upgrades (switch to another branch) or updates one or
# many MediaWiki instances. It expects the following options:
#
# $1: Mode ('install', 'update' or 'upgrade')
# $@: One or many paths to instances. These paths must exist for mode 'update'
#     or 'upgrade'
#
# Usage:
#   deploy-mediawiki.sh <install|upgrade|update> <PATH> [PATH ...]
#
# ------------------------------------------------------------------------------

set -o 'noglob' -o 'nounset' -o 'pipefail' # -o 'errexit' -o 'xtrace'

# ------------------------------------------------------------------------------
# Configuration
# -------------

DM_BASE_BRANCH='REL1_41'

DM_GERRIT_URL='https://gerrit.wikimedia.org/r/mediawiki'

DM_GERRIT_EXTENSIONS=(
  'Cite'                              "${DM_BASE_BRANCH}"
  'OATHAuth'                          "${DM_BASE_BRANCH}"
  'ParserFunctions'                   "${DM_BASE_BRANCH}"
  'ReplaceText'                       "${DM_BASE_BRANCH}"
  'SyntaxHighlight_GeSHi'             "${DM_BASE_BRANCH}"
)

DM_GERRIT_SKINS=(
  'Vector'                            "${DM_BASE_BRANCH}"
)

DM_GITHUB_URL='https://github.com'

DM_GITHUB_EXTENSIONS=(
  'Universal-Omega/DynamicPageList3'  'master'
)

DM_WIKI_DIR='w'

# ------------------------------------------------------------------------------
# Binary declaration
# ------------------

DM_X_COMPOSER=('/bin/composer')
DM_X_CHMOD=('/bin/chmod')
DM_X_FIND=('/bin/find')
DM_X_GIT=('/bin/git')
DM_X_MKDIR=('/bin/mkdir' '-p')
DM_X_PHP=('/opt/php82/bin/php')
DM_X_RM=('/bin/rm' '-r')
DM_X_SED=('/bin/sed')

# ------------------------------------------------------------------------------
# Private functions
# -----------------

dm::_get_code() {
  # This private function gets the code from different Git repositories.
  #
  # Arguments:
  #   $1: Mode ('install', 'update' or 'upgrade')
  #   $2: Repository URL
  #   $3: Repository branch
  #   $4: Path to installation
  #
  # Returns:
  #   0:  Success
  #   >0: Error

  if [[ "$#" -ne 4 ]]; then
    echo "Error calling function: $*!"
    return 1
  fi

  if [[ "$1" == 'install' ]]; then
    if [[ ! -d "${4%/*}" ]]; then
      "${DM_X_MKDIR[@]}" "${4%/*}"
    fi

    if ! "${DM_X_GIT[@]}" clone --branch="$3" --progress "$2.git" "$4"; then
      echo "Error cloning repository: $4!"
      return 1
    fi
  else
    if [[ ! -d "$4" ]]; then
      echo "Error finding directory: $4!"
      return 1
    fi

    if ! "${DM_X_GIT[@]}" -C "$4" pull --progress; then
      echo "Error pulling repository: $4!"
      return 1
    fi
  fi

  if [[ "$1" == 'upgrade' ]]; then
    echo

    if ! "${DM_X_GIT[@]}" -C "$4" checkout --force --progress "$3"; then
      echo "Error checking out branch: $4!"
      return 1
    fi

    echo

    if ! "${DM_X_GIT[@]}" -C "$4" gc --force --keep-largest-pack; then
      echo "Error cleaning up repository: $4!"
      return 1
    fi
  fi

  return 0
}

dm::_update_deps() {
  # This private function runs 'composer' to update the vendor dependencies.
  #
  # Arguments:
  #   $1: Path to installation
  #
  # Returns:
  #   0:  Success
  #   >0: Error

  if [[ "$#" -ne 1 ]]; then
    echo "Error calling function: $*!"
    return 1
  fi

  if [[ ! -d "$1" ]]; then
    echo "Error finding directory: $1!"
    return 1
  fi

  if ! "${DM_X_PHP[@]}" "${DM_X_COMPOSER[@]}" update --no-dev \
         --optimize-autoloader --with-dependencies --working-dir="$1"
  then
    echo "Error running Composer update: $1!"
    return 1
  fi

  return 0
}

dm::_usage() {
  # This private function prints the 'usage' message.
  #
  # Arguments:
  #   $@: Error message
  #
  # Returns:
  #   0:  Success
  #   >0: Error

  if [[ "$#" -lt 1 ]]; then
    echo "Error calling function: $*!"
    return 1
  fi

  echo "$*"
  echo
  echo "Usage: ${BASH_SOURCE[0]##*/} <install|upgrade|update> <PATH> [PATH ...]"

  return 0
} 1>&2

# ------------------------------------------------------------------------------
# Main
# ----

if [[ "$#" -lt 2 ]]; then
  dm::_usage "Error calling script: $*!"
  exit 1
fi

mode="$1"; shift
mode_ingform="${mode%%e}ing"

if [[ ! "${mode}" =~ ^install|update|upgrade$ ]]; then
  dm::_usage "Error validating mode: ${mode}!"
  exit 1
fi

for path in "$@"; do
  echo
  "${DM_X_SED[@]}" 'p; s/./=/g' <<<"MediaWiki instance: ${path}"
  echo

  path+="/${DM_WIKI_DIR}"

  # Core
  "${DM_X_SED[@]}" 'p; s/./-/g' <<<"${mode_ingform^} Core from Gerrit"
  echo

  if ! dm::_get_code "${mode}" "${DM_GERRIT_URL}/core" "${DM_BASE_BRANCH}" \
                     "${path}"
  then
    exit 1
  fi

  echo

  if ! dm::_update_deps "${path}"; then
    exit 1
  fi

  if [[ -d "${path}/tests" ]]; then
    if ! "${DM_X_RM[@]}" "${path}/tests"; then
      echo "Error deleting directory: ${path}/tests!"
    fi
  fi

  # Extensions & Skins
  for source in 'Gerrit' 'GitHub'; do
    for type in 'extensions' 'skins'; do
      case "${type}@${source}" in
        'extensions@Gerrit')  packages=("${DM_GERRIT_EXTENSIONS[@]}") ;;
        'skins@Gerrit')       packages=("${DM_GERRIT_SKINS[@]}") ;;
        'extensions@GitHub')  packages=("${DM_GITHUB_EXTENSIONS[@]}") ;;
        *)                    continue ;;
      esac

      for ((i=0; i<${#packages[@]}; i=i+2)); do
        package="${packages[$i]}"
        branch="${packages[(($i+1))]}"

        echo
        sed 'p; s/./-/g' <<<"${mode_ingform^} ${type%%s} '${package}' from ${source}"
        echo

        if [[ "${source}" == 'Gerrit' ]]; then
          url="${DM_GERRIT_URL}/${type}/${package}"
          dir="${path}/${type}/${package}"
        elif [[ "${source}" == 'GitHub' ]]; then
          url="${DM_GITHUB_URL}/${package}"
          dir="${path}/${type}/${package##*/}"
        fi

        if ! dm::_get_code "${mode}" "${url}" "${branch}" "${dir}"; then
          exit 1
        fi

        echo

        if ! dm::_update_deps "${dir}"; then
          exit 1
        fi
      done
    done
  done

  # Permissions
  echo
  "${DM_X_SED[@]}" 'p; s/./-/g' <<<'Adjusting permissions'
  echo

  if ! "${DM_X_FIND[@]}" "${path}" \
             -type 'd' -exec "${DM_X_CHMOD[@]}" 0755 '{}' '+' \
         -or -type 'f' '(' \
               -name '*pygmentize' -execdir "${DM_X_CHMOD[@]}" 0755 '{}' '+' \
           -or -execdir "${DM_X_CHMOD[@]}" 0644 '{}' '+' \
         ')'
  then
    echo 'Error adjusting permissions!'
    exit 1
  fi

  echo

  # Update script
  if [[ "${mode}" == 'install' ]]; then
    echo 'Visit https://www.my-domain.com/w/mw-config/index.php to configure' \
         'your newly installed MediaWiki!'
  else
    "${DM_X_SED[@]}" 'p; s/./-/g' <<<'Running update script'
    echo

    if ! "${DM_X_PHP[@]}" "${path}/maintenance/run.php" 'update.php' --quick
    then
      echo 'Error running update script!'
      exit 1
    fi
  fi
done

echo

# ------------------------------------------------------------------------------

exit 0

Usage

NOTE:
See MediaWiki Howto for further information.
Install MediaWiki
~/bin/deploy-mediawiki.sh 'install' '<HTDOCS>'
Upgrade MediaWiki
~/bin/deploy-mediawiki.sh 'upgrade' '<HTDOCS>'
Update MediaWiki
~/bin/deploy-mediawiki.sh 'update' '<HTDOCS>'