store

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Jun 30, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package store owns the database schema, GORM models, repositories, and the goose-driven migration runner. Callers depend on small interfaces declared where they consume the store (handler packages); only this package needs to know about GORM.

Index

Constants

This section is empty.

Variables

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

ErrNotFound is returned when a lookup matches no row.

Functions

func MigrateDown

func MigrateDown(ctx context.Context, db *gorm.DB) error

MigrateDown rolls back the most recent migration.

func MigrateStatus

func MigrateStatus(ctx context.Context, db *gorm.DB) (string, error)

MigrateStatus returns a human-readable list of each migration and whether it has been applied.

func MigrateUp

func MigrateUp(ctx context.Context, db *gorm.DB) error

MigrateUp applies all pending migrations.

func NewTestDB

func NewTestDB(t *testing.T) *gorm.DB

NewTestDB returns a *gorm.DB backed by a fresh on-disk SQLite database inside t.TempDir, with all migrations applied. The database is closed and removed automatically when the test completes.

We use an on-disk file rather than `:memory:` because the goose-sqlite driver expects a stable database name to record migration state, and multiple in-memory connections in the same process are not always shared.

func Open

func Open(url string) (*gorm.DB, error)

Open opens a SQLite database for production use. The url accepts either a raw file path or the "file:..." DSN form used in our config defaults.

GORM's logger is silenced for "record not found" because we treat ErrNotFound as a normal return value, not a warning condition.

func RawCreateForTest

func RawCreateForTest(db *gorm.DB, pr PullRequest) error

RawCreateForTest inserts a pull_requests row preserving the caller's CreatedAt/UpdatedAt/ClosedAt, bypassing GORM's autoCreate/UpdateTime. Used by tests that need to seed PRs with a controlled age and open/closed state. A zero CreatedAt defaults to UpdatedAt.

func SQLDB

func SQLDB(db *gorm.DB) (*sql.DB, error)

SQLDB returns the underlying *sql.DB. Useful for the migrate binary which hands the connection to goose.

Types

type Message added in v0.20.0

type Message struct {
	ID            uint   `gorm:"primaryKey"`
	PullRequestID uint   `gorm:"column:pull_request_id;not null"`
	Channel       string `gorm:"column:channel;not null"`
	MessageID     string `gorm:"column:message_id;not null"`
}

Message is one posted messenger message for a PR. (PullRequestID, Channel) is unique — at most one message per channel per PR. Channel is a room in the messenger; MessageID is the messenger's id for the post (Slack's ts).

func (Message) TableName added in v0.20.0

func (Message) TableName() string

TableName pins the table name.

type PullRequest added in v0.20.0

type PullRequest struct {
	ID         uint       `gorm:"primaryKey"`
	Repository string     `gorm:"column:gh_repository;not null"`
	PRNumber   int        `gorm:"column:pr_number;not null"`
	CreatedAt  time.Time  `gorm:"column:created_at;not null"`
	UpdatedAt  time.Time  `gorm:"column:updated_at;not null"`
	ClosedAt   *time.Time `gorm:"column:closed_at"`
	Messages   []Message  `gorm:"foreignKey:PullRequestID;constraint:OnDelete:CASCADE"`
}

PullRequest is one tracked PR. (Repository, PRNumber) is the natural key; CreatedAt is kept for later statistics, UpdatedAt is the activity clock (bumped on open and every review/comment) driving digest idle-detection and cleanup, and ClosedAt (nil = open) marks merged/closed so the digest skips it.

func (PullRequest) TableName added in v0.20.0

func (PullRequest) TableName() string

TableName pins the table name; do not rely on GORM pluralization.

type PullRequests added in v0.20.0

type PullRequests struct {
	// contains filtered or unexported fields
}

PullRequests persists tracked PRs and their per-channel messenger messages.

func NewPullRequests added in v0.20.0

func NewPullRequests(db *gorm.DB) *PullRequests

NewPullRequests constructs a PullRequests repository bound to db.

func (*PullRequests) AddMessage added in v0.20.0

func (r *PullRequests) AddMessage(ctx context.Context, repository string, prNumber int, channel, messageID string) error

AddMessage records one posted message, creating the PR row on first sight. Insertion is idempotent on (pull_request_id, channel): re-adding the same channel for the same PR is a no-op, which makes the open fan-out safe to replay after a partial failure or GitHub redelivery.

func (*PullRequests) Delete added in v0.20.0

func (r *PullRequests) Delete(ctx context.Context, repository string, prNumber int) error

Delete removes the PR and (by cascade) its messages. Missing PR is a no-op.

func (*PullRequests) DeleteStaleBefore added in v0.20.0

func (r *PullRequests) DeleteStaleBefore(ctx context.Context, cutoff time.Time) (int64, error)

DeleteStaleBefore removes PRs idle since before cutoff (messages cascade).

func (*PullRequests) FindStuck added in v0.20.0

func (r *PullRequests) FindStuck(ctx context.Context, cutoff time.Time) ([]PullRequest, error)

FindStuck returns open PRs idle since before cutoff, messages preloaded, oldest first.

func (*PullRequests) ListOpen added in v0.20.0

func (r *PullRequests) ListOpen(ctx context.Context) ([]PullRequest, error)

ListOpen returns every not-yet-closed PR, ordered for stable output.

func (*PullRequests) MarkClosed added in v0.20.0

func (r *PullRequests) MarkClosed(ctx context.Context, repository string, prNumber int) error

MarkClosed sets closed_at. Missing PR is a no-op.

func (*PullRequests) Messages added in v0.20.0

func (r *PullRequests) Messages(ctx context.Context, repository string, prNumber int) ([]Message, error)

Messages returns the PR's messages, or ErrNotFound when the PR is unknown.

func (*PullRequests) Touch added in v0.20.0

func (r *PullRequests) Touch(ctx context.Context, repository string, prNumber int) error

Touch bumps updated_at, recording activity. Missing PR is a no-op.

type Reactions added in v0.18.0

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 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 Target added in v0.20.0

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.

Jump to

Keyboard shortcuts

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