vcs

package
v0.10.0 Latest Latest
Warning

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

Go to latest
Published: Mar 23, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package vcs defines the VCS (Version Control System) provider interface that abstracts platform-specific operations (PR creation, merging, status checks, etc.) so Forge can work with GitHub, GitLab, Forgejo, Bitbucket, and Azure DevOps.

The GitHub implementation lives in the vcs/github sub-package.

Index

Constants

This section is empty.

Variables

View Source
var ErrPRAlreadyExists = errors.New("pull request already exists for branch")

ErrPRAlreadyExists is returned by CreatePR when a PR already exists for the given branch. Callers should use errors.Is to check for this sentinel.

ValidPlatforms is the set of recognised platform values.

Functions

func ParseGitLabRepoURL

func ParseGitLabRepoURL(rawURL string) (owner, repo string, err error)

ParseGitLabRepoURL parses a git remote URL into namespace (owner) and project name. Supports both HTTPS and SSH URLs, including nested groups.

func ParseGiteaRepoURL

func ParseGiteaRepoURL(rawURL string) (baseURL, owner, repo string, err error)

ParseGiteaRepoURL parses a git remote URL into base URL, owner, and repo name. Supports HTTPS, HTTP, SCP-style SSH (git@host:path), and ssh:// scheme URLs.

HTTPS: https://gitea.example.com/owner/repo.git → ("https://gitea.example.com", "owner", "repo") SSH: git@gitea.example.com:owner/repo.git → ("https://gitea.example.com", "owner", "repo") SSH: ssh://git@gitea.example.com:2222/owner/repo → ("https://gitea.example.com", "owner", "repo")

Note: SCP-style URLs (git@host:path) do NOT support port numbers; the part after ":" is always interpreted as a path. For custom SSH ports, use the ssh:// scheme instead. SSH URLs cannot convey whether the API is served over HTTP or HTTPS — the base URL defaults to HTTPS. Set GITEA_URL or FORGEJO_URL to override.

func RegisterGitHubProvider

func RegisterGitHubProvider(f func() Provider)

RegisterGitHubProvider registers the GitHub provider factory. Called from init() in internal/vcs/github.

Types

type CICheck

type CICheck struct {
	Name   string // check name
	Status string // platform-normalized: "pass", "fail", "pending"
	Link   string // platform-specific URL to the check run details
}

CICheck represents a CI check result from the platform.

type CheckRun

type CheckRun struct {
	Name       string
	Status     string // CheckRun: QUEUED, IN_PROGRESS, COMPLETED, WAITING, PENDING, REQUESTED
	Conclusion string // CheckRun: SUCCESS, FAILURE, NEUTRAL, SKIPPED, CANCELLED, TIMED_OUT, etc.
	// State and Context are populated for GitHub StatusContext items.
	State   string // StatusContext: PENDING, SUCCESS, FAILURE, ERROR, EXPECTED
	Context string // StatusContext: the check name (e.g., "ci/build")
}

CheckRun represents a CI check on a PR.

GitHub's statusCheckRollup returns two types: CheckRun (GitHub Actions) and StatusContext (legacy commit status API). They use different field schemas:

  • CheckRun: Name, Status (QUEUED/IN_PROGRESS/COMPLETED/…), Conclusion (SUCCESS/FAILURE/…)
  • StatusContext: Context (the check name), State (PENDING/SUCCESS/FAILURE/ERROR/EXPECTED)

Both types are deserialized into this struct. Callers should use the helper methods (CIsInProgress, CIsPassing) which handle both schemas.

type CreateParams

type CreateParams struct {
	// WorktreePath is the git worktree directory to run CLI commands from.
	WorktreePath string
	// BeadID to reference in the PR.
	BeadID string
	// Title for the PR (auto-generated if empty).
	Title string
	// Body for the PR (auto-generated if empty).
	Body string
	// Branch is the feature branch name.
	Branch string
	// Base is the target branch (default: main).
	Base string
	// AnvilName for state tracking.
	AnvilName string
	// Draft creates a draft PR if true.
	Draft bool

	// BeadTitle is the bead's human-readable title (used in the PR body).
	BeadTitle string
	// BeadDescription is the bead's problem/task description (used in the PR body).
	BeadDescription string
	// BeadType is the bead's issue type (bug, feature, task, etc.).
	BeadType string
	// ChangeSummary is a summary of what changed (from warden review or diff stat).
	ChangeSummary string
}

CreateParams holds the inputs for creating a pull/merge request.

type GitLabProvider

type GitLabProvider struct{}

GitLabProvider implements the Provider interface for GitLab using the glab CLI.

func NewGitLabProvider

func NewGitLabProvider() *GitLabProvider

NewGitLabProvider returns a new GitLab VCS provider.

func (*GitLabProvider) CheckStatus

func (g *GitLabProvider) CheckStatus(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

CheckStatus returns the full status of a merge request.

func (*GitLabProvider) CheckStatusLight

func (g *GitLabProvider) CheckStatusLight(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

CheckStatusLight returns a lightweight status focused on reviewRequests and mergeability. It fetches pending review requests in addition to the basic MR view, since callers (e.g. immediately after PR creation) rely on ReviewRequests being populated.

func (*GitLabProvider) CreatePR

func (g *GitLabProvider) CreatePR(ctx context.Context, params CreateParams) (*PR, error)

CreatePR creates a merge request using the glab CLI.

func (*GitLabProvider) FetchCILogs

func (g *GitLabProvider) FetchCILogs(ctx context.Context, worktreePath string, checks []CICheck) (map[string]string, error)

FetchCILogs fetches CI job logs from GitLab pipelines for failing checks.

func (*GitLabProvider) FetchPRChecks

func (g *GitLabProvider) FetchPRChecks(ctx context.Context, worktreePath string, prNumber int) (string, []CICheck, error)

FetchPRChecks returns CI check results for a merge request by inspecting the head pipeline jobs.

func (*GitLabProvider) FetchPendingReviewRequests

func (g *GitLabProvider) FetchPendingReviewRequests(ctx context.Context, worktreePath string, prNumber int) ([]ReviewRequest, error)

FetchPendingReviewRequests returns pending review requests for a MR. GitLab uses approvers/approval rules rather than explicit review requests. We map unapproved required approvers to review requests.

func (*GitLabProvider) FetchReviewComments

func (g *GitLabProvider) FetchReviewComments(ctx context.Context, worktreePath string, prNumber int) ([]ReviewComment, error)

FetchReviewComments returns unresolved discussion threads and MR-level notes.

func (*GitLabProvider) FetchUnresolvedThreadCount

func (g *GitLabProvider) FetchUnresolvedThreadCount(ctx context.Context, worktreePath string, prNumber int) (int, error)

FetchUnresolvedThreadCount returns the number of unresolved discussion threads on a MR.

func (*GitLabProvider) GetRepoOwnerAndName

func (g *GitLabProvider) GetRepoOwnerAndName(ctx context.Context, worktreePath string) (owner, repo string, err error)

GetRepoOwnerAndName extracts the namespace (group/subgroup) and project name from the git remote.

func (*GitLabProvider) ListOpenPRs

func (g *GitLabProvider) ListOpenPRs(ctx context.Context, worktreePath string) ([]OpenPR, error)

ListOpenPRs returns all open merge requests in the repository.

func (*GitLabProvider) MergePR

func (g *GitLabProvider) MergePR(ctx context.Context, worktreePath string, prNumber int, strategy string) error

MergePR merges a merge request using the glab CLI. Valid strategies: "squash", "merge", "rebase". Defaults to "squash" if empty.

func (*GitLabProvider) Platform

func (g *GitLabProvider) Platform() Platform

Platform returns GitLab.

func (*GitLabProvider) ResolveThread

func (g *GitLabProvider) ResolveThread(ctx context.Context, worktreePath string, threadID string) error

ResolveThread resolves a discussion thread on a GitLab MR. The threadID is expected in the format "mrIID:discussionID" as produced by FetchReviewComments.

type GiteaProvider

type GiteaProvider struct{}

GiteaProvider implements the Provider interface for Gitea/Forgejo instances using the Gitea REST API v1. Authentication is via a personal access token supplied through the GITEA_TOKEN or FORGEJO_TOKEN environment variable.

func NewGiteaProvider

func NewGiteaProvider() *GiteaProvider

NewGiteaProvider returns a new Gitea/Forgejo VCS provider.

func (*GiteaProvider) CheckStatus

func (g *GiteaProvider) CheckStatus(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

CheckStatus returns the full status of a pull request.

func (*GiteaProvider) CheckStatusLight

func (g *GiteaProvider) CheckStatusLight(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

CheckStatusLight returns a lightweight status focused on mergeability and review requests.

func (*GiteaProvider) CreatePR

func (g *GiteaProvider) CreatePR(ctx context.Context, params CreateParams) (*PR, error)

CreatePR creates a pull request using the Gitea API.

func (*GiteaProvider) FetchCILogs

func (g *GiteaProvider) FetchCILogs(_ context.Context, _ string, _ []CICheck) (map[string]string, error)

FetchCILogs fetches CI job logs for failing checks from Gitea/Forgejo. Gitea does not expose a public API for retrieving raw job logs, so this method returns an empty map without error (graceful no-op).

func (*GiteaProvider) FetchPRChecks

func (g *GiteaProvider) FetchPRChecks(ctx context.Context, worktreePath string, prNumber int) (string, []CICheck, error)

FetchPRChecks returns CI check results for a Gitea/Forgejo pull request by inspecting the commit status of the PR head SHA.

func (*GiteaProvider) FetchPendingReviewRequests

func (g *GiteaProvider) FetchPendingReviewRequests(ctx context.Context, worktreePath string, prNumber int) ([]ReviewRequest, error)

FetchPendingReviewRequests returns pending review requests for a PR.

func (*GiteaProvider) FetchReviewComments

func (g *GiteaProvider) FetchReviewComments(ctx context.Context, worktreePath string, prNumber int) ([]ReviewComment, error)

FetchReviewComments returns review comments (changes-requested feedback) on a Gitea/Forgejo pull request. It iterates all reviews and collects inline comments from reviews with a CHANGES_REQUESTED state.

func (*GiteaProvider) FetchUnresolvedThreadCount

func (g *GiteaProvider) FetchUnresolvedThreadCount(ctx context.Context, worktreePath string, prNumber int) (int, error)

FetchUnresolvedThreadCount returns the number of unresolved review comments on a PR. Gitea tracks review comments rather than threaded discussions. We count review comments that have not been resolved.

func (*GiteaProvider) GetRepoOwnerAndName

func (g *GiteaProvider) GetRepoOwnerAndName(ctx context.Context, worktreePath string) (owner, repo string, err error)

GetRepoOwnerAndName extracts the owner and repository name from the git remote.

func (*GiteaProvider) ListOpenPRs

func (g *GiteaProvider) ListOpenPRs(ctx context.Context, worktreePath string) ([]OpenPR, error)

ListOpenPRs returns all open pull requests in the repository. It paginates through the Gitea API to collect all results.

func (*GiteaProvider) MergePR

func (g *GiteaProvider) MergePR(ctx context.Context, worktreePath string, prNumber int, strategy string) error

MergePR merges a pull request using the Gitea API. Valid strategies: "squash", "merge", "rebase". Defaults to "squash" if empty.

func (*GiteaProvider) Platform

func (g *GiteaProvider) Platform() Platform

Platform returns Gitea.

func (*GiteaProvider) ResolveThread

func (g *GiteaProvider) ResolveThread(_ context.Context, _ string, _ string) error

ResolveThread marks a review thread as resolved. Gitea does not expose a public API for resolving individual review threads, so this is a no-op.

type MergeabilityInputs

type MergeabilityInputs struct {
	HasConflicts         bool
	HasUnresolvedThreads bool
	HasPendingReviews    bool
}

MergeabilityInputs holds the computed boolean inputs for UpdatePRMergeability, extracted from a PRStatus.

func MergeabilityFromStatus

func MergeabilityFromStatus(s *PRStatus) MergeabilityInputs

MergeabilityFromStatus converts a PRStatus into mergeability inputs.

type OpenPR

type OpenPR struct {
	Number int
	Title  string
	Branch string
	Body   string
}

OpenPR is a lightweight view of a PR used for reconciliation.

type PR

type PR struct {
	Number  int
	URL     string
	Title   string
	Branch  string
	Base    string
	BeadID  string
	Anvil   string
	Created time.Time
}

PR represents a created pull/merge request, independent of the hosting platform.

type PRStatus

type PRStatus struct {
	// State is the PR lifecycle state. Platforms map their native values
	// to these canonical strings: "OPEN", "MERGED", "CLOSED".
	State             string
	StatusCheckRollup []CheckRun
	Reviews           []Review
	ReviewRequests    []ReviewRequest
	// Mergeable indicates conflict state. Canonical values:
	// "MERGEABLE", "CONFLICTING", "UNKNOWN".
	Mergeable         string
	UnresolvedThreads int
	HeadRefName       string
	URL               string
}

PRStatus represents the platform-agnostic state of a pull/merge request.

func (*PRStatus) CIsInProgress added in v0.9.0

func (s *PRStatus) CIsInProgress() bool

CIsInProgress returns true if any CI check is still running (not yet completed). GitHub check runs use Status values like "IN_PROGRESS", "QUEUED", "PENDING", or "WAITING". StatusContext items use State values like "PENDING" or "EXPECTED".

func (*PRStatus) CIsPassing

func (s *PRStatus) CIsPassing() bool

CIsPassing returns true if all CI checks have completed with a passing result. Checks that are still in progress are treated as not passing (their empty Conclusion does not match SUCCESS/NEUTRAL/SKIPPED). Use CIsInProgress() to distinguish "failing" from "not yet completed".

func (*PRStatus) HasApproval

func (s *PRStatus) HasApproval() bool

HasApproval returns true if at least one review is APPROVED.

func (*PRStatus) HasPendingReviewRequests

func (s *PRStatus) HasPendingReviewRequests() bool

HasPendingReviewRequests returns true if there are outstanding review requests.

func (*PRStatus) IsClosed

func (s *PRStatus) IsClosed() bool

IsClosed returns true if the PR has been closed without merging.

func (*PRStatus) IsMerged

func (s *PRStatus) IsMerged() bool

IsMerged returns true if the PR has been merged.

func (*PRStatus) NeedsChanges

func (s *PRStatus) NeedsChanges() bool

NeedsChanges returns true if any review requests changes or there are unresolved threads.

type Platform

type Platform string

Platform identifies a VCS hosting platform.

const (
	GitHub      Platform = "github"
	GitLab      Platform = "gitlab"
	Gitea       Platform = "gitea"
	Bitbucket   Platform = "bitbucket"
	AzureDevOps Platform = "azuredevops"
)

func ParsePlatform

func ParsePlatform(s string) (Platform, error)

ParsePlatform normalises and validates a platform string. It trims surrounding whitespace and folds the input to lowercase before matching, so "GitHub", " GITLAB ", etc. are accepted. An empty string defaults to GitHub.

type Provider

type Provider interface {
	// CreatePR creates a pull/merge request and returns its metadata.
	CreatePR(ctx context.Context, params CreateParams) (*PR, error)

	// MergePR merges the PR identified by prNumber using the given strategy
	// ("squash", "merge", or "rebase").
	MergePR(ctx context.Context, worktreePath string, prNumber int, strategy string) error

	// CheckStatus returns the full status of a PR including CI checks,
	// reviews, unresolved threads, and mergeability.
	CheckStatus(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

	// CheckStatusLight returns a lightweight status (no unresolved thread
	// count pagination). Use when only reviewRequests/mergeable are needed.
	CheckStatusLight(ctx context.Context, worktreePath string, prNumber int) (*PRStatus, error)

	// ListOpenPRs returns all open PRs in the repository.
	ListOpenPRs(ctx context.Context, worktreePath string) ([]OpenPR, error)

	// GetRepoOwnerAndName extracts the owner and repository name from the
	// git remote. The semantics of "owner" vary by platform (org, group,
	// project namespace, etc.).
	GetRepoOwnerAndName(ctx context.Context, worktreePath string) (owner, repo string, err error)

	// FetchUnresolvedThreadCount returns the number of unresolved review
	// threads on a PR. Platforms without thread resolution tracking should
	// return 0, nil.
	FetchUnresolvedThreadCount(ctx context.Context, worktreePath string, prNumber int) (int, error)

	// FetchPendingReviewRequests returns pending review requests, including
	// bot reviewers. Platforms that don't distinguish reviewer types may
	// return the standard review request list.
	FetchPendingReviewRequests(ctx context.Context, worktreePath string, prNumber int) ([]ReviewRequest, error)

	// FetchPRChecks returns the CI check results for a PR. The raw string
	// is a human-readable summary suitable for inclusion in prompts; the
	// CICheck slice contains only the failing checks parsed from the output.
	FetchPRChecks(ctx context.Context, worktreePath string, prNumber int) (raw string, failing []CICheck, err error)

	// FetchCILogs retrieves CI log output for the given failing checks.
	// Returns a map of check name → log text. Checks without available
	// logs are omitted from the result.
	FetchCILogs(ctx context.Context, worktreePath string, checks []CICheck) (map[string]string, error)

	// FetchReviewComments returns review comments and unresolved threads
	// on a PR, including PR-level review comments and inline thread comments.
	FetchReviewComments(ctx context.Context, worktreePath string, prNumber int) ([]ReviewComment, error)

	// ResolveThread marks a review thread as resolved. Platforms without
	// thread resolution support should return nil.
	ResolveThread(ctx context.Context, worktreePath string, threadID string) error

	// Platform returns which platform this provider implements.
	Platform() Platform
}

Provider is the interface that VCS platform implementations must satisfy. Each method corresponds to an operation Forge performs against the hosting platform (GitHub via gh CLI, GitLab via glab CLI, etc.).

func ForPlatform

func ForPlatform(platform string) (Provider, error)

ForPlatform returns a Provider for the given platform. An empty string defaults to GitHub. Unsupported platforms return an error. For GitHub, internal/vcs/github must be imported (e.g. via blank import) to register the provider factory before calling this function.

func NewGitHubProvider

func NewGitHubProvider() Provider

NewGitHubProvider returns a new GitHub VCS provider. Requires internal/vcs/github to have been imported (directly or via a blank import) so that its init() registers the factory.

type Review

type Review struct {
	Author ReviewAuthor
	State  string
	Body   string
}

Review represents a PR review.

type ReviewAuthor

type ReviewAuthor struct {
	Login string
}

ReviewAuthor identifies the author of a review.

type ReviewComment

type ReviewComment struct {
	Author   string // reviewer login
	Body     string // comment text
	Path     string // file path (empty for PR-level comments)
	Line     int    // line number (0 for PR-level comments)
	State    string // "CHANGES_REQUESTED", etc. (empty for thread comments)
	ThreadID string // platform-specific thread identifier
}

ReviewComment represents a review comment on a PR/MR.

type ReviewRequest

type ReviewRequest struct {
	Login string
	Slug  string
	Name  string
}

ReviewRequest represents a pending review request on a PR.

Directories

Path Synopsis
Package github implements the vcs.Provider interface for GitHub using the gh CLI.
Package github implements the vcs.Provider interface for GitHub using the gh CLI.

Jump to

Keyboard shortcuts

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