Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python2.7 |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 2 | # Copyright 2017 gRPC authors. |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 3 | # |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 7 | # |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 9 | # |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 15 | """Build and upload docker images to Google Container Registry per matrix.""" |
| 16 | |
| 17 | from __future__ import print_function |
| 18 | |
| 19 | import argparse |
| 20 | import atexit |
| 21 | import multiprocessing |
| 22 | import os |
| 23 | import shutil |
| 24 | import subprocess |
| 25 | import sys |
| 26 | import tempfile |
| 27 | |
| 28 | # Langauage Runtime Matrix |
| 29 | import client_matrix |
| 30 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 31 | python_util_dir = os.path.abspath( |
| 32 | os.path.join(os.path.dirname(__file__), '../run_tests/python_utils')) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 33 | sys.path.append(python_util_dir) |
| 34 | import dockerjob |
| 35 | import jobset |
| 36 | |
| 37 | _IMAGE_BUILDER = 'tools/run_tests/dockerize/build_interop_image.sh' |
| 38 | _LANGUAGES = client_matrix.LANG_RUNTIME_MATRIX.keys() |
| 39 | # All gRPC release tags, flattened, deduped and sorted. |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 40 | _RELEASES = sorted( |
| 41 | list( |
| 42 | set( |
| 43 | client_matrix.get_release_tag_name(info) |
| 44 | for lang in client_matrix.LANG_RELEASE_MATRIX.values() |
| 45 | for info in lang))) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 46 | |
| 47 | # Destination directory inside docker image to keep extra info from build time. |
| 48 | _BUILD_INFO = '/var/local/build_info' |
| 49 | |
| 50 | argp = argparse.ArgumentParser(description='Run interop tests.') |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 51 | argp.add_argument( |
| 52 | '--gcr_path', |
| 53 | default='gcr.io/grpc-testing', |
| 54 | help='Path of docker images in Google Container Registry') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 55 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 56 | argp.add_argument( |
| 57 | '--release', |
| 58 | default='master', |
| 59 | choices=['all', 'master'] + _RELEASES, |
| 60 | help='github commit tag to checkout. When building all ' |
| 61 | 'releases defined in client_matrix.py, use "all". Valid only ' |
| 62 | 'with --git_checkout.') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 63 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 64 | argp.add_argument( |
| 65 | '-l', |
| 66 | '--language', |
| 67 | choices=['all'] + sorted(_LANGUAGES), |
| 68 | nargs='+', |
| 69 | default=['all'], |
| 70 | help='Test languages to build docker images for.') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 71 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 72 | argp.add_argument( |
| 73 | '--git_checkout', |
| 74 | action='store_true', |
| 75 | help='Use a separate git clone tree for building grpc stack. ' |
| 76 | 'Required when using --release flag. By default, current' |
| 77 | 'tree and the sibling will be used for building grpc stack.') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 78 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 79 | argp.add_argument( |
| 80 | '--git_checkout_root', |
| 81 | default='/export/hda3/tmp/grpc_matrix', |
| 82 | help='Directory under which grpc-go/java/main repo will be ' |
| 83 | 'cloned. Valid only with --git_checkout.') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 84 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 85 | argp.add_argument( |
| 86 | '--keep', |
| 87 | action='store_true', |
| 88 | help='keep the created local images after uploading to GCR') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 89 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 90 | argp.add_argument( |
| 91 | '--reuse_git_root', |
| 92 | default=False, |
| 93 | action='store_const', |
| 94 | const=True, |
| 95 | help='reuse the repo dir. If False, the existing git root ' |
| 96 | 'directory will removed before a clean checkout, because ' |
| 97 | 'reusing the repo can cause git checkout error if you switch ' |
| 98 | 'between releases.') |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 99 | |
Jan Tattermusch | c093a7f | 2018-05-30 17:43:56 +0200 | [diff] [blame] | 100 | argp.add_argument( |
| 101 | '--upload_images', |
| 102 | action='store_true', |
Jan Tattermusch | f1f456b | 2018-05-31 11:45:44 +0200 | [diff] [blame] | 103 | help='If set, images will be uploaded to container registry after building.' |
| 104 | ) |
Jan Tattermusch | c093a7f | 2018-05-30 17:43:56 +0200 | [diff] [blame] | 105 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 106 | args = argp.parse_args() |
| 107 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 108 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 109 | def add_files_to_image(image, with_files, label=None): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 110 | """Add files to a docker image. |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 111 | |
| 112 | image: docker image name, i.e. grpc_interop_java:26328ad8 |
| 113 | with_files: additional files to include in the docker image. |
| 114 | label: label string to attach to the image. |
| 115 | """ |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 116 | tag_idx = image.find(':') |
| 117 | if tag_idx == -1: |
| 118 | jobset.message( |
| 119 | 'FAILED', 'invalid docker image %s' % image, do_newline=True) |
| 120 | sys.exit(1) |
| 121 | orig_tag = '%s_' % image |
| 122 | subprocess.check_output(['docker', 'tag', image, orig_tag]) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 123 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 124 | lines = ['FROM ' + orig_tag] |
| 125 | if label: |
| 126 | lines.append('LABEL %s' % label) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 127 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 128 | temp_dir = tempfile.mkdtemp() |
| 129 | atexit.register(lambda: subprocess.call(['rm', '-rf', temp_dir])) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 130 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 131 | # Copy with_files inside the tmp directory, which will be the docker build |
| 132 | # context. |
| 133 | for f in with_files: |
| 134 | shutil.copy(f, temp_dir) |
| 135 | lines.append('COPY %s %s/' % (os.path.basename(f), _BUILD_INFO)) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 136 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 137 | # Create a Dockerfile. |
| 138 | with open(os.path.join(temp_dir, 'Dockerfile'), 'w') as f: |
| 139 | f.write('\n'.join(lines)) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 140 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 141 | jobset.message('START', 'Repackaging %s' % image, do_newline=True) |
| 142 | build_cmd = ['docker', 'build', '--rm', '--tag', image, temp_dir] |
| 143 | subprocess.check_output(build_cmd) |
| 144 | dockerjob.remove_image(orig_tag, skip_nonexistent=True) |
| 145 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 146 | |
Adele Zhou | bcd23cd | 2017-11-01 15:42:00 -0700 | [diff] [blame] | 147 | def build_image_jobspec(runtime, env, gcr_tag, stack_base): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 148 | """Build interop docker image for a language with runtime. |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 149 | |
| 150 | runtime: a <lang><version> string, for example go1.8. |
| 151 | env: dictionary of env to passed to the build script. |
| 152 | gcr_tag: the tag for the docker image (i.e. v1.3.0). |
Adele Zhou | bcd23cd | 2017-11-01 15:42:00 -0700 | [diff] [blame] | 153 | stack_base: the local gRPC repo path. |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 154 | """ |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 155 | basename = 'grpc_interop_%s' % runtime |
| 156 | tag = '%s/%s:%s' % (args.gcr_path, basename, gcr_tag) |
| 157 | build_env = {'INTEROP_IMAGE': tag, 'BASE_NAME': basename, 'TTY_FLAG': '-t'} |
| 158 | build_env.update(env) |
| 159 | image_builder_path = _IMAGE_BUILDER |
| 160 | if client_matrix.should_build_docker_interop_image_from_release_tag(lang): |
| 161 | image_builder_path = os.path.join(stack_base, _IMAGE_BUILDER) |
| 162 | build_job = jobset.JobSpec( |
| 163 | cmdline=[image_builder_path], |
| 164 | environ=build_env, |
| 165 | shortname='build_docker_%s' % runtime, |
| 166 | timeout_seconds=30 * 60) |
| 167 | build_job.tag = tag |
| 168 | return build_job |
| 169 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 170 | |
| 171 | def build_all_images_for_lang(lang): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 172 | """Build all docker images for a language across releases and runtimes.""" |
| 173 | if not args.git_checkout: |
| 174 | if args.release != 'master': |
Jan Tattermusch | f1f456b | 2018-05-31 11:45:44 +0200 | [diff] [blame] | 175 | print( |
| 176 | 'Cannot use --release without also enabling --git_checkout.\n') |
Jan Tattermusch | c093a7f | 2018-05-30 17:43:56 +0200 | [diff] [blame] | 177 | sys.exit(1) |
| 178 | releases = [args.release] |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 179 | else: |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 180 | if args.release == 'all': |
| 181 | releases = client_matrix.get_release_tags(lang) |
| 182 | else: |
| 183 | # Build a particular release. |
Mehrdad Afshari | 87cd994 | 2018-01-02 14:40:00 -0800 | [diff] [blame] | 184 | if args.release not in ['master' |
| 185 | ] + client_matrix.get_release_tags(lang): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 186 | jobset.message( |
| 187 | 'SKIPPED', |
| 188 | '%s for %s is not defined' % (args.release, lang), |
| 189 | do_newline=True) |
| 190 | return [] |
| 191 | releases = [args.release] |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 192 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 193 | images = [] |
| 194 | for release in releases: |
| 195 | images += build_all_images_for_release(lang, release) |
| 196 | jobset.message( |
| 197 | 'SUCCESS', |
| 198 | 'All docker images built for %s at %s.' % (lang, releases), |
| 199 | do_newline=True) |
| 200 | return images |
| 201 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 202 | |
| 203 | def build_all_images_for_release(lang, release): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 204 | """Build all docker images for a release across all runtimes.""" |
| 205 | docker_images = [] |
| 206 | build_jobs = [] |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 207 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 208 | env = {} |
| 209 | # If we not using current tree or the sibling for grpc stack, do checkout. |
| 210 | stack_base = '' |
| 211 | if args.git_checkout: |
| 212 | stack_base = checkout_grpc_stack(lang, release) |
| 213 | var = { |
| 214 | 'go': 'GRPC_GO_ROOT', |
| 215 | 'java': 'GRPC_JAVA_ROOT', |
| 216 | 'node': 'GRPC_NODE_ROOT' |
| 217 | }.get(lang, 'GRPC_ROOT') |
| 218 | env[var] = stack_base |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 219 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 220 | for runtime in client_matrix.LANG_RUNTIME_MATRIX[lang]: |
| 221 | job = build_image_jobspec(runtime, env, release, stack_base) |
| 222 | docker_images.append(job.tag) |
| 223 | build_jobs.append(job) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 224 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 225 | jobset.message('START', 'Building interop docker images.', do_newline=True) |
| 226 | print('Jobs to run: \n%s\n' % '\n'.join(str(j) for j in build_jobs)) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 227 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 228 | num_failures, _ = jobset.run( |
| 229 | build_jobs, |
| 230 | newline_on_success=True, |
| 231 | maxjobs=multiprocessing.cpu_count()) |
| 232 | if num_failures: |
| 233 | jobset.message( |
| 234 | 'FAILED', 'Failed to build interop docker images.', do_newline=True) |
| 235 | docker_images_cleanup.extend(docker_images) |
| 236 | sys.exit(1) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 237 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 238 | jobset.message( |
| 239 | 'SUCCESS', |
| 240 | 'All docker images built for %s at %s.' % (lang, release), |
| 241 | do_newline=True) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 242 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 243 | if release != 'master': |
| 244 | commit_log = os.path.join(stack_base, 'commit_log') |
| 245 | if os.path.exists(commit_log): |
| 246 | for image in docker_images: |
| 247 | add_files_to_image(image, [commit_log], 'release=%s' % release) |
| 248 | return docker_images |
| 249 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 250 | |
| 251 | def cleanup(): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 252 | if not args.keep: |
| 253 | for image in docker_images_cleanup: |
| 254 | dockerjob.remove_image(image, skip_nonexistent=True) |
| 255 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 256 | |
| 257 | docker_images_cleanup = [] |
| 258 | atexit.register(cleanup) |
| 259 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 260 | |
Alex Polcyn | 8426329 | 2017-11-15 00:32:50 +0000 | [diff] [blame] | 261 | def maybe_apply_patches_on_git_tag(stack_base, lang, release): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 262 | files_to_patch = [] |
| 263 | for release_info in client_matrix.LANG_RELEASE_MATRIX[lang]: |
| 264 | if client_matrix.get_release_tag_name(release_info) == release: |
Menghan Li | caada99 | 2017-12-12 17:46:21 -0800 | [diff] [blame] | 265 | if release_info[release] is not None: |
| 266 | files_to_patch = release_info[release].get('patch') |
| 267 | break |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 268 | if not files_to_patch: |
| 269 | return |
| 270 | patch_file_relative_path = 'patches/%s_%s/git_repo.patch' % (lang, release) |
| 271 | patch_file = os.path.abspath( |
| 272 | os.path.join(os.path.dirname(__file__), patch_file_relative_path)) |
| 273 | if not os.path.exists(patch_file): |
ncteisen | 173c477 | 2017-12-11 16:52:44 -0800 | [diff] [blame] | 274 | jobset.message('FAILED', |
| 275 | 'expected patch file |%s| to exist' % patch_file) |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 276 | sys.exit(1) |
Alex Polcyn | 8426329 | 2017-11-15 00:32:50 +0000 | [diff] [blame] | 277 | subprocess.check_output( |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 278 | ['git', 'apply', patch_file], cwd=stack_base, stderr=subprocess.STDOUT) |
Jan Tattermusch | d851d82 | 2018-05-30 18:59:51 +0200 | [diff] [blame] | 279 | |
| 280 | # TODO(jtattermusch): this really would need simplification and refactoring |
| 281 | # - "git add" and "git commit" can easily be done in a single command |
| 282 | # - it looks like the only reason for the existence of the "files_to_patch" |
| 283 | # entry is to perform "git add" - which is clumsy and fragile. |
| 284 | # - we only allow a single patch with name "git_repo.patch". A better design |
| 285 | # would be to allow multiple patches that can have more descriptive names. |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 286 | for repo_relative_path in files_to_patch: |
| 287 | subprocess.check_output( |
| 288 | ['git', 'add', repo_relative_path], |
| 289 | cwd=stack_base, |
| 290 | stderr=subprocess.STDOUT) |
| 291 | subprocess.check_output( |
| 292 | [ |
| 293 | 'git', 'commit', '-m', |
| 294 | ('Hack performed on top of %s git ' |
| 295 | 'tag in order to build and run the %s ' |
| 296 | 'interop tests on that tag.' % (lang, release)) |
| 297 | ], |
Alex Polcyn | 8426329 | 2017-11-15 00:32:50 +0000 | [diff] [blame] | 298 | cwd=stack_base, |
| 299 | stderr=subprocess.STDOUT) |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 300 | |
Alex Polcyn | 8426329 | 2017-11-15 00:32:50 +0000 | [diff] [blame] | 301 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 302 | def checkout_grpc_stack(lang, release): |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 303 | """Invokes 'git check' for the lang/release and returns directory created.""" |
| 304 | assert args.git_checkout and args.git_checkout_root |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 305 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 306 | if not os.path.exists(args.git_checkout_root): |
| 307 | os.makedirs(args.git_checkout_root) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 308 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 309 | repo = client_matrix.get_github_repo(lang) |
| 310 | # Get the subdir name part of repo |
| 311 | # For example, 'git@github.com:grpc/grpc-go.git' should use 'grpc-go'. |
| 312 | repo_dir = os.path.splitext(os.path.basename(repo))[0] |
| 313 | stack_base = os.path.join(args.git_checkout_root, repo_dir) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 314 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 315 | # Clean up leftover repo dir if necessary. |
| 316 | if not args.reuse_git_root and os.path.exists(stack_base): |
| 317 | jobset.message('START', 'Removing git checkout root.', do_newline=True) |
| 318 | shutil.rmtree(stack_base) |
Adele Zhou | a366468 | 2017-11-14 17:30:32 -0800 | [diff] [blame] | 319 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 320 | if not os.path.exists(stack_base): |
| 321 | subprocess.check_call( |
| 322 | ['git', 'clone', '--recursive', repo], |
| 323 | cwd=os.path.dirname(stack_base)) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 324 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 325 | # git checkout. |
| 326 | jobset.message( |
| 327 | 'START', |
| 328 | 'git checkout %s from %s' % (release, stack_base), |
| 329 | do_newline=True) |
| 330 | # We should NEVER do checkout on current tree !!! |
| 331 | assert not os.path.dirname(__file__).startswith(stack_base) |
| 332 | output = subprocess.check_output( |
| 333 | ['git', 'checkout', release], cwd=stack_base, stderr=subprocess.STDOUT) |
| 334 | maybe_apply_patches_on_git_tag(stack_base, lang, release) |
| 335 | commit_log = subprocess.check_output(['git', 'log', '-1'], cwd=stack_base) |
| 336 | jobset.message( |
| 337 | 'SUCCESS', |
| 338 | 'git checkout', |
| 339 | '%s: %s' % (str(output), commit_log), |
| 340 | do_newline=True) |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 341 | |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 342 | # Write git log to commit_log so it can be packaged with the docker image. |
| 343 | with open(os.path.join(stack_base, 'commit_log'), 'w') as f: |
| 344 | f.write(commit_log) |
| 345 | return stack_base |
| 346 | |
Yong Ni | b2e4bfa | 2017-05-09 18:12:10 -0700 | [diff] [blame] | 347 | |
| 348 | languages = args.language if args.language != ['all'] else _LANGUAGES |
| 349 | for lang in languages: |
ncteisen | e4bef08 | 2017-12-11 16:51:34 -0800 | [diff] [blame] | 350 | docker_images = build_all_images_for_lang(lang) |
| 351 | for image in docker_images: |
Jan Tattermusch | c093a7f | 2018-05-30 17:43:56 +0200 | [diff] [blame] | 352 | if args.upload_images: |
| 353 | jobset.message('START', 'Uploading %s' % image, do_newline=True) |
| 354 | # docker image name must be in the format <gcr_path>/<image>:<gcr_tag> |
| 355 | assert image.startswith(args.gcr_path) and image.find(':') != -1 |
| 356 | subprocess.call(['gcloud', 'docker', '--', 'push', image]) |
| 357 | else: |
| 358 | # Uploading (and overwriting images) by default can easily break things. |
Jan Tattermusch | f1f456b | 2018-05-31 11:45:44 +0200 | [diff] [blame] | 359 | print('Not uploading image %s, run with --upload_images to upload.' |
| 360 | % image) |