Documentation
¶
Overview ¶
Package mappings owns the declarative repository → Slack-channel configuration: parsing mappings.yaml, the in-memory Provider used at runtime, and the mappings.lock cache that records which entries have been validated. The package replaces the database-backed RepoMappings store.
Index ¶
- Constants
- func LockPath(yamlPath string) string
- func ValidateMappings(m map[string]Org) error
- func WriteLock(path string, l Lock) error
- type Defaults
- type Diff
- type DigestConfig
- type Entry
- type File
- type FileNotFoundError
- type Lock
- type LockEntry
- type Org
- type ParseError
- type Provider
- type ReactionsOverride
- type RepoConfig
- type Resolved
Constants ¶
const ChannelMention = "<!channel>"
ChannelMention is the Slack wire token used when an entry omits the `mentions:` key — operators see `@channel` in Slack.
const DefaultDigestSchedule = "0 9 * * *"
DefaultDigestSchedule is the cron spec used when the digest section is absent or omits `schedule`: 9am every morning, in the configured digest timezone (default UTC; see DigestConfig.Timezone).
const LockFileComment = "DO NOT EDIT — regenerated by notifycat on validation"
LockFileComment is the human-facing warning baked into every written lock.
const LockVersion = 1
LockVersion is the current lock-file schema version.
Variables ¶
This section is empty.
Functions ¶
func LockPath ¶
LockPath derives the lock-file path that lives next to the given mappings.yaml. .yaml / .yml extensions are swapped for .lock; any other suffix gets .lock appended.
func ValidateMappings ¶ added in v0.18.0
ValidateMappings runs the same per-org/per-tier structural checks as Parse over a mappings map. An empty map (no orgs) is valid. Returns an error for invalid org names, empty orgs, bad repo keys, malformed channel IDs, or any repo tier that cannot resolve a channel.
Types ¶
type Defaults ¶ added in v0.18.0
Defaults is the global tier: the config.yaml top-level behavioral settings that per-repo tiers override.
type Diff ¶
Diff is the result of DiffEntries: entries needing validation + lock keys that should be dropped on the next write.
func DiffEntries ¶
DiffEntries compares the current entries against the lock and returns which entries need validation (new or hash-changed) and which lock keys are stale (present in the lock but not in the file).
type DigestConfig ¶ added in v0.16.0
DigestConfig is the `digest:` section: a scheduled reminder that lists open PRs nobody has touched since the previous day. The global section is optional and the feature is on by default, so an absent section behaves like `{enabled: true}` with the default schedule. Per-repo tiers reuse this type to override Enabled/Schedule.
Timezone is global-only — the server runs a single cron clock, so the zone belongs on the global section and is rejected on a per-repo tier. Empty means the default (UTC); config.Load resolves it to a *time.Location and fails fast on an invalid zone.
func (*DigestConfig) UnmarshalYAML ¶ added in v0.16.0
func (d *DigestConfig) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML walks the mapping node by hand (like Org) so we can default Enabled to true — distinguishing a missing `enabled:` key from an explicit `enabled: false` — while keeping KnownFields-style rejection of typos.
type Entry ¶
type Entry struct {
Org string
Repo string // empty when Wildcard is true
Wildcard bool
Channel string
Mentions []string
}
Entry is one validation unit: an explicit (org, repo) pair or an (org, "*") wildcard. Each entry has its own hash in mappings.lock.
func (Entry) Hash ¶
Hash is the cache key for an entry: sha256 over canonical JSON of the validation-relevant fields. Mentions are deliberately excluded — they only affect message formatting at Slack-send time, not anything the validator checks (channel membership, bot scopes, webhook events). A mention edit shouldn't invalidate the entry's cache.
type File ¶
type File struct {
Digest *DigestConfig `yaml:"digest"`
Mappings map[string]Org `yaml:"mappings"`
}
File is the parsed mappings.yaml document.
type FileNotFoundError ¶ added in v0.7.0
FileNotFoundError is returned by Load when the mappings file cannot be opened.
func (*FileNotFoundError) Error ¶ added in v0.7.0
func (e *FileNotFoundError) Error() string
func (*FileNotFoundError) Unwrap ¶ added in v0.7.0
func (e *FileNotFoundError) Unwrap() error
type Lock ¶
type Lock struct {
Comment string `json:"_comment,omitempty"`
Version int `json:"version"`
Entries map[string]LockEntry `json:"entries"`
}
Lock is the on-disk validation cache.
type Org ¶
type Org map[string]RepoConfig
Org maps each repo name (or the literal "*") to its tier config. The "*" key is the org-level tier: it both supplies defaults that explicit repo tiers inherit and matches any repo not named explicitly.
type ParseError ¶ added in v0.7.0
ParseError is returned by Load when the mappings file cannot be parsed.
func (*ParseError) Error ¶ added in v0.7.0
func (e *ParseError) Error() string
func (*ParseError) Unwrap ¶ added in v0.7.0
func (e *ParseError) Unwrap() error
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider serves repository → mapping lookups from a parsed mappings.yaml. Construct with Load; safe for concurrent reads (no mutation after Load).
func NewProvider ¶ added in v0.17.0
func NewProvider(defaults Defaults, m map[string]Org, digest *DigestConfig) *Provider
NewProvider builds a Provider from already-decoded sections (config.yaml's `mappings:` map and `digest:` block), the in-memory counterpart to Load. A nil digest leaves the feature on by default (see Digest).
func (*Provider) Digest ¶ added in v0.16.0
func (p *Provider) Digest() DigestConfig
Digest returns the effective stuck-PR digest configuration. The feature is enabled by default, so an absent `digest:` section yields {Enabled: true, Schedule: DefaultDigestSchedule}. An explicit section may disable it or override the schedule.
func (*Provider) DigestFor ¶ added in v0.18.0
func (p *Provider) DigestFor(repository string) DigestConfig
DigestFor returns the effective digest config for a repository: the global Digest() merged with the org/* and org/repo tiers (most-specific tier that sets enabled/schedule wins). An unmapped repo yields the global digest.
func (*Provider) Entries ¶
Entries returns validation units in deterministic order: orgs A→Z, explicit repos within each org A→Z, the wildcard entry last. Each entry's Channel is the resolved channel (the tier's own, or inherited from org/*), so the validator and lock operate on what a webhook would actually route to.
type ReactionsOverride ¶ added in v0.18.0
type ReactionsOverride struct {
Enabled *bool
NewPR *string
MergedPR *string
ClosedPR *string
Approved *string
Commented *string
RequestChange *string
BotReview *string
}
ReactionsOverride is a tier's optional reaction overrides; each nil field inherits from a less-specific tier (org/* then the global config.yaml set).
func (*ReactionsOverride) UnmarshalYAML ¶ added in v0.18.0
func (r *ReactionsOverride) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML walks the reactions mapping by hand so unknown keys are rejected and every leaf is optional (nil = inherit).
type RepoConfig ¶ added in v0.18.0
type RepoConfig struct {
Channel string
Mentions []string
MentionsPresent bool
Reactions *ReactionsOverride
IgnoreAIReviews *bool
DependabotFormat *bool
Digest *DigestConfig
}
RepoConfig is one tier (org/repo or org/*). Phase A carries routing only. An empty Channel means this tier does not set a channel (it inherits). MentionsPresent distinguishes an absent mentions key (inherit) from an explicit empty list (ping nobody).
func (*RepoConfig) UnmarshalYAML ¶ added in v0.18.0
func (rc *RepoConfig) UnmarshalYAML(node *yaml.Node) error
UnmarshalYAML walks the mapping node by hand so we can keep the mentions tri-state (absent vs [] vs null) and reject unknown keys, mirroring the 0.17 Org decoder but at the per-repo tier level.