forge

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Jun 5, 2026 License: AGPL-3.0, AGPL-3.0-only Imports: 16 Imported by: 0

Documentation

Overview

Package forge provides a platform-agnostic abstraction over git forges (GitLab, GitHub, Gitea/Forgejo). Every write operation (release creation, badge update, file commit, MR/PR creation) goes through this interface so StageFreight works identically regardless of where the repo is hosted.

Index

Constants

This section is empty.

Variables

View Source
var ErrBranchMoved = errors.New("target branch moved during commit")

ErrBranchMoved is returned when the target branch has moved since the expected SHA.

View Source
var ErrNotSupported = errors.New("operation not supported by this forge")

ErrNotSupported is returned when a forge does not support a particular operation.

Functions

func BaseURL

func BaseURL(remoteURL string) string

BaseURL extracts the forge base URL from a git remote URL. Handles SSH (git@host:path) and HTTPS (https://host/path) formats.

Types

type APIError

type APIError struct {
	Method     string
	URL        string
	StatusCode int
	Body       string
}

APIError is returned by doJSON when the API returns a non-2xx status.

func (*APIError) Error

func (e *APIError) Error() string

type Asset

type Asset struct {
	Name     string // display name
	FilePath string // local file to upload
	MIMEType string // e.g., "application/json"
}

Asset is a file to attach to a release.

type AzureDevOpsForge added in v0.6.0

type AzureDevOpsForge struct {
	// BaseURL is the organization collection URL, e.g. "https://dev.azure.com/myorg"
	// (Azure DevOps Services) or "https://server/tfs/DefaultCollection" (Server).
	BaseURL string
	Project string
	Repo    string
	Token   string // Personal Access Token (HTTP Basic, empty username)
}

AzureDevOpsForge is Azure DevOps's first-class forge client.

Azure differs structurally from the other forges: its addressing is organization → project → repository (not owner/repo), it authenticates with a PAT over HTTP Basic, every REST call carries an api-version, and — crucially — it has NO native git-release object. Release operations therefore return ErrNotSupported rather than being faked; tagging, PRs, commits, and content reads map to the Azure DevOps Git REST API (7.1).

TODO(azure-live-validation): endpoints and auth follow the documented Azure DevOps REST API but have NOT been exercised against a live instance. Run a real end-to-end pass (render → build → every client op) before treating this client as production-ready; until then it is experimental.

func NewAzureDevOps added in v0.6.0

func NewAzureDevOps(baseURL string) *AzureDevOpsForge

NewAzureDevOps creates an Azure DevOps client, resolving org/project/repo and the token from the Azure Pipelines environment when present.

SYSTEM_COLLECTIONURI  → BaseURL (org collection)
SYSTEM_TEAMPROJECT    → Project
BUILD_REPOSITORY_NAME → Repo
AZURE_DEVOPS_EXT_PAT / AZURE_DEVOPS_TOKEN / SYSTEM_ACCESSTOKEN → Token
func (a *AzureDevOpsForge) AddReleaseLink(ctx context.Context, releaseID string, link ReleaseLink) error

func (*AzureDevOpsForge) BranchHeadSHA added in v0.6.0

func (a *AzureDevOpsForge) BranchHeadSHA(ctx context.Context, branch string) (string, error)

BranchHeadSHA returns the current HEAD object id of a branch.

func (*AzureDevOpsForge) CancelPipeline added in v0.6.0

func (a *AzureDevOpsForge) CancelPipeline(ctx context.Context, pipelineID string) error

func (*AzureDevOpsForge) CommitFile added in v0.6.0

func (a *AzureDevOpsForge) CommitFile(ctx context.Context, opts CommitFileOptions) error

CommitFile is a single-file CommitFiles.

func (*AzureDevOpsForge) CommitFiles added in v0.6.0

func (a *AzureDevOpsForge) CommitFiles(ctx context.Context, opts CommitFilesOptions) (*CommitResult, error)

CommitFiles creates/updates/deletes files in a single push.

func (*AzureDevOpsForge) CreateMR added in v0.6.0

func (a *AzureDevOpsForge) CreateMR(ctx context.Context, opts MROptions) (*MR, error)

CreateMR opens a pull request.

func (*AzureDevOpsForge) CreateRelease added in v0.6.0

func (a *AzureDevOpsForge) CreateRelease(ctx context.Context, opts ReleaseOptions) (*Release, error)

func (*AzureDevOpsForge) CreateTag added in v0.6.0

func (a *AzureDevOpsForge) CreateTag(ctx context.Context, tagName, ref string) error

CreateTag creates a lightweight tag ref pointing at a commit.

func (*AzureDevOpsForge) DefaultBranch added in v0.6.0

func (a *AzureDevOpsForge) DefaultBranch(ctx context.Context) (string, error)

DefaultBranch returns the repo's default branch (short name).

func (*AzureDevOpsForge) DeleteRelease added in v0.6.0

func (a *AzureDevOpsForge) DeleteRelease(ctx context.Context, tagName string) error

func (*AzureDevOpsForge) DeleteTag added in v0.6.0

func (a *AzureDevOpsForge) DeleteTag(ctx context.Context, tagName string) error

DeleteTag deletes a tag ref.

func (*AzureDevOpsForge) DownloadJobArtifact added in v0.6.0

func (a *AzureDevOpsForge) DownloadJobArtifact(ctx context.Context, ref, jobName, artifactPath string) ([]byte, error)

func (*AzureDevOpsForge) GetFileContent added in v0.6.0

func (a *AzureDevOpsForge) GetFileContent(ctx context.Context, path, ref string) ([]byte, error)

GetFileContent reads a file from the repo at a branch ref.

func (*AzureDevOpsForge) ListReleases added in v0.6.0

func (a *AzureDevOpsForge) ListReleases(ctx context.Context) ([]ReleaseInfo, error)

func (*AzureDevOpsForge) Provider added in v0.6.0

func (a *AzureDevOpsForge) Provider() Provider

Provider reports Azure DevOps.

func (*AzureDevOpsForge) UploadAsset added in v0.6.0

func (a *AzureDevOpsForge) UploadAsset(ctx context.Context, releaseID string, asset Asset) error

type BasicFactory added in v0.5.0

type BasicFactory struct {
	ProviderName string // "gitlab", "github", "gitea"
	BaseURL      string // e.g., "https://gitlab.prplanit.com"
	CredPrefix   string // credential env var prefix
}

BasicFactory creates Forge instances for repos on a single forge platform. Used by governance reconciler for cross-repo operations.

func (*BasicFactory) ForRepo added in v0.5.0

func (f *BasicFactory) ForRepo(ctx context.Context, repo string) (Forge, error)

ForRepo creates a Forge client for the given repo (e.g., "PrPlanIT/HASteward").

type CommitFileOptions

type CommitFileOptions struct {
	Branch  string
	Path    string // file path in repo
	Content []byte
	Message string
}

CommitFileOptions configures a file commit via forge API.

type CommitFilesOptions

type CommitFilesOptions struct {
	Branch      string
	Message     string
	Files       []FileAction
	ExpectedSHA string // optional: fail if branch head != this SHA
}

CommitFilesOptions configures a multi-file atomic commit via forge API.

type CommitResult

type CommitResult struct {
	SHA string
}

CommitResult holds the result of a forge commit operation.

type Factory added in v0.5.0

type Factory interface {
	ForRepo(ctx context.Context, repo string) (Forge, error)
}

Factory creates Forge instances for target repos. Used by governance and asset distribution for cross-repo operations. Centralizes provider selection and credential resolution.

type FileAction

type FileAction struct {
	Path    string
	Content []byte // nil for deletes
	Delete  bool   // true = delete this file
}

FileAction describes a single file operation within a multi-file commit.

type Forge

type Forge interface {
	// Provider returns which platform this forge represents.
	Provider() Provider

	// CreateRelease creates a release/tag on the forge.
	CreateRelease(ctx context.Context, opts ReleaseOptions) (*Release, error)

	// UploadAsset attaches a file to an existing release.
	UploadAsset(ctx context.Context, releaseID string, asset Asset) error

	// AddReleaseLink adds a URL link to a release (e.g., registry image links).
	AddReleaseLink(ctx context.Context, releaseID string, link ReleaseLink) error

	// CommitFile creates or updates a file in the repo via the forge API.
	// Used for badge SVG updates without a local clone.
	CommitFile(ctx context.Context, opts CommitFileOptions) error

	// CommitFiles creates or updates multiple files in a single atomic commit
	// via the forge API. Used by the commit subsystem for CI push.
	CommitFiles(ctx context.Context, opts CommitFilesOptions) (*CommitResult, error)

	// BranchHeadSHA returns the current HEAD SHA of a branch via the forge API.
	BranchHeadSHA(ctx context.Context, branch string) (string, error)

	// CreateMR opens a merge/pull request.
	CreateMR(ctx context.Context, opts MROptions) (*MR, error)

	// CancelPipeline cancels the currently running pipeline (best-effort cleanup
	// after deps pushes a repaired commit). Returns nil if the provider doesn't
	// support pipeline cancellation.
	CancelPipeline(ctx context.Context, pipelineID string) error

	// ListReleases returns all releases, newest first.
	ListReleases(ctx context.Context) ([]ReleaseInfo, error)

	// DeleteRelease removes a release by its tag name.
	DeleteRelease(ctx context.Context, tagName string) error

	// CreateTag creates a lightweight git tag pointing at a ref.
	// Used for rolling tag aliases (e.g., "latest") that are not releases.
	CreateTag(ctx context.Context, tagName, ref string) error

	// DeleteTag deletes a git tag.
	DeleteTag(ctx context.Context, tagName string) error

	// DownloadJobArtifact fetches a single file from the latest successful job's
	// artifacts for the given ref. Returns the raw file bytes.
	// Returns os.ErrNotExist (or equivalent) if no artifacts found.
	// Implementations may return ErrNotSupported if the forge doesn't support this.
	DownloadJobArtifact(ctx context.Context, ref, jobName, artifactPath string) ([]byte, error)

	// GetFileContent reads a file from the repo at the given ref.
	// Returns the raw file content. Returns os.ErrNotExist if file is not found.
	// Used by governance drift detection, asset sync, and repo inspection.
	GetFileContent(ctx context.Context, path, ref string) ([]byte, error)

	// DefaultBranch returns the default branch name for the repo.
	DefaultBranch(ctx context.Context) (string, error)
}

Forge is the interface every platform implements.

func NewFromAccessory added in v0.4.1

func NewFromAccessory(provider, baseURL, projectID, credPrefix string) (Forge, error)

NewFromAccessory creates a forge client from an accessory config. This is a config adapter only — no orchestration or sync logic. Uses credentials.ResolvePrefix for token resolution — same model as the mirror layer and all other StageFreight credential consumers.

type ForgejoForge added in v0.6.0

type ForgejoForge struct {
	*GiteaForge
}

ForgejoForge is Forgejo's first-class forge client.

Forgejo is a Gitea fork and its REST API (/api/v1) is Gitea-compatible, so this client recycles GiteaForge as its backend and overrides only the identity it reports. The embedded *GiteaForge promotes the entire Forge interface implementation (releases, commits, MRs, tags, artifacts); ForgejoForge is the seam where Forgejo-specific behavior (federation, package registry, its own OIDC) will land when it diverges — without touching the Gitea client.

This mirrors the render layer: a first-class identity package over a shared, internal backend. The reuse is an implementation detail; "forgejo" is a real provider with its own detection, config, and output everywhere a user looks.

func NewForgejo added in v0.6.0

func NewForgejo(baseURL string) *ForgejoForge

NewForgejo creates a Forgejo client. It resolves config exactly like Gitea (the constructor already reads FORGEJO_TOKEN) and reports the Forgejo identity.

func (*ForgejoForge) Provider added in v0.6.0

func (f *ForgejoForge) Provider() Provider

Provider reports Forgejo, overriding the embedded Gitea identity.

type GitHubForge

type GitHubForge struct {
	BaseURL string // "https://api.github.com" or "https://ghes.example.com/api/v3"
	Token   string
	Owner   string
	Repo    string
}

GitHubForge implements the Forge interface for GitHub and GitHub Enterprise.

func NewGitHub

func NewGitHub(baseURL string) *GitHubForge

NewGitHub creates a GitHub forge client. Token is resolved from env: GITHUB_TOKEN, GH_TOKEN. Owner/Repo is resolved from env: GITHUB_REPOSITORY (owner/repo).

func (g *GitHubForge) AddReleaseLink(ctx context.Context, releaseID string, link ReleaseLink) error

func (*GitHubForge) BranchHeadSHA

func (g *GitHubForge) BranchHeadSHA(ctx context.Context, branch string) (string, error)

func (*GitHubForge) CancelPipeline

func (g *GitHubForge) CancelPipeline(ctx context.Context, pipelineID string) error

func (*GitHubForge) CommitFile

func (g *GitHubForge) CommitFile(ctx context.Context, opts CommitFileOptions) error

func (*GitHubForge) CommitFiles

func (g *GitHubForge) CommitFiles(ctx context.Context, opts CommitFilesOptions) (*CommitResult, error)

func (*GitHubForge) CreateMR

func (g *GitHubForge) CreateMR(ctx context.Context, opts MROptions) (*MR, error)

func (*GitHubForge) CreateRelease

func (g *GitHubForge) CreateRelease(ctx context.Context, opts ReleaseOptions) (*Release, error)

func (*GitHubForge) CreateTag added in v0.3.2

func (g *GitHubForge) CreateTag(ctx context.Context, tagName, ref string) error

func (*GitHubForge) DefaultBranch added in v0.5.0

func (g *GitHubForge) DefaultBranch(ctx context.Context) (string, error)

func (*GitHubForge) DeleteRelease

func (g *GitHubForge) DeleteRelease(ctx context.Context, tagName string) error

func (*GitHubForge) DeleteTag added in v0.3.2

func (g *GitHubForge) DeleteTag(ctx context.Context, tagName string) error

func (*GitHubForge) DownloadJobArtifact

func (g *GitHubForge) DownloadJobArtifact(ctx context.Context, ref, jobName, artifactPath string) ([]byte, error)

func (*GitHubForge) GetFileContent added in v0.5.0

func (g *GitHubForge) GetFileContent(ctx context.Context, path, ref string) ([]byte, error)

func (*GitHubForge) ListReleases

func (g *GitHubForge) ListReleases(ctx context.Context) ([]ReleaseInfo, error)

func (*GitHubForge) Provider

func (g *GitHubForge) Provider() Provider

func (*GitHubForge) UploadAsset

func (g *GitHubForge) UploadAsset(ctx context.Context, releaseID string, asset Asset) error

type GitLabForge

type GitLabForge struct {
	BaseURL   string // e.g., "https://gitlab.prplanit.com"
	Token     string // private token or job token
	ProjectID string // numeric ID or "group/project" URL-encoded path
	// contains filtered or unexported fields
}

GitLabForge implements the Forge interface for GitLab instances.

func NewGitLab

func NewGitLab(baseURL string) *GitLabForge

NewGitLab creates a GitLab forge client. Token is resolved from env: GITLAB_TOKEN, CI_JOB_TOKEN. ProjectID is resolved from env: CI_PROJECT_ID, CI_PROJECT_PATH.

func (g *GitLabForge) AddReleaseLink(ctx context.Context, releaseID string, link ReleaseLink) error

func (*GitLabForge) BranchHeadSHA

func (g *GitLabForge) BranchHeadSHA(ctx context.Context, branch string) (string, error)

func (*GitLabForge) CancelPipeline

func (g *GitLabForge) CancelPipeline(ctx context.Context, pipelineID string) error

func (*GitLabForge) CommitFile

func (g *GitLabForge) CommitFile(ctx context.Context, opts CommitFileOptions) error

func (*GitLabForge) CommitFiles

func (g *GitLabForge) CommitFiles(ctx context.Context, opts CommitFilesOptions) (*CommitResult, error)

func (*GitLabForge) CreateMR

func (g *GitLabForge) CreateMR(ctx context.Context, opts MROptions) (*MR, error)

func (*GitLabForge) CreateRelease

func (g *GitLabForge) CreateRelease(ctx context.Context, opts ReleaseOptions) (*Release, error)

func (*GitLabForge) CreateTag added in v0.3.2

func (g *GitLabForge) CreateTag(ctx context.Context, tagName, ref string) error

func (*GitLabForge) DefaultBranch added in v0.5.0

func (g *GitLabForge) DefaultBranch(ctx context.Context) (string, error)

func (*GitLabForge) DeleteRelease

func (g *GitLabForge) DeleteRelease(ctx context.Context, tagName string) error

func (*GitLabForge) DeleteTag added in v0.3.2

func (g *GitLabForge) DeleteTag(ctx context.Context, tagName string) error

func (*GitLabForge) DownloadJobArtifact

func (g *GitLabForge) DownloadJobArtifact(ctx context.Context, ref, jobName, artifactPath string) ([]byte, error)

func (*GitLabForge) GetFileContent added in v0.5.0

func (g *GitLabForge) GetFileContent(ctx context.Context, path, ref string) ([]byte, error)

func (*GitLabForge) ListReleases

func (g *GitLabForge) ListReleases(ctx context.Context) ([]ReleaseInfo, error)

func (*GitLabForge) Provider

func (g *GitLabForge) Provider() Provider

func (*GitLabForge) UploadAsset

func (g *GitLabForge) UploadAsset(ctx context.Context, releaseID string, asset Asset) error

type GiteaForge

type GiteaForge struct {
	BaseURL string // e.g., "https://codeberg.org"
	Token   string
	Owner   string
	Repo    string
}

GiteaForge implements the Forge interface for Gitea and Forgejo instances.

func NewGitea

func NewGitea(baseURL string) *GiteaForge

NewGitea creates a Gitea/Forgejo forge client. Token is resolved from env: GITEA_TOKEN, FORGEJO_TOKEN. Owner/Repo is resolved from env: CI_REPO (Woodpecker CI) or GITHUB_REPOSITORY (Gitea Actions, which uses GitHub-compatible vars).

func (g *GiteaForge) AddReleaseLink(ctx context.Context, releaseID string, link ReleaseLink) error

func (*GiteaForge) BranchHeadSHA

func (g *GiteaForge) BranchHeadSHA(ctx context.Context, branch string) (string, error)

func (*GiteaForge) CancelPipeline

func (g *GiteaForge) CancelPipeline(ctx context.Context, pipelineID string) error

func (*GiteaForge) CommitFile

func (g *GiteaForge) CommitFile(ctx context.Context, opts CommitFileOptions) error

func (*GiteaForge) CommitFiles

func (g *GiteaForge) CommitFiles(ctx context.Context, opts CommitFilesOptions) (*CommitResult, error)

func (*GiteaForge) CreateMR

func (g *GiteaForge) CreateMR(ctx context.Context, opts MROptions) (*MR, error)

func (*GiteaForge) CreateRelease

func (g *GiteaForge) CreateRelease(ctx context.Context, opts ReleaseOptions) (*Release, error)

func (*GiteaForge) CreateTag added in v0.3.2

func (g *GiteaForge) CreateTag(ctx context.Context, tagName, ref string) error

func (*GiteaForge) DefaultBranch added in v0.5.0

func (g *GiteaForge) DefaultBranch(ctx context.Context) (string, error)

func (*GiteaForge) DeleteRelease

func (g *GiteaForge) DeleteRelease(ctx context.Context, tagName string) error

func (*GiteaForge) DeleteTag added in v0.3.2

func (g *GiteaForge) DeleteTag(ctx context.Context, tagName string) error

func (*GiteaForge) DownloadJobArtifact

func (g *GiteaForge) DownloadJobArtifact(ctx context.Context, ref, jobName, artifactPath string) ([]byte, error)

func (*GiteaForge) GetFileContent added in v0.5.0

func (g *GiteaForge) GetFileContent(ctx context.Context, path, ref string) ([]byte, error)

func (*GiteaForge) ListReleases

func (g *GiteaForge) ListReleases(ctx context.Context) ([]ReleaseInfo, error)

func (*GiteaForge) Provider

func (g *GiteaForge) Provider() Provider

func (*GiteaForge) UploadAsset

func (g *GiteaForge) UploadAsset(ctx context.Context, releaseID string, asset Asset) error

type MR

type MR struct {
	ID  string
	URL string
}

MR is a created merge/pull request.

type MROptions

type MROptions struct {
	Title        string
	Description  string
	SourceBranch string
	TargetBranch string
	Draft        bool
}

MROptions configures a merge/pull request.

type Provider

type Provider string

Provider identifies a git forge platform.

const (
	GitLab      Provider = "gitlab"
	GitHub      Provider = "github"
	Gitea       Provider = "gitea"
	Forgejo     Provider = "forgejo"
	AzureDevOps Provider = "azuredevops"
	Unknown     Provider = "unknown"
)

func DetectProvider

func DetectProvider(remoteURL string) Provider

DetectProvider determines the forge platform from a git remote URL.

type Release

type Release struct {
	ID  string // platform-specific ID
	URL string // web URL to the release page
}

Release is a created release on a forge.

type ReleaseInfo

type ReleaseInfo struct {
	ID          string // platform-specific ID (numeric for GitHub/Gitea, tag_name for GitLab)
	TagName     string
	Name        string // release title
	Description string // release body (markdown)
	Draft       bool
	Prerelease  bool
	CreatedAt   time.Time
}

ReleaseInfo describes an existing release on a forge.

type ReleaseLink struct {
	Name     string // display name (e.g., "Docker Hub 1.3.0")
	URL      string // target URL
	LinkType string // "image", "package", "other"
}

ReleaseLink is a URL to embed in a release (e.g., registry image link).

type ReleaseOptions

type ReleaseOptions struct {
	TagName     string
	Ref         string // commit SHA, branch, or tag to create the release from (required by GitLab when tag doesn't exist)
	Name        string
	Description string // markdown body (release notes)
	Draft       bool
	Prerelease  bool
}

ReleaseOptions configures a new release.

Jump to

Keyboard shortcuts

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