blob: 0e1b78d890e0df65ef25d25fef050833e02a682f [file] [log] [blame]
Yang Guo4fd355c2019-09-19 10:59:03 +02001# Copyright 2019 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4"""
5Helper to manage DEPS.
6"""
7
8import os
9import os.path as path
Yang Guo4fd355c2019-09-19 10:59:03 +020010import json
Yang Guo91178352019-10-31 08:50:19 +010011import shutil
12import subprocess
13import sys
14
15scripts_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16sys.path.append(scripts_path)
17
18import devtools_paths
Yang Guo4fd355c2019-09-19 10:59:03 +020019
Paul Lewise184c4c2019-12-02 12:30:15 +000020LICENSES = [
21 "MIT",
22 "Apache-2.0",
23 "BSD",
24 "BSD-2-Clause",
25 "BSD-3-Clause",
26 "CC0-1.0",
27 "CC-BY-3.0",
28 "ISC",
29]
30
Yang Guo4fd355c2019-09-19 10:59:03 +020031# List all DEPS here.
32DEPS = {
33 "@types/chai": "4.2.0",
34 "@types/mocha": "5.2.7",
35 "chai": "4.2.0",
Paul Lewis75090cf2019-10-25 14:13:11 +010036 "escodegen": "1.12.0",
Yang Guo4fd355c2019-09-19 10:59:03 +020037 "eslint": "6.0.1",
Paul Lewis75090cf2019-10-25 14:13:11 +010038 "esprima": "git+https://git@github.com/ChromeDevTools/esprima.git#4d0f0e18bd8d3731e5f931bf573af3394cbf7cbe",
Paul Lewis66e12062019-12-02 12:04:54 +000039 "handlebars": "4.3.1",
Yang Guo4fd355c2019-09-19 10:59:03 +020040 "karma": "4.2.0",
41 "karma-chai": "0.1.0",
42 "karma-chrome-launcher": "3.1.0",
Paul Lewisd9039092019-11-27 17:06:23 +000043 "karma-coverage-istanbul-instrumenter": "1.0.1",
44 "karma-coverage-istanbul-reporter": "2.1.0",
Yang Guo4fd355c2019-09-19 10:59:03 +020045 "karma-mocha": "1.3.0",
46 "karma-typescript": "4.1.1",
Paul Lewise184c4c2019-12-02 12:30:15 +000047 "license-checker": "25.0.1",
Yang Guo4fd355c2019-09-19 10:59:03 +020048 "mocha": "6.2.0",
Paul Lewisd9039092019-11-27 17:06:23 +000049 "puppeteer": "2.0.0",
Paul Lewis66e12062019-12-02 12:04:54 +000050 "rollup": "1.23.1",
51 "typescript": "3.5.3",
52 "yargs": "15.0.2"
Yang Guo4fd355c2019-09-19 10:59:03 +020053}
54
Paul Lewis66e12062019-12-02 12:04:54 +000055def exec_command(cmd):
Yang Guo4fd355c2019-09-19 10:59:03 +020056 try:
Paul Lewis66e12062019-12-02 12:04:54 +000057 cmd_proc_result = subprocess.check_call(cmd, cwd=devtools_paths.root_path())
58 except CalledProcessError as error:
59 print(error.output)
60 return True
61
62 return False
Yang Guo4fd355c2019-09-19 10:59:03 +020063
64
Paul Lewise184c4c2019-12-02 12:30:15 +000065def ensure_licenses():
66 cmd = [
67 devtools_paths.node_path(),
68 devtools_paths.license_checker_path(),
69 '--onlyAllow',
70 ('%s' % (';'.join(LICENSES)))
71 ]
72
73 return exec_command(cmd)
74
75
Yang Guo4fd355c2019-09-19 10:59:03 +020076def strip_private_fields():
77 # npm adds private fields which need to be stripped.
78 pattern = path.join(devtools_paths.node_modules_path(), 'package.json')
79 packages = []
80 for root, dirnames, filenames in os.walk(devtools_paths.node_modules_path()):
81 for filename in filter(lambda f: f == 'package.json', filenames):
82 packages.append(path.join(root, filename))
83
84 for pkg in packages:
85 with open(pkg, 'r+') as pkg_file:
86 prop_removal_count = 0
87 try:
88 pkg_data = json.load(pkg_file)
89
90 # Remove anything that begins with an underscore, as these are
91 # the private fields in a package.json
92 for key in pkg_data.keys():
93 if key.find(u'_') == 0:
94 pkg_data.pop(key)
95 prop_removal_count = prop_removal_count + 1
96
97 pkg_file.truncate(0)
98 pkg_file.seek(0)
99 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
100 print("(%s): %s" % (prop_removal_count, pkg))
101 except:
102 print('Unable to fix: %s' % pkg)
103 return True
104
105 return False
106
107
Paul Lewis66e12062019-12-02 12:04:54 +0000108def install_missing_deps():
109 with open(devtools_paths.package_lock_json_path(), 'r+') as pkg_lock_file:
110 try:
111 pkg_lock_data = json.load(pkg_lock_file)
112 existing_deps = pkg_lock_data[u'dependencies']
113 new_deps = []
114
115 # Find any new DEPS and add them in.
116 for dep, version in DEPS.items():
Paul Lewise184c4c2019-12-02 12:30:15 +0000117 if not dep in existing_deps or not existing_deps[dep]['version'] == version:
Paul Lewis66e12062019-12-02 12:04:54 +0000118 new_deps.append("%s@%s" % (dep, version))
119
120 # Now install.
121 if len(new_deps) > 0:
122 cmd = ['npm', 'install', '--save-dev']
123 cmd.extend(new_deps)
124 return exec_command(cmd)
125
126 except Exception as exception:
Paul Lewise184c4c2019-12-02 12:30:15 +0000127 print('Unable to install: %s' % exception)
Paul Lewis66e12062019-12-02 12:04:54 +0000128 return True
129
130 return False
131
132
Paul Lewisd9039092019-11-27 17:06:23 +0000133def append_package_json_entries():
134 with open(devtools_paths.package_json_path(), 'r+') as pkg_file:
135 try:
136 pkg_data = json.load(pkg_file)
137
138 # Replace the dev deps.
139 pkg_data[u'devDependencies'] = DEPS
140
141 pkg_file.truncate(0)
142 pkg_file.seek(0)
143 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
144
145 except:
146 print('Unable to fix: %s' % sys.exc_info()[0])
147 return True
148 return False
149
150
Paul Lewis75090cf2019-10-25 14:13:11 +0100151def remove_package_json_entries():
152 with open(devtools_paths.package_json_path(), 'r+') as pkg_file:
153 try:
154 pkg_data = json.load(pkg_file)
155
156 # Remove the dependencies and devDependencies from the root package.json
157 # so that they can't be used to overwrite the node_modules managed by this file.
158 for key in pkg_data.keys():
159 if key.find(u'dependencies') == 0 or key.find(u'devDependencies') == 0:
160 pkg_data.pop(key)
161
162 pkg_file.truncate(0)
163 pkg_file.seek(0)
164 json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
165 except:
166 print('Unable to fix: %s' % pkg)
167 return True
168 return False
169
170
Yang Guo4fd355c2019-09-19 10:59:03 +0200171def install_deps():
Paul Lewis66e12062019-12-02 12:04:54 +0000172 for (name, version) in DEPS.items():
173 if (version.find(u'^') == 0):
174 print('Versions must be locked to a specific version; remove ^ from the start of the version.')
175 return True
Yang Guo4fd355c2019-09-19 10:59:03 +0200176
Paul Lewis66e12062019-12-02 12:04:54 +0000177 if append_package_json_entries():
178 return True
179
180 if install_missing_deps():
Paul Lewisd9039092019-11-27 17:06:23 +0000181 return True
182
183 # Run the CI version of npm, which prevents updates to the versions of modules.
Paul Lewis66e12062019-12-02 12:04:54 +0000184 if exec_command(['npm', 'ci']):
Yang Guo4fd355c2019-09-19 10:59:03 +0200185 return True
186
Paul Lewis66e12062019-12-02 12:04:54 +0000187 if strip_private_fields():
Paul Lewis75090cf2019-10-25 14:13:11 +0100188 return True
189
Paul Lewise184c4c2019-12-02 12:30:15 +0000190 if remove_package_json_entries():
191 return True
192
193 return ensure_licenses()
Yang Guo4fd355c2019-09-19 10:59:03 +0200194
195
196npm_errors_found = install_deps()
197
198if npm_errors_found:
199 print('npm installation failed')
200else:
201 print('npm installation successful')