Wednesday, January 29, 2014

Moving the OU Moodle code to Moodle 2.6.1

I spent today upgrading our Moodle codebase from Moodle 2.5.4 to Moodle 2.6.1. This is the start of work towards our June release of the VLE. We have a March release based on Moodle 2.5.4 to get on the live servers first, and testing that will overlap with the development of the 2.6.1-based version.

Doing the merge

The first stage of the process is to merge in the new code. This is non-trivial because even if you just do

git checkout -b temp v2.5.4
git merge v2.6.1

Then you will get a lot of merge conflicts. That is a product of how the Moodle project manages its stable branches. If your own code changes also lead to other merge conflicts, then sorting out the two is a real mess.

Fortunately, there is a better way, because we know how we want to resolve any conflicts between 2.5.4 and 2.6.1. We want to end up with 2.6.1. Using git merge strategies, you can do that:

git checkout -b merge_helper_branch v2.6.1
git merge --strategy=ours v2.5.4

That gives you a commit that is upstream of both v2.5.4 and v2.6.1, and which contains code that is identical to v2.6.1. You can verify that using git diff v2.6.1 merge_helper_branch. That should produce no output.

Having built that helper branch, you can then proceed to upgrade your version of the code. Our version of Moodle lives on a branch called ouvle which we originally branched off Moodle 2.1.2 in October 2011. Since then, we have made lots of changes, including adding many custom plugins, and merging in many Moodle releases. Continuting from the above we do

git checkout ouvle
git merge --strategy-option=patience merge_helper_branch

That gave a lot of merge conflicts, but they were all to do with our changes. Most of them were due to MDL-38189, which sam marshall developed for Moodle 2.6, and which we had back-ported into our 2.5 code. That back-port made a big mess, but fortunately most of the files affected did not have any other ou-specific changes, so I could just overwrite them with the latest versions from v2.6.1.

git checkout --theirs lang/en backup lib/filestorage admin/settings/development.php lib/form/form.js
git add lang/en backup lib/filestorage admin/settings/development.php lib/form/form.js

Simiarly, we had backported MDL-35053 which lead to more conflicts that were easy to resolve. Another case was the Single activity course format which we had used as an add-on to Moodle 2.5. That is now part of the standard Moodle release. The change caused merge conflits, but again there was a simple solution: take the latest from 2.6.1.

After all that, there were only about 5 files that needed more detailed attention. They were mostly where a change had been made to standard Moodle code right next to a place where we had made a change. (Silly rules about full stops at the ends of comments!) They were easily to fix manually. The one tricky file was in lib/moodlelib.php where about 400 lines of code had been moved lib/classes/useragent.php. There were two ou-specific changes in the middle of that, which I had to re-do in the new version of that code.

Verifying the merge

Having resolved all the conflicts, it was then time to try to convince myself that I had not screwed anything up. The main check was to comparing our ouvle code with the standard 2.6.1 code. Just doing git diff v2.6.1 ouvle does not work well because it shows all contents of all the new files we have added. You need to read the git documentation and work out the incantation

git diff --patience --diff-filter=CDMRTUXB v2.6.1 ouvle

That tells git to just show changes to existing files - the ones that are part of standard Moodle 2.6.1. That is a manageable amount of output to review. We have a strict policy that any change to core Moodle code is marked up like this:

// ou-specific begins #2381 MDL-28567
        $select = new single_select(new moodle_url(CALENDAR_URL.'set.php',
                array('return' => base64_encode($returnurl->out(false)),
                        'var' => 'setcourse', 'sesskey'=>sesskey())),
                'id', $courseoptions, $selected, null);
        $select = new single_select(new moodle_url(CALENDAR_URL.'view.php',
                array('return' => $returnurl, 'view' => 'month')),
                'course', $courseoptions, $selected, null);
// ou-specific ends #2381 MDL-28567

That is, the original Moodle code is still there, but commented out, alongside our modified version, and the whole thing is wrapped in paired begin and end markers that refer to a ticket id in our issues database and if applicable a Moodle tracker issue. In this case I can check that MDL-28567 has still not been resolved, so we still need this ou-specific change. What I am doing looking at the diff output is verifying that every change is marked up like that, and that any issues mentioned are things that are still relevant.

The other check is to search the whole codebase for ou-specific and again review all the issue numbers mentioned. These combined checks find a few ou-specific changes that are no longer needed, which is a good thing.

What happens next

Now that I think the code seems right, it is time to test it, so I upgrade my development install. It mostly works, except that our custom memcache session handler no longer works (the session code seems to have changed a lot, including an official memcached session hander in core). For now I just switch back to default Moodle sessions, and make a note to investigate this later.

Apart from that, the upgrade goes smootly, and, apart from thousands of debugging warnings about use of deprecated code, I have a working Moodle site, so I push the code to our git server, and warn the rest of the team that they can upgrade if they feel brave.

The next thing, which will take place over the next few weeks is to check every single one of our custom plugins to verify that it still works properly in Moodle 2.6. To manage that we use a Google Docs spreadsheet that we can all edit that lists all the add-ons, with who is going to be responsible for checking it, and whether they have done so yet. Here is a small section.

The state of OU Moodle customisation

Our regular code-merges are a good moment to take stock of the extend to which we have customised Moodle. Here are some headline numbers:

  • 212 custom plug-ins: Of those 10 are ones we have taken from the community, including Questionnaire, Certificate, Code-checker and STACK (we helped create those last two). Of our own plugins, 58 (over a quarter) are shared with the community, though the counting is odd because ForumNG contains 20 sub-plugins.
  • 17 ou-specific issues: That is, reasons we made a change to core code that could not be an add-on.
  • Due to those 17 reasons, there are 42 pairs of // ou-specific begins/ends comments in the code.

So, we continue to be disciplined about not changing core code unless we really have to, but the number of plugins is getting a bit crazy. A lot of the plugins, are, however, very small. They just do one thing. Also, we run a range of very different sites, including OpenLearn, OpenLearn works, The Open Science Lab and our exams server. A significant number of our plugisn were just designed to be used on one of those sites.

Here are the numbers of custom plugins broken down by type (and ignoring sub-plugins of our custom plugins).

Plugin typeNumber
Activity module25
Admin tools8
Authentication methods2
Course formats3
Enrolment methods1
Gradebook reports1
Local plugins44
Message outputs2
Portfolio outputs1
Question behaviours4
Question types14
Quiz reports6
Quiz access rules2
TinyMCE plugins1