blob: 4dd5013adea42068d2cf4baaa430a85942e46e5a [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 Fagerburga8c7e342020-02-25 13:30:49 -0700825 ec_bin = os.path.join('/build', status.base, 'firmware', status.variant,
826 'ec.bin')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700827 logging.debug('ec.bin = "%s"', ec_bin)
828
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700829 if not file_exists(ec, ec_bin):
830 logging.error('EC binary %s not found', ec_bin)
831 return False
832 return True
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700833
834
835def ec_buildall(status):
836 """Do a make buildall -j for the EC, which is required for repo upload
837
838 The upload hook checks to ensure that the entire EC codebase builds
839 without error, so we have to run make buildall -j before uploading.
840
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700841 Args:
842 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700843
844 Returns:
845 True if the script and test build succeeded, False if something failed
846 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700847 logging.info('Running step ec_buildall')
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700848 del status # unused parameter
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700849 ec = '/mnt/host/source/src/platform/ec'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700850 logging.debug('ec = "%s"', ec)
Paul Fagerburg042a5252020-03-16 21:49:18 -0600851 return run_process(['make', 'buildall', '-j'], cwd=ec)
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700852
853
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700854def add_variant_to_public_yaml(status):
855 """Add the new variant to the public model.yaml file
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700856
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700857 This function calls add_variant_to_yaml.sh to add the new variant to
858 the public model.yaml file.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700859
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700860 Args:
861 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700862
863 Returns:
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700864 True if the script succeeded, False is something failed
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700865 """
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700866 logging.info('Running step add_variant_to_public_yaml')
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700867 add_variant_to_yaml_sh = os.path.join(status.my_loc,
868 'add_variant_to_yaml.sh')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600869 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700870 [add_variant_to_yaml_sh,
Paul Fagerburge868e832020-01-22 17:14:04 -0700871 status.base,
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700872 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600873 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700874 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700875 status.commits[step_names.ADD_PUB_YAML] = get_git_commit_data(
Paul Fagerburg5f794bf2020-02-12 13:01:36 -0700876 '/mnt/host/source/src/overlays')
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700877 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700878
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700879
880def add_variant_to_private_yaml(status):
881 """Add the new variant to the private model.yaml file
882
883 This function calls add_variant.sh to add the new variant to
884 the private model.yaml file.
885
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700886 Args:
887 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700888
889 Returns:
890 True if the script succeeded, False is something failed
891 """
892 logging.info('Running step add_variant_to_private_yaml')
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700893 add_variant_sh = os.path.expanduser(os.path.join(status.private_yaml_dir, 'add_variant.sh'))
Paul Fagerburg042a5252020-03-16 21:49:18 -0600894 rc = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700895 [add_variant_sh,
896 status.variant,
Paul Fagerburg042a5252020-03-16 21:49:18 -0600897 status.bug])
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700898 if rc:
Paul Fagerburga8c7e342020-02-25 13:30:49 -0700899 status.commits[step_names.ADD_PRIV_YAML] = get_git_commit_data(status.private_yaml_dir)
Paul Fagerburg1d043c32020-02-03 08:57:08 -0700900 return rc
901
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700902
903
904def build_yaml(status):
905 """Build config files from the yaml files
906
907 This function builds the yaml files into the JSON and C code that
908 mosys and other tools use, then verifies that the new variant's name
909 shows up in all of the output files.
910
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700911 Args:
912 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700913
914 Returns:
915 True if the scripts and build succeeded, False is something failed
916 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700917 logging.info('Running step build_yaml')
Paul Fagerburg042a5252020-03-16 21:49:18 -0600918 if not run_process([status.emerge_cmd] + status.yaml_emerge_pkgs):
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700919 return False
920
921 # Check generated files for occurences of the variant name.
922 # Each file should have at least one occurence, so use `grep -c` to
923 # count the occurrences of the variant name in each file.
924 # The results will be something like this:
925 # config.json:10
926 # yaml/config.c:6
927 # yaml/config.yaml:27
928 # yaml/model.yaml:6
929 # yaml/private-model.yaml:10
930 # If the variant name doesn't show up in the file, then the count
931 # will be 0, so we would see, e.g.
932 # config.json:0
Paul Fagerburge868e832020-01-22 17:14:04 -0700933 # Note that we leave out yaml/model.yaml (the public one) because for
934 # some boards, there is nothing in the public yaml file.
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700935 # We gather the output from grep, then look for any of the strings
936 # ending in :0. If none of them match, then we're good, but if even
937 # one of them ends with :0 then there was a problem with generating
938 # the files from the yaml.
Paul Fagerburge868e832020-01-22 17:14:04 -0700939 chromeos_config = '/build/' + status.base + '/usr/share/chromeos-config'
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700940 logging.debug('chromeos_config = "%s"', chromeos_config)
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700941 grep = run_process(
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700942 ['grep',
Paul Fagerburge868e832020-01-22 17:14:04 -0700943 '-ci',
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700944 status.variant,
945 'config.json',
946 'yaml/config.c',
947 'yaml/config.yaml',
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700948 'yaml/private-model.yaml'], cwd=chromeos_config, capture_output=True)
949
950 if grep is None:
951 return False
952
Paul Fagerburg042a5252020-03-16 21:49:18 -0600953 return not [s for s in grep if re.search(r':0$', s)]
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700954
955
956def emerge_all(status):
957 """Build the coreboot BIOS and EC code for the new variant
958
Paul Fagerburg75398072020-03-16 13:51:24 -0600959 This build step will cros_workon start a list of packages provided by
960 the reference board data as status.workon_pkgs, then emerge a list of
961 packages (status.emerge_pkgs), and then cros_workon stop any packages
962 that it started, as opposed to ones that were already being worked on.
963
964 To determine which packages this program started and which ones were
965 already started, we query the list of packages being worked on, then
966 cros_workon start the entire list (which will produce a "package already
967 being worked on" type of message for anything already started), and then
968 query the list of packages being worked on again. The difference between
969 the before and after lists are the packages that this program started,
970 and so that's the list of packages to cros_workon stop after the emerge
971 is done.
972
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -0700973 Args:
974 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700975
976 Returns:
977 True if the build succeeded, False if something failed
978 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700979 logging.info('Running step emerge_all')
Paul Fagerburg75398072020-03-16 13:51:24 -0600980 # Get the list of packages that are already cros_workon started.
981 build_target = BuildTarget(status.base)
982 workon = workon_helper.WorkonHelper(build_target.root, build_target.name)
983 before_workon = workon.ListAtoms()
984
985 # Start working on the list of packages specified by the reference board.
986 cros_workon(status, 'start', status.workon_pkgs)
987
988 # Get the list of packages that are cros_workon started now.
989 after_workon = workon.ListAtoms()
990 # Determine which packages we need to cros_workon stop.
991 stop_packages = list(set(after_workon) - set(before_workon))
992
993 # Build up the command for emerge from all the packages in the list.
Paul Fagerburg3b534f92019-11-07 15:05:22 -0700994 environ = os.environ.copy()
995 environ['FW_NAME'] = status.variant
Paul Fagerburgbab5dde2020-01-10 15:10:29 -0700996 emerge_cmd_and_params = [status.emerge_cmd] + status.emerge_pkgs
Paul Fagerburg042a5252020-03-16 21:49:18 -0600997 emerge_result = run_process(emerge_cmd_and_params, env=environ)
Paul Fagerburg75398072020-03-16 13:51:24 -0600998
999 # cros_workon stop before possibly returning an error code.
1000 cros_workon(status, 'stop', stop_packages)
1001
1002 # Check if emerge failed, and then check if the expected build outputs
1003 # exist.
1004 if not emerge_result:
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001005 return False
1006
Paul Fagerburge868e832020-01-22 17:14:04 -07001007 build_path = '/build/' + status.base + '/firmware'
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001008 logging.debug('build_path = "%s"', build_path)
1009 if not file_exists(build_path, 'image-' + status.variant + '.bin'):
1010 logging.error('emerge failed because image-%s.bin does not exist',
1011 status.variant)
1012 return False
1013
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001014 if not file_exists(build_path, 'image-' + status.variant + '.serial.bin'):
1015 logging.error('emerge failed because image-%s.serial.bin does not exist',
1016 status.variant)
1017 return False
1018
1019 return True
1020
1021
1022def push_coreboot(status):
1023 """Push the coreboot CL to coreboot.org
1024
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001025 Args:
1026 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001027
1028 Returns:
1029 True if the build succeeded, False if something failed
1030 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001031 logging.info('Running step push_coreboot')
Paul Fagerburg8d850932020-02-25 14:13:32 -07001032
1033 # Set up a return code that may change to False if we find that a
1034 # coreboot CL has not been uploaded.
1035 rc = True
1036
1037 for commit_key in status.coreboot_push_list:
1038 logging.debug(f'Processing key {commit_key}')
1039 commit = status.commits[commit_key]
1040 if 'gerrit' not in commit or 'cl_number' not in commit:
1041 change_id = commit['change_id']
1042 cl = find_change_id(change_id)
1043 if cl is not None:
1044 save_cl_data(status, commit_key, cl)
1045 else:
1046 logging.debug(f'Not found {change_id}, need to upload')
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001047 logging.error('The following commit needs to be pushed to coreboot.org:')
1048 logging.error(' Branch "%s"', commit['branch_name'])
1049 logging.error(' in directory "%s"', commit['dir'])
1050 logging.error(' with change-id "%s"', commit['change_id'])
1051 logging.error('Please push the branch to review.coreboot.org, '
1052 'and then re-start this program with --continue')
Paul Fagerburg8d850932020-02-25 14:13:32 -07001053 # Since this commit needs to be uploaded, do not continue after
1054 # this step returns.
1055 rc = False
1056 else:
1057 instance_name = commit['gerrit']
1058 cl_number = commit['cl_number']
1059 logging.debug(f'Already uploaded ({instance_name}, {cl_number})')
1060
1061 return rc
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001062
1063
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001064def query_gerrit(instance, change_id):
1065 """Search a gerrit instance for a specific change_id
1066
1067 Args:
1068 instance: gerrit instance to query. Suitable values come from
1069 gerrit.GetCrosInternal() and gerrit.GetCrosExternal()
1070 change_id: The change_id to search for
1071
1072 Returns:
1073 CL number if found, None if not
1074 """
1075 raw = instance.Query(change=change_id, raw=True)
1076 if raw:
1077 # If the CL was found by change_id, there will be only one,
1078 # because the change_id is used to recognize a new patchset
1079 # on an existing CL.
1080 return raw[0]['number']
1081
1082 return None
1083
1084
Paul Fagerburg8d850932020-02-25 14:13:32 -07001085def query_coreboot_gerrit(change_id):
1086 """Search the coreboot gerrit for a specific change_id
1087
1088 Use the REST API to look for the change_id. See
1089 https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html
1090 for details on the REST API to search for a change-id.
1091
1092 We can't use query_gerrit with a manually constructed GerritHelper
1093 because we need the user's private SSH key to access review.coreboot.org,
1094 but these are not available inside the chroot.
1095
1096 Args:
1097 change_id: The change_id to search for
1098
1099 Returns:
1100 CL number if found, None if not
1101 """
1102 r = requests.get('https://review.coreboot.org/changes/' + change_id)
1103 response = r.content.decode('utf-8')
1104 # Check if the response starts with 'Not found', in which case return None
1105 if response.startswith('Not found:'):
1106 return None
1107 # Strip off the initial )]}'\n that is used as XSS protections, see
1108 # https://gerrit-review.googlesource.com/Documentation/rest-api.html#output
1109 # and decode as JSON.
1110 data = json.loads(response[5:])
1111 if '_number' in data:
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001112 return str(data['_number'])
Paul Fagerburg8d850932020-02-25 14:13:32 -07001113 return None
1114
1115
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001116def find_change_id(change_id):
1117 """Search the public and private ChromeOS gerrit instances for a change-id
1118
1119 Args:
1120 change_id: Change-Id to search for in both gerrit instances
1121
1122 Returns:
1123 Tuple of the gerrit instance ('chromium' or 'chrome-internal') and
1124 the CL number if the Change-Id is found.
1125 None if not found.
1126 """
1127 cl_number = query_gerrit(gerrit.GetCrosExternal(), change_id)
1128 if cl_number:
1129 return 'chromium', cl_number
1130 cl_number = query_gerrit(gerrit.GetCrosInternal(), change_id)
1131 if cl_number:
1132 return 'chrome-internal', cl_number
Paul Fagerburg8d850932020-02-25 14:13:32 -07001133 cl_number = query_coreboot_gerrit(change_id)
1134 if cl_number:
1135 return 'coreboot', cl_number
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001136 return None
1137
1138
1139def save_cl_data(status, commit_key, cl):
1140 """Save the gerrit instance and CL number to the yaml file
1141
1142 Args:
1143 status: variant_status object tracking our board, variant, etc.
1144 commit_key: Which key in the commits map we're processing
1145 cl: Value returned by find_change_id, should be a tuple
1146 of instance_name, cl_number
1147 """
1148 instance_name, cl_number = cl
1149 print(f'Found ({instance_name}, {cl_number}), saving to yaml')
1150 status.commits[commit_key]['gerrit'] = instance_name
1151 status.commits[commit_key]['cl_number'] = cl_number
1152 status.save()
1153
1154
1155def repo_upload(branch_name, cwd):
1156 """Upload a branch to gerrit
1157
1158 This function runs `repo upload` in the specified directory to upload
1159 a branch to gerrit. Because it's operating in a directory and with a
1160 branch name, it could upload more than one commit, which is OK because
1161 we'll look for each commit by change-id before trying to upload in that
1162 directory. For example, this happens in Zork, where the cb_config step
1163 and the cras_config step both have a commit in src/overlays. When we're
1164 processing the cb_config step and we `repo upload` in src/overlays, it
1165 will also upload the commit for cras_config. Then we come around to the
1166 cras_config step, and since we can find a CL with the change-id, we don't
1167 try to upload again.
1168
1169 Args:
1170 branch_name: the name of the branch to upload. Gets passed to
1171 repo upload with the --br flag
1172 cwd: directory where we want to upload. Gets set as the working
1173 directory for executing repo upload.
1174
1175 Returns:
1176 True if repo upload exits with a successful error code, false otherwise
1177 """
Paul Fagerburg042a5252020-03-16 21:49:18 -06001178 return run_process(
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001179 ['repo',
1180 'upload',
1181 '.',
1182 '--br=' + branch_name,
1183 '--wip',
1184 '--verify',
1185 '--yes'],
Paul Fagerburg042a5252020-03-16 21:49:18 -06001186 cwd=cwd)
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001187
1188
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001189def upload_CLs(status):
1190 """Upload all CLs to chromiumos
1191
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001192 Args:
1193 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001194
1195 Returns:
1196 True if the build succeeded, False if something failed
1197 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001198 logging.info('Running step upload_CLs')
Paul Fagerburga8c7e342020-02-25 13:30:49 -07001199
1200 for commit_key in status.repo_upload_list:
1201 logging.debug(f'Processing key {commit_key}')
1202 commit = status.commits[commit_key]
1203 if 'gerrit' not in commit or 'cl_number' not in commit:
1204 change_id = commit['change_id']
1205 cl = find_change_id(change_id)
1206 if cl is not None:
1207 save_cl_data(status, commit_key, cl)
1208 else:
1209 logging.debug(f'Not found {change_id}, need to upload')
1210 if not repo_upload(commit['branch_name'], commit['dir']):
1211 branch_name = commit['branch_name']
1212 dirname = commit['dir']
1213 logging.error(f'Repo upload {branch_name} in {dirname} failed!')
1214 return False
1215 cl = find_change_id(change_id)
1216 if cl is None:
1217 logging.error(f'repo upload {commit_key} succeeded, ' \
1218 'but change_id is not found!')
1219 return False
1220 save_cl_data(status, commit_key, cl)
1221 else:
1222 instance_name = commit['gerrit']
1223 cl_number = commit['cl_number']
1224 logging.debug(f'Already uploaded ({instance_name}, {cl_number})')
1225
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001226 return True
1227
1228
1229def find_coreboot_upstream(status):
1230 """Find the coreboot CL after it has been upstreamed to chromiumos
1231
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001232 When the coreboot variant CL is first uploaded to review.coreboot.org,
1233 it is not visible in the chromiumos tree (and also cannot be used as
1234 a target for cq-depend). There is a process for upstreaming CLs from
1235 coreboot after they have been reviewed, approved, and merged. We can
1236 track a specific coreboot CL if we know the change-id that it used on
1237 the coreboot gerrit instance, by looking for that change-id as
1238 'original-change-id' in the public chromium gerrit instance.
1239
1240 The change-id for the coreboot variant will be under the 'cb_variant' key,
1241 but this is for the 'coreboot' gerrit instance.
1242
1243 When we find the upstreamed CL, we will record the gerrit instance and
1244 CL number in the yaml file under the 'find' key ("find upstream coreboot")
1245 so that we don't need to search coreboot again.
1246
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001247 Args:
1248 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001249
1250 Returns:
1251 True if the build succeeded, False if something failed
1252 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001253 logging.info('Running step find_coreboot_upstream')
Paul Fagerburgaec8d992020-02-27 15:51:47 -07001254
1255 # If we have already found the upstream coreboot CL, then exit with success
1256 if step_names.FIND in status.commits:
1257 commit = status.commits[step_names.FIND]
1258 if 'gerrit' in commit and 'cl_number' in commit:
1259 instance_name = commit['gerrit']
1260 cl_number = commit['cl_number']
1261 logging.debug(f'Already found ({instance_name}, {cl_number})')
1262 return True
1263
1264 # Make sure we have a CB_VARIANT commit and a change_id for it
1265 if step_names.CB_VARIANT not in status.commits:
1266 logging.error('Key %s not found in status.commits',
1267 step_names.CB_VARIANT)
1268 return False
1269 if 'change_id' not in status.commits[step_names.CB_VARIANT]:
1270 logging.error('Key change_id not found in status.commits[%s]',
1271 step_names.CB_VARIANT)
1272 return False
1273
1274 # Find the CL by the Original-Change-Id
1275 original_change_id = status.commits[step_names.CB_VARIANT]['change_id']
1276 gerrit_query_args = {
1277 'Original-Change-Id': original_change_id
1278 }
1279 cros = gerrit.GetCrosExternal()
1280 upstream = cros.Query(**gerrit_query_args)
1281 # If nothing is found, the patch hasn't been upstreamed yet
1282 if not upstream:
1283 logging.error('Program cannot continue until coreboot CL is upstreamed.')
1284 logging.error('(coreboot:%s, change-id %s)',
1285 status.commits[step_names.CB_VARIANT]['cl_number'],
1286 status.commits[step_names.CB_VARIANT]['change_id'])
1287 logging.error('Please wait for the CL to be upstreamed, then run this'
1288 ' program again with --continue')
1289 return False
1290
1291 # If more than one CL is found, something is very wrong
1292 if len(upstream) != 1:
1293 logging.error('More than one CL was found with Original-Change-Id %s',
1294 original_change_id)
1295 return False
1296
1297 # At this point, we know there is only one CL and we can get the
1298 # repo and CL number by splitting on the colon between them.
1299 patchlink = upstream[0].PatchLink()
1300 instance_name, cl_number = patchlink.split(':')
1301
1302 # Can't use get_git_commit_data because we're not pulling this
1303 # information from a git commit, but rather from gerrit.
1304 # We only need the gerrit instance and the CL number so we can have
1305 # other CLs cq-depend on this CL. The other keys are not needed because:
1306 # dir - not needed because we're not going to `cd` there to `repo upload`
1307 # branch_name - not valid; the CL is already merged
1308 # change_id - we use the change_id to find a CL number, and since we
1309 # just found the CL number via original-change-id, this is moot.
1310 status.commits[step_names.FIND] = {
1311 'gerrit': instance_name,
1312 'cl_number': str(cl_number)
1313 }
1314
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001315 return True
1316
1317
1318def add_cq_depends(status):
1319 """Add Cq-Depends to all of the CLs in chromiumos
1320
1321 The CL in coreboot needs to be pushed to coreboot.org, get merged,
1322 and then get upstreamed into the chromiumos tree before the other
1323 CLs can cq-depend on it and pass CQ.
1324
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001325 Args:
1326 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001327
1328 Returns:
1329 True if the build succeeded, False if something failed
1330 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001331 logging.info('Running step add_cq_depends')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001332 del status # unused parameter
1333 logging.error('TODO (pfagerburg): implement add_cq_depends')
1334 return True
1335
1336
1337def clean_up(status):
1338 """Final clean-up, including delete the status file
1339
Paul Fagerburg92fcb4b2020-02-19 21:21:43 -07001340 Args:
1341 status: variant_status object tracking our board, variant, etc.
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001342
1343 Returns:
1344 True
1345 """
Paul Fagerburgbab5dde2020-01-10 15:10:29 -07001346 logging.info('Running step clean_up')
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001347 status.rm()
1348 return True
1349
1350
Paul Fagerburg042a5252020-03-16 21:49:18 -06001351def abort(status):
1352 """Abort the creation of a new variant by abandoning commits
1353
1354 When the user specifies the --abort flag, we override status.step to
1355 be 'abort' and there is no transition from 'abort' to anything else.
1356 We look at status.commits and for each key, see if we have already
1357 been in that directory and abandoned that specific branch. If not,
1358 abandon the commit and then add the branch+dir to a list of abandoned
1359 commits. We do this because some boards (such as Zork) can have multiple
1360 commits in the same directory and with the same branch name, and we only
1361 want to repo abandon that branch once.
1362
1363 Args:
1364 status: variant_status object tracking our board, variant, etc.
1365
1366 Returns:
1367 True
1368 """
1369 logging.info('Running step abort')
1370 # Use the set 'abandoned' to keep track of each branch+dir abandoned.
1371 abandoned = set()
1372 for step in status.commits:
1373 logging.debug('Processing step %s', step)
1374 commit = status.commits[step]
1375 branch = commit['branch_name']
1376 cwd = commit['dir']
1377 if (branch, cwd) in abandoned:
1378 logging.debug('Branch %s in directory %s already abandoned',
1379 branch, cwd)
1380 else:
1381 logging.info('Abandoning branch %s in directory %s',
1382 branch, cwd)
1383 if run_process(['repo', 'abandon', branch, '.'], cwd=cwd):
1384 abandoned.add((branch, cwd))
1385 else:
1386 logging.error('Error while abandoning branch %s', branch)
1387 return False
1388
1389 return True
1390
1391
Paul Fagerburg3b534f92019-11-07 15:05:22 -07001392if __name__ == '__main__':
1393 sys.exit(not int(main()))