Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 1 | # Copyright 2017 The Chromium OS 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. |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 4 | """Module for setup environemtn for local testing & Google App Engine. |
| 5 | |
| 6 | DO NOT RUN THIS MODULE DIRECTLY. |
| 7 | |
| 8 | Use bin/setup_environment instead. |
| 9 | See [README.md]. |
| 10 | """ |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 11 | |
Xixuan Wu | 8929a30 | 2017-12-07 18:09:31 -0800 | [diff] [blame] | 12 | from __future__ import print_function |
| 13 | |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 14 | import argparse |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 15 | import collections |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 16 | import os |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 17 | import pipes |
Xixuan Wu | 30244f9 | 2019-03-21 09:49:17 -0700 | [diff] [blame] | 18 | import shutil |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 19 | import subprocess |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 20 | import sys |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 21 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 22 | _ROOT = os.path.dirname(os.path.realpath(__file__)) |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 23 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 24 | _INFRA_LIBS_PATH = os.path.join(_ROOT, 'infra_libs') |
| 25 | _REFRESH_CREDENTIALS_SCRIPT = os.path.join(_ROOT, 'bin', 'refresh_credentials') |
| 26 | _REQUIREMENTS_PATH = os.path.join(_ROOT, "requirements.txt") |
| 27 | _THIRD_PARTY_LIB_PATH = os.path.join(_ROOT, 'lib') |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 28 | |
Xinan Lin | 3ba18a0 | 2019-08-13 15:44:55 -0700 | [diff] [blame] | 29 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 30 | def _install_third_party_lib(): |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 31 | """Install useful third-party lib. |
| 32 | |
| 33 | The libraries are specified in requirement.txt. They're used in both local |
| 34 | development environment and Google App Engine, which means they will be |
| 35 | uploaded to GAE. |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 36 | """ |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 37 | if os.path.exists(_THIRD_PARTY_LIB_PATH): |
| 38 | shutil.rmtree(_THIRD_PARTY_LIB_PATH) |
| 39 | os.mkdir(_THIRD_PARTY_LIB_PATH) |
| 40 | print('Installing third party dependencies in %s' % |
| 41 | (_THIRD_PARTY_LIB_PATH, )) |
| 42 | try: |
| 43 | subprocess.check_call([ |
| 44 | sys.executable, '-m', 'pip', 'install', '-t', _THIRD_PARTY_LIB_PATH, |
| 45 | '-r', _REQUIREMENTS_PATH |
| 46 | ]) |
| 47 | except OSError: |
| 48 | print('Please check that `pip` is installed. See README.md') |
| 49 | raise |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 50 | |
| 51 | |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 52 | def create_file(fname): |
| 53 | """Create an empty file by opening it for writing and closing.""" |
| 54 | open(fname, 'w').close() |
| 55 | |
| 56 | |
| 57 | def fixup_chromite_imports(): |
| 58 | """Fixup chromite __init__.py files. |
| 59 | |
| 60 | Chromite runs Python3 now so relies on implicit namespacing, which Python2 |
| 61 | doesn't support, so we have to go back and add a few __init__.py files to make |
| 62 | things importable. |
| 63 | """ |
| 64 | def remove_third_party(fname, package): |
| 65 | "Remove 'chromite.third_party.' prefix from given import string." |
| 66 | cmd = [ |
| 67 | 'sed', |
| 68 | '-i', |
| 69 | 's/%s/%s/' % ('chromite.third_party.%s' % package, package), |
| 70 | fname, |
| 71 | ] |
| 72 | subprocess.check_call(cmd) |
| 73 | |
| 74 | for root, _, files in os.walk('infra_libs/chromite'): |
| 75 | for fname in files: |
| 76 | if fname.endswith('_pb2.py'): |
| 77 | path = os.path.join(root, fname) |
| 78 | remove_third_party(path, 'google.protobuf') |
| 79 | |
| 80 | # Add explicit __init__.py files to workaround implicit namespaces in python3 |
| 81 | create_file('infra_libs/chromite/__init__.py') |
| 82 | create_file('infra_libs/chromite/third_party/__init__.py') |
| 83 | create_file('infra_libs/chromite/third_party/google/__init__.py') |
| 84 | create_file('infra_libs/chromite/third_party/google/api/__init__.py') |
| 85 | |
| 86 | |
| 87 | # _GITDEP Specifies a dependency in the form of a particular reference in a git |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 88 | # project. |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 89 | # |
| 90 | # local_name: Name of the local directory to fetch into. |
| 91 | # project: URL to the git project to fetch from. |
| 92 | # ref: Git ref to fetch. |
| 93 | # sparse_checkout_paths: A list of paths to checkout. Some of the dependencies |
| 94 | # contain too many files and AppEngine does not allow uploading > 10K files. |
| 95 | # Thus, we checkout only required sub-packages. This list is passed in to |
| 96 | # (and interpreted by) `git sparse-checkout`. |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 97 | # post_process: An optional callable to evaluate after cloning dependency |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 98 | _GitDep = collections.namedtuple( |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 99 | '_GitDep', |
| 100 | 'local_name git_project git_ref sparse_checkout_paths post_process') |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 101 | |
| 102 | # List of all git project dependencies. |
| 103 | _GIT_DEPS = [ |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 104 | # Note: When upreving chromite, ensure that protobuf version in |
| 105 | # requirements.txt still matches the protobuf version used by chromite. |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 106 | _GitDep( |
| 107 | 'chromite', |
| 108 | 'https://chromium.googlesource.com/chromiumos/chromite', |
Azizur Rahman | a9a189f | 2022-07-29 20:28:28 +0000 | [diff] [blame] | 109 | '1678d4792a11268172ff7ff79535706b6c0f7c03', |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 110 | [ |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 111 | '/api/gen/**/*.py', |
| 112 | '/api/__init__.py', |
| 113 | '/third_party/infra_libs/*', |
| 114 | '/third_party/six/*', |
| 115 | '/third_party/google/api/*', |
| 116 | '/third_party/google/rpc/*', |
| 117 | '/third_party/__init__.py', |
| 118 | '/__init__.py', |
| 119 | '!*test.py', |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 120 | ], |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 121 | fixup_chromite_imports, |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 122 | ), |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 123 | _GitDep('luci', 'https://chromium.googlesource.com/infra/luci/luci-py', |
| 124 | '33a910c714948a5189f9c58101ce9b131f01c1fd', [ |
| 125 | '/appengine/components/components/auth/**/*.py', |
| 126 | '/appengine/components/components/datastore_utils/**/*.py', |
| 127 | '/appengine/components/components/prpc/**/*.py', |
| 128 | '/appengine/components/components/*.py', |
| 129 | '!*test.py', |
| 130 | ], None), |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 131 | ] |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 132 | |
Xinan Lin | 3ba18a0 | 2019-08-13 15:44:55 -0700 | [diff] [blame] | 133 | |
Xinan Lin | 83c1a31 | 2020-04-13 23:31:47 -0700 | [diff] [blame] | 134 | def _install_infra_libs(): |
Xinan Lin | cd6d40b | 2019-08-09 15:53:43 -0700 | [diff] [blame] | 135 | """Install useful libs from Chromium infra and Chromite. |
| 136 | |
| 137 | infra_libs consists of prpc client from luci and necessary proto files from |
| 138 | Chromite. Suite scheduler relies on those libs to conduct prpc call to |
| 139 | Buildbucket. |
Xinan Lin | cd6d40b | 2019-08-09 15:53:43 -0700 | [diff] [blame] | 140 | """ |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 141 | if os.path.exists(_INFRA_LIBS_PATH): |
| 142 | shutil.rmtree(_INFRA_LIBS_PATH) |
| 143 | os.mkdir(_INFRA_LIBS_PATH) |
Xinan Lin | cd6d40b | 2019-08-09 15:53:43 -0700 | [diff] [blame] | 144 | |
Prathmesh Prabhu | 4a880bc | 2020-06-22 13:38:50 -0700 | [diff] [blame] | 145 | for dep in _GIT_DEPS: |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 146 | dep_path = os.path.join(_INFRA_LIBS_PATH, dep.local_name) |
| 147 | print('Creating sparse checkout of %s at %s in %s' % |
| 148 | (dep.git_project, dep.git_ref, dep_path)) |
| 149 | subprocess.check_call( |
| 150 | ['git', 'clone', '--no-checkout', dep.git_project, dep.local_name], |
| 151 | cwd=_INFRA_LIBS_PATH) |
| 152 | subprocess.check_call(['git', 'sparse-checkout', 'init'], cwd=dep_path) |
| 153 | _set_sparse_checkout_paths(dep_path, dep.sparse_checkout_paths) |
Xinan Lin | d37e622 | 2020-07-07 22:37:57 -0700 | [diff] [blame] | 154 | subprocess.check_call( |
| 155 | ['git', 'checkout', dep.git_ref, '-b', 'deploy', '-f'], cwd=dep_path) |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 156 | |
Sean McAllister | af32bfb | 2021-07-19 09:20:17 -0600 | [diff] [blame] | 157 | if dep.post_process: |
| 158 | dep.post_process() |
| 159 | |
Xinan Lin | 3ba18a0 | 2019-08-13 15:44:55 -0700 | [diff] [blame] | 160 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 161 | def _set_sparse_checkout_paths(checkout_dir, sparse_checkout_paths): |
| 162 | """Set the path patterns to checkout in a git checkout.""" |
| 163 | # Pass in path patterns via stdin to avoid shell escaping issues. |
Jack Neus | 366cadb | 2022-06-24 21:24:28 +0000 | [diff] [blame] | 164 | proc = subprocess.Popen(['git', 'sparse-checkout', 'set', '--no-cone', '--stdin'], |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 165 | stdin=subprocess.PIPE, |
| 166 | cwd=checkout_dir) |
| 167 | proc.communicate(input='\n'.join(sparse_checkout_paths)) |
| 168 | if proc.poll() is None: |
| 169 | raise Exception('Leaked process when setting sparse checkout paths') |
| 170 | if proc.poll() != 0: |
| 171 | raise Exception('Failed to set sparse checkout paths') |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 172 | |
| 173 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 174 | def _load_credentials(): |
| 175 | subprocess.check_call([_REFRESH_CREDENTIALS_SCRIPT]) |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 176 | |
| 177 | |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 178 | def main(): |
| 179 | """Entry point of the script""" |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 180 | parser = argparse.ArgumentParser( |
| 181 | description=__doc__, |
| 182 | formatter_class=argparse.RawDescriptionHelpFormatter) |
| 183 | parser.add_argument( |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 184 | '--load-creds', |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 185 | action='store_true', |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 186 | help='Also install credentials needed for releasing suite ' |
| 187 | 'scheduler. Not needed to modify config/*') |
| 188 | |
| 189 | args = parser.parse_args() |
| 190 | _install_third_party_lib() |
| 191 | _install_infra_libs() |
| 192 | if args.load_creds: |
| 193 | _load_credentials() |
Xixuan Wu | 26d06e0 | 2017-09-20 14:50:28 -0700 | [diff] [blame] | 194 | |
| 195 | |
| 196 | if __name__ == '__main__': |
Prathmesh Prabhu | 8dff3e2 | 2020-06-23 13:49:45 -0700 | [diff] [blame] | 197 | main() |