diff options
author | Paul Eggleton <paul.eggleton@linux.intel.com> | 2016-03-09 17:48:55 +1300 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2016-03-09 17:00:29 +0000 |
commit | bc0e99d2b165ff547e02c7169a8b0d210de54a1a (patch) | |
tree | 94ca561bf4a2c0e3824bfdc6b2673e760145d61b /scripts/lib | |
parent | 309b2e6c571248a3b77c432ed96dfb976cb840bc (diff) | |
download | poky-bc0e99d2b165ff547e02c7169a8b0d210de54a1a.tar.gz |
recipetool: create: shrinkwrap and lockdown npm modules
"npm shrinkwrap" creates a file that ensures that the exact same
versions get fetched the next time the recipe is built. lockdown is
similar but also includes sha1sums of the modules thus validating they
haven't changed between builds. These ensure that the build is
reproducible.
Fixes [YOCTO #9225].
(From OE-Core rev: 277377f13b2b771915eb853e336ca24b84523ed1)
Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'scripts/lib')
-rw-r--r-- | scripts/lib/recipetool/create_npm.py | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/scripts/lib/recipetool/create_npm.py b/scripts/lib/recipetool/create_npm.py index 4bf6caed5c..b3ffcdbc5b 100644 --- a/scripts/lib/recipetool/create_npm.py +++ b/scripts/lib/recipetool/create_npm.py | |||
@@ -15,14 +15,27 @@ | |||
15 | # with this program; if not, write to the Free Software Foundation, Inc., | 15 | # with this program; if not, write to the Free Software Foundation, Inc., |
16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 16 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
17 | 17 | ||
18 | import os | ||
18 | import logging | 19 | import logging |
20 | import subprocess | ||
21 | import tempfile | ||
22 | import shutil | ||
19 | import json | 23 | import json |
20 | from recipetool.create import RecipeHandler, split_pkg_licenses | 24 | from recipetool.create import RecipeHandler, split_pkg_licenses |
21 | 25 | ||
22 | logger = logging.getLogger('recipetool') | 26 | logger = logging.getLogger('recipetool') |
23 | 27 | ||
24 | 28 | ||
29 | tinfoil = None | ||
30 | |||
31 | def tinfoil_init(instance): | ||
32 | global tinfoil | ||
33 | tinfoil = instance | ||
34 | |||
35 | |||
25 | class NpmRecipeHandler(RecipeHandler): | 36 | class NpmRecipeHandler(RecipeHandler): |
37 | lockdownpath = None | ||
38 | |||
26 | def _handle_license(self, data): | 39 | def _handle_license(self, data): |
27 | ''' | 40 | ''' |
28 | Handle the license value from an npm package.json file | 41 | Handle the license value from an npm package.json file |
@@ -34,7 +47,44 @@ class NpmRecipeHandler(RecipeHandler): | |||
34 | license = license.get('type', None) | 47 | license = license.get('type', None) |
35 | return None | 48 | return None |
36 | 49 | ||
50 | def _shrinkwrap(self, srctree, localfilesdir, extravalues, lines_before): | ||
51 | try: | ||
52 | runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH', True)) | ||
53 | bb.process.run('npm shrinkwrap', cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True) | ||
54 | except bb.process.ExecutionError as e: | ||
55 | logger.warn('npm shrinkwrap failed:\n%s' % e.stdout) | ||
56 | return | ||
57 | |||
58 | tmpfile = os.path.join(localfilesdir, 'npm-shrinkwrap.json') | ||
59 | shutil.move(os.path.join(srctree, 'npm-shrinkwrap.json'), tmpfile) | ||
60 | extravalues.setdefault('extrafiles', {}) | ||
61 | extravalues['extrafiles']['npm-shrinkwrap.json'] = tmpfile | ||
62 | lines_before.append('NPM_SHRINKWRAP := "${THISDIR}/${PN}/npm-shrinkwrap.json"') | ||
63 | |||
64 | def _lockdown(self, srctree, localfilesdir, extravalues, lines_before): | ||
65 | runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH', True)) | ||
66 | if not NpmRecipeHandler.lockdownpath: | ||
67 | NpmRecipeHandler.lockdownpath = tempfile.mkdtemp('recipetool-npm-lockdown') | ||
68 | bb.process.run('npm install lockdown --prefix %s' % NpmRecipeHandler.lockdownpath, | ||
69 | cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True) | ||
70 | relockbin = os.path.join(NpmRecipeHandler.lockdownpath, 'node_modules', 'lockdown', 'relock.js') | ||
71 | if not os.path.exists(relockbin): | ||
72 | logger.warn('Could not find relock.js within lockdown directory; skipping lockdown') | ||
73 | return | ||
74 | try: | ||
75 | bb.process.run('node %s' % relockbin, cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True) | ||
76 | except bb.process.ExecutionError as e: | ||
77 | logger.warn('lockdown-relock failed:\n%s' % e.stdout) | ||
78 | return | ||
79 | |||
80 | tmpfile = os.path.join(localfilesdir, 'lockdown.json') | ||
81 | shutil.move(os.path.join(srctree, 'lockdown.json'), tmpfile) | ||
82 | extravalues.setdefault('extrafiles', {}) | ||
83 | extravalues['extrafiles']['lockdown.json'] = tmpfile | ||
84 | lines_before.append('NPM_LOCKDOWN := "${THISDIR}/${PN}/lockdown.json"') | ||
85 | |||
37 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): | 86 | def process(self, srctree, classes, lines_before, lines_after, handled, extravalues): |
87 | import bb.utils | ||
38 | import oe | 88 | import oe |
39 | from collections import OrderedDict | 89 | from collections import OrderedDict |
40 | 90 | ||
@@ -58,6 +108,13 @@ class NpmRecipeHandler(RecipeHandler): | |||
58 | if 'homepage' in data: | 108 | if 'homepage' in data: |
59 | lines_before.append('HOMEPAGE = "%s"' % data['homepage']) | 109 | lines_before.append('HOMEPAGE = "%s"' % data['homepage']) |
60 | 110 | ||
111 | # Shrinkwrap | ||
112 | localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm') | ||
113 | self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before) | ||
114 | |||
115 | # Lockdown | ||
116 | self._lockdown(srctree, localfilesdir, extravalues, lines_before) | ||
117 | |||
61 | # Split each npm module out to is own package | 118 | # Split each npm module out to is own package |
62 | npmpackages = oe.package.npm_split_package_dirs(srctree) | 119 | npmpackages = oe.package.npm_split_package_dirs(srctree) |
63 | for item in handled: | 120 | for item in handled: |