Skip to content
This repository has been archived by the owner on Jan 31, 2018. It is now read-only.

Commit

Permalink
[bug 1142093] Replace jingo-minify with django-pipeline
Browse files Browse the repository at this point in the history
* switch to django-pipeline 1.5.2
* update all the templates
* update docs
* update travis
* introduce lockdown and more npm stuff
  • Loading branch information
rehandalal authored and willkg committed Jul 29, 2015
1 parent b61d3dd commit 0753b01
Show file tree
Hide file tree
Showing 54 changed files with 633 additions and 92 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Expand Up @@ -100,3 +100,6 @@
[submodule "vendor/src/elasticsearch-dsl-py"]
path = vendor/src/elasticsearch-dsl-py
url = https://github.com/elastic/elasticsearch-dsl-py.git
[submodule "vendor/src/django-pipeline"]
path = vendor/src/django-pipeline
url = https://github.com/cyberdelia/django-pipeline.git
202 changes: 202 additions & 0 deletions bin/lockdown.js
@@ -0,0 +1,202 @@
#!/usr/bin/env node

if (process.env['NPM_LOCKDOWN_RUNNING']) process.exit(0);

console.log("NPM Lockdown is here to check your dependencies! Never fear!");

var http = require('http'),
crypto = require('crypto'),
exec = require('child_process').exec,
fs = require('fs'),
path = require('path');

try {
var lockdownJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'lockdown.json')));
} catch(e) {
console.log("\nERROR: I cannot read lockdown.json! run node_modules/.bin/lockdown-relock to generate!\n");
process.exit(1);
}

const registry = process.env['NPM_CONFIG_REGISTRY'] || 'registry.npmjs.org';

console.log("using registry: " + registry);

var boundPort;

// during execution fatal errors will be appended to this list
var errors = [];

// during execution non-fatal warnings will be appended to this list
var warn = [];

function rewriteURL(u) {
return u.replace(registry, '127.0.0.1:' + boundPort);
}

function packageOk(name, ver, sha, required) {
if (!lockdownJson[name]) {
if (required) {
errors.push("package '" + name + "' not in lockdown.json!");
}
return false;
}

if (lockdownJson[name][ver] === undefined) {
if (required) {
errors.push("package version " + name + "@" + ver + " not in lockdown.json!");
}
return false;
}

// a '*' shasum is not checked
var wantSHA = lockdownJson[name][ver];
if (wantSHA !== '*' && wantSHA !== sha) {
if (required) {
errors.push("package " + name + "@" + ver + " has a different checksum (" +
wantSHA + " v. " + sha + ")");
}
return false;
}

if (wantSHA === '*') {
warn.push("Lockdown cannot guarantee your safety! No sha for pkg " + name + "@" + ver +
" in lockdown.json");
}

return true;
}


function rewriteVersionMD(json) {
if (typeof json === 'string') json = JSON.parse(json);
if (!json.error) {
json.dist.tarball = rewriteURL(json.dist.tarball);

// is the name/version/sha in our lockdown.json?
if (!packageOk(json.name, json.version, json.dist.shasum, true)) return null;
}
return JSON.stringify(json);
}

function rewritePackageMD(json) {
if (typeof json === 'string') json = JSON.parse(json);
if (!json.error) {
Object.keys(json.versions).forEach(function(ver) {
var data = json.versions[ver];
var name = data.name;
var sha = data.dist ? data.dist.shasum : undefined;

if (packageOk(name, ver, sha, false)) {
data.dist.tarball = rewriteURL(data.dist.tarball);
} else {
delete json.versions[ver];
}
});
}
return JSON.stringify(json);
}

function copy(from, to) {
for (var k in from) {
to[k] = from[k];
}
return to;
}

var server = http.createServer(function (req, res) {
if (req.method !== 'GET') {
return res.end('non GET requests not supported', 501);
}

// what type of request is this?
// 1. specific version json metadata (when explicit dependency is expressed)
// - for these requests we should verify the name/version/sha advertised is allowed
// 2. package version json metadata (when version range is expressed - including '*')
// XXX: for these requests we should prune all versions that are not allowed
// 3. tarball - actual bits
// XXX: for these requests we should verify the name/version/sha matches something
// allowed, otherwise block the transaction
var arr = req.url.substr(1).split('/');
var type = [ '', 'package_metadata', 'version_metadata', 'tarball' ][arr.length];

// let's extract pkg name and version sensitive to the type of request being performed.
var pkgname, pkgver;
if (type === 'tarball') {
pkgname = arr[0];
var getVer = new RegExp("^" + pkgname + "-(.*)\\.tgz$");
pkgver = getVer.exec(arr[2])[1];
} else if (type === 'version_metadata') {
pkgname = arr[0];
pkgver = arr[1];
} else if (type === 'package_metadata') {
pkgname = arr[0];
}

var hash = crypto.createHash('sha1');

var r = http.request({
host: registry,
port: 80,
method: req.method,
path: req.url,
agent: false
}, function(rres) {
res.setHeader('Content-Type', rres.headers['content-type']);
if (type === 'tarball') res.setHeader('Content-Length', rres.headers['content-length']);
var b = "";
rres.on('data', function(d) {
hash.update(d);
if (type != 'tarball') b += d;
else res.write(d);
});
rres.on('end', function() {
if (type === 'tarball') {
res.end();
} else {
if (type === 'package_metadata') {
b = rewritePackageMD(b);
} else if (type === 'version_metadata') {
b = rewriteVersionMD(b);
}
if (b === null) {
res.writeHead(404);
res.end("package installation disallowed by lockdown");
} else {
res.setHeader('Content-Length', Buffer.byteLength(b));
res.writeHead(rres.statusCode);
res.end(b);
}
}
});
});
r.end();
});

server.listen(process.env['LOCKDOWN_PORT'] || 0, '127.0.0.1', function() {
boundPort = server.address().port;
var env = copy(process.env, {
NPM_CONFIG_REGISTRY: 'http://127.0.0.1:' + boundPort,
NPM_LOCKDOWN_RUNNING: "true"
});

var child = exec('npm install', {
cwd: process.cwd(),
env: env
}, function(e) {
if (warn.length) {
console.log();
console.log("LOCKDOWN WARNINGS:");
warn.forEach(function(e) { console.log(" ", e); });
console.log();
}
if (errors.length) {
console.log();
console.log("LOCKDOWN ERRORS:");
errors.forEach(function(e) { console.log(" ", e); });
console.log();
}
process.exit(e ? 1 : 0);
});
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
});
1 change: 0 additions & 1 deletion bin/travis/setup.sh
Expand Up @@ -30,4 +30,3 @@ python manage.py update_product_details

echo "Doing static dance"
python manage.py collectstatic --noinput > /dev/null
python manage.py compress_assets > /dev/null
6 changes: 4 additions & 2 deletions bin/update/update.py
Expand Up @@ -64,8 +64,7 @@ def update_locales(ctx):
@task
def update_assets(ctx):
with ctx.lcd(settings.SRC_DIR):
ctx.local(PYTHON + ' manage.py collectstatic --noinput')
ctx.local(PYTHON + ' manage.py compress_assets')
ctx.local(PYTHON + " manage.py collectstatic --noinput")


@task
Expand Down Expand Up @@ -131,6 +130,9 @@ def setup_dependencies(ctx):
# Test npm version
ctx.local('npm -v')

# Install Node dependencies
ctx.local('npm install --production --unsafe-perm')


@task
def pre_update(ctx, ref=settings.UPDATE_REF):
Expand Down
18 changes: 16 additions & 2 deletions docs/getting_started.rst
Expand Up @@ -449,8 +449,8 @@ reflected in your database tables. To update your database, do this::
See :ref:`getting-started-chapter-migrate`.


Updating requirements
---------------------
Updating Python requirements
----------------------------

Fjord will often tell you when you need to update your virtualenv
with new requirements. You'll see something like this::
Expand All @@ -472,6 +472,20 @@ with new requirements. You'll see something like this::
Follow the instructions to update them.


Updating Node.js dependencies
-----------------------------

If you need to update your node.js dependencies. To do so simply use::

npm install

.. Note::

If you see a "npm ERR! notarget No valid targets found." error while
installing the Node packages, this is due to npm-lockdown being unable to
find a package that matches the hash in ``lockdown.json``.


Where to go from here?
======================

Expand Down
4 changes: 2 additions & 2 deletions fjord/analytics/templates/analytics/dashboard_base.html
@@ -1,10 +1,10 @@
{% extends "base.html" %}

{% block site_css %}
{{ css('dashboard') }}
{% stylesheet 'dashboard' %}
{% endblock %}

{% block site_js %}
{{ js('dashboard') }}
{% javascript 'dashboard' %}
<script type="text/javascript" src="https://login.persona.org/include.js"></script>
{% endblock %}
2 changes: 1 addition & 1 deletion fjord/analytics/templates/analytics/mobile/response.html
@@ -1,7 +1,7 @@
{% extends "mobile/base.html" %}

{% block site_css %}
{{ css('dashboard') }}
{% stylesheet 'dashboard' %}
{% endblock %}

{# Remove site header. #}
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 17 additions & 17 deletions fjord/base/static/css/ui-lightness-jquery-ui.css
Expand Up @@ -56,26 +56,26 @@
.ui-widget { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS, Tahoma, Verdana, Arial, sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(img/jq-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
.ui-widget-content a { color: #333333; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(img/jq-ui/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; }
.ui-widget-header a { color: #ffffff; }

/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(img/jq-ui/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(img/jq-ui/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; }
.ui-state-hover a, .ui-state-hover a:hover { color: #c77405; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(img/jq-ui/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; }
.ui-widget :active { outline: none; }

/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fed22f; background: #ffe45c url(img/jq-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #b81900 url(img/jq-ui/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
Expand All @@ -86,14 +86,14 @@
----------------------------------*/

/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(images/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(images/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(images/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_ffd27a_256x240.png); }
.ui-icon { width: 16px; height: 16px; background-image: url(img/jq-ui/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(img/jq-ui/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(img/jq-ui/ui-icons_ffffff_256x240.png); }
.ui-state-default .ui-icon { background-image: url(img/jq-ui/ui-icons_ef8c08_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(img/jq-ui/ui-icons_ef8c08_256x240.png); }
.ui-state-active .ui-icon {background-image: url(img/jq-ui/ui-icons_ef8c08_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(img/jq-ui/ui-icons_228ef1_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(img/jq-ui/ui-icons_ffd27a_256x240.png); }

/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
Expand Down Expand Up @@ -283,8 +283,8 @@
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }

/* Overlays */
.ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*!
.ui-widget-overlay { background: #666666 url(img/jq-ui/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .50;filter:Alpha(Opacity=50); }
.ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(img/jq-ui/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .20;filter:Alpha(Opacity=20); -moz-border-radius: 5px; -khtml-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; }/*!
* jQuery UI Datepicker 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
Expand Down
16 changes: 0 additions & 16 deletions fjord/base/static_utils.py

This file was deleted.

2 changes: 1 addition & 1 deletion fjord/base/templates/500.html
Expand Up @@ -7,7 +7,7 @@
<head>
<title>{{ _('Something has gone horribly wrong') }} :: {{ _('Firefox Input') }}</title>

{{ css('base') }}
{% stylesheet 'base' %}

{# Settings isn't available when rendering this page, so hard code the static url.
# If this turns out to be the wrong setting, oh well, it's just a favicon. #}
Expand Down

0 comments on commit 0753b01

Please sign in to comment.