Documentation
¶
Overview ¶
Package rules holds the declarative catalogue the sweep loads at runtime. A rule names a detection signal, one action of the closed remedy vocabulary and the evidence written on the PR. Guards live in the action, so a rule can add a refusal and never remove one.
Index ¶
- Constants
- func Remediable(state pr.StatusState) bool
- type Action
- type BaseHead
- type Catalogue
- type CheckMatch
- type CheckState
- type Evidence
- type Hit
- type Loader
- type LogMatch
- type LogSource
- type Match
- type PRMatch
- type ProtectionMatch
- type Rule
- func (r *Rule) CheckPattern() *regexp.Regexp
- func (r *Rule) FilePatterns() []*regexp.Regexp
- func (r *Rule) Guards() []remedy.Guard
- func (r *Rule) Kinds() map[pr.Kind]bool
- func (r *Rule) LogBytes() int
- func (r *Rule) LogPattern() *regexp.Regexp
- func (r *Rule) MissingContextPatterns() []*regexp.Regexp
- func (r *Rule) States() map[pr.StatusState]bool
- func (r *Rule) TitlePattern() *regexp.Regexp
- type Skipped
- type Subject
Constants ¶
const ( DefaultOwner = "giantswarm" DefaultRepo = "marge" DefaultDir = "rules" DefaultRef = "main" )
The catalogue lives in marge's own repository and is read from its default branch at the start of every sweep, so a merged rule is live on the next run without a release.
Variables ¶
This section is empty.
Functions ¶
func Remediable ¶
func Remediable(state pr.StatusState) bool
Remediable reports whether a rule may act on a classification.
Types ¶
type BaseHead ¶
type BaseHead string
BaseHead is what the base branch head reported for the checks failing on the PR. Every failing check the rule selected must report it, so a PR that carries one transient failure and one real failure matches neither green nor red. Absent is its own value: a check the base never ran is not green.
type Catalogue ¶
type Catalogue struct {
// Rules are ordered by name. The first rule that matches a PR wins, so
// the order is part of the contract and a scenario test pins it.
Rules []*Rule
// Digest identifies the exact catalogue this sweep ran, and is written
// into the evidence of every action a rule selected.
Digest string
// Source says where the catalogue came from.
Source string
// Ref is the branch the catalogue was read from, empty for a local
// directory.
Ref string
// Skipped names the documents that failed to parse, with the reason.
// They are left out; the rest of the catalogue still runs.
Skipped []Skipped
}
Catalogue is the loaded rule set of one sweep.
type CheckMatch ¶
type CheckMatch struct {
// Name is a glob over the failing check names.
Name string `yaml:"name"`
}
CheckMatch matches the name of a failing check. A check name alone never justifies a write, so a rule whose action writes also needs a log signal.
type CheckState ¶
type CheckState string
CheckState is what the base branch head reported for one check name.
const ( CheckGreen CheckState = "green" CheckRed CheckState = "red" CheckAbsent CheckState = "absent" )
type Evidence ¶
type Evidence struct {
// Reason is the line written on the PR under the action name.
Reason string `yaml:"reason"`
}
Evidence is the marker the sweep writes when the action applied. The marker's outcome is the action name, so a later sweep recognises what ran on this change whichever rule selected it.
type Hit ¶
type Hit struct {
Rule *Rule
// Check is the failing check the signal matched, or "" for a rule whose
// signal is PR metadata alone.
Check string
// Excerpt is the log excerpt the pattern matched, empty for a rule with
// no log signal.
Excerpt string
// LogMatched reports whether a log excerpt decided the match. An action
// that writes is guarded on it.
LogMatched bool
// MissingContexts are the required contexts the protection signal
// selected. An action that rewrites a protection touches these and no
// other.
MissingContexts []string
}
Hit is the rule that matched, with what made it match.
type Loader ¶
type Loader struct {
Client *github.Client
Owner string
Repo string
// Dir is the directory inside the repository that holds the documents.
Dir string
Ref string
// LocalPath reads the catalogue from this directory instead of GitHub.
LocalPath string
}
Loader reads the catalogue from a repository, or from LocalPath when that is set.
type LogMatch ¶
type LogMatch struct {
// Source selects where the excerpt comes from.
Source LogSource `yaml:"source"`
// Pattern is an RE2 expression matched against the excerpt.
Pattern string `yaml:"pattern"`
// MaxBytes bounds the excerpt read from the tail of the log. Zero uses
// the default.
MaxBytes int `yaml:"maxBytes"`
}
LogMatch matches an excerpt of the failing step's log.
type Match ¶
type Match struct {
// States names the classifications the rule applies to, from the
// remediable set. Empty applies to every remediable state.
States []string `yaml:"states"`
// Kinds names the bot PR kinds. Empty applies to every trusted kind.
Kinds []string `yaml:"kinds"`
Check *CheckMatch `yaml:"check"`
Log *LogMatch `yaml:"log"`
PR *PRMatch `yaml:"pr"`
Protection *ProtectionMatch `yaml:"protection"`
}
Match is the detection signal. Every field present must hold; a rule with no signal beyond states and kinds is refused, because it would match every PR in that classification.
type PRMatch ¶
type PRMatch struct {
// BaseHead states what the base head must report for the failing checks.
BaseHead BaseHead `yaml:"baseHead"`
// TitlePattern is an RE2 expression matched against the PR title.
TitlePattern string `yaml:"titlePattern"`
// Files are globs; every one of them must match a file of the diff.
Files []string `yaml:"files"`
}
PRMatch matches metadata of the pull request itself.
type ProtectionMatch ¶
type ProtectionMatch struct {
// MissingContexts are globs over the required contexts the head never
// reported. They are alternatives: the rule matches when any of them
// selects a context, and the action drops only what they selected.
MissingContexts []string `yaml:"missingContexts"`
}
ProtectionMatch reads the base branch's protection rather than the pull request. A PR waiting on a context nobody reported carries no failing check, so no signal of the PR itself reaches it.
type Rule ¶
type Rule struct {
// Name identifies the rule and matches its file name.
Name string `yaml:"name"`
// Summary says in one line what the rule recognises.
Summary string `yaml:"summary"`
// Source cites where the pattern comes from, for instance the runbook
// row it was imported from.
Source string `yaml:"source"`
Match Match `yaml:"match"`
Action Action `yaml:"action"`
Refuse []string `yaml:"refuse"`
Evidence Evidence `yaml:"evidence"`
// contains filtered or unexported fields
}
Rule is one document of the catalogue.
func Parse ¶
Parse decodes and validates one rule document. Decoding is strict: an unknown key is an error, so no document can carry an option the schema does not define. fileName is the document's path, reported in errors and checked against the rule name.
func (*Rule) CheckPattern ¶
CheckPattern returns the compiled check-name glob, or nil when the rule has no check signal.
func (*Rule) FilePatterns ¶
FilePatterns returns the compiled file globs. Every one of them must match a file of the diff.
func (*Rule) Kinds ¶
Kinds reports the bot PR kinds the rule applies to. An empty set in the document means every trusted kind.
func (*Rule) LogPattern ¶
LogPattern returns the compiled log expression, or nil when the rule has no log signal.
func (*Rule) MissingContextPatterns ¶
MissingContextPatterns returns the compiled globs over the required contexts the head never reported, or nil when the rule reads no protection.
func (*Rule) States ¶
func (r *Rule) States() map[pr.StatusState]bool
States reports the classifications the rule applies to. An empty set in the document means every remediable state.
func (*Rule) TitlePattern ¶
TitlePattern returns the compiled title expression, or nil.
type Subject ¶
type Subject struct {
State pr.StatusState
Kind pr.Kind
Title string
// Failing names the red checks that produced a verdict, in the order the
// classification found them.
Failing []string
// BaseState says what the base head reported for each failing check.
// A name absent from the map is CheckAbsent, and absent is not green.
BaseState map[string]CheckState
// MissingContexts names the required contexts of the base branch that
// the head never reported.
MissingContexts []string
// Files returns the paths of the PR diff. It is called only for a rule
// that carries a file signal, so a catalogue without one costs no
// comparison. Nil returns no files, and such a rule does not match.
Files func() []string
// Log returns a bounded excerpt of one check's log. A rule with a log
// signal never matches when Log is nil or reports false: an unreadable
// log leaves the failure as it was classified.
Log func(source LogSource, check string, maxBytes int) (string, bool)
}
Subject is the classified PR a rule is matched against. The engine fills it once per PR; matching performs no request of its own except the log excerpt, which it asks Log for.