store

package
v0.18.0 Latest Latest
Warning

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

Go to latest
Published: Jun 26, 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, m SlackMessage) error

RawCreateForTest inserts a SlackMessage row preserving the caller's UpdatedAt and ClosedAt values, bypassing GORM's autoUpdateTime. Used by tests that need to seed rows with a controlled age and open/closed state.

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 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 SlackMessage

type SlackMessage struct {
	PRNumber   int        `gorm:"column:pr_number;primaryKey"`
	Repository string     `gorm:"column:gh_repository;primaryKey"`
	TS         string     `gorm:"column:ts;not null"`
	UpdatedAt  time.Time  `gorm:"column:updated_at;autoUpdateTime;not null"`
	ClosedAt   *time.Time `gorm:"column:closed_at"`
}

SlackMessage tracks the Slack message thread-timestamp for one PR in one repository. (PRNumber, Repository) is the composite primary key — replaying the same PR event simply updates the TS.

UpdatedAt is bumped on Save (autoUpdateTime) and on Touch (review/comment activity); it drives both the scheduled cleanup of stale rows and the stuck-PR digest's idle detection. ClosedAt is set when the PR is merged/closed so the digest skips it; nil means the PR is still open.

func (SlackMessage) TableName

func (SlackMessage) TableName() string

TableName pins the table name to match the migration; do not rely on GORM's pluralisation heuristics.

type SlackMessages

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

SlackMessages persists the Slack message TS associated with each PR.

func NewSlackMessages

func NewSlackMessages(db *gorm.DB) *SlackMessages

NewSlackMessages constructs a SlackMessages repository bound to db.

func (*SlackMessages) Delete

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

Delete removes the message; missing rows are a no-op (idempotent).

func (*SlackMessages) DeleteStaleBefore

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

DeleteStaleBefore removes every row whose updated_at is strictly older than cutoff. Returns the number of rows deleted. An empty table returns (0, nil).

func (*SlackMessages) FindStuck added in v0.16.0

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

FindStuck returns every open (closed_at IS NULL) message whose updated_at is strictly older than cutoff — the PRs that saw no activity since cutoff. Results are ordered oldest-first for stable digest output. An empty result is (nil, nil).

func (*SlackMessages) Get

func (r *SlackMessages) Get(ctx context.Context, repository string, prNumber int) (SlackMessage, error)

Get returns the message for the given (repository, prNumber), or ErrNotFound.

func (*SlackMessages) ListOpen added in v0.16.0

func (r *SlackMessages) ListOpen(ctx context.Context) ([]SlackMessage, error)

ListOpen returns every message not yet marked closed, ordered for stable output. Used by the one-time reconcile to check each row against its real PR state on GitHub. An empty result is (nil, nil).

func (*SlackMessages) MarkClosed added in v0.16.0

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

MarkClosed records that the PR has been merged/closed so the stuck-PR digest skips it. A missing row is a no-op (idempotent).

func (*SlackMessages) Save

Save upserts the message by composite key (pr_number, gh_repository). The `updated_at` column is bumped on every Save (both insert and update paths) to drive stale-row cleanup.

func (*SlackMessages) Touch added in v0.16.0

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

Touch bumps updated_at to the current time for the given PR, recording review/comment activity so the stuck-PR digest can tell idle PRs from active ones. A missing row is a no-op (idempotent).

Jump to

Keyboard shortcuts

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