"""Custom swarming trigger script for ChromeOS device tests.
CrOS device tests are unique in that the device OS they prefer to run on is
continuously changing. The LKGM file, checked into src at
//chromeos/CHROMEOS_LKGM, represents the ChromeOS version Chrome's ToT aims
to be compatible with. Therefore, a CrOS test for Chrome ideally targets a
device running the LKGM.
Since the LKGM file gets updated frequently (~daily), we can't reasonably
hardcode the LKGM in the test specs. So this special trigger script will read
the current LKGM (at the time of trigger) and append that to the task's
dimensions. If such a device isn't available in time, the task will fallback
to one running any OS.
"""
import argparse
import os
import re
import sys
import base_test_triggerer
SRC_DIR = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
LKGM_FILE_PATH = os.path.join(SRC_DIR, 'chromeos', 'CHROMEOS_LKGM')
LKGM_RE = re.compile(r'\d+\.\d+\.\d+')
PRIMARY_SLICE_EXPIRATION_S = 300
def read_current_lkgm():
if not os.path.exists(LKGM_FILE_PATH):
sys.stderr.write('LKGM file not present at %s\n' % LKGM_FILE_PATH)
return None
with open(LKGM_FILE_PATH) as f:
lkgm = f.read().strip()
if not LKGM_RE.match(lkgm):
sys.stderr.write('Unknown format of LKGM: %s\n' % lkgm)
return None
return lkgm.split('.')[0]
def parse_args(triggerer):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
'-d',
'--dimension',
default=[],
action='append',
nargs=2,
dest='dimensions',
help=
'Dimensions to filter on. Duplicated from the `swarming.py trigger` '
'command. Parsed here to ensure `device_os` is not added.')
parser.add_argument(
'--optional-dimension',
default=[],
action='append',
nargs=3,
dest='optional_dimensions',
help='Optional dimensions which will result in additional task slices. '
'Duplicated from the `swarming.py trigger` command.')
base_test_triggerer.BaseTestTriggerer.setup_parser_contract(parser)
args, additional_args = parser.parse_known_args()
additional_args = triggerer.modify_args(additional_args, 0,
args.shard_index, args.shards,
args.dump_json)
if additional_args[0] != 'trigger':
parser.error(
'This script is only supported for `swarming.py trigger`'
' invocations.'
)
for k, _ in args.dimensions:
if k == 'device_os':
parser.error(
'Must not specify the device_os dimension when using this'
' script. (It will be added automatically.)')
if args.optional_dimensions:
parser.error(
'Must not specify optional dimensions when using this script.')
return args, additional_args
def main():
triggerer = base_test_triggerer.BaseTestTriggerer()
args, additional_args = parse_args(triggerer)
current_lkgm = read_current_lkgm()
if not current_lkgm:
return 1
new_args = additional_args[:1]
needs_device_status = True
for k, v in args.dimensions:
new_args.extend(['--dimension', k, v])
if k == 'device_status':
needs_device_status = False
if needs_device_status:
new_args.extend(['--dimension', 'device_status', 'available'])
new_args.extend([
'-optional-dimension',
'device_os=%s:%d' % (current_lkgm, PRIMARY_SLICE_EXPIRATION_S),
])
new_args += additional_args[1:]
return triggerer.run_swarming_go(new_args, args.dump_json,
args.shard_index or 0, args.shards)
if __name__ == '__main__':
sys.exit(main())