summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggleton <paul.eggleton@linux.intel.com>2016-03-09 17:48:55 +1300
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-03-09 16:59:57 +0000
commit277377f13b2b771915eb853e336ca24b84523ed1 (patch)
tree5dcbc7a23da8d58c44df6ce4fccf747c48fd3ee8
parent334b9451111b7e3efbb43b3a4eecebcab8ec6f0e (diff)
downloadopenembedded-core-277377f13b2b771915eb853e336ca24b84523ed1.tar.gz
openembedded-core-277377f13b2b771915eb853e336ca24b84523ed1.tar.bz2
openembedded-core-277377f13b2b771915eb853e336ca24b84523ed1.zip
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]. Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--scripts/lib/recipetool/create_npm.py57
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 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import os
import logging
+import subprocess
+import tempfile
+import shutil
import json
from recipetool.create import RecipeHandler, split_pkg_licenses
logger = logging.getLogger('recipetool')
+tinfoil = None
+
+def tinfoil_init(instance):
+ global tinfoil
+ tinfoil = instance
+
+
class NpmRecipeHandler(RecipeHandler):
+ lockdownpath = None
+
def _handle_license(self, data):
'''
Handle the license value from an npm package.json file
@@ -34,7 +47,44 @@ class NpmRecipeHandler(RecipeHandler):
license = license.get('type', None)
return None
+ def _shrinkwrap(self, srctree, localfilesdir, extravalues, lines_before):
+ try:
+ runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH', True))
+ bb.process.run('npm shrinkwrap', cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True)
+ except bb.process.ExecutionError as e:
+ logger.warn('npm shrinkwrap failed:\n%s' % e.stdout)
+ return
+
+ tmpfile = os.path.join(localfilesdir, 'npm-shrinkwrap.json')
+ shutil.move(os.path.join(srctree, 'npm-shrinkwrap.json'), tmpfile)
+ extravalues.setdefault('extrafiles', {})
+ extravalues['extrafiles']['npm-shrinkwrap.json'] = tmpfile
+ lines_before.append('NPM_SHRINKWRAP := "${THISDIR}/${PN}/npm-shrinkwrap.json"')
+
+ def _lockdown(self, srctree, localfilesdir, extravalues, lines_before):
+ runenv = dict(os.environ, PATH=tinfoil.config_data.getVar('PATH', True))
+ if not NpmRecipeHandler.lockdownpath:
+ NpmRecipeHandler.lockdownpath = tempfile.mkdtemp('recipetool-npm-lockdown')
+ bb.process.run('npm install lockdown --prefix %s' % NpmRecipeHandler.lockdownpath,
+ cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True)
+ relockbin = os.path.join(NpmRecipeHandler.lockdownpath, 'node_modules', 'lockdown', 'relock.js')
+ if not os.path.exists(relockbin):
+ logger.warn('Could not find relock.js within lockdown directory; skipping lockdown')
+ return
+ try:
+ bb.process.run('node %s' % relockbin, cwd=srctree, stderr=subprocess.STDOUT, env=runenv, shell=True)
+ except bb.process.ExecutionError as e:
+ logger.warn('lockdown-relock failed:\n%s' % e.stdout)
+ return
+
+ tmpfile = os.path.join(localfilesdir, 'lockdown.json')
+ shutil.move(os.path.join(srctree, 'lockdown.json'), tmpfile)
+ extravalues.setdefault('extrafiles', {})
+ extravalues['extrafiles']['lockdown.json'] = tmpfile
+ lines_before.append('NPM_LOCKDOWN := "${THISDIR}/${PN}/lockdown.json"')
+
def process(self, srctree, classes, lines_before, lines_after, handled, extravalues):
+ import bb.utils
import oe
from collections import OrderedDict
@@ -58,6 +108,13 @@ class NpmRecipeHandler(RecipeHandler):
if 'homepage' in data:
lines_before.append('HOMEPAGE = "%s"' % data['homepage'])
+ # Shrinkwrap
+ localfilesdir = tempfile.mkdtemp(prefix='recipetool-npm')
+ self._shrinkwrap(srctree, localfilesdir, extravalues, lines_before)
+
+ # Lockdown
+ self._lockdown(srctree, localfilesdir, extravalues, lines_before)
+
# Split each npm module out to is own package
npmpackages = oe.package.npm_split_package_dirs(srctree)
for item in handled: