vcs

package
v1.2.2 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package vcs abstracts the version-control operations releasegen needs.

The Repo interface is defined here in the consumer package per Go best practice. The default implementation is GitRepo (in git.go), which uses go-git. Tests use mockery-generated mocks under internal/vcs/mocks.

Index

Constants

This section is empty.

Variables

View Source
var ErrVCS = errors.New("vcs error")

ErrVCS is the sentinel returned (wrapped) when any git-side operation (open, walk, commit, tag, push) fails. Callers should use errors.Is to branch on it for exit code mapping rather than scanning error strings.

Functions

func LatestTagForModule

func LatestTagForModule(tags []TagInfo, moduleName string) string

LatestTagForModule returns the most recent tag in tags belonging to the named module (empty name = root). It returns "" when no tag is found.

Types

type CommitTagPushOptions

type CommitTagPushOptions struct {
	ChangelogPath string
	ModuleName    string
	Version       string // bare semver
	Actor         string
	Token         string // pushed via basic auth
}

CommitTagPushOptions describes a single per-module commit + tag + push.

type GitRepo

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

GitRepo is a Repo implementation backed by go-git operating on an on-disk repository.

func Open

func Open(repoPath, branch string, log *slog.Logger) (*GitRepo, error)

Open opens the git repository at the given path and returns a GitRepo configured for the named release branch.

func (*GitRepo) AllChangelogPaths

func (g *GitRepo) AllChangelogPaths(ctx context.Context) ([]string, error)

AllChangelogPaths walks HEAD's tree and returns every CHANGELOG.md path.

func (*GitRepo) ChangedFiles added in v1.2.0

func (g *GitRepo) ChangedFiles(ctx context.Context, baseRef string) ([]string, error)

ChangedFiles returns the set of file paths that differ between the tree at baseRef and the state that *will be* at HEAD after the next commit — i.e. the union of the HEAD-vs-base tree diff and any path currently staged in the index. The HEAD-vs-base portion is a two-dot diff (HEAD vs baseRef directly), matching `git diff <base>` rather than the merge-base "three-dot" form.

Including the staged portion is essential for pre-commit use cases (e.g. a prenup hook). Without it, ChangedFiles would only see what is already in HEAD, which during a pre-commit hook is still the unchanged parent commit — and the caller would conclude "nothing changed" even when the developer has staged a hundred lines of new code.

Unstaged worktree edits and untracked files are deliberately ignored: they will not be in the commit being created, and counting them would (a) flag callers like `validate --require-changelog-entry` for local dirt unrelated to the commit and (b) disagree with FileAtIndex, which also reads the staged/index view.

baseRef may be any revision spec go-git can resolve (branch name, tag, remote-tracking ref like "origin/main", or a raw hash). When baseRef does not resolve, an error wrapping ErrVCS is returned so the caller can map it to a useful CI message ("did you fetch with depth 0?").

func (*GitRepo) CommitTagAndPush

func (g *GitRepo) CommitTagAndPush(ctx context.Context, opts CommitTagPushOptions) error

CommitTagAndPush stages, commits, pushes, tags, and pushes the tag for a single module release. Errors are wrapped with the failing step name so the caller can decide on recovery.

func (*GitRepo) FileAtIndex added in v1.2.1

func (g *GitRepo) FileAtIndex(ctx context.Context, filePath string) (string, error)

FileAtIndex returns the contents of filePath as it appears in the git index — i.e. the version that will be written to the next commit. This is the right "current state" for any pre-commit validation: comparing it against the base ref tells us what the resulting commit will contain, regardless of whether the developer has staged their changes or left them in the worktree.

When filePath is not in the index (untracked, or staged for deletion), the empty string is returned with a nil error so callers can treat it as "the file will not be in the next commit."

func (*GitRepo) FileAtRef added in v1.2.0

func (g *GitRepo) FileAtRef(ctx context.Context, ref, filePath string) (string, error)

FileAtRef returns the contents of the file at filePath as it appears in the tree of ref's commit. When the file does not exist in that tree the empty string is returned with a nil error — callers can treat this as "the file was added in HEAD." Other errors (unresolvable ref, unreadable blob) are wrapped with ErrVCS.

func (*GitRepo) IsChangelogModifiedSinceTag

func (g *GitRepo) IsChangelogModifiedSinceTag(ctx context.Context, changelogPath, tagName string) (bool, error)

IsChangelogModifiedSinceTag returns true if changelogPath was changed between the commit referenced by tagName and HEAD. When tagName is empty the function returns true (first release).

func (*GitRepo) ReachableTags

func (g *GitRepo) ReachableTags(ctx context.Context) ([]TagInfo, error)

ReachableTags returns all tags whose target commits are ancestors of the configured release branch tip.

type Repo

type Repo interface {
	// AllChangelogPaths returns every CHANGELOG.md file in HEAD's tree.
	AllChangelogPaths(ctx context.Context) ([]string, error)

	// ReachableTags returns all tags whose commits are reachable from the
	// configured release branch.
	ReachableTags(ctx context.Context) ([]TagInfo, error)

	// IsChangelogModifiedSinceTag reports whether the file at changelogPath
	// has been modified between the commit pointed at by tagName and HEAD.
	// When tagName is empty (no prior tag) the function returns true.
	IsChangelogModifiedSinceTag(ctx context.Context, changelogPath, tagName string) (bool, error)

	// CommitTagAndPush stages the changelog file, commits it with a
	// "[skip ci]" message, pushes the commit, creates an annotated tag for
	// the release name, and pushes the tag. It is intentionally a single
	// operation so the implementation can attempt cleanup on failure.
	CommitTagAndPush(ctx context.Context, opts CommitTagPushOptions) error
}

Repo is the abstraction the runner uses to interact with git. It is intentionally tiny so it can be mocked easily.

type TagInfo

type TagInfo struct {
	Name       string        // e.g. "v1.2.3" or "module/v1.2.3"
	ModuleName string        // empty for root tags
	Date       int64         // unix seconds (commit or tagger date)
	Hash       plumbing.Hash // the commit the tag points at
}

TagInfo describes a single tag reachable from the release branch.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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