Open main menu

MediaWiki/Upgrade/REL1 26 to REL1 27

Upgrading to REL1_27 was a bit harder than expected.

I had to struggle with Composer and the Composer merge plugin and finally figured out how to get everything to work in concert. The trick was NOT to use the glob wildcards as suggested. Instead, your composer.local.json should look something like this:

{
  "require": {
    "mediawiki/lingo": "^2.0",
    "mediawiki/chameleon-skin": "^1.5",
    "mediawiki/semantic-media-wiki": "2.4"
  },
  "extra": {
  }
}

Extension and Skin Upgrades

I built out on my previous shell script to get a more general purpose tool that lets me see the provenance of the code in the extensions and skins directories.

<?php

/**
 * Script for discovering and upgrading all MediaWiki extensions
 * 
 * @author Greg Rundlett greg@eQuality-Tech.com
 * @copyright 2016 
 * @license GPLv3 or later
 *
 * INSTALL
 * Place the script in the installation root of your MediaWiki instance i.e. "$IP"
 *
 * CONFIG
 * The script must be configured to specify which Release you are currently running
 * and the Release you want to upgrade to.
 * 
 * You can also tell it whether you want to run composer with '--no-dev' (default)
 *
 * USAGE
 * This script expects that you are currently using some checkout of a MediaWiki Core release
 * and you want to move from that "old" release to a "new" release.
 *
 * Configure the $oldRelease and $newRelease variables to branch names found in 
 * MediaWiki core and extensions.
 * 
 * php inspect-extensions.php 
 *
 * SIDE-EFFECTS
 * This script will run a git fetch on all your (git-controlled) extensions.
 * 
 * LIMITATIONS
 * This script will pass over any extension that doesn't have a .git folder
 * It assumes that these extensions were 
 *    * installed via Composer (without the --prefer-source option)
 *    * developed locally or from non-git sources
 *    * or downloaded as a package and we don't assume where you want to get it from
 * 
 * This script can and will inadvertently change your checkout for extensions
 * which were installed using Composer and the --prefer-source option. In those
 * cases, redo a manual checkout to the branch that composer wants.
 * 
 * This script runs on GNU/Linux. No attempt has been made to make it XP
 *
 */
 
///////////////////////////////////////////////////////////////////////////////
//                   BEGIN CONFIGURATION                                     //
///////////////////////////////////////////////////////////////////////////////

// set the current and next release to upgrade to.
// it is not recommended to skip releases
$oldRelease = 'REL1_27';
$newRelease = 'REL1_28';

// if true, add composer "require-dev" modules
// if false, 'composer [install|update] --no-dev' will be used
$devMode = false; 

///////////////////////////////////////////////////////////////////////////////
//                  END OF CONFIGURATION                                     //
///////////////////////////////////////////////////////////////////////////////

// Security
// DO NOT ALLOW THIS SCRIPT TO BE CALLED FROM THE WEB !
(PHP_SAPI !== 'cli' || isset($_SERVER['HTTP_USER_AGENT'])) && die('eQuality-Tech.com can upgrade your wiki');


// by default, do not install require-dev modules
$devSwitch = ($devMode) ? "" : ' --no-dev';

$IP = dirname(__FILE__);
//  work within the extensions directory so as not to conflict with the main composer.json
$dir = "$IP/extensions";
if (!is_dir($dir)) {
  die ('This script should be placed in your wiki root, and run from there');
} else {
  // use colors by \033[32m some colored text \033[0m
  echo "Directories marked with \033[35m * \033[0m are git controlled\n";
  echo "and decorated with their current branch matching $oldRelease\n";
}
chdir ($dir);

// https://secure.php.net/manual/en/function.glob.php
// automatically sorted (unless you tell it not to)
// using the "pattern" of $dir . '/*', we get the full path for each extension
// $directories = glob($dir . '/*' , GLOB_ONLYDIR);
// using just '*' for the pattern, we get just the extension folder name
// since we've already changed into the extensions directory
$directories = glob('*' , GLOB_ONLYDIR);
// print_r($directories);
$doUpgrade = true;
$doUpgrade = false;

foreach ($directories as $ext) {
  $hasGit = false;      // detect presence of .git directories
  $hasLock = false;     // detect prior use of 'composer install'
  $gitBranch = '';      // what branch is in use currently
  $hasOldRelease = '';  // is $oldRelease the current branch?
  $upgradable = false;  // does $newRelease exist upstream?
  $hasComposer = false; // does the extension use Composer?
  
  if (is_dir("{$ext}/.git")) {
    $hasGit = true;
  }
  echo ($hasGit)? "\033[36m$ext\033[0m" : "\033[31m$ext\033[0m";
  // we can ONLY operate on an extension directory that is git controlled, 
  // otherwise, all git commands will 'see' the git repo of core
  if ($hasGit) {
    chdir ("$IP/extensions/$ext");
    $gitBranch = `git branch | grep '^*' | awk '{print $2}'`;
    $gitBranch = trim($gitBranch);
    // see if oldRelease is available locally
    $hasOldRelease = `git branch --list $oldRelease | grep '^*' | awk '{print $2}'`;
    $hasOldRelease = trim($hasOldRelease);
    // print the branch in orange (warning) if it doesn't match the expected 'oldRelease'
    echo ($gitBranch == $hasOldRelease) ? " \033[36m$gitBranch\033[0m" : " \033[33m$gitBranch\033[0m";
    // git branch -r doesn't know about remote branches it hasn't fetched yet
    exec('git fetch $1 > /dev/null');
    // add the -r option look at those remote branches
    $upgradable = `git branch -r --list "*$newRelease"`;
    // could be a multi-line string in the case of multiple remotes
    // take off leading whitespace and the last newline, and convert to an array
    $upgradable = trim($upgradable);
    if (strlen($upgradable)) {
      $upgradable = explode("\n", $upgradable);
      if (count($upgradable)) { echo "\033[35m upgradable \033[0m" ; }
      echo implode($upgradable);
      // blindly take the first remote if more than one
      $cmd = "git checkout -b $newRelease {$upgradable[0]}";

      if ($doUpgrade) {
        exec($cmd);
      } else {
        echo " $cmd";
      }
      // see if this extension has it's own composer.json
      $hasComposer = glob('composer.json');
      $hasLock = glob('composer.lock');
      $cmd = ($hasLock)? "composer update $devSwitch" : "composer install $devSwitch";
      if ($doUpgrade && $hasComposer) {
        exec($cmd);
      } elseif ($hasComposer) {
        echo " && $cmd";
      } 
    }
  }
  chdir ("$IP/extensions");
  echo "\n";
}