OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """CQ config validation library.""" | |
7 | |
8 import argparse | |
9 # The 'from google import protobuf' below was replaced to fix an issue where | |
10 # some users may have built-in google package installed on their system, which | |
11 # is incompatible with cq_pb2 below. This hack can be removed after | |
12 # http://crbug.com/503067 is resolved. | |
13 import protobuf26 as protobuf | |
14 import logging | |
15 import re | |
16 import sys | |
17 | |
18 from cq_client import cq_pb2 | |
19 | |
20 | |
21 REQUIRED_FIELDS = [ | |
22 'version', | |
23 'rietveld', | |
24 'rietveld.url', | |
25 'verifiers', | |
26 'cq_name', | |
27 ] | |
28 | |
29 LEGACY_FIELDS = [ | |
30 'svn_repo_url', | |
31 'server_hooks_missing', | |
32 'verifiers_with_patch', | |
33 ] | |
34 | |
35 EMAIL_REGEXP = '^[^@]+@[^@]+\.[^@]+$' | |
36 | |
37 | |
38 def _HasField(message, field_path): | |
39 """Checks that at least one field with given path exist in the proto message. | |
40 | |
41 This function correctly handles repeated fields and will make sure that each | |
42 repeated field will have required sub-path, e.g. if 'abc' is a repeated field | |
43 and field_path is 'abc.def', then the function will only return True when each | |
44 entry for 'abc' will contain at least one value for 'def'. | |
45 | |
46 Args: | |
47 message: Protocol Buffer message to check. | |
48 field_path: Path to the target field separated with ".". | |
pgervais
2015/06/24 01:10:43
Nit: add the type of the arguments.
Sergiy Byelozyorov
2015/06/24 05:30:59
Done.
| |
49 | |
50 Return: | |
51 True if at least one such field is explicitly set in the message. | |
52 """ | |
53 path_parts = field_path.split('.', 1) | |
54 field_name = path_parts[0] | |
55 sub_path = path_parts[1] if len(path_parts) == 2 else None | |
56 | |
57 field_labels = {fd.name: fd.label for fd in message.DESCRIPTOR.fields} | |
58 repeated_field = (field_labels[field_name] == | |
59 protobuf.descriptor.FieldDescriptor.LABEL_REPEATED) | |
60 | |
61 if sub_path: | |
62 field = getattr(message, field_name) | |
63 if repeated_field: | |
64 if not field: | |
65 return False | |
66 return all(_HasField(entry, sub_path) for entry in field) | |
67 else: | |
68 return _HasField(field, sub_path) | |
69 else: | |
70 if repeated_field: | |
71 return len(getattr(message, field_name)) > 0 | |
72 else: | |
73 return message.HasField(field_name) | |
74 | |
75 | |
76 def IsValid(cq_config): | |
77 """Validates a CQ config and prints errors/warnings to the screen. | |
78 | |
79 Args: | |
80 cq_config (string): Unparsed text format of the CQ config proto. | |
81 | |
82 Returns: | |
83 True if the config is valid. | |
84 """ | |
85 try: | |
86 config = cq_pb2.Config() | |
87 protobuf.text_format.Merge(cq_config, config) | |
88 except protobuf.text_format.ParseError as e: | |
89 logging.error('Failed to parse config as protobuf:\n%s', e) | |
90 return False | |
91 | |
92 for fname in REQUIRED_FIELDS: | |
93 if not _HasField(config, fname): | |
94 logging.error('%s is a required field', fname) | |
95 return False | |
96 | |
97 for fname in LEGACY_FIELDS: | |
98 if _HasField(config, fname): | |
99 logging.warn('%s is a legacy field', fname) | |
100 | |
101 | |
102 for base in config.rietveld.project_bases: | |
103 try: | |
104 re.compile(base) | |
105 except Exception: | |
pgervais
2015/06/24 01:10:43
expect re.error:
instead. We don't want to catch
Sergiy Byelozyorov
2015/06/24 05:30:59
Done.
| |
106 logging.error('failed to parse "%s" in project_bases as a regexp', base) | |
107 return False | |
108 | |
109 if not config.rietveld.HasField('url'): | |
110 logging.error('rietveld.url is a required field') | |
111 return False | |
pgervais
2015/06/24 01:10:43
Why are you checking that again? rietveld.url is i
Sergiy Byelozyorov
2015/06/24 05:30:59
Done.
| |
112 | |
113 # TODO(sergiyb): For each field, check valid values depending on its | |
114 # semantics, e.g. email addresses, regular expressions etc. | |
115 | |
116 return True | |
OLD | NEW |