1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package predicate
16
17 import (
18 "context"
19 "fmt"
20 "sort"
21
22 "github.com/pkg/errors"
23
24 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/pull"
25
26 "edge-infra.dev/pkg/f8n/devinfra/repo/owners/policybot/policy/common"
27 )
28
29 type HasAuthorIn struct {
30 common.Actors `yaml:",inline"`
31 }
32
33 var _ Predicate = &HasAuthorIn{}
34
35 func (pred *HasAuthorIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
36 author := prctx.Author()
37
38 result, err := pred.IsActor(ctx, prctx, author)
39 desc := ""
40 if !result {
41 desc = fmt.Sprintf("The pull request author %q does not meet the required membership conditions", author)
42 }
43
44 predicateResult := common.PredicateResult{
45 Satisfied: result,
46 Description: desc,
47 ValuePhrase: "authors",
48 Values: []string{author},
49 ConditionPhrase: "meet the required membership conditions",
50 ConditionsMap: map[string][]string{
51 "Organizations": pred.Organizations,
52 "Teams": pred.Teams,
53 "Users": pred.Users,
54 },
55 }
56 return &predicateResult, err
57 }
58
59 func (pred *HasAuthorIn) Trigger() common.Trigger {
60 return common.TriggerStatic
61 }
62
63 type OnlyHasContributorsIn struct {
64 common.Actors `yaml:",inline"`
65 }
66
67 var _ Predicate = &OnlyHasContributorsIn{}
68
69 func (pred *OnlyHasContributorsIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
70 commits, err := prctx.Commits()
71
72 predicateResult := common.PredicateResult{
73 ValuePhrase: "contributors",
74 ConditionPhrase: "all meet the required membership conditions",
75 ConditionsMap: map[string][]string{
76 "Organizations": pred.Organizations,
77 "Teams": pred.Teams,
78 "Users": pred.Users,
79 },
80 }
81
82 if err != nil {
83 return nil, errors.Wrap(err, "failed to get commits")
84 }
85
86 users := make(map[string]struct{})
87 users[prctx.Author()] = struct{}{}
88
89 for _, c := range commits {
90 for _, u := range c.Users() {
91 users[u] = struct{}{}
92 }
93 }
94
95 userList := make([]string, 0, len(users))
96 for user := range users {
97 userList = append(userList, user)
98 }
99 sort.Strings(userList)
100
101 for _, user := range userList {
102 member, err := pred.IsActor(ctx, prctx, user)
103 if err != nil {
104 return nil, err
105 }
106 if !member {
107 predicateResult.Description = fmt.Sprintf("Contributor %q does not meet the required membership conditions", user)
108 predicateResult.Values = []string{user}
109 predicateResult.Satisfied = false
110 return &predicateResult, nil
111 }
112 }
113 predicateResult.Values = userList
114 predicateResult.Satisfied = true
115 return &predicateResult, nil
116 }
117
118 func (pred *OnlyHasContributorsIn) Trigger() common.Trigger {
119 return common.TriggerCommit
120 }
121
122 type HasContributorIn struct {
123 common.Actors `yaml:",inline"`
124 }
125
126 var _ Predicate = &HasContributorIn{}
127
128 func (pred *HasContributorIn) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
129 commits, err := prctx.Commits()
130
131 predicateResult := common.PredicateResult{
132 ValuePhrase: "contributors",
133 ConditionPhrase: "meet the required membership conditions ",
134 ConditionsMap: map[string][]string{
135 "Organizations": pred.Organizations,
136 "Teams": pred.Teams,
137 "Users": pred.Users,
138 },
139 }
140
141 if err != nil {
142 return nil, errors.Wrap(err, "failed to get commits")
143 }
144
145 users := make(map[string]struct{})
146 users[prctx.Author()] = struct{}{}
147
148 for _, c := range commits {
149 for _, u := range c.Users() {
150 users[u] = struct{}{}
151 }
152 }
153
154 userList := make([]string, 0, len(users))
155 for user := range users {
156 userList = append(userList, user)
157 }
158 sort.Strings(userList)
159
160 for _, user := range userList {
161 member, err := pred.IsActor(ctx, prctx, user)
162 if err != nil {
163 return nil, err
164 }
165 if member {
166 predicateResult.Satisfied = true
167 predicateResult.Values = []string{user}
168 return &predicateResult, nil
169 }
170 }
171 predicateResult.Description = "No contributors meet the required membership conditions"
172 predicateResult.Satisfied = false
173 predicateResult.Values = userList
174 return &predicateResult, nil
175 }
176
177 func (pred *HasContributorIn) Trigger() common.Trigger {
178 return common.TriggerCommit
179 }
180
181 type AuthorIsOnlyContributor bool
182
183 var _ Predicate = AuthorIsOnlyContributor(false)
184
185 func (pred AuthorIsOnlyContributor) Evaluate(ctx context.Context, prctx pull.Context) (*common.PredicateResult, error) {
186 commits, err := prctx.Commits()
187
188 predicateResult := common.PredicateResult{
189 ValuePhrase: "authors",
190 ConditionPhrase: "meet the condition",
191 }
192 if pred {
193 predicateResult.ConditionValues = []string{"they are the only contributors"}
194 } else {
195 predicateResult.ConditionValues = []string{"they are not the only contributors"}
196 }
197
198 if err != nil {
199 return nil, errors.Wrap(err, "failed to get commits")
200 }
201
202 author := prctx.Author()
203 predicateResult.Values = []string{author}
204
205 for _, c := range commits {
206 if c.Author != author || (!c.CommittedViaWeb && c.Committer != author) {
207 if pred {
208 predicateResult.Description = fmt.Sprintf("Commit %.10s was authored or committed by a different user", c.SHA)
209 predicateResult.Satisfied = false
210 return &predicateResult, nil
211 }
212 predicateResult.Satisfied = true
213 return &predicateResult, nil
214 }
215 }
216
217 if pred {
218 predicateResult.Satisfied = true
219 return &predicateResult, nil
220 }
221 predicateResult.Description = fmt.Sprintf("All commits were authored and committed by %s", author)
222 predicateResult.Satisfied = false
223 return &predicateResult, nil
224 }
225
226 func (pred AuthorIsOnlyContributor) Trigger() common.Trigger {
227 return common.TriggerCommit
228 }
229
View as plain text