forge

package
v1.39.1 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Overview

Package forge defines the Forge interface and shared types for source-code hosting integrations (GitHub, GitLab, …).

Concrete implementations: GitHubForge (github.go) and GitLabForge (gitlab.go).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CloneURL

func CloneURL(kind ForgeKind, slug, host, token string) string

CloneURL constructs the HTTPS clone URL for a repository.

func ExtractOwnerRepo

func ExtractOwnerRepo(rawURL string) (owner, repo string, ok bool)

ExtractOwnerRepo parses a full repository URL and splits it into owner and repo components. Only github.com and gitlab.com hosts are accepted.

GitLab nested groups are supported: "group/sub/repo" yields owner="group/sub", repo="repo".

func ExtractSlug

func ExtractSlug(input string) (string, bool)

ExtractSlug returns the canonical slug from any of the standard repository identifier forms (bare slug, HTTPS URL, SSH URL, bare host-prefix form). Returns ("", false) for any input that cannot be parsed as a valid slug.

GitLab subgroup paths (e.g. "group/sub/repo") are accepted and returned as the full slug ("group/sub/repo"). For strict two-segment enforcement use slugparse.Parse directly.

func IsRemote

func IsRemote(input string) bool

IsRemote reports whether input refers to a remote repository (i.e. it is not empty and not a local file-system path).

func NormalizeGitHubRepo added in v1.30.1

func NormalizeGitHubRepo(input string) (string, error)

NormalizeGitHubRepo converts a variety of GitHub repository identifier forms to the canonical "owner/repo" slug.

Types

type AppAuthConfig

type AppAuthConfig struct {
	// AppID is the numeric GitHub App ID (e.g. 3613880).
	AppID int64
	// InstallationID is the numeric installation ID for the target account.
	InstallationID int64
	// PrivateKeyPEM is the PEM-encoded RSA private key generated in App settings.
	PrivateKeyPEM []byte
}

AppAuthConfig holds the credentials for GitHub App authentication.

type AppConfig

type AppConfig struct {
	AppID          int64
	InstallationID int64
	// KeyPEM is the PEM-encoded RSA private key. Empty means App auth disabled.
	KeyPEM []byte
}

AppConfig carries optional GitHub App credentials. When all three fields are non-zero, App authentication is used in place of a static PAT.

func (AppConfig) IsConfigured added in v1.20.0

func (a AppConfig) IsConfigured() bool

IsConfigured reports whether all three App credentials are present. When false, callers should fall back to a static PAT.

type AppTokenSource

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

AppTokenSource returns installation access tokens, refreshing automatically. Concurrency-safe: a singleflight group de-duplicates concurrent refreshes so the network call happens at most once even under N goroutines.

func NewAppTokenSource

func NewAppTokenSource(cfg AppAuthConfig) (*AppTokenSource, error)

NewAppTokenSource parses the PEM key and returns a ready AppTokenSource. Returns an error if the PEM is missing, malformed, or not an RSA key.

func (*AppTokenSource) Token

func (a *AppTokenSource) Token(ctx context.Context) (string, error)

Token returns a valid installation access token, refreshing when within refreshLeeway of expiry. Falls back to the cached token on network errors if the cache is still valid.

The hot path takes only a read lock. Concurrent refreshes are coalesced via singleflight so the HTTP roundtrip happens at most once.

type CodeResult

type CodeResult struct {
	Name    string
	Path    string
	URL     string
	Repo    string
	Content string // joined text-match fragments
}

CodeResult represents a single result from a code search.

type CodeSearchResult added in v1.29.0

type CodeSearchResult struct {
	Results    []CodeResult
	Total      int
	Query      string
	Incomplete bool
}

CodeSearchResult is the full result of a code search.

type Forge

type Forge interface {
	// Kind returns the ForgeKind for this implementation.
	Kind() ForgeKind

	// FetchRepoMeta returns metadata for the repository identified by slug
	// ("owner/repo" or a full URL).
	FetchRepoMeta(ctx context.Context, slug string) (*RepoMeta, error)

	// FetchREADME returns the raw README content for the repository.
	// Implementations should return an empty string (not an error) when no
	// README exists.
	FetchREADME(ctx context.Context, slug string) (string, error)

	// SearchCode searches for code matching query, optionally restricted to
	// the given repos ("owner/repo" slugs).
	SearchCode(ctx context.Context, query string, repos []string, opts ...SearchCodeOptions) (CodeSearchResult, error)

	// SearchIssues searches issues and pull requests matching query.
	SearchIssues(ctx context.Context, query string) ([]IssueItem, error)

	// SearchRepos searches for repositories matching query.
	// sort may be forge-specific (e.g. "stars", "forks", "updated") or empty
	// for relevance ordering.
	SearchRepos(ctx context.Context, query, sort string) ([]RepoSearchResult, error)
}

Forge is the common interface that every forge implementation must satisfy.

type ForgeKind

type ForgeKind int

ForgeKind identifies the type of a forge.

const (
	// Unknown is returned when the forge type cannot be determined.
	Unknown ForgeKind = iota
	// GitHub represents github.com.
	GitHub
	// GitLab represents gitlab.com or a self-hosted GitLab instance.
	GitLab
)

func DetectForge

func DetectForge(input string) ForgeKind

DetectForge infers the ForgeKind from a repository identifier.

Rules (evaluated in order):

  1. Empty string → Unknown.
  2. Local path prefix ("/", "./", "../") → Unknown.
  3. URL with host github.com → GitHub.
  4. URL with host gitlab.com → GitLab.
  5. Other URL → Unknown.
  6. SSH form git@github.com:… → GitHub.
  7. SSH form git@gitlab.com:… → GitLab.
  8. Bare slug with host prefix (github.com/… or gitlab.com/…) → appropriate forge.
  9. Bare owner/repo slug (no host prefix) → GitHub (default forge).

func (ForgeKind) String

func (k ForgeKind) String() string

String returns the lowercase name of the forge kind.

type GitHubForge

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

GitHubForge implements Forge for github.com.

func NewGitHubForge

func NewGitHubForge(token string, app AppConfig, opts ...GitHubForgeOption) *GitHubForge

NewGitHubForge creates a GitHubForge targeting api.github.com.

Authentication priority (first match wins):

  1. App auth — when app.AppID, app.InstallationID, and app.KeyPEM are all non-zero. Uses installation access tokens (separate 5000/h pool from the user's gh CLI PAT). Falls back to PAT on key-parse error (logged as warning).
  2. PAT — when token is non-empty.
  3. Unauthenticated — 60 req/h rate limit.

func (*GitHubForge) FetchREADME

func (g *GitHubForge) FetchREADME(ctx context.Context, slug string) (_ string, err error)

FetchREADME implements Forge. Returns empty string (not an error) when no README exists.

func (*GitHubForge) FetchRepoMeta

func (g *GitHubForge) FetchRepoMeta(ctx context.Context, slug string) (_ *RepoMeta, err error)

FetchRepoMeta implements Forge.

func (*GitHubForge) Kind

func (g *GitHubForge) Kind() ForgeKind

Kind implements Forge.

func (*GitHubForge) PostCommitComment

func (g *GitHubForge) PostCommitComment(ctx context.Context, slug, sha, body string) (string, error)

PostCommitComment posts a comment on a specific commit SHA.

func (*GitHubForge) PostIssueComment

func (g *GitHubForge) PostIssueComment(ctx context.Context, slug string, number int, body string) (string, error)

PostIssueComment posts a comment on a PR or issue thread.

func (*GitHubForge) PostReview

func (g *GitHubForge) PostReview(ctx context.Context, slug string, pr int, p ReviewPayload) (string, error)

PostReview posts a pull request review (body + inline comments).

func (*GitHubForge) SearchCode

func (g *GitHubForge) SearchCode(ctx context.Context, query string, repos []string, opts ...SearchCodeOptions) (CodeSearchResult, error)

SearchCode implements Forge. It supports repo restriction, language/extension filters, exclude_repos, min_stars, sort/order, pagination and result caching.

func (*GitHubForge) SearchIssues

func (g *GitHubForge) SearchIssues(ctx context.Context, query string) (_ []IssueItem, err error)

SearchIssues implements Forge.

func (*GitHubForge) SearchRepos

func (g *GitHubForge) SearchRepos(ctx context.Context, query, sort string) (_ []RepoSearchResult, err error)

SearchRepos implements Forge. sort may be "stars", "forks", "updated", or "" for relevance.

type GitHubForgeOption added in v1.29.0

type GitHubForgeOption func(*GitHubForge)

GitHubForgeOption configures a GitHubForge.

func WithCache added in v1.29.0

func WithCache(c *kitcache.Cache) GitHubForgeOption

WithCache sets the cache used by GitHubForge.

type GitLabForge

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

GitLabForge implements Forge for gitlab.com and self-hosted GitLab instances.

func NewGitLabForge

func NewGitLabForge(token, apiBase string) *GitLabForge

NewGitLabForge creates a GitLabForge targeting gitlab.com. token may be empty for unauthenticated requests (lower rate limits). If apiBase is empty, defaults to "https://gitlab.com".

func (*GitLabForge) FetchREADME

func (g *GitLabForge) FetchREADME(ctx context.Context, slug string) (_ string, err error)

FetchREADME implements Forge. Returns empty string (not an error) when no README exists.

func (*GitLabForge) FetchRepoMeta

func (g *GitLabForge) FetchRepoMeta(ctx context.Context, slug string) (_ *RepoMeta, err error)

FetchRepoMeta implements Forge.

func (*GitLabForge) Kind

func (g *GitLabForge) Kind() ForgeKind

Kind implements Forge.

func (*GitLabForge) PostCommitComment

func (g *GitLabForge) PostCommitComment(_ context.Context, _, _, _ string) (string, error)

func (*GitLabForge) PostIssueComment

func (g *GitLabForge) PostIssueComment(_ context.Context, _ string, _ int, _ string) (string, error)

func (*GitLabForge) PostReview

func (g *GitLabForge) PostReview(_ context.Context, _ string, _ int, _ ReviewPayload) (string, error)

func (*GitLabForge) SearchCode

func (g *GitLabForge) SearchCode(ctx context.Context, query string, repos []string, opts ...SearchCodeOptions) (CodeSearchResult, error)

SearchCode implements Forge. GitLab code search is per-project, so we iterate over repos. When repos is empty we return an empty result — GitLab has no global code search in v4 REST.

func (*GitLabForge) SearchIssues

func (g *GitLabForge) SearchIssues(ctx context.Context, query string) (_ []IssueItem, err error)

SearchIssues implements Forge. Extracts a repo slug from "repo:owner/name" token in query if present, then searches that project's issues. Falls back to empty when no repo specified.

func (*GitLabForge) SearchRepos

func (g *GitLabForge) SearchRepos(ctx context.Context, query, _ string) (_ []RepoSearchResult, err error)

SearchRepos implements Forge. Uses the GitLab projects listing API, sorted by star_count descending.

type InlineComment

type InlineComment struct {
	Path string // repo-relative
	Line int    // 1-based, on the diff's new side
	Body string
}

InlineComment is a single file:line suggestion.

type IssueItem

type IssueItem struct {
	Number    int
	Title     string
	URL       string
	State     string
	Author    string
	Labels    []string
	Body      string
	Comments  int
	CreatedAt string
	MergedAt  string
	Repo      string
}

IssueItem represents an issue or pull request from a forge search.

type Poster

type Poster interface {
	PostReview(ctx context.Context, slug string, pr int, p ReviewPayload) (htmlURL string, err error)
	PostIssueComment(ctx context.Context, slug string, number int, body string) (htmlURL string, err error)
	PostCommitComment(ctx context.Context, slug, sha, body string) (htmlURL string, err error)
}

Poster is the write-side of a forge. Separate from Forge so forges that cannot post (yet) stay compilable.

type Registry

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

Registry holds configured forge implementations and dispatches by URL.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates an empty forge registry.

func (*Registry) ForURL

func (r *Registry) ForURL(input string) Forge

ForURL detects the forge from the input URL/slug and returns the matching implementation. Returns nil if no matching forge is registered.

func (*Registry) Get

func (r *Registry) Get(kind ForgeKind) Forge

Get returns the forge for the given kind, or nil if not registered.

func (*Registry) Register

func (r *Registry) Register(kind ForgeKind, f Forge)

Register adds a forge implementation for the given kind.

type RepoMeta

type RepoMeta struct {
	// FullName is the "owner/repo" slug.
	FullName string `json:"full_name"`

	// Description is the repository description.
	Description string `json:"description"`

	// DefaultBranch is the default branch name.
	DefaultBranch string `json:"default_branch"`

	// Language is the primary programming language.
	Language string `json:"language"`

	// Stars is the stargazer count.
	Stars int `json:"stargazers_count"`

	// Forks is the fork count.
	Forks int `json:"forks_count"`

	// CloneURL is the HTTPS clone URL.
	CloneURL string `json:"clone_url"`

	// Private indicates whether the repository is private.
	Private bool `json:"private"`

	// Size is the approximate disk size in kilobytes.
	Size int `json:"size"`
}

RepoMeta contains key metadata about a repository. JSON tags are present so implementations can decode API responses directly into this type.

type RepoSearchResult

type RepoSearchResult struct {
	FullName    string
	Description string
	Stars       int
	Language    string
	Topics      []string
	LastPush    string
	Archived    bool
	HTMLURL     string
}

RepoSearchResult represents a repository returned by a forge search.

type RetryConfig added in v1.29.0

type RetryConfig struct {
	MaxRetries  int
	InitialWait time.Duration
	MaxWait     time.Duration
	Multiplier  float64
}

RetryConfig controls the exponential backoff for transient failures.

type ReviewPayload

type ReviewPayload struct {
	Body     string          // summary markdown
	Event    string          // "COMMENT", "REQUEST_CHANGES", "APPROVE"
	Comments []InlineComment // inline findings
}

ReviewPayload is the body of a PR review.

type SearchCodeOptions added in v1.29.0

type SearchCodeOptions struct {
	ExcludeRepos   []string
	FileExtensions []string
	Language       string
	Sort           string
	Order          string
	MinStars       int
	MaxResults     int
	PerPage        int
	Page           int
	// MaxFragmentChars limits each text-match fragment. 0 means no limit.
	MaxFragmentChars int
	// MaxTotalChars limits the total joined content per result. 0 means no limit.
	MaxTotalChars int
}

SearchCodeOptions holds optional server-side filters for code search.

Jump to

Keyboard shortcuts

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