|
| 1 | +================================================================================ |
| 2 | + Serving Static Datatracker Files via a CDN |
| 3 | +================================================================================ |
| 4 | + |
| 5 | +Intro |
| 6 | +===== |
| 7 | + |
| 8 | +With release 6.4.0, the way that the static files used by the datatracker are |
| 9 | +handled changes substantially. Static files were previously versioned under a |
| 10 | +top-level ``static/`` directory, but this is not the case any more. External |
| 11 | +files (such as for instance ``jquery.min.js``) are now placed under |
| 12 | +``ietf/externals/static/`` and updated using a tool called bower_, while |
| 13 | +datatracker-specific files (images, css, js, etc.) are located under |
| 14 | +``ietf/static/ietf/`` and ``ietf/secr/static/secr/`` respectively. |
| 15 | + |
| 16 | +The following sections provide more details about handling of internals, |
| 17 | +externals, and how deployment is done. |
| 18 | + |
| 19 | + |
| 20 | +Serving Static Files via CDN |
| 21 | +============================ |
| 22 | + |
| 23 | +If resources served over a CDN and/or with a high max-age don't have different |
| 24 | +URLs for different versions, then any component upgrade which is accompanied |
| 25 | +by a change in template functionality will have a long transition time |
| 26 | +during which the new pages are served with old components, with possible |
| 27 | +breakage. We want to avoid this. |
| 28 | + |
| 29 | +The intention is that after a release has been checked out, but before it is |
| 30 | +deployed, the standard django 'collectstatic' management command will be |
| 31 | +run, resulting in all static files being collected from their working |
| 32 | +directory location and placed in an appropiate location for serving via CDN. |
| 33 | +This location will have the datatracker release version as part of its URL, |
| 34 | +so that after the deployment of a new release, the CDN will be forced to fetch |
| 35 | +the appropriate static files for that release. |
| 36 | + |
| 37 | +An important part of this is to set up the ``STATIC_ROOT`` and ``STATIC_URL`` |
| 38 | +settings appropriately. In 6.4.0, the setting is as follows in production |
| 39 | +mode:: |
| 40 | + |
| 41 | + STATIC_URL = "https://www.ietf.org/lib/dt/%s/"%__version__ |
| 42 | + STATIC_ROOT = CDN_ROOT + "/a/www/www6s/lib/dt/%s/"%__version__ |
| 43 | + |
| 44 | +The result is that all static files collected via the ``collectstatic`` |
| 45 | +command will be placed in a location served via CDN, with the release |
| 46 | +version being part of the URL. |
| 47 | + |
| 48 | +In development mode, ``STATIC_URL`` is set to ``/static/``, and Django's |
| 49 | +``staticfiles`` infrastructure makes the static files available under that |
| 50 | +local URL root. |
| 51 | + |
| 52 | + |
| 53 | +Handling of External Javascript and CSS Components |
| 54 | +================================================== |
| 55 | + |
| 56 | +In order to make it easy to keep track of and upgrade external components, |
| 57 | +these are now handled by a tool called ``bower``, via a new management |
| 58 | +command ``bower_install``. Each external component is listed in a file |
| 59 | +``ietf/bower.json``. In order to update the version of a component listed in |
| 60 | +``ietf/bower.json``, or add a new one, you should edit ``bower.json``, and |
| 61 | +then run the management command:: |
| 62 | + |
| 63 | + $ ietf/manage.py bower_install |
| 64 | + |
| 65 | +(Not surprisingly, you need to have bower_ installed in order to use this |
| 66 | +management command.) |
| 67 | + |
| 68 | +That command will fetch the required version of each external component listed |
| 69 | +in ``bower.json`` (actually, it will do this for *all* ``bower.json`` files |
| 70 | +found in the ``static/`` directories of all ``INSTALLED_APPS`` and the |
| 71 | +directories in ``settings.STATICFILES_DIRS``), saving them temporarily under |
| 72 | +``.tmp/bower_components/``; it will then extract the relevant production |
| 73 | +``js`` and ``css`` files and place them in an appropriately named directory |
| 74 | +under ``ietf/externals/static/``. The latter location is taken from |
| 75 | +``COMPONENT_ROOT`` in ``settings.py``. |
| 76 | + |
| 77 | +Managing external components via bower has the additional benefit of |
| 78 | +managing dependencies -- components that have dependencies will pull in |
| 79 | +these, so that they also are placed under ``ietf/externals/static/``. |
| 80 | +You still have to manually add the necessary stylesheet and/or javascript |
| 81 | +references to your templates, though. |
| 82 | + |
| 83 | +The ``bower_install`` command is not run automatically by ``bin/mkrelease``, |
| 84 | +since it needs an updated ``bower.json`` in order to do anything interesting. |
| 85 | +So when you're intending to update an external web asset to a newer version, |
| 86 | +you need to edit the ``bower.json`` file, run ``manage.py bower_install``, |
| 87 | +verify that the new version doesn't break things, and then commit the new |
| 88 | +files under ``ietf/externals/static/`` and the updated ``bower.json``. |
| 89 | + |
| 90 | +.. _bower: http://bower.io/ |
| 91 | + |
| 92 | +The ``ietf/externals/static/`` Directory |
| 93 | +----------------------------------------- |
| 94 | + |
| 95 | +The directory ``ietf/externals/static/`` holds a number of subdirectories |
| 96 | +which hold distribution files for external client-side components, collected |
| 97 | +by ``bower_install`` as described above. Currently |
| 98 | +(01 Aug 2015) this means ``js`` and ``css`` components and fonts. |
| 99 | + |
| 100 | +These components each reside in their own subdirectory, which is named with |
| 101 | +the component name:: |
| 102 | + |
| 103 | + henrik@zinfandel $ ls -l ietf/externals/static/ |
| 104 | + total 40 |
| 105 | + drwxr-xr-x 6 henrik henrik 4096 Jul 25 15:25 bootstrap |
| 106 | + drwxr-xr-x 4 henrik henrik 4096 Jul 25 15:25 bootstrap-datepicker |
| 107 | + drwxr-xr-x 4 henrik henrik 4096 Jul 25 15:25 font-awesome |
| 108 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 jquery |
| 109 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 jquery.cookie |
| 110 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptmono |
| 111 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptsans |
| 112 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:24 ptserif |
| 113 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 select2 |
| 114 | + drwxr-xr-x 2 henrik henrik 4096 Jul 25 15:25 select2-bootstrap-css |
| 115 | + |
| 116 | +The ``pt*`` fonts are an exception, in that there is no bower component |
| 117 | +available for these fonts, so they have been put in place manually. |
| 118 | + |
| 119 | + |
| 120 | +Handling of Internal Static Files |
| 121 | +================================= |
| 122 | + |
| 123 | +Previous to this release, internal static files were located under |
| 124 | +``static/``, mixed together with the external components. They are now |
| 125 | +located under ``ietf/static/ietf/`` and ``ietf/secr/static/secr``, and will be |
| 126 | +collected for serving via CDN by the ``collectstatic`` command. Any static |
| 127 | +files associated with a particular app will be handled the same way (which |
| 128 | +means that all ``admin/`` static files automatically will be handled correctly, too). |
| 129 | + |
| 130 | +Handling of Customised Bootstrap Files |
| 131 | +====================================== |
| 132 | + |
| 133 | +We are using a customised version of Bootstrap_, which is handled specially, |
| 134 | +by a SVN externals definition in ``ietf/static/ietf``. That pulls the content |
| 135 | +of the ``bootstrap/dist/`` directory (which is generated by running ``grunt`` |
| 136 | +in the ``bootstrap/`` directory) into ``ietf/static/ietf/bootstrap``, from |
| 137 | +where it is collected by ``collectstatic``. |
| 138 | + |
| 139 | +Changes to Template Files |
| 140 | +========================= |
| 141 | + |
| 142 | +In order to make the template files refer to the correct versioned CDN URL |
| 143 | +(as given by the STATIC_URL root) all references to static files in the |
| 144 | +templates have been updated to use the ``static`` template tag when referring |
| 145 | +to static files. This will automatically result in both serving static files |
| 146 | +from the right place in development mode, and referring to the correct |
| 147 | +versioned URL in production mode and the simpler ``/static/`` urls in |
| 148 | +development mode. |
| 149 | + |
| 150 | +.. _bootstrap: http://getbootstrap.com/ |
| 151 | + |
| 152 | +Deployment |
| 153 | +========== |
| 154 | + |
| 155 | +During deployment, it is now necessary to run the management command:: |
| 156 | + |
| 157 | + $ ietf/manage.py collectstatic |
| 158 | + |
| 159 | +before activating a new release. The deployment README file has been updated |
| 160 | +accordingly, and now reads as follows:: |
| 161 | + |
| 162 | + In order to fetch a new release of the django datatracker code, simply |
| 163 | + check out the appropriate tag from svn: |
| 164 | + |
| 165 | + svn co http://svn.tools.ietf.org/svn/tools/ietfdb/tags/$releasenumber |
| 166 | + |
| 167 | + Don't forget to copy $releasenumber/ietf/settings_local.py from the |
| 168 | + old release to the new one; otherwise it won't work! |
| 169 | + |
| 170 | + cp $oldreleasenumber/ietf/settings_local.py $releasenumber/ietf/ |
| 171 | + |
| 172 | + Change into the new directory: |
| 173 | + |
| 174 | + cd $releasenumber |
| 175 | + |
| 176 | + Next, upgrade pip and install requirements: |
| 177 | + |
| 178 | + pip install --upgrade pip |
| 179 | + pip install -r requirements.txt |
| 180 | + |
| 181 | + Run migrations: |
| 182 | + |
| 183 | + ietf/manage.py migrate |
| 184 | + |
| 185 | + * NEW * |
| 186 | + Move static files to the appropriate directory for serving via CDN: |
| 187 | + |
| 188 | + ietf/manage.py collectstatic |
| 189 | + |
| 190 | + * NEW * |
| 191 | + Run some basic datatracker system checks: |
| 192 | + |
| 193 | + ietf/manage.py check |
| 194 | + |
| 195 | + Change back out to the parent directory: |
| 196 | + |
| 197 | + cd .. |
| 198 | + |
| 199 | + and then re-point the 'web' symlink: |
| 200 | + |
| 201 | + rm ./web; ln -s $releasenumber web |
| 202 | + |
| 203 | + and finally restart apache: |
| 204 | + |
| 205 | + sudo /etc/init.d/apache2 restart |
| 206 | + |
| 207 | + It's now also a good idea to go to the datatracker front page: |
| 208 | + |
| 209 | + http://datatracker.ietf.org/ |
| 210 | + |
| 211 | + to check that it's alive and kicking, and displaying the new release |
| 212 | + number at the bottom of the left-side menubar :-) -- if not, revert the |
| 213 | + symlink step, re-pointing the symlink to the release that was running |
| 214 | + before the new release, and restart apache again to roll back to that. |
| 215 | + |
| 216 | + Finally, make sure the datatracker rsyncs over to IETFB, and then run the |
| 217 | + PIP commands on ietfb as well: |
| 218 | + |
| 219 | + ssh ietfb |
| 220 | + pip install --upgrade pip |
| 221 | + pip install -r requirements.txt |
| 222 | + |
0 commit comments