xref: /aosp_15_r20/tools/repohooks/rh/results.py (revision d68f33bc6fb0cc2476107c2af0573a2f5a63dfc1)
1*d68f33bcSAndroid Build Coastguard Worker# Copyright 2016 The Android Open Source Project
2*d68f33bcSAndroid Build Coastguard Worker#
3*d68f33bcSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*d68f33bcSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*d68f33bcSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*d68f33bcSAndroid Build Coastguard Worker#
7*d68f33bcSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*d68f33bcSAndroid Build Coastguard Worker#
9*d68f33bcSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*d68f33bcSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*d68f33bcSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d68f33bcSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*d68f33bcSAndroid Build Coastguard Worker# limitations under the License.
14*d68f33bcSAndroid Build Coastguard Worker
15*d68f33bcSAndroid Build Coastguard Worker"""Common errors thrown when repo preupload checks fail."""
16*d68f33bcSAndroid Build Coastguard Worker
17*d68f33bcSAndroid Build Coastguard Workerimport os
18*d68f33bcSAndroid Build Coastguard Workerimport sys
19*d68f33bcSAndroid Build Coastguard Workerfrom typing import List, NamedTuple, Optional
20*d68f33bcSAndroid Build Coastguard Worker
21*d68f33bcSAndroid Build Coastguard Worker_path = os.path.realpath(__file__ + '/../..')
22*d68f33bcSAndroid Build Coastguard Workerif sys.path[0] != _path:
23*d68f33bcSAndroid Build Coastguard Worker    sys.path.insert(0, _path)
24*d68f33bcSAndroid Build Coastguard Workerdel _path
25*d68f33bcSAndroid Build Coastguard Worker
26*d68f33bcSAndroid Build Coastguard Worker
27*d68f33bcSAndroid Build Coastguard Workerclass HookResult(object):
28*d68f33bcSAndroid Build Coastguard Worker    """A single hook result."""
29*d68f33bcSAndroid Build Coastguard Worker
30*d68f33bcSAndroid Build Coastguard Worker    def __init__(self, hook, project, commit, error, files=(),
31*d68f33bcSAndroid Build Coastguard Worker                 fixup_cmd: Optional[List[str]] = None):
32*d68f33bcSAndroid Build Coastguard Worker        """Initialize.
33*d68f33bcSAndroid Build Coastguard Worker
34*d68f33bcSAndroid Build Coastguard Worker        Args:
35*d68f33bcSAndroid Build Coastguard Worker          hook: The name of the hook.
36*d68f33bcSAndroid Build Coastguard Worker          project: The name of the project.
37*d68f33bcSAndroid Build Coastguard Worker          commit: The git commit sha.
38*d68f33bcSAndroid Build Coastguard Worker          error: A string representation of the hook's result.  Empty on
39*d68f33bcSAndroid Build Coastguard Worker              success.
40*d68f33bcSAndroid Build Coastguard Worker          files: The list of files that were involved in the hook execution.
41*d68f33bcSAndroid Build Coastguard Worker          fixup_cmd: A command that can automatically fix errors found in the
42*d68f33bcSAndroid Build Coastguard Worker              hook's execution.  Can be None if the hook does not support
43*d68f33bcSAndroid Build Coastguard Worker              automatic fixups.
44*d68f33bcSAndroid Build Coastguard Worker        """
45*d68f33bcSAndroid Build Coastguard Worker        self.hook = hook
46*d68f33bcSAndroid Build Coastguard Worker        self.project = project
47*d68f33bcSAndroid Build Coastguard Worker        self.commit = commit
48*d68f33bcSAndroid Build Coastguard Worker        self.error = error
49*d68f33bcSAndroid Build Coastguard Worker        self.files = files
50*d68f33bcSAndroid Build Coastguard Worker        self.fixup_cmd = fixup_cmd
51*d68f33bcSAndroid Build Coastguard Worker
52*d68f33bcSAndroid Build Coastguard Worker    def __bool__(self):
53*d68f33bcSAndroid Build Coastguard Worker        """Whether this result is an error."""
54*d68f33bcSAndroid Build Coastguard Worker        return bool(self.error)
55*d68f33bcSAndroid Build Coastguard Worker
56*d68f33bcSAndroid Build Coastguard Worker    def is_warning(self):
57*d68f33bcSAndroid Build Coastguard Worker        """Whether this result is a non-fatal warning."""
58*d68f33bcSAndroid Build Coastguard Worker        return False
59*d68f33bcSAndroid Build Coastguard Worker
60*d68f33bcSAndroid Build Coastguard Worker
61*d68f33bcSAndroid Build Coastguard Workerclass HookCommandResult(HookResult):
62*d68f33bcSAndroid Build Coastguard Worker    """A single hook result based on a CompletedProcess."""
63*d68f33bcSAndroid Build Coastguard Worker
64*d68f33bcSAndroid Build Coastguard Worker    def __init__(self, hook, project, commit, result, files=(),
65*d68f33bcSAndroid Build Coastguard Worker                 fixup_cmd=None):
66*d68f33bcSAndroid Build Coastguard Worker        HookResult.__init__(self, hook, project, commit,
67*d68f33bcSAndroid Build Coastguard Worker                            result.stderr if result.stderr else result.stdout,
68*d68f33bcSAndroid Build Coastguard Worker                            files=files, fixup_cmd=fixup_cmd)
69*d68f33bcSAndroid Build Coastguard Worker        self.result = result
70*d68f33bcSAndroid Build Coastguard Worker
71*d68f33bcSAndroid Build Coastguard Worker    def __bool__(self):
72*d68f33bcSAndroid Build Coastguard Worker        """Whether this result is an error."""
73*d68f33bcSAndroid Build Coastguard Worker        return self.result.returncode not in (None, 0, 77)
74*d68f33bcSAndroid Build Coastguard Worker
75*d68f33bcSAndroid Build Coastguard Worker    def is_warning(self):
76*d68f33bcSAndroid Build Coastguard Worker        """Whether this result is a non-fatal warning."""
77*d68f33bcSAndroid Build Coastguard Worker        return self.result.returncode == 77
78*d68f33bcSAndroid Build Coastguard Worker
79*d68f33bcSAndroid Build Coastguard Worker
80*d68f33bcSAndroid Build Coastguard Workerclass ProjectResults(NamedTuple):
81*d68f33bcSAndroid Build Coastguard Worker    """All results for a single project."""
82*d68f33bcSAndroid Build Coastguard Worker
83*d68f33bcSAndroid Build Coastguard Worker    project: str
84*d68f33bcSAndroid Build Coastguard Worker    workdir: str
85*d68f33bcSAndroid Build Coastguard Worker
86*d68f33bcSAndroid Build Coastguard Worker    # All the results from running all the hooks.
87*d68f33bcSAndroid Build Coastguard Worker    results: List[HookResult] = []
88*d68f33bcSAndroid Build Coastguard Worker
89*d68f33bcSAndroid Build Coastguard Worker    # Whether there were any non-hook related errors.  For example, trying to
90*d68f33bcSAndroid Build Coastguard Worker    # parse the project configuration.
91*d68f33bcSAndroid Build Coastguard Worker    internal_failure: bool = False
92*d68f33bcSAndroid Build Coastguard Worker
93*d68f33bcSAndroid Build Coastguard Worker    def add_results(self, results: Optional[List[HookResult]]) -> None:
94*d68f33bcSAndroid Build Coastguard Worker        """Add |results| to our results."""
95*d68f33bcSAndroid Build Coastguard Worker        if results:
96*d68f33bcSAndroid Build Coastguard Worker            self.results.extend(results)
97*d68f33bcSAndroid Build Coastguard Worker
98*d68f33bcSAndroid Build Coastguard Worker    @property
99*d68f33bcSAndroid Build Coastguard Worker    def fixups(self):
100*d68f33bcSAndroid Build Coastguard Worker        """Yield results that have a fixup available."""
101*d68f33bcSAndroid Build Coastguard Worker        yield from (x for x in self.results if x and x.fixup_cmd)
102*d68f33bcSAndroid Build Coastguard Worker
103*d68f33bcSAndroid Build Coastguard Worker    def __bool__(self):
104*d68f33bcSAndroid Build Coastguard Worker        """Whether there are any errors in this set of results."""
105*d68f33bcSAndroid Build Coastguard Worker        return self.internal_failure or any(self.results)
106