blob: d7c0e80dcc2d7b157da48e93290972c7b2460e15 [file] [log] [blame]
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07003#
4# Copyright 2020 The Chromium OS Authors. All rights reserved.
5# Use of this source code is governed by a BSD-style license that can be
6# found in the LICENSE file.
7#
Paul Fagerburge868e832020-01-22 17:14:04 -07008"""Create a new variant of an existing reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -07009
10This program will call all of the scripts that create the various pieces
11of a new variant. For example to create a new variant of the hatch base
12board, the following scripts are called:
13
Paul Fagerburg5f794bf2020-02-12 13:01:36 -070014* platform/dev/contrib/variant/create_coreboot_variant.sh
Paul Fagerburg3b534f92019-11-07 15:05:22 -070015* platform/dev/contrib/variant/create_coreboot_config.sh
16* private-overlays/baseboard-hatch-private/sys-boot/
17 * coreboot-private-files-hatch/files/add_fitimage.sh
18 * coreboot-private-files-hatch/asset_generation/gen_fit_image.sh
19 * Outside the chroot, because it uses WINE to run the FIT tools
20* platform/dev/contrib/variant/create_initial_ec_image.sh
21* platform/dev/contrib/variant/add_variant_to_yaml.sh
22* private-overlays/overlay-hatch-private/chromeos-base/
23 * chromeos-config-bsp-hatch-private/add_variant.sh
24
25Once the scripts are done, the following repos have changes
26
27* third_party/coreboot
28* third_party/chromiumos-overlay
29* private-overlays/baseboard-hatch-private
30* platform/ec
31* private-overlays/overlay-hatch-private
32* overlays
33
Paul Fagerburge868e832020-01-22 17:14:04 -070034The program has support for multiple reference boards, so the repos, directories,
35and scripts above can change depending on what the reference board is.
Paul Fagerburg3b534f92019-11-07 15:05:22 -070036"""
37
38from __future__ import print_function
39import argparse
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070040import importlib
Paul Fagerburg8d850932020-02-25 14:13:32 -070041import json
Paul Fagerburg3b534f92019-11-07 15:05:22 -070042import logging
43import os
44import re
45import shutil
46import subprocess
47import sys
Paul Fagerburg1d043c32020-02-03 08:57:08 -070048from chromite.lib import git
Paul Fagerburga8c7e342020-02-25 13:30:49 -070049from chromite.lib import gerrit
Paul Fagerburg75398072020-03-16 13:51:24 -060050from chromite.lib import workon_helper
51from chromite.lib.build_target_lib import BuildTarget
Paul Fagerburg8d850932020-02-25 14:13:32 -070052import requests
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070053import step_names
Paul Fagerburg3b534f92019-11-07 15:05:22 -070054import variant_status
55
56
57def main():
Paul Fagerburge868e832020-01-22 17:14:04 -070058 """Create a new variant of an existing reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -070059
60 This program automates the creation of a new variant of an existing
Paul Fagerburge868e832020-01-22 17:14:04 -070061 reference board by calling various scripts that copy the reference board,
62 modify files for the new variant, stage commits, and upload to gerrit.
Paul Fagerburg3b534f92019-11-07 15:05:22 -070063
64 Note that one of the following is required:
65 * --continue
66 * --board=BOARD --variant=VARIANT [--bug=BUG]
67 """
Paul Fagerburg042a5252020-03-16 21:49:18 -060068 board, variant, bug, continue_flag, abort_flag = get_args()
Paul Fagerburg3b534f92019-11-07 15:05:22 -070069
Paul Fagerburg042a5252020-03-16 21:49:18 -060070 if not check_flags(board, variant, bug, continue_flag, abort_flag):
Paul Fagerburg3b534f92019-11-07 15:05:22 -070071 return False
72
Paul Fagerburg042a5252020-03-16 21:49:18 -060073 status = get_status(board, variant, bug, continue_flag, abort_flag)
Paul Fagerburg3b534f92019-11-07 15:05:22 -070074 if status is None:
75 return False
76
77 status.load()
78
Paul Fagerburg5f794bf2020-02-12 13:01:36 -070079 # Where is new_variant.py located?
80 status.my_loc = os.path.dirname(os.path.abspath(__file__))
81
Paul Fagerburg042a5252020-03-16 21:49:18 -060082 # If the user specified --abort, override the current step.
83 if abort_flag:
84 status.step = step_names.ABORT
85
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070086 while status.step is not None:
Paul Fagerburg3b534f92019-11-07 15:05:22 -070087 status.save()
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070088 if not perform_step(status):
89 logging.debug('perform_step returned False; exiting ...')
Paul Fagerburg3b534f92019-11-07 15:05:22 -070090 return False
91
Paul Fagerburgbab5dde2020-01-10 15:10:29 -070092 move_to_next_step(status)
Paul Fagerburg3b534f92019-11-07 15:05:22 -070093
94 return True
95
96
97def get_args():
98 """Parse the command-line arguments
99
100 There doesn't appear to be a way to specify that --continue is
101 mutually exclusive with --board, --variant, and --bug. As a result,
102 all arguments are optional, and another function will apply the logic
103 to check if there is an illegal combination of arguments.
104
105 Returns a list of:
Paul Fagerburge868e832020-01-22 17:14:04 -0700106 board Name of the reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700107 variant Name of the variant being created
108 bug Text for bug number, if any ('None' otherwise)
109 continue_flag Flag if --continue was specified
110 """
111 parser = argparse.ArgumentParser(
112 description=main.__doc__,
113 formatter_class=argparse.RawTextHelpFormatter)
Paul Fagerburge868e832020-01-22 17:14:04 -0700114 parser.add_argument('--board', type=str, help='Name of the reference board')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700115 parser.add_argument(
116 '--variant', type=str, help='Name of the new variant to create')
117 parser.add_argument(
118 '--bug', type=str, help='Bug number to reference in commits')
Paul Fagerburg2e48a192020-03-24 17:57:05 -0600119 # Use a group so that we can enforce mutually-exclusive argurments.
120 # argparse does not support nesting groups, so we can't put board,
121 # variant, and bug into a group and have that group as another mutually
122 # exclusive option.
123 group = parser.add_mutually_exclusive_group()
124 group.add_argument(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700125 '--continue', action='store_true',
126 dest='continue_flag', help='Continue the process from where it paused')
Paul Fagerburg2e48a192020-03-24 17:57:05 -0600127 group.add_argument(
Paul Fagerburg042a5252020-03-16 21:49:18 -0600128 '--abort', action='store_true',
129 dest='abort_flag', help='Cancel the process and abandon all commits')
130 parser.add_argument(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700131 '--verbose', action='store_true',
132 dest='verbose_flag', help='Enable verbose output of progress')
133 args = parser.parse_args()
134
135 if args.verbose_flag:
136 logging.basicConfig(level=logging.DEBUG)
137 else:
138 logging.basicConfig(level=logging.INFO)
139
140 board = args.board
141 if board is not None:
142 board = board.lower()
143
144 variant = args.variant
145 if variant is not None:
146 variant = variant.lower()
147
148 bug = args.bug or 'None'
149
Paul Fagerburg042a5252020-03-16 21:49:18 -0600150 return (board, variant, bug, args.continue_flag, args.abort_flag)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700151
152
Paul Fagerburg042a5252020-03-16 21:49:18 -0600153def check_flags(board, variant, bug, continue_flag, abort_flag):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700154 """Check the flags to ensure no invalid combinations
155
156 We allow any of the following:
Paul Fagerburg042a5252020-03-16 21:49:18 -0600157 --abort
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700158 --continue
159 --board=board_name --variant=variant_name
160 --board=board_name --variant=variant_name --bug=bug_text
161
162 The argument parser does have the functionality to represent the
163 combination of --board and --variant as a single mutually-exclusive
164 argument, so we have to use this function to do the checking.
165
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700166 Args:
167 board: Name of the reference board
168 variant: Name of the variant being created
169 bug: Text for bug number, if any ('None' otherwise)
170 continue_flag: Flag if --continue was specified
Paul Fagerburg042a5252020-03-16 21:49:18 -0600171 abort_flag: Flag if --abort was specified
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700172
173 Returns:
174 True if the arguments are acceptable, False otherwise
175 """
Paul Fagerburg042a5252020-03-16 21:49:18 -0600176 # If either --abort or --continue is set, then disallow any of the
177 # board name, variant name, or bug number to be set.
178 if continue_flag or abort_flag:
179 if board is not None or variant is not None or bug != 'None':
180 logging.error('Do not use --board, --variant, or --bug with '
181 '--continue or --abort')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700182 return False
Paul Fagerburg042a5252020-03-16 21:49:18 -0600183 return True
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700184
Paul Fagerburg042a5252020-03-16 21:49:18 -0600185 # At this point, neither --continue nor --abort are set, so we must have
186 # both --board and --variant values.
187 if board is None or variant is None:
188 logging.error('Both --board and --variant must be specified')
189 return False
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700190
191 return True
192
193
194def file_exists(filepath, filename):
195 """Determine if a path and file exists
196
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700197 Args:
198 filepath: Path where build outputs should be found, e.g.
199 /build/hatch/firmware
200 filename: File that should exist in that path, e.g. image-sushi.bin
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700201
202 Returns:
203 True if file exists in that path, False otherwise
204 """
205 fullname = os.path.join(filepath, filename)
206 return os.path.exists(fullname) and os.path.isfile(fullname)
207
208
Paul Fagerburg042a5252020-03-16 21:49:18 -0600209def get_status(board, variant, bug, continue_flag, abort_flag):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700210 """Create the status file or get the previous status
211
212 This program can stop at several places as we have to wait for CLs
213 to work through CQ or be upstreamed into the chromiumos tree, so just
214 like a git cherry-pick, there is a --continue option to pick up where
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700215 you left off by reading a specially-named status file.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700216
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700217 If --continue is specified, the status file must exist.
218 If the status file exists, then --continue must be specified.
219 When --continue is specified, we read the status file and return
220 with the contents.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700221
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700222 If the status file does not exist, we will create the state file with
223 the board, variant, and (optional) bug details.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700224
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700225 To decouple the list of boards supported from this main program, we
Paul Fagerburge868e832020-01-22 17:14:04 -0700226 try to import a module with the same name as the reference board,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700227 so --board=hatch means that we import hatch.py. If we can't import
Paul Fagerburge868e832020-01-22 17:14:04 -0700228 the file, then we don't support that reference board.
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700229
230 The board-specific module will set several variables, which we will
231 copy into the object that we return.
232
Paul Fagerburge868e832020-01-22 17:14:04 -0700233 * base - the name of the base board, such as Hatch, Volteer, or Zork.
234 This can be different from the reference board, e.g. the Trembyle
235 reference board in the Zork project.
Paul Fagerburg4d343452020-01-24 15:23:53 -0700236 * coreboot_dir - base directory for coreboot, usually third_party/coreboot
237 but could differ for processors that use a private repo
238 * cb_config_dir - base directory for coreboot configs, usually
239 third_party/chromiumos-overlay/sys-boot/coreboot/files/configs but
240 could differ for processors that use a private repo
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700241 * step_list - list of steps (named in step_names.py) to run in sequence
Paul Fagerburge868e832020-01-22 17:14:04 -0700242 to create the new variant of the reference board
243 * fsp - package name for FSP. This may be None, depending on the
244 processor on the reference board
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700245 * fitimage_pkg - package name for the fitimage
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700246 * fitimage_dir - directory for fitimage; prepend '/mnt/host/source/src/'
247 in chroot, prepend '~/chromiumos/src' outside the chroot
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700248 * workon_pkgs - list of packages to cros_workon
249 * emerge_cmd - the emerge command, e.g. 'emerge-hatch'
250 * emerge_pkgs - list of packages to emerge
251 * yaml_emerge_pkgs - list of packages to emerge just to build the yaml
252 * private_yaml_dir - directory for the private yaml file
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700253 * commits - map of commits for the various steps. Indexed by step name,
254 and the step names used are the same ones in step_names.py
255 * repo_upload_list - list of commits to upload using `repo upload`
256 * coreboot_push_list - list of commits to upload using `git push` to
257 coreboot
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700258
259 Additionally, the following fields will be set:
260
Paul Fagerburge868e832020-01-22 17:14:04 -0700261 * board - the name of the reference board, e.g. 'hatch'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700262 * variant - the name of the variant, e.g. 'sushi'
263 * bug - optional text for a bug ID, used in the git commit messages.
264 Could be 'None' (as text, not the python None), or something like
265 'b:12345' for buganizer, or 'chromium:12345'
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700266 * step - internal state tracking, what step of the variant creation
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700267 we are at.
268 * yaml_file - internal, just the name of the file where all this data
269 gets saved.
Paul Fagerburgaec8d992020-02-27 15:51:47 -0700270 * commit - a map of maps that tracks all of the git commit and gerrit CL
271 data for each of the steps in the process. For example,
272 status.commit['add_priv_yaml'] is a map that has all the information
273 about the 'add_priv_yaml' step. The keys in the maps allow us to
274 determine where the commit is, the change_id, if it has been uploaded
275 to gerrit and where.
276
277 branch_name - the name of the git branch
278 change_id - the change-id assigned by the commit hook. Gerrit
279 uses the change_id to track new patchsets in the CL
280 dir - the directory where the commit has been created
281 gerrit - the name of the gerrit instance to which the CL has
282 been uploaded, one of 'chromium', 'chrome-internal', or
283 'coreboot'
284 cl_number - the CL number on the gerrit instance
285
286 When the commit is created, branch_name, change_id, and dir are all
287 set. The gerrit and cl_number keys are not set until the CL has been
288 uploaded to a gerrit instance.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700289
290 These data might come from the status file (because we read it), or
291 they might be the initial values after we created the file (because
292 it did not already exist).
293
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700294 Args:
295 board: Name of the reference board
296 variant: Name of the variant being created
297 bug: Text for bug number, if any ('None' otherwise)
298 continue_flag: Flag if --continue was specified
Paul Fagerburg042a5252020-03-16 21:49:18 -0600299 abort_flag: Flag if --abort was specified
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700300
301 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700302 variant_status object with all the data mentioned above
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700303 """
304 status = variant_status.variant_status()
Paul Fagerburg042a5252020-03-16 21:49:18 -0600305 if continue_flag or abort_flag:
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700306 if status.yaml_file_exists():
Paul Fagerburg042a5252020-03-16 21:49:18 -0600307 return status
308 else:
309 if continue_flag:
310 op = '--continue'
311 if abort_flag:
312 op = '--abort'
313 logging.error('%s does not exist; cannot %s', status.yaml_file, op)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700314 return None
315
Paul Fagerburg042a5252020-03-16 21:49:18 -0600316 # If we get here, the user provided --board and --variant (because
317 # check_flags() returned Trued), but the yaml file already exists,
318 # so we print an error message and bail.
319 if status.yaml_file_exists():
320 logging.error(
321 'new_variant already in progress; did you forget --continue?')
322 return None
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700323
Paul Fagerburg042a5252020-03-16 21:49:18 -0600324 # At this point, it's not --continue, not --abort, the yaml file doesn't
325 # exist, and we have valid values for --board, --variant, and --bug (bug
326 # might be the default value of "None"). Create the yaml file with data
327 # from the reference board's loadable module.
328 status.board = board
329 status.variant = variant
330 status.bug = bug
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700331
Paul Fagerburg042a5252020-03-16 21:49:18 -0600332 # Load the appropriate module and copy all the data from it.
333 try:
334 module = importlib.import_module(board)
335 except ImportError:
336 print('Unsupported board "' + board + '"')
337 sys.exit(1)
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700338
Paul Fagerburg042a5252020-03-16 21:49:18 -0600339 # pylint: disable=bad-whitespace
340 # Allow extra spaces around = so that we can line things up nicely
341 status.base = module.base
342 status.coreboot_dir = module.coreboot_dir
343 status.cb_config_dir = module.cb_config_dir
344 status.emerge_cmd = module.emerge_cmd
345 status.emerge_pkgs = module.emerge_pkgs
346 status.fitimage_dir = module.fitimage_dir
347 status.fitimage_pkg = module.fitimage_pkg
348 status.fitimage_cmd = module.fitimage_cmd
349 status.fsp = module.fsp
350 status.private_yaml_dir = module.private_yaml_dir
351 status.step_list = module.step_list
352 status.workon_pkgs = module.workon_pkgs
353 status.yaml_emerge_pkgs = module.yaml_emerge_pkgs
354 status.coreboot_push_list = module.coreboot_push_list
355 status.repo_upload_list = module.repo_upload_list
356 # pylint: enable=bad-whitespace
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700357
Paul Fagerburg042a5252020-03-16 21:49:18 -0600358 # Start at the first entry in the step list
359 status.step = status.step_list[0]
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700360
Paul Fagerburg042a5252020-03-16 21:49:18 -0600361 # Start an empty map for tracking CL data
362 status.commits = {}
363
364 status.save()
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700365
366 return status
367
368
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700369def perform_step(status):
370 """Call the appropriate function for the current step
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700371
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700372 Args:
373 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700374
375 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700376 True if the step succeeded, False if it failed
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700377 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700378 # Function to call based on the step
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700379 dispatch = {
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700380 step_names.CB_VARIANT: create_coreboot_variant,
381 step_names.CB_CONFIG: create_coreboot_config,
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700382 step_names.CRAS_CONFIG: copy_cras_config,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700383 step_names.ADD_FIT: add_fitimage,
384 step_names.GEN_FIT: gen_fit_image_outside_chroot,
385 step_names.COMMIT_FIT: commit_fitimage,
386 step_names.EC_IMAGE: create_initial_ec_image,
387 step_names.EC_BUILDALL: ec_buildall,
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700388 step_names.ADD_PUB_YAML: add_variant_to_public_yaml,
389 step_names.ADD_PRIV_YAML: add_variant_to_private_yaml,
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700390 step_names.BUILD_YAML: build_yaml,
391 step_names.EMERGE: emerge_all,
392 step_names.PUSH: push_coreboot,
393 step_names.UPLOAD: upload_CLs,
394 step_names.FIND: find_coreboot_upstream,
395 step_names.CQ_DEPEND: add_cq_depends,
396 step_names.CLEAN_UP: clean_up,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600397 step_names.ABORT: abort,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700398 }
399
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700400 if status.step not in dispatch:
401 logging.error('Unknown step "%s", aborting...', status.step)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700402 sys.exit(1)
403
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700404 return dispatch[status.step](status)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700405
406
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700407def move_to_next_step(status):
408 """Move to the next step in the list
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700409
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700410 Args:
411 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700412 """
Paul Fagerburg042a5252020-03-16 21:49:18 -0600413 # Special case: the next step after 'abort' is 'clean_up'. Always.
414 if status.step == step_names.ABORT:
415 status.step = step_names.CLEAN_UP
416 return
417
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700418 if status.step not in status.step_list:
419 logging.error('Unknown step "%s", aborting...', status.step)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700420 sys.exit(1)
421
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700422 idx = status.step_list.index(status.step)
423 if idx == len(status.step_list)-1:
424 status.step = None
Paul Fagerburgdd3e9c32020-01-07 14:00:35 -0700425 else:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700426 status.step = status.step_list[idx+1]
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700427
428
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700429def run_process(args, cwd=None, env=None, capture_output=False):
430 """Run a process, log debug messages, return text output of process
431
432 The capture_output parameter allows us to capture the output when we
433 care about it (and not sending it to the screen), or ignoring it when
434 we don't care, and letting the user see the output so they know that
435 the build is still running, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700436
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700437 Args:
438 args: List of the command and its params
439 cwd: If not None, cd to this directory before running
440 env: Environment to use for execution; if needed, get os.environ.copy()
441 and add variables. If None, just use the current environment
442 capture_output: True if we should capture the stdout, false if we
443 just care about success or not.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700444
445 Returns:
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700446 If capture_output == True, we return the text output from running
447 the subprocess as a list of lines, or None if the process failed.
448 If capture_output == False, we return a True if it successed, or
449 None if the process failed.
450
451 The caller can evaluate as a bool, because bool(None) == False, and
452 bool() of a non-empty list is True, or the caller can use the returned
453 text for further processing.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700454 """
455 logging.debug('Run %s', str(args))
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700456 if cwd is not None:
457 logging.debug('cwd = %s', cwd)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700458 try:
459 if capture_output:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700460 output = subprocess.run(args, cwd=cwd, env=env, check=True,
461 stderr=subprocess.STDOUT, stdout=subprocess.PIPE).stdout
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700462 else:
463 subprocess.run(args, cwd=cwd, env=env, check=True)
464 # Just something to decode so we don't get an empty list
465 output = b'True'
466
467 logging.debug('process returns 0')
468 # Convert from byte string to ASCII
469 decoded = output.decode('utf-8')
470 # Split into array of individual lines
471 lines = decoded.split('\n')
472 return lines
473 except subprocess.CalledProcessError as err:
474 logging.debug('process returns %s', str(err.returncode))
475 return None
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700476
477
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700478def get_git_commit_data(cwd):
479 """Get the branch name and change id of the current commit
480
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700481 Args:
482 cwd: The current working directory, where we want to get the branch
483 name and change id
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700484
485 Returns:
486 Map with 'dir', 'branch_name' and 'change_id' keys. The 'dir'
487 key maps to the value of os.path.expanduser(cwd)
488 """
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700489 cwd = git.FindGitTopLevel(os.path.expanduser(cwd))
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700490 logging.debug('get_git_commit_data(%s)', cwd)
491
492 branch_name = git.GetCurrentBranch(cwd)
493 if branch_name is None:
494 logging.error('Cannot determine git branch name in %s; exiting', cwd)
495 sys.exit(1)
496 logging.debug('git current branch is %s', branch_name)
497
498 change_id = git.GetChangeId(cwd)
499 if change_id is None:
500 logging.error('Cannot determine Change-Id in %s; exiting', cwd)
501 sys.exit(1)
502 logging.debug('git Change-Id is %s', change_id)
503
504 return {
505 'dir': cwd,
506 'branch_name': branch_name,
507 'change_id': change_id
508 }
509
510
Paul Fagerburg75398072020-03-16 13:51:24 -0600511def cros_workon(status, action, workon_pkgs):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700512 """Call cros_workon for all the 9999 ebuilds we'll be touching
513
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700514 Args:
515 status: variant_status object tracking our board, variant, etc.
516 action: 'start' or 'stop'
Paul Fagerburg75398072020-03-16 13:51:24 -0600517 workon_pkgs: list of packages to start or stop
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700518
519 Returns:
520 True if the call to cros_workon was successful, False if failed
521 """
522
523 # Build up the command from all the packages in the list
Paul Fagerburg75398072020-03-16 13:51:24 -0600524 workon_cmd = ['cros_workon', '--board=' + status.base, action] + workon_pkgs
Paul Fagerburg042a5252020-03-16 21:49:18 -0600525 return run_process(workon_cmd)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700526
527
528def create_coreboot_variant(status):
Paul Fagerburge868e832020-01-22 17:14:04 -0700529 """Create source files for a new variant of the reference board in coreboot
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700530
531 This function calls create_coreboot_variant.sh to set up a new variant
Paul Fagerburge868e832020-01-22 17:14:04 -0700532 of the reference board.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700533
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700534 Args:
535 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700536
537 Returns:
538 True if everything succeeded, False if something failed
539 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700540 logging.info('Running step create_coreboot_variant')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700541 cb_src_dir = os.path.join('/mnt/host/source/src/', status.coreboot_dir)
542 environ = os.environ.copy()
543 environ['CB_SRC_DIR'] = cb_src_dir
544 create_coreboot_variant_sh = os.path.join(status.my_loc,
545 'create_coreboot_variant.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600546 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700547 [create_coreboot_variant_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700548 status.base,
Paul Fagerburgabb15622020-02-07 15:41:29 -0700549 status.board,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700550 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600551 status.bug], env=environ)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700552 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700553 status.commits[step_names.CB_VARIANT] = get_git_commit_data(cb_src_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700554 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700555
556
557def create_coreboot_config(status):
558 """Create a coreboot configuration for a new variant
559
560 This function calls create_coreboot_config.sh, which will make a copy
561 of coreboot.${BOARD} into coreboot.${VARIANT}.
562
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700563 Args:
564 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700565
566 Returns:
567 True if the script and test build succeeded, False if something failed
568 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700569 logging.info('Running step create_coreboot_config')
Paul Fagerburg4d343452020-01-24 15:23:53 -0700570 environ = os.environ.copy()
571 if status.cb_config_dir is not None:
572 environ['CB_CONFIG_DIR'] = status.cb_config_dir
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700573 create_coreboot_config_sh = os.path.join(status.my_loc,
574 'create_coreboot_config.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600575 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700576 [create_coreboot_config_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700577 status.base,
578 status.board,
579 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600580 status.bug], env=environ)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700581 if rc:
582 # Use status.cb_config_dir if defined, or if not, use
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700583 # '/mnt/host/source/src/third_party/chromiumos-overlay'
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700584 if status.cb_config_dir is not None:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700585 cb_config_dir = os.path.join('/mnt/host/source/src/', status.cb_config_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700586 else:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700587 cb_config_dir = '/mnt/host/source/src/third_party/chromiumos-overlay'
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700588 status.commits[step_names.CB_CONFIG] = get_git_commit_data(cb_config_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700589 return rc
Paul Fagerburge868e832020-01-22 17:14:04 -0700590
591
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700592def copy_cras_config(status):
593 """Copy the cras config for a new variant
594
595 This is only necessary for the Zork baseboard right now.
596 This function calls copy_cras_config.sh, which will copy the
597 cras config in
598 overlays/overlay-${BASE}/chromeos-base/chromeos-bsp-${BASE}/files/cras-config/${BASE}
599 to .../${VARIANT}
600
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700601 Args:
602 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700603
604 Returns:
605 True if the script and test build succeeded, False if something failed
606 """
607 logging.info('Running step copy_cras_config')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700608 copy_cras_config_sh = os.path.join(status.my_loc, 'copy_cras_config.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600609 rc = run_process(
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700610 [copy_cras_config_sh,
611 status.base,
612 status.board,
613 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600614 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700615 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700616 status.commits[step_names.CRAS_CONFIG] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700617 '/mnt/host/source/src/overlays')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700618 return rc
Paul Fagerburg2fd23f42020-02-07 14:04:48 -0700619
620
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700621def add_fitimage(status):
622 """Add the source files for a fitimage for the new variant
623
624 This function calls add_fitimage.sh to create a new XSL file for the
Paul Fagerburge868e832020-01-22 17:14:04 -0700625 variant's fitimage, which can override settings from the reference board's
626 XSL. When this is done, the user will have to build the fitimage by running
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700627 gen_fit_image.sh outside of the chroot (and outside of this program's
628 control) because gen_fit_image.sh uses WINE, which is not installed in
629 the chroot. (There is a linux version of FIT, but it requires Open GL,
630 which is also not installed in the chroot.)
631
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700632 Args:
633 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700634
635 Returns:
636 True if the script succeeded, False otherwise
637 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700638 logging.info('Running step add_fitimage')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700639 add_fitimage_sh = os.path.expanduser(os.path.join(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700640 '/mnt/host/source/src', status.fitimage_dir, 'files/add_fitimage.sh'))
Paul Fagerburg042a5252020-03-16 21:49:18 -0600641 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700642 [add_fitimage_sh,
643 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600644 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700645 if rc:
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700646 fitimage_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir)
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700647 status.commits[step_names.COMMIT_FIT] = get_git_commit_data(fitimage_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700648 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700649
650
651def gen_fit_image_outside_chroot(status):
652 """Tell the user to run gen_fit_image.sh outside the chroot
653
654 As noted for add_Fitimage(), gen_fit_image.sh cannot run inside the
655 chroot. This function tells the user to run gen_fit_image.sh in
656 their normal environment, and then come back (--continue) when that
657 is done.
658
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700659 Args:
660 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700661
662 Returns:
663 True
664 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700665 logging.info('Running step gen_fit_image_outside_chroot')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700666 fit_image_files = check_fit_image_files(status)
667 # If the list is empty, then `not` of the list is True, so the files
668 # we need are all present and we can continue.
669 if not fit_image_files:
670 return True
671
Paul Fagerburgaec8d992020-02-27 15:51:47 -0700672 logging.error('The following files need to be generated:')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700673 for filename in fit_image_files:
Paul Fagerburgaec8d992020-02-27 15:51:47 -0700674 logging.error('* %s', filename)
675 logging.error('The fitimage sources are ready for gen_fit_image.sh to process.')
676 logging.error('gen_fit_image.sh cannot run inside the chroot. Please open a new terminal')
677 logging.error('window, change to the directory where gen_fit_image.sh is located, and run')
678 logging.error(status.fitimage_cmd, status.variant)
679 logging.error('Then re-start this program with --continue.')
680 logging.error('If your chroot is based in ~/chromiumos, then the folder you want is')
681 logging.error('~/chromiumos/src/%s/asset_generation', status.fitimage_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700682 return False
683
684
685def check_fit_image_files(status):
686 """Check if the fitimage has been generated
687
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700688 This function is not called directly as a step, and so it doesn't need
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700689 to produce any error messages to the user (except with --verbose).
690 gen_fit_image_outside_chroot will call this function to see if the
691 fitimage files exist, and if not, then that function will print the
692 message about how the user needs to run gen_fit_image.sh outside the
693 chroot.
694
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700695 Args:
696 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700697
698 Returns:
699 List of files that *DO NOT* exist and need to be created, [] if
700 all files are present.
701 """
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700702 outputs_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir,
703 'asset_generation/outputs')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700704 logging.debug('outputs_dir = "%s"', outputs_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700705
706 files = []
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700707 if not file_exists(outputs_dir, 'fitimage-' + status.variant + '.bin'):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700708 files.append('fitimage-' + status.variant + '.bin')
709
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700710 if not file_exists(outputs_dir,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700711 'fitimage-' + status.variant + '-versions.txt'):
712 files.append('fitimage-' + status.variant + '-versions.txt')
713
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700714 if not file_exists(outputs_dir, 'fit.log'):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700715 files.append('fit.log')
716
717 return files
718
719
720def move_fitimage_file(fitimage_dir, filename):
721 """Move fitimage files from create-place to commit-place
722
723 commit_fitimage needs to move the fitimage files from the place where
724 they were created to a different directory in the tree. This utility
725 function handles joining paths and calling a file move function.
726
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700727 Args:
728 fitimage_dir: Directory where the fitimage files are
729 filename: Name of the file being moved
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700730
731 Returns:
732 True if the move succeeded, False if it failed
733 """
734 src_dir = os.path.join(fitimage_dir, 'asset_generation/outputs')
735 src = os.path.join(src_dir, filename)
736 dest_dir = os.path.join(fitimage_dir, 'files')
737 dest = os.path.join(dest_dir, filename)
738 # If src does not exist and dest does, the move is already done => success!
739 if not file_exists(src_dir, filename) and file_exists(dest_dir, filename):
740 logging.debug('move "%s", "%s" unnecessary because dest exists and'
741 ' src does not exist', src, dest)
742 return True
743
744 logging.debug('move "%s", "%s"', src, dest)
745 return shutil.move(src, dest)
746
747
748def commit_fitimage(status):
749 """Move the fitimage files and add them to a git commit
750
751 This function moves the fitimage binary and -versions files from
752 asset_generation/outputs to files/ and then adds those files and
753 fit.log to the existing git commit.
754
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700755 Args:
756 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700757
758 Returns:
759 True if the copy, git add, and git commit --amend all succeeded.
760 False if something failed.
761 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700762 logging.info('Running step commit_fitimage')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700763 fitimage_dir = os.path.join('/mnt/host/source/src', status.fitimage_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700764 logging.debug('fitimage_dir = "%s"', fitimage_dir)
765
766 # The copy operation will check that the source file exists, so no
767 # need to check separately.
768 if not move_fitimage_file(fitimage_dir,
769 'fitimage-' + status.variant + '.bin'):
770 logging.error('Moving fitimage binary failed')
771 return False
772
773 if not move_fitimage_file(fitimage_dir,
774 'fitimage-' + status.variant + '-versions.txt'):
775 logging.error('Moving fitimage versions.txt failed')
776 return False
777
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700778 # TODO(pfagerburg) volteer also needs files/blobs/descriptor-${VARIANT}.bin
Paul Fagerburg042a5252020-03-16 21:49:18 -0600779 if not run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700780 ['git', 'add',
781 'asset_generation/outputs/fit.log',
782 'files/fitimage-' + status.variant + '.bin',
783 'files/fitimage-' + status.variant + '-versions.txt'
784 ],
Paul Fagerburg042a5252020-03-16 21:49:18 -0600785 cwd=fitimage_dir):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700786 return False
787
Paul Fagerburg042a5252020-03-16 21:49:18 -0600788 return run_process(['git', 'commit', '--amend', '--no-edit'],
789 cwd=fitimage_dir)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700790
791
792def create_initial_ec_image(status):
Paul Fagerburge868e832020-01-22 17:14:04 -0700793 """Create an EC image for the variant as a clone of the reference board
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700794
795 This function calls create_initial_ec_image.sh, which will clone the
Paul Fagerburge868e832020-01-22 17:14:04 -0700796 reference board to create the variant. The shell script will build the
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700797 EC code for the variant, but the repo upload hook insists that we
798 have done a `make buildall` before it will allow an upload, so this
799 function does the buildall.
800
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700801 Args:
802 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700803
804 Returns:
805 True if the script and test build succeeded, False if something failed
806 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700807 logging.info('Running step create_initial_ec_image')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700808 create_initial_ec_image_sh = os.path.join(status.my_loc,
809 'create_initial_ec_image.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600810 if not run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700811 [create_initial_ec_image_sh,
812 status.board,
813 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600814 status.bug]):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700815 return False
816
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700817 # No need to `if rc:` because we already tested the run_process result above
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700818 status.commits[step_names.EC_IMAGE] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700819 '/mnt/host/source/src/platform/ec/board')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700820
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700821 # create_initial_ec_image.sh will build the ec.bin for this variant
822 # if successful.
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700823 ec = '/mnt/host/source/src/platform/ec'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700824 logging.debug('ec = "%s"', ec)
Paul Fagerburg59834f42020-03-24 14:37:09 -0600825 ec_bin = os.path.join('build', status.variant, 'ec.bin')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700826 logging.debug('ec.bin = "%s"', ec_bin)
827
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700828 if not file_exists(ec, ec_bin):
829 logging.error('EC binary %s not found', ec_bin)
830 return False
831 return True
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700832
833
834def ec_buildall(status):
835 """Do a make buildall -j for the EC, which is required for repo upload
836
837 The upload hook checks to ensure that the entire EC codebase builds
838 without error, so we have to run make buildall -j before uploading.
839
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700840 Args:
841 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700842
843 Returns:
844 True if the script and test build succeeded, False if something failed
845 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700846 logging.info('Running step ec_buildall')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700847 del status # unused parameter
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700848 ec = '/mnt/host/source/src/platform/ec'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700849 logging.debug('ec = "%s"', ec)
Paul Fagerburg042a5252020-03-16 21:49:18 -0600850 return run_process(['make', 'buildall', '-j'], cwd=ec)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700851
852
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700853def add_variant_to_public_yaml(status):
854 """Add the new variant to the public model.yaml file
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700855
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700856 This function calls add_variant_to_yaml.sh to add the new variant to
857 the public model.yaml file.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700858
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700859 Args:
860 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700861
862 Returns:
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700863 True if the script succeeded, False is something failed
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700864 """
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700865 logging.info('Running step add_variant_to_public_yaml')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700866 add_variant_to_yaml_sh = os.path.join(status.my_loc,
867 'add_variant_to_yaml.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600868 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700869 [add_variant_to_yaml_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700870 status.base,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700871 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600872 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700873 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700874 status.commits[step_names.ADD_PUB_YAML] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700875 '/mnt/host/source/src/overlays')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700876 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700877
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700878
879def add_variant_to_private_yaml(status):
880 """Add the new variant to the private model.yaml file
881
882 This function calls add_variant.sh to add the new variant to
883 the private model.yaml file.
884
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700885 Args:
886 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700887
888 Returns:
889 True if the script succeeded, False is something failed
890 """
891 logging.info('Running step add_variant_to_private_yaml')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700892 add_variant_sh = os.path.expanduser(os.path.join(status.private_yaml_dir, 'add_variant.sh'))
Paul Fagerburg042a5252020-03-16 21:49:18 -0600893 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700894 [add_variant_sh,
895 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600896 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700897 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700898 status.commits[step_names.ADD_PRIV_YAML] = get_git_commit_data(status.private_yaml_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700899 return rc
900
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700901
902
903def build_yaml(status):
904 """Build config files from the yaml files
905
906 This function builds the yaml files into the JSON and C code that
907 mosys and other tools use, then verifies that the new variant's name
908 shows up in all of the output files.
909
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700910 Args:
911 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700912
913 Returns:
914 True if the scripts and build succeeded, False is something failed
915 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700916 logging.info('Running step build_yaml')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600917 if not run_process([status.emerge_cmd] + status.yaml_emerge_pkgs):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700918 return False
919
920 # Check generated files for occurences of the variant name.
921 # Each file should have at least one occurence, so use `grep -c` to
922 # count the occurrences of the variant name in each file.
923 # The results will be something like this:
924 # config.json:10
925 # yaml/config.c:6
926 # yaml/config.yaml:27
927 # yaml/model.yaml:6
928 # yaml/private-model.yaml:10
929 # If the variant name doesn't show up in the file, then the count
930 # will be 0, so we would see, e.g.
931 # config.json:0
Paul Fagerburge868e832020-01-22 17:14:04 -0700932 # Note that we leave out yaml/model.yaml (the public one) because for
933 # some boards, there is nothing in the public yaml file.
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700934 # We gather the output from grep, then look for any of the strings
935 # ending in :0. If none of them match, then we're good, but if even
936 # one of them ends with :0 then there was a problem with generating
937 # the files from the yaml.
Paul Fagerburge868e832020-01-22 17:14:04 -0700938 chromeos_config = '/build/' + status.base + '/usr/share/chromeos-config'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700939 logging.debug('chromeos_config = "%s"', chromeos_config)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700940 grep = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700941 ['grep',
Paul Fagerburge868e832020-01-22 17:14:04 -0700942 '-ci',
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700943 status.variant,
944 'config.json',
945 'yaml/config.c',
946 'yaml/config.yaml',
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700947 'yaml/private-model.yaml'], cwd=chromeos_config, capture_output=True)
948
949 if grep is None:
950 return False
951
Paul Fagerburg042a5252020-03-16 21:49:18 -0600952 return not [s for s in grep if re.search(r':0$', s)]
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700953
954
955def emerge_all(status):
956 """Build the coreboot BIOS and EC code for the new variant
957
Paul Fagerburg75398072020-03-16 13:51:24 -0600958 This build step will cros_workon start a list of packages provided by
959 the reference board data as status.workon_pkgs, then emerge a list of
960 packages (status.emerge_pkgs), and then cros_workon stop any packages
961 that it started, as opposed to ones that were already being worked on.
962
963 To determine which packages this program started and which ones were
964 already started, we query the list of packages being worked on, then
965 cros_workon start the entire list (which will produce a "package already
966 being worked on" type of message for anything already started), and then
967 query the list of packages being worked on again. The difference between
968 the before and after lists are the packages that this program started,
969 and so that's the list of packages to cros_workon stop after the emerge
970 is done.
971
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700972 Args:
973 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700974
975 Returns:
976 True if the build succeeded, False if something failed
977 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700978 logging.info('Running step emerge_all')
Paul Fagerburg75398072020-03-16 13:51:24 -0600979 # Get the list of packages that are already cros_workon started.
980 build_target = BuildTarget(status.base)
981 workon = workon_helper.WorkonHelper(build_target.root, build_target.name)
982 before_workon = workon.ListAtoms()
983
984 # Start working on the list of packages specified by the reference board.
985 cros_workon(status, 'start', status.workon_pkgs)
986
987 # Get the list of packages that are cros_workon started now.
988 after_workon = workon.ListAtoms()
989 # Determine which packages we need to cros_workon stop.
990 stop_packages = list(set(after_workon) - set(before_workon))
991
992 # Build up the command for emerge from all the packages in the list.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700993 environ = os.environ.copy()
994 environ['FW_NAME'] = status.variant
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700995 emerge_cmd_and_params = [status.emerge_cmd] + status.emerge_pkgs
Paul Fagerburg042a5252020-03-16 21:49:18 -0600996 emerge_result = run_process(emerge_cmd_and_params, env=environ)
Paul Fagerburg75398072020-03-16 13:51:24 -0600997
998 # cros_workon stop before possibly returning an error code.
999 cros_workon(status, 'stop', stop_packages)
1000
1001 # Check if emerge failed, and then check if the expected build outputs
1002 # exist.
1003 if not emerge_result:
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001004 return False
1005
Paul Fagerburge868e832020-01-22 17:14:04 -07001006 build_path = '/build/' + status.base + '/firmware'
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001007 logging.debug('build_path = "%s"', build_path)
1008 if not file_exists(build_path, 'image-' + status.variant + '.bin'):
1009 logging.error('emerge failed because image-%s.bin does not exist',
1010 status.variant)
1011 return False
1012
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001013 if not file_exists(build_path, 'image-' + status.variant + '.serial.bin'):
1014 logging.error('emerge failed because image-%s.serial.bin does not exist',
1015 status.variant)
1016 return False
1017
1018 return True
1019
1020
1021def push_coreboot(status):
1022 """Push the coreboot CL to coreboot.org
1023
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001024 Args:
1025 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001026
1027 Returns:
1028 True if the build succeeded, False if something failed
1029 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001030 logging.info('Running step push_coreboot')
Paul Fagerburg8d850932020-02-25 14:13:32 -07001031
1032 # Set up a return code that may change to False if we find that a
1033 # coreboot CL has not been uploaded.
1034 rc = True
1035
1036 for commit_key in status.coreboot_push_list:
1037 logging.debug(f'Processing key {commit_key}')
1038 commit = status.commits[commit_key]
1039 if 'gerrit' not in commit or 'cl_number' not in commit:
1040 change_id = commit['change_id']
1041 cl = find_change_id(change_id)
1042 if cl is not None:
1043 save_cl_data(status, commit_key, cl)
1044 else:
1045 logging.debug(f'Not found {change_id}, need to upload')
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001046 logging.error('The following commit needs to be pushed to coreboot.org:')
1047 logging.error(' Branch "%s"', commit['branch_name'])
1048 logging.error(' in directory "%s"', commit['dir'])
1049 logging.error(' with change-id "%s"', commit['change_id'])
1050 logging.error('Please push the branch to review.coreboot.org, '
1051 'and then re-start this program with --continue')
Paul Fagerburg8d850932020-02-25 14:13:32 -07001052 # Since this commit needs to be uploaded, do not continue after
1053 # this step returns.
1054 rc = False
1055 else:
1056 instance_name = commit['gerrit']
1057 cl_number = commit['cl_number']
1058 logging.debug(f'Already uploaded ({instance_name}, {cl_number})')
1059
1060 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001061
1062
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001063def query_gerrit(instance, change_id):
1064 """Search a gerrit instance for a specific change_id
1065
1066 Args:
1067 instance: gerrit instance to query. Suitable values come from
1068 gerrit.GetCrosInternal() and gerrit.GetCrosExternal()
1069 change_id: The change_id to search for
1070
1071 Returns:
1072 CL number if found, None if not
1073 """
1074 raw = instance.Query(change=change_id, raw=True)
1075 if raw:
1076 # If the CL was found by change_id, there will be only one,
1077 # because the change_id is used to recognize a new patchset
1078 # on an existing CL.
1079 return raw[0]['number']
1080
1081 return None
1082
1083
Paul Fagerburg8d850932020-02-25 14:13:32 -07001084def query_coreboot_gerrit(change_id):
1085 """Search the coreboot gerrit for a specific change_id
1086
1087 Use the REST API to look for the change_id. See
1088 https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html
1089 for details on the REST API to search for a change-id.
1090
1091 We can't use query_gerrit with a manually constructed GerritHelper
1092 because we need the user's private SSH key to access review.coreboot.org,
1093 but these are not available inside the chroot.
1094
1095 Args:
1096 change_id: The change_id to search for
1097
1098 Returns:
1099 CL number if found, None if not
1100 """
1101 r = requests.get('https://review.coreboot.org/changes/' + change_id)
1102 response = r.content.decode('utf-8')
1103 # Check if the response starts with 'Not found', in which case return None
1104 if response.startswith('Not found:'):
1105 return None
1106 # Strip off the initial )]}'\n that is used as XSS protections, see
1107 # https://gerrit-review.googlesource.com/Documentation/rest-api.html#output
1108 # and decode as JSON.
1109 data = json.loads(response[5:])
1110 if '_number' in data:
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001111 return str(data['_number'])
Paul Fagerburg8d850932020-02-25 14:13:32 -07001112 return None
1113
1114
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001115def find_change_id(change_id):
1116 """Search the public and private ChromeOS gerrit instances for a change-id
1117
1118 Args:
1119 change_id: Change-Id to search for in both gerrit instances
1120
1121 Returns:
1122 Tuple of the gerrit instance ('chromium' or 'chrome-internal') and
1123 the CL number if the Change-Id is found.
1124 None if not found.
1125 """
1126 cl_number = query_gerrit(gerrit.GetCrosExternal(), change_id)
1127 if cl_number:
1128 return 'chromium', cl_number
1129 cl_number = query_gerrit(gerrit.GetCrosInternal(), change_id)
1130 if cl_number:
1131 return 'chrome-internal', cl_number
Paul Fagerburg8d850932020-02-25 14:13:32 -07001132 cl_number = query_coreboot_gerrit(change_id)
1133 if cl_number:
1134 return 'coreboot', cl_number
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001135 return None
1136
1137
1138def save_cl_data(status, commit_key, cl):
1139 """Save the gerrit instance and CL number to the yaml file
1140
1141 Args:
1142 status: variant_status object tracking our board, variant, etc.
1143 commit_key: Which key in the commits map we're processing
1144 cl: Value returned by find_change_id, should be a tuple
1145 of instance_name, cl_number
1146 """
1147 instance_name, cl_number = cl
1148 print(f'Found ({instance_name}, {cl_number}), saving to yaml')
1149 status.commits[commit_key]['gerrit'] = instance_name
1150 status.commits[commit_key]['cl_number'] = cl_number
1151 status.save()
1152
1153
1154def repo_upload(branch_name, cwd):
1155 """Upload a branch to gerrit
1156
1157 This function runs `repo upload` in the specified directory to upload
1158 a branch to gerrit. Because it's operating in a directory and with a
1159 branch name, it could upload more than one commit, which is OK because
1160 we'll look for each commit by change-id before trying to upload in that
1161 directory. For example, this happens in Zork, where the cb_config step
1162 and the cras_config step both have a commit in src/overlays. When we're
1163 processing the cb_config step and we `repo upload` in src/overlays, it
1164 will also upload the commit for cras_config. Then we come around to the
1165 cras_config step, and since we can find a CL with the change-id, we don't
1166 try to upload again.
1167
1168 Args:
1169 branch_name: the name of the branch to upload. Gets passed to
1170 repo upload with the --br flag
1171 cwd: directory where we want to upload. Gets set as the working
1172 directory for executing repo upload.
1173
1174 Returns:
1175 True if repo upload exits with a successful error code, false otherwise
1176 """
Paul Fagerburg042a5252020-03-16 21:49:18 -06001177 return run_process(
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001178 ['repo',
1179 'upload',
1180 '.',
1181 '--br=' + branch_name,
1182 '--wip',
1183 '--verify',
1184 '--yes'],
Paul Fagerburg042a5252020-03-16 21:49:18 -06001185 cwd=cwd)
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001186
1187
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001188def upload_CLs(status):
1189 """Upload all CLs to chromiumos
1190
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001191 Args:
1192 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001193
1194 Returns:
1195 True if the build succeeded, False if something failed
1196 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001197 logging.info('Running step upload_CLs')
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001198
1199 for commit_key in status.repo_upload_list:
1200 logging.debug(f'Processing key {commit_key}')
1201 commit = status.commits[commit_key]
1202 if 'gerrit' not in commit or 'cl_number' not in commit:
1203 change_id = commit['change_id']
1204 cl = find_change_id(change_id)
1205 if cl is not None:
1206 save_cl_data(status, commit_key, cl)
1207 else:
1208 logging.debug(f'Not found {change_id}, need to upload')
1209 if not repo_upload(commit['branch_name'], commit['dir']):
1210 branch_name = commit['branch_name']
1211 dirname = commit['dir']
1212 logging.error(f'Repo upload {branch_name} in {dirname} failed!')
1213 return False
1214 cl = find_change_id(change_id)
1215 if cl is None:
1216 logging.error(f'repo upload {commit_key} succeeded, ' \
1217 'but change_id is not found!')
1218 return False
1219 save_cl_data(status, commit_key, cl)
1220 else:
1221 instance_name = commit['gerrit']
1222 cl_number = commit['cl_number']
1223 logging.debug(f'Already uploaded ({instance_name}, {cl_number})')
1224
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001225 return True
1226
1227
1228def find_coreboot_upstream(status):
1229 """Find the coreboot CL after it has been upstreamed to chromiumos
1230
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001231 When the coreboot variant CL is first uploaded to review.coreboot.org,
1232 it is not visible in the chromiumos tree (and also cannot be used as
1233 a target for cq-depend). There is a process for upstreaming CLs from
1234 coreboot after they have been reviewed, approved, and merged. We can
1235 track a specific coreboot CL if we know the change-id that it used on
1236 the coreboot gerrit instance, by looking for that change-id as
1237 'original-change-id' in the public chromium gerrit instance.
1238
1239 The change-id for the coreboot variant will be under the 'cb_variant' key,
1240 but this is for the 'coreboot' gerrit instance.
1241
1242 When we find the upstreamed CL, we will record the gerrit instance and
1243 CL number in the yaml file under the 'find' key ("find upstream coreboot")
1244 so that we don't need to search coreboot again.
1245
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001246 Args:
1247 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001248
1249 Returns:
1250 True if the build succeeded, False if something failed
1251 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001252 logging.info('Running step find_coreboot_upstream')
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001253
1254 # If we have already found the upstream coreboot CL, then exit with success
1255 if step_names.FIND in status.commits:
1256 commit = status.commits[step_names.FIND]
1257 if 'gerrit' in commit and 'cl_number' in commit:
1258 instance_name = commit['gerrit']
1259 cl_number = commit['cl_number']
1260 logging.debug(f'Already found ({instance_name}, {cl_number})')
1261 return True
1262
1263 # Make sure we have a CB_VARIANT commit and a change_id for it
1264 if step_names.CB_VARIANT not in status.commits:
1265 logging.error('Key %s not found in status.commits',
1266 step_names.CB_VARIANT)
1267 return False
1268 if 'change_id' not in status.commits[step_names.CB_VARIANT]:
1269 logging.error('Key change_id not found in status.commits[%s]',
1270 step_names.CB_VARIANT)
1271 return False
1272
1273 # Find the CL by the Original-Change-Id
1274 original_change_id = status.commits[step_names.CB_VARIANT]['change_id']
1275 gerrit_query_args = {
1276 'Original-Change-Id': original_change_id
1277 }
1278 cros = gerrit.GetCrosExternal()
1279 upstream = cros.Query(**gerrit_query_args)
1280 # If nothing is found, the patch hasn't been upstreamed yet
1281 if not upstream:
1282 logging.error('Program cannot continue until coreboot CL is upstreamed.')
1283 logging.error('(coreboot:%s, change-id %s)',
1284 status.commits[step_names.CB_VARIANT]['cl_number'],
1285 status.commits[step_names.CB_VARIANT]['change_id'])
1286 logging.error('Please wait for the CL to be upstreamed, then run this'
1287 ' program again with --continue')
1288 return False
1289
1290 # If more than one CL is found, something is very wrong
1291 if len(upstream) != 1:
1292 logging.error('More than one CL was found with Original-Change-Id %s',
1293 original_change_id)
1294 return False
1295
1296 # At this point, we know there is only one CL and we can get the
1297 # repo and CL number by splitting on the colon between them.
1298 patchlink = upstream[0].PatchLink()
1299 instance_name, cl_number = patchlink.split(':')
1300
1301 # Can't use get_git_commit_data because we're not pulling this
1302 # information from a git commit, but rather from gerrit.
1303 # We only need the gerrit instance and the CL number so we can have
1304 # other CLs cq-depend on this CL. The other keys are not needed because:
1305 # dir - not needed because we're not going to `cd` there to `repo upload`
1306 # branch_name - not valid; the CL is already merged
1307 # change_id - we use the change_id to find a CL number, and since we
1308 # just found the CL number via original-change-id, this is moot.
1309 status.commits[step_names.FIND] = {
1310 'gerrit': instance_name,
1311 'cl_number': str(cl_number)
1312 }
1313
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001314 return True
1315
1316
1317def add_cq_depends(status):
1318 """Add Cq-Depends to all of the CLs in chromiumos
1319
1320 The CL in coreboot needs to be pushed to coreboot.org, get merged,
1321 and then get upstreamed into the chromiumos tree before the other
1322 CLs can cq-depend on it and pass CQ.
1323
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001324 Args:
1325 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001326
1327 Returns:
1328 True if the build succeeded, False if something failed
1329 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001330 logging.info('Running step add_cq_depends')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001331 del status # unused parameter
1332 logging.error('TODO (pfagerburg): implement add_cq_depends')
1333 return True
1334
1335
1336def clean_up(status):
1337 """Final clean-up, including delete the status file
1338
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001339 Args:
1340 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001341
1342 Returns:
1343 True
1344 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001345 logging.info('Running step clean_up')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001346 status.rm()
1347 return True
1348
1349
Paul Fagerburg042a5252020-03-16 21:49:18 -06001350def abort(status):
1351 """Abort the creation of a new variant by abandoning commits
1352
1353 When the user specifies the --abort flag, we override status.step to
1354 be 'abort' and there is no transition from 'abort' to anything else.
1355 We look at status.commits and for each key, see if we have already
1356 been in that directory and abandoned that specific branch. If not,
1357 abandon the commit and then add the branch+dir to a list of abandoned
1358 commits. We do this because some boards (such as Zork) can have multiple
1359 commits in the same directory and with the same branch name, and we only
1360 want to repo abandon that branch once.
1361
1362 Args:
1363 status: variant_status object tracking our board, variant, etc.
1364
1365 Returns:
1366 True
1367 """
1368 logging.info('Running step abort')
1369 # Use the set 'abandoned' to keep track of each branch+dir abandoned.
1370 abandoned = set()
1371 for step in status.commits:
1372 logging.debug('Processing step %s', step)
1373 commit = status.commits[step]
1374 branch = commit['branch_name']
1375 cwd = commit['dir']
1376 if (branch, cwd) in abandoned:
1377 logging.debug('Branch %s in directory %s already abandoned',
1378 branch, cwd)
1379 else:
1380 logging.info('Abandoning branch %s in directory %s',
1381 branch, cwd)
1382 if run_process(['repo', 'abandon', branch, '.'], cwd=cwd):
1383 abandoned.add((branch, cwd))
1384 else:
1385 logging.error('Error while abandoning branch %s', branch)
1386 return False
1387
1388 return True
1389
1390
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001391if __name__ == '__main__':
1392 sys.exit(not int(main()))