domain

package
v0.22.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package domain holds the routing domain's contracts: the ports, DTOs, enums, constants, and pure validation for resolving a repository (and a PR's changed files) to the Slack channel(s) and behavioural config that apply, across the global/org/repo tiers and monorepo path rules.

It depends only on the standard library, the shared kernel, and the YAML codec used to decode the mappings section of config.yaml onto these types (transition debt: the wire-decoding lives on the domain types until a later phase splits wire types from domain types). It never imports application, infrastructure, or a platform client (store/slack/github).

Index

Constants

View Source
const ChannelMention = "<!channel>"

ChannelMention is the Slack wire token used when an entry omits the `mentions:` key — operators see `@channel` in Slack.

View Source
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).

View Source
const WildcardKey = "*"

WildcardKey is the org-level tier key (the literal "*"): it both supplies defaults that explicit repo tiers inherit and matches any repo not named explicitly.

Variables

View Source
var ErrNotFound = errors.New("store: not found")

ErrNotFound is returned when a repository resolves to no mapping. It is the routing provider's port-contract sentinel. The message string is retained verbatim ("store: not found") so store.ErrNotFound can alias this value during the migration without changing any error text or errors.Is behaviour.

Functions

This section is empty.

Types

type ChangedFilesReader

type ChangedFilesReader interface {
	ListPullRequestFiles(ctx context.Context, owner, repo string, number int) ([]string, error)
}

ChangedFilesReader fetches the repo-relative paths a PR touches. The GitHub client satisfies it.

type Defaults

type Defaults struct {
	Reactions        Reactions
	IgnoreAIReviews  bool
	DependabotFormat bool
	// GitProvider is the deployment's single git_provider; the Provider stamps it
	// on every entry so it hashes into the lock (see Entry.Provider).
	GitProvider kernel.Provider
}

Defaults is the global tier: the config.yaml top-level behavioral settings that per-repo tiers override.

type DigestConfig

type DigestConfig struct {
	Enabled  bool
	Schedule string
	Timezone string
}

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.

type Entry

type Entry struct {
	Org      string
	Repo     string // empty when Wildcard is true
	Wildcard bool
	Channel  string
	Mentions []string
	// PathChannels are the distinct channels a repo's `paths:` rules add on top
	// of Channel (sorted, deduped). They feed both validation (bot membership)
	// and the entry hash, so adding or repointing a path channel re-triggers
	// validation. Always empty for a wildcard entry (paths are named-tier only).
	PathChannels []string
	// Provider is the deployment's git_provider (e.g. "github"). It hashes into
	// every entry so flipping the provider — under which the same org/repo names
	// point at different remote objects — revalidates the whole lock.
	Provider kernel.Provider
}

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

func (e Entry) Hash() string

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.

func (Entry) Key

func (e Entry) Key() string

Key returns the lock-file key for the entry: "org/repo" or "org/*".

type File

type File struct {
	Digest   *DigestConfig  `yaml:"digest"`
	Mappings map[string]Org `yaml:"mappings"`
}

File is the parsed mappings.yaml document.

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 PathRule

type PathRule struct {
	Dir             string
	Channel         string
	Mentions        []string
	MentionsPresent bool
}

PathRule is one entry in a repo tier's `paths:` block: a normalized directory and the routing applied to files under it. Channel/Mentions carry the same tri-state inheritance as a repo tier (empty Channel inherits; MentionsPresent distinguishes absent from an explicit empty list).

type Reactions

type Reactions struct {
	Enabled       bool
	NewPR         string
	MergedPR      string
	ClosedPR      string
	Approved      string
	Commented     string
	RequestChange string
	BotReview     string
}

Reactions is the resolved per-repo reaction-emoji set (Slack emoji names without colons). Enabled gates whether close/review reactions are added at all. Empty BotReview disables the bot-reviewer marker.

type ReactionsOverride

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).

type RepoConfig

type RepoConfig struct {
	Channel         string
	Mentions        []string
	MentionsPresent bool

	Reactions        *ReactionsOverride
	IgnoreAIReviews  *bool
	DependabotFormat *bool
	Digest           *DigestConfig

	// Paths is the optional per-directory routing for a monorepo, in
	// declaration order (order is significant for tie-breaking). Only valid on
	// a named repo tier — ValidateMappings rejects it on the "*" tier.
	Paths []PathRule
}

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).

type RepoMapping

type RepoMapping struct {
	Repository   string
	SlackChannel string
	Mentions     []string
	// Resolved per-repo behavioral config (global config.yaml defaults merged
	// with org/* and org/repo overrides). Formatting-only — not part of
	// validation or the lock.
	Reactions        Reactions
	IgnoreAIReviews  bool
	DependabotFormat bool
}

RepoMapping is the value object handlers and validators consume — a GitHub repository routed to a Slack channel with an optional mentions list, and resolved behavioral config (global defaults merged with org/* and org/repo overrides). The source of truth for routing lives in config.yaml's mappings: section (loaded by internal/config / internal/mappings); the type stays here so consumers don't have to know who produced it.

type Resolved

type Resolved struct {
	Channel  string
	Mentions []string
}

Resolved is the effective routing config for one repository after merging the org/repo tier over the org/* tier.

type RoutingProvider

type RoutingProvider interface {
	// Get returns the resolved mapping for "org/repo", or ErrNotFound when no
	// tier matches.
	Get(ctx context.Context, repository string) (RepoMapping, error)
	// RepoHasPathRules reports whether the repository configures a `paths:` block.
	RepoHasPathRules(repository string) bool
	// TargetsForFiles returns the fan-out destinations for a PR touching files.
	TargetsForFiles(repository string, files []string) []Target
}

RoutingProvider resolves a repository to its behavioural mapping and, for a monorepo with path rules, the per-channel fan-out targets for a set of changed files. The application-layer provider satisfies it; the per-PR router depends on it.

type Target

type Target struct {
	Channel  string
	Mentions []string
}

Target is one fan-out destination resolved for a PR: a channel and the mentions to ping there. Produced by the mappings resolver, consumed by the open handler.

type TargetResolver

type TargetResolver interface {
	ResolveTargets(ctx context.Context, repository string, prNumber int) (RepoMapping, []Target, error)
}

TargetResolver resolves the per-PR fan-out: the repository's behaviour plus the per-channel targets, layering path rules over the base tier when a changed-files reader is available.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL