Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(734)

Unified Diff: third_party/WebKit/Source/devtools/scripts/buildbot/node.py

Issue 2278803004: DevTools: Add scripts for buildbot to use node.js/npm (Closed)
Patch Set: rename folder Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/scripts/buildbot/node.py
diff --git a/third_party/WebKit/Source/devtools/scripts/buildbot/node.py b/third_party/WebKit/Source/devtools/scripts/buildbot/node.py
new file mode 100755
index 0000000000000000000000000000000000000000..5bb6e6cf298324b007eb461a3f4bf8d9219b47da
--- /dev/null
+++ b/third_party/WebKit/Source/devtools/scripts/buildbot/node.py
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+import subprocess
+import tarfile
+import tempfile
+import urllib2
+
+THIS_DIR = os.path.dirname(os.path.abspath(__file__))
+
+DEFAULT_VERSION = '0.12.2'
+BUCKET = 'chromium-infra-bins'
+
+
+def install_latest_node_js(version, tmp_dir):
+ target_dir = os.path.join(THIS_DIR, 'runtimes', version)
+ version_file = os.path.join(target_dir, 'VERSION')
+
+ if sys.platform == 'win32':
+ bin_location = os.path.join(target_dir, 'node.exe')
+ else:
+ bin_location = os.path.join(target_dir, 'bin', 'node')
+
+ # We assume that, if the VERSION file exists, then the installation is good.
+ if os.path.exists(version_file):
+ with open(version_file, 'r') as f:
+ if f.read() == version:
+ return bin_location
+
+ # TODO(hinoka): This probably doesn't work that well on Windows...
+ shutil.rmtree(target_dir, ignore_errors=True)
+
+ # Get the target name correct.
+ if sys.platform == 'win32':
+ target = 'node.exe'
+ elif sys.platform == 'darwin':
+ target = 'node-v%s-darwin-x86.tar.gz' % version
+ elif sys.platform == 'linux2':
+ target = 'node-v%s-linux-x86.tar.gz' % version
+ else:
+ raise Exception('Unrecognized platform %s' % sys.platform)
+
+ dest = os.path.join(tmp_dir, 'node_download')
+ url = 'https://storage.googleapis.com/%s/node/%s/%s' % (
+ BUCKET, version, target)
+ print('Fetching %s' % url)
+ u = urllib2.urlopen(url)
+ with open(dest, 'wb') as f:
+ while True:
+ chunk = u.read(2 ** 20)
+ if not chunk:
+ break
+ f.write(chunk)
+
+ # When multiple node.py instances run at the same time for the first time,
+ # the check to see whether or not the installation occured already. But then
+ # they all race to see who's the first to run shutil.move(), which obviously
+ # fails for everyone other than the first instance. This CL makes
+ # os.rename() not fail, since its assumed that if it fails that means
+ # someone else already created an installation.
+ #
+ # Another approach is to use an flock, but then it starts to get messy when
+ # you have to keep polling filesystem state to see if another instance
+ # finished, or add timeouts to remove an flock if it was left on the system by
+ # a failed attempt, etc, etc. This just seemed like a less flaky solution,
+ # despite the fact that it means multiple network requests are spawned.
+ write_version = True
+ if sys.platform != 'win32':
+ # The Windows version comes as a self contained executable, the other
+ # versions come as a tar.gz that needs to be extracted.
+ with tarfile.open(dest, 'r:gz') as f:
+ f.extractall(path=tmp_dir)
+ try:
+ os.mkdir(os.path.join(THIS_DIR, 'runtimes'))
+ os.rename(os.path.join(tmp_dir, target[:-len('.tar.gz')]),
+ target_dir)
+ except OSError:
+ write_version = False
+ os.remove(dest)
+ else:
+ try:
+ # Still potentiall racy, from python docs:
+ # "On Windows...there may be no way to implement an atomic rename when dst
+ # names an existing file."
+ os.mkdir(target_dir)
+ os.rename(dest, bin_location)
+ except OSError:
+ write_version = False
+
+ if write_version:
+ with open(version_file, 'w') as f:
+ f.write(version)
+
+ return bin_location
+
+
+def main(mode=None):
+ version = os.environ.get('NODE_VERSION', DEFAULT_VERSION)
+ try:
+ tmp_dir = tempfile.mkdtemp(dir=THIS_DIR)
+ bin_location = install_latest_node_js(version, tmp_dir)
+ finally:
+ if os.path.exists(tmp_dir):
+ shutil.rmtree(tmp_dir)
+
+ if mode == 'npm':
+ # TODO(hinoka): How about Windows...?
+ bin_location = os.path.join(os.path.dirname(bin_location), 'npm')
+
+ return subprocess.call([bin_location, ] + sys.argv[1:])
+
+
+if __name__ == '__main__':
+ sys.exit(main())

Powered by Google App Engine
This is Rietveld 408576698