blob: 06364065f5648795278b72cea3e7a785a778c85b [file] [log] [blame]
Wenbin Zhanga3801ed2022-05-04 21:49:151#!/usr/bin/env python3
Avi Drissmandfd880852022-09-15 20:11:092# Copyright 2019 The Chromium Authors
Ben Pastenea9e583b2019-01-16 02:57:263# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
Ben Pastenea9e583b2019-01-16 02:57:265"""Custom swarming trigger script for ChromeOS device tests.
6
7CrOS device tests are unique in that the device OS they prefer to run on is
8continuously changing. The LKGM file, checked into src at
9//chromeos/CHROMEOS_LKGM, represents the ChromeOS version Chrome's ToT aims
10to be compatible with. Therefore, a CrOS test for Chrome ideally targets a
11device running the LKGM.
12
13Since the LKGM file gets updated frequently (~daily), we can't reasonably
14hardcode the LKGM in the test specs. So this special trigger script will read
15the current LKGM (at the time of trigger) and append that to the task's
16dimensions. If such a device isn't available in time, the task will fallback
17to one running any OS.
18"""
19
20import argparse
21import os
22import re
23import sys
24
25import base_test_triggerer
26
Takuto Ikutac8ebda32021-06-28 15:28:1727SRC_DIR = os.path.dirname(
28 os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
Ben Pastenea9e583b2019-01-16 02:57:2629LKGM_FILE_PATH = os.path.join(SRC_DIR, 'chromeos', 'CHROMEOS_LKGM')
30# Should match something that looks like "12345.0.0".
31LKGM_RE = re.compile(r'\d+\.\d+\.\d+')
Ben Pastenefdd4a772020-07-20 22:38:2032PRIMARY_SLICE_EXPIRATION_S = 300
Ben Pastenea9e583b2019-01-16 02:57:2633
34
35def read_current_lkgm():
Takuto Ikutac8ebda32021-06-28 15:28:1736 if not os.path.exists(LKGM_FILE_PATH):
37 sys.stderr.write('LKGM file not present at %s\n' % LKGM_FILE_PATH)
38 return None
Ben Pastenea9e583b2019-01-16 02:57:2639
Takuto Ikutac8ebda32021-06-28 15:28:1740 with open(LKGM_FILE_PATH) as f:
41 lkgm = f.read().strip()
Ben Pastenea9e583b2019-01-16 02:57:2642
Takuto Ikutac8ebda32021-06-28 15:28:1743 if not LKGM_RE.match(lkgm):
44 sys.stderr.write('Unknown format of LKGM: %s\n' % lkgm)
45 return None
Ben Pastenea9e583b2019-01-16 02:57:2646
Takuto Ikutac8ebda32021-06-28 15:28:1747 # Just the major version should be sufficient.
48 return lkgm.split('.')[0]
Ben Pastenea9e583b2019-01-16 02:57:2649
50
Ben Pastene789bdca2019-02-26 18:22:0151def parse_args(triggerer):
Takuto Ikutac8ebda32021-06-28 15:28:1752 # This script will do nothing but inspect and tweak the dimension args to
53 # `swarming.py trigger`. So let's pull just those out.
54 parser = argparse.ArgumentParser(description=__doc__)
55 parser.add_argument(
56 '-d',
57 '--dimension',
58 default=[],
59 action='append',
60 nargs=2,
61 dest='dimensions',
Ben Pasteneb5c67262024-05-15 21:24:0162 help='Dimensions to filter on. Duplicated from the `swarming.py '
63 'trigger` command. Parsed here to ensure `device_os` is not added.')
Takuto Ikutac8ebda32021-06-28 15:28:1764 parser.add_argument(
65 '--optional-dimension',
66 default=[],
67 action='append',
68 nargs=3,
69 dest='optional_dimensions',
70 help='Optional dimensions which will result in additional task slices. '
71 'Duplicated from the `swarming.py trigger` command.')
72 base_test_triggerer.BaseTestTriggerer.setup_parser_contract(parser)
73 args, additional_args = parser.parse_known_args()
74 additional_args = triggerer.modify_args(additional_args, 0,
75 args.shard_index, args.shards,
76 args.dump_json)
Ben Pastenea9e583b2019-01-16 02:57:2677
Takuto Ikutac8ebda32021-06-28 15:28:1778 if additional_args[0] != 'trigger':
Ben Pasteneb5c67262024-05-15 21:24:0179 parser.error('This script is only supported for `swarming.py trigger`'
80 ' invocations.')
Ben Pastenea9e583b2019-01-16 02:57:2681
Takuto Ikutac8ebda32021-06-28 15:28:1782 for k, _ in args.dimensions:
83 if k == 'device_os':
84 parser.error(
85 'Must not specify the device_os dimension when using this'
86 ' script. (It will be added automatically.)')
Ben Pastenea9e583b2019-01-16 02:57:2687
Takuto Ikutac8ebda32021-06-28 15:28:1788 # It might be a valid use-case to include optional-dimensions in the initial
89 # invocation. But it'd be difficult to integrate them into what we're doing
90 # here. So let's just ensure there aren't any.
91 if args.optional_dimensions:
92 parser.error(
93 'Must not specify optional dimensions when using this script.')
Ben Pastenea9e583b2019-01-16 02:57:2694
Takuto Ikutac8ebda32021-06-28 15:28:1795 return args, additional_args
Ben Pastenea9e583b2019-01-16 02:57:2696
97
98def main():
Takuto Ikutac8ebda32021-06-28 15:28:1799 triggerer = base_test_triggerer.BaseTestTriggerer()
100 args, additional_args = parse_args(triggerer)
Ben Pastenea9e583b2019-01-16 02:57:26101
Takuto Ikutac8ebda32021-06-28 15:28:17102 current_lkgm = read_current_lkgm()
103 if not current_lkgm:
104 return 1
Ben Pastenea9e583b2019-01-16 02:57:26105
Takuto Ikutac8ebda32021-06-28 15:28:17106 new_args = additional_args[:1]
107 # Insert our modified dimension args in between the 1st and 2nd args of the
108 # initial `swarming.py` invocation. This avoids the presence of the special
109 # `--` arg from causing swarming.py to ignore them.
110 needs_device_status = True
111 for k, v in args.dimensions:
112 new_args.extend(['--dimension', k, v])
113 if k == 'device_status':
114 needs_device_status = False
Ben Pastene41041782019-02-16 04:21:58115
Takuto Ikutac8ebda32021-06-28 15:28:17116 # Only CrOS device bots with a device_status dimension of "available" should
117 # run tests. So target those explicitly if we aren't already.
118 if needs_device_status:
119 new_args.extend(['--dimension', 'device_status', 'available'])
Ben Pastene41041782019-02-16 04:21:58120
Takuto Ikutac8ebda32021-06-28 15:28:17121 new_args.extend([
122 '-optional-dimension',
123 'device_os=%s:%d' % (current_lkgm, PRIMARY_SLICE_EXPIRATION_S),
124 ])
125 new_args += additional_args[1:]
Ben Pastenea9e583b2019-01-16 02:57:26126
Ben Pasteneb5c67262024-05-15 21:24:01127 return triggerer.run_swarming_go(new_args, args.dump_json, args.shard_index
128 or 0, args.shards)
Ben Pastenea9e583b2019-01-16 02:57:26129
130
131if __name__ == '__main__':
Takuto Ikutac8ebda32021-06-28 15:28:17132 sys.exit(main())