Archived
Judge the one protection rule the forge applies, and keep a recorded repository id
The forge applies the rule named for a branch, else the first glob covering it; the judge passed a branch whose applied rule let pushes when a later rule happened to guard it. And a registration whose id the forge could not give cleared the id already recorded (the confirmation review of 2026-10-09).
This commit is contained in:
@@ -175,33 +175,54 @@ var askTheForge = func(ctx context.Context, owner, repo, branch string) (forgeFa
|
||||
return forgeFacts{}, fmt.Errorf("the forge named no id for %s/%s", owner, repo)
|
||||
}
|
||||
var rules struct {
|
||||
Rules []struct {
|
||||
Rule string `json:"rule"`
|
||||
Push bool `json:"push"`
|
||||
RequiredStatuses []string `json:"required_statuses"`
|
||||
AdminMayOverride bool `json:"admin_may_override"`
|
||||
} `json:"rules"`
|
||||
Rules []protectionRule `json:"rules"`
|
||||
}
|
||||
if err := ask("gitea_branch_protection_get", map[string]any{"owner": owner, "repo": repo}, &rules); err != nil {
|
||||
return forgeFacts{}, err
|
||||
}
|
||||
facts := forgeFacts{ID: found.Result.ID, Why: fmt.Sprintf("no protection rule covers %s", branch)}
|
||||
for _, r := range rules.Rules {
|
||||
if !ruleCovers(r.Rule, branch) {
|
||||
continue
|
||||
}
|
||||
switch {
|
||||
case r.Push:
|
||||
facts.Why = fmt.Sprintf("the rule %s lets a person push to %s directly", r.Rule, branch)
|
||||
case len(r.RequiredStatuses) == 0:
|
||||
facts.Why = fmt.Sprintf("the rule %s requires no status before a merge into %s", r.Rule, branch)
|
||||
case r.AdminMayOverride:
|
||||
facts.Why = fmt.Sprintf("the rule %s lets an administrator merge into %s past a status", r.Rule, branch)
|
||||
default:
|
||||
return forgeFacts{ID: facts.ID, Guarded: true}, nil
|
||||
facts := judgedRule(rules.Rules, branch)
|
||||
facts.ID = found.Result.ID
|
||||
return facts, nil
|
||||
}
|
||||
|
||||
// protectionRule is a branch protection rule as the forge's tool summarises it.
|
||||
type protectionRule struct {
|
||||
Rule string `json:"rule"`
|
||||
Push bool `json:"push"`
|
||||
RequiredStatuses []string `json:"required_statuses"`
|
||||
AdminMayOverride bool `json:"admin_may_override"`
|
||||
}
|
||||
|
||||
// judgedRule judges the one rule the forge applies to a branch, as the forge picks it: the rule named for the
|
||||
// branch, else the first glob rule, in the forge's order, that covers it (gitea's first matching rule). Never a
|
||||
// later rule that happens to be stronger: the forge does not read it.
|
||||
func judgedRule(rules []protectionRule, branch string) forgeFacts {
|
||||
var applied *protectionRule
|
||||
for i := range rules {
|
||||
if rules[i].Rule == branch {
|
||||
applied = &rules[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
return facts, nil
|
||||
if applied == nil {
|
||||
for i := range rules {
|
||||
if ruleCovers(rules[i].Rule, branch) {
|
||||
applied = &rules[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
switch r := applied; {
|
||||
case r == nil:
|
||||
return forgeFacts{Why: fmt.Sprintf("no protection rule covers %s", branch)}
|
||||
case r.Push:
|
||||
return forgeFacts{Why: fmt.Sprintf("the rule %s lets a person push to %s directly", r.Rule, branch)}
|
||||
case len(r.RequiredStatuses) == 0:
|
||||
return forgeFacts{Why: fmt.Sprintf("the rule %s requires no status before a merge into %s", r.Rule, branch)}
|
||||
case r.AdminMayOverride:
|
||||
return forgeFacts{Why: fmt.Sprintf("the rule %s lets an administrator merge into %s past a status", r.Rule, branch)}
|
||||
}
|
||||
return forgeFacts{Guarded: true}
|
||||
}
|
||||
|
||||
// ruleCovers says a protection rule's name — a branch, or a glob of them — covers a branch, as the forge reads it.
|
||||
|
||||
Reference in New Issue
Block a user