Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: third_party/cq_client/validate_config.py

Issue 1200863002: Update cq_client and add validate command to commit_queue binary (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Fix Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 """Validates a given CQ config file. May format the config in place.
6
7 This script returns 0 when config is valid, other value if not. This allows this
8 script to be used in automated tests, e.g. in PRESUBMIT. It can also
9 automatically format valid configs in place: sort keys in dictionaries and
10 pretty-print config with 4-space indent.
11 """
12
13 import argparse
14 # The 'from google import protobuf' below was replaced to fix an issue where
15 # some users may have built-in google package installed on their system, which
16 # is incompatible with cq_pb2 below. This hack can be removed after
17 # http://crbug.com/503067 is resolved.
18 import protobuf26 as protobuf
19 import logging
20 import re
21 import sys
22
23 from cq_client import cq_pb2
24
25
26 REQUIRED_FIELDS = [
27 'version',
28 'rietveld',
29 'rietveld.url',
30 'verifiers',
31 'cq_name',
32 ]
33
34 LEGACY_FIELDS = [
35 'svn_repo_url',
36 'server_hooks_missing',
37 'verifiers_with_patch',
38 ]
39
40 EMAIL_REGEXP = '^[^@]+@[^@]+\.[^@]+$'
41
42
43 def parse_args():
44 parser = argparse.ArgumentParser(description=sys.modules['__main__'].__doc__)
45 parser.add_argument('config_file', type=argparse.FileType('r'),
46 help='Path to the CQ config file.')
47 return parser.parse_args()
48
49
50 def has_field(message, field_path):
51 """Checks that at least one field with given path exist in the proto message.
52
53 This function correctly handles repeated fields and will make sure that each
54 repeated field will have required sub-path, e.g. if 'abc' is a repeated field
55 and field_path is 'abc.def', then the function will only return True when each
56 entry for 'abc' will contain at least one value for 'def'.
57
58 Args:
59 message: Protocol Buffer message to check.
60 field_path: Path to the target field separated with ".".
61
62 Return:
63 True if at least one such field is explicitly set in the message.
64 """
65 path_parts = field_path.split('.', 1)
66 field_name = path_parts[0]
67 sub_path = path_parts[1] if len(path_parts) == 2 else None
68
69 field_labels = {fd.name: fd.label for fd in message.DESCRIPTOR.fields}
70 repeated_field = (field_labels[field_name] ==
71 protobuf.descriptor.FieldDescriptor.LABEL_REPEATED)
72
73 if sub_path:
74 field = getattr(message, field_name)
75 if repeated_field:
76 if not field:
77 return False
78 return all(has_field(entry, sub_path) for entry in field)
79 else:
80 return has_field(field, sub_path)
81 else:
82 if repeated_field:
83 return len(getattr(message, field_name)) > 0
84 else:
85 return message.HasField(field_name)
86
87
88 def validate(cq_config):
89 """Validates a CQ config and prints errors/warnings to the screen.
90
91 Args:
92 cq_config (string): Unparsed text format of the CQ config proto.
93
94 Returns:
95 0 if the file is valid, non-zero otherwise.
96 """
97 try:
98 config = cq_pb2.Config()
99 protobuf.text_format.Merge(cq_config, config)
100 except protobuf.text_format.ParseError as e:
101 logging.error('Failed to parse config as protobuf:\n%s', e)
102 return 1
103
104 for fname in REQUIRED_FIELDS:
105 if not has_field(config, fname):
106 logging.error('%s is a required field', fname)
107 return 1
108
109 for fname in LEGACY_FIELDS:
110 if has_field(config, fname):
111 logging.warn('%s is a legacy field', fname)
112
113
114 for base in config.rietveld.project_bases:
115 try:
116 re.compile(base)
117 except Exception:
118 logging.error('failed to parse "%s" in project_bases as a regexp', base)
119 return 1
120
121 if not config.rietveld.HasField('url'):
122 logging.error('rietveld.url is a required field')
123 return 1
124
125 # TODO(sergiyb): For each field, check valid values depending on its
126 # semantics, e.g. email addresses, regular expressions etc.
127
128 return 0
129
130
131 if __name__ == '__main__':
132 args = parse_args()
133 with args.config_file:
134 sys.exit(validate(args.config_file.read()))
OLDNEW
« third_party/cq_client/README.md ('K') | « third_party/cq_client/test/validate_config_test.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698