YUI/Patching

Revision as of 08:55, 5 February 2014 by Andrew Nicols (talk | contribs) (Wrote some initial instructions)

Jump to: navigation, search

Moodle 2.7

This document provides an overview on how to include fixes in the upstream YUI library between point releases of that library.

Description of the problem

We use the YUI JavaScript library within Moodle. We distribute a single version with each release. YUI do not release point releases and only support one version of the framework at a time. We do not upgrade to new versions of libraries in our point releases. Therefore, if we encounter an issue in a library, we must patch that issue (preferably without upgrading the entire library).

The problem with this is two-fold:

  1. it is possible to serve the YUI framework from an externally hosted content-delivery network. Files distributed from the CDN will not include any patches that we have made; and
  2. when JS files are served from our repository, we serve headers such that browsers will aggressively cache them.

Solution

To the CDN issue

In order to work around the CDN issue, we must serve any patched code from our systems. We should preferably still return all other content from the CDN.

To the aggressive browser caching issue

We must use a different URL for any content that we have modified. This is then seen as new content and used instead of the previously cached version. It is, effectively, a new resource.

Implementation

We introduce two new variables in lib/setup.php:

  • a patch level (or revision); and
  • a list of modules which have been patched.

Any time that we wish to patch a module we must both:

  • add the exact module name to the list of modules; and
  • increment the patch revision.

Both of these things must be performed.

This has the following effects:

For CDN delivered content

We add specific module configuration to the YUI_config->modules object which includes the full path on the local server for the module. This:

  • uses the combo loader located in theme/yui_combo.php; and
  • specifies a modified version number for the YUI library - e.g. for YUI 3.13.0 and a patch level of 4, this version would be '3.13.0_4'.

For locally delivered content

We add a new group object to the YUI_config->groups object which we ship with each page. This:

  • specifies each affected module as a list of patterns and modules so that it is used in preference of the standard definition; and
  • includes metadata to use the a modified version number for the YUI library - e.g. for YUI 3.13.0 and a patch level of 4, this version would be '3.13.0_4'.

For non combo-loaded content

In order to use the locally hosted version, we *must* use the combo loader. When not using the combo loader, it is not possible to add a revision as the file is served straight from disk and is subject to server caching configuration. We only use the combo loader for the specified module. Other modules continue to be loaded from the file system using the non combo-loaded method.

How to use

Now that you've read all of that, and understand it, in order to include a patched module:

  • checkout the YUI project;
  • check out the tag for the version used in Moodle (e.g. git checkout v3.13.0);
  • patch the module in the YUI src repository;
  • run shifter for that module, specifying the --replace-version option to shifter;
  • copy the relevant files in the build directory to the correct location in Moodle;
  • edit lib/setup.php and find the $CFG->yuipatchlevel variable;
  • increment the patchlevel by one;
  • add the changed module only to the $CFG->yuipatchedmodules array

If you are patching a module which has sub-modules, only include the affected modules.

Upgrades to YUI

When we include a new version of the YUI library, you must:

  • reset the $CFG->yuipatchlevel to 0; and
  • empty the $CFG->yuipatchedmodules array.
  • check whether the patch has been included and if not, now re-run the initial instructions (e.g. after resetting the patch level). Do NOT forget to rebuild with the correct YUI version number

Example configurations

Scenario: Patching dd-ddm

$CFG->yuipatchlevel = 1;
$CFG->yuipatchedmodules = array(
    'dd-ddm',
);

Scenario: Patching dd-ddm-base

$CFG->yuipatchlevel = 1;
$CFG->yuipatchedmodules = array(
    'dd-ddm-base',
);

Scenario: Patching dd-ddm, and dd-drop, and dd-gestures

$CFG->yuipatchlevel = 2;
$CFG->yuipatchedmodules = array(
    'dd-ddm',
    'dd-dd-drop',
    'dd-dd-gestures',
);

Scenario: Patching panel, dd-ddm, and dd-drop, and dd-gestures

$CFG->yuipatchlevel = 3;
$CFG->yuipatchedmodules = array(
    'panel',
    'dd-ddm',
    'dd-dd-drop',
    'dd-dd-gestures',
);