Help us shape the future of Go! Take the 2026 Go Developer Survey

forge

package
v0.9.2 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: AGPL-3.0, AGPL-3.0-only Imports: 17 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.

func KnownProviders added in v0.8.0

func KnownProviders() []string

KnownProviders returns the recognized forge provider names — for docs and tooling that list allowed values from the authoritative source. Excludes the internal Unknown.

func NormalizeTopic added in v0.8.0

func NormalizeTopic(s string) (normalized string, changed bool)

NormalizeTopic lowers an authored topic to the strict lowercase-hyphenated form the forges require (GitHub/Gitea enforce it; GitLab is lenient but accepts it — the portable subset). Returns the normalized value and whether it changed, so the caller can warn. A topic that normalizes to empty (all-invalid) yields "".

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) DeletePackageVersion added in v0.7.0

func (a *AzureDevOpsForge) DeletePackageVersion(ctx context.Context, packageName, version string) error

func (*AzureDevOpsForge) DeleteRelease added in v0.6.0

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

func (*AzureDevOpsForge) DeleteReleaseAsset added in v0.8.0

func (a *AzureDevOpsForge) DeleteReleaseAsset(ctx context.Context, releaseID, assetID 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) DownloadReleaseAsset added in v0.8.0

func (a *AzureDevOpsForge) DownloadReleaseAsset(ctx context.Context, asset ReleaseAsset) (io.ReadCloser, 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) ListPackageVersions added in v0.7.0

func (a *AzureDevOpsForge) ListPackageVersions(ctx context.Context, packageName string) ([]PackageVersion, error)

func (*AzureDevOpsForge) ListReleaseAssets added in v0.8.0

func (a *AzureDevOpsForge) ListReleaseAssets(ctx context.Context, releaseID string) ([]ReleaseAsset, error)

── Release-reconciliation leaf ops — not yet supported ──────────────────

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) PublishPackageFile added in v0.7.0

func (a *AzureDevOpsForge) PublishPackageFile(ctx context.Context, opts PublishPackageOptions) (*PublishedPackage, error)

Azure DevOps has no generic package registry analogous to GitLab's; binary distribution there is out of scope for generic-package.

func (*AzureDevOpsForge) UpdateReleaseNotes added in v0.8.0

func (a *AzureDevOpsForge) UpdateReleaseNotes(ctx context.Context, releaseID, body string) error

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)

	// PublishPackageFile uploads a single file to the forge's generic package
	// registry under (package, version, filename). Returns the published reference.
	// Forges without a generic package registry return ErrNotSupported.
	PublishPackageFile(ctx context.Context, opts PublishPackageOptions) (*PublishedPackage, error)

	// ListPackageVersions returns the versions of a generic package, newest first.
	// Forges without a generic package registry return ErrNotSupported.
	ListPackageVersions(ctx context.Context, packageName string) ([]PackageVersion, error)

	// DeletePackageVersion removes a single version of a generic package (used by
	// retention). Forges without a generic package registry return ErrNotSupported.
	DeletePackageVersion(ctx context.Context, packageName, version string) error

	// ListReleaseAssets returns the FILE assets attached to a release (binaries/
	// archives), not link assets. Digest/Size drive granular per-asset
	// convergence. releaseID is the platform release id (numeric for GitHub,
	// tag name for GitLab).
	ListReleaseAssets(ctx context.Context, releaseID string) ([]ReleaseAsset, error)

	// DownloadReleaseAsset streams a file asset's bytes from THIS forge (the
	// source side of a re-host). Caller closes the reader.
	DownloadReleaseAsset(ctx context.Context, asset ReleaseAsset) (io.ReadCloser, error)

	// DeleteReleaseAsset removes a single file asset from a release, by its
	// platform asset id — used to replace a drifted asset before re-uploading.
	DeleteReleaseAsset(ctx context.Context, releaseID, assetID string) error

	// UpdateReleaseNotes replaces a release's body (markdown) — used to converge
	// notes and the provenance/fingerprint marker.
	UpdateReleaseNotes(ctx context.Context, releaseID, body 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) DeletePackageVersion added in v0.7.0

func (g *GitHubForge) DeletePackageVersion(ctx context.Context, packageName, version string) error

func (*GitHubForge) DeleteRelease

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

func (*GitHubForge) DeleteReleaseAsset added in v0.8.0

func (g *GitHubForge) DeleteReleaseAsset(ctx context.Context, releaseID, assetID 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) DownloadReleaseAsset added in v0.8.0

func (g *GitHubForge) DownloadReleaseAsset(ctx context.Context, asset ReleaseAsset) (io.ReadCloser, error)

func (*GitHubForge) GetFileContent added in v0.5.0

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

func (*GitHubForge) ListPackageVersions added in v0.7.0

func (g *GitHubForge) ListPackageVersions(ctx context.Context, packageName string) ([]PackageVersion, error)

func (*GitHubForge) ListReleaseAssets added in v0.8.0

func (g *GitHubForge) ListReleaseAssets(ctx context.Context, releaseID string) ([]ReleaseAsset, error)

func (*GitHubForge) ListReleases

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

func (*GitHubForge) Provider

func (g *GitHubForge) Provider() Provider

func (*GitHubForge) PublishPackageFile added in v0.7.0

func (g *GitHubForge) PublishPackageFile(ctx context.Context, opts PublishPackageOptions) (*PublishedPackage, error)

GitHub has no generic package registry (GitHub Packages is typed-only: npm/maven/container/etc.). Binary distribution uses kind: release instead.

func (*GitHubForge) UpdateReleaseNotes added in v0.8.0

func (g *GitHubForge) UpdateReleaseNotes(ctx context.Context, releaseID, body string) error

func (*GitHubForge) UpdateRepoMetadata added in v0.8.0

func (g *GitHubForge) UpdateRepoMetadata(ctx context.Context, meta RepoMetadata) (MetadataOutcome, error)

UpdateRepoMetadata sets project identity on the GitHub repo: description + homepage (website) via PATCH, topics via PUT (full replace). GitHub repos have no avatar (org/user only), so logo is skipped. Implements MetadataSetter.

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) DeletePackageVersion added in v0.7.0

func (g *GitLabForge) DeletePackageVersion(ctx context.Context, packageName, version string) error

DeletePackageVersion deletes a generic-package version by resolving it to its GitLab package id and DELETE-ing that package. Not-found is treated as success (idempotent prune).

func (*GitLabForge) DeleteRelease

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

func (*GitLabForge) DeleteReleaseAsset added in v0.8.0

func (g *GitLabForge) DeleteReleaseAsset(ctx context.Context, releaseID, assetID 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) DownloadReleaseAsset added in v0.8.0

func (g *GitLabForge) DownloadReleaseAsset(ctx context.Context, asset ReleaseAsset) (io.ReadCloser, error)

func (*GitLabForge) GetFileContent added in v0.5.0

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

func (*GitLabForge) ListPackageVersions added in v0.7.0

func (g *GitLabForge) ListPackageVersions(ctx context.Context, packageName string) ([]PackageVersion, error)

ListPackageVersions returns generic-package versions newest-first. Each GitLab package id maps to one (name, version); that id is the deletion handle.

func (*GitLabForge) ListReleaseAssets added in v0.8.0

func (g *GitLabForge) ListReleaseAssets(ctx context.Context, releaseID string) ([]ReleaseAsset, error)

func (*GitLabForge) ListReleases

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

func (*GitLabForge) Provider

func (g *GitLabForge) Provider() Provider

func (*GitLabForge) PublishPackageFile added in v0.7.0

func (g *GitLabForge) PublishPackageFile(ctx context.Context, opts PublishPackageOptions) (*PublishedPackage, error)

PublishPackageFile uploads one file to GitLab's generic package registry via PUT .../packages/generic/{pkg}/{ver}/{file}. The raw request body is the file bytes (octet-stream), not multipart. PullURL is the same path served by GET — tokenless on public projects.

func (*GitLabForge) UpdateReleaseNotes added in v0.8.0

func (g *GitLabForge) UpdateReleaseNotes(ctx context.Context, releaseID, body string) error

func (*GitLabForge) UpdateRepoMetadata added in v0.8.0

func (g *GitLabForge) UpdateRepoMetadata(ctx context.Context, meta RepoMetadata) (MetadataOutcome, error)

UpdateRepoMetadata sets project identity on the GitLab project: description + topics via PUT /projects/:id. GitLab has no per-project homepage field, so website is skipped. The avatar (logo) is a multipart upload handled by the idempotent avatar step, not here. Implements MetadataSetter.

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) DeletePackageVersion added in v0.7.0

func (g *GiteaForge) DeletePackageVersion(ctx context.Context, packageName, version string) error

func (*GiteaForge) DeleteRelease

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

func (*GiteaForge) DeleteReleaseAsset added in v0.8.0

func (g *GiteaForge) DeleteReleaseAsset(ctx context.Context, releaseID, assetID 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) DownloadReleaseAsset added in v0.8.0

func (g *GiteaForge) DownloadReleaseAsset(ctx context.Context, asset ReleaseAsset) (io.ReadCloser, error)

func (*GiteaForge) GetFileContent added in v0.5.0

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

func (*GiteaForge) ListPackageVersions added in v0.7.0

func (g *GiteaForge) ListPackageVersions(ctx context.Context, packageName string) ([]PackageVersion, error)

func (*GiteaForge) ListReleaseAssets added in v0.8.0

func (g *GiteaForge) ListReleaseAssets(ctx context.Context, releaseID string) ([]ReleaseAsset, error)

── Release-reconciliation leaf ops — not yet supported ──────────────────

func (*GiteaForge) ListReleases

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

func (*GiteaForge) Provider

func (g *GiteaForge) Provider() Provider

func (*GiteaForge) PublishPackageFile added in v0.7.0

func (g *GiteaForge) PublishPackageFile(ctx context.Context, opts PublishPackageOptions) (*PublishedPackage, error)

Generic package registry support is deferred for Gitea/Forgejo. Both DO have a generic package API; it is simply not wired yet. (ForgejoForge inherits these via its embedded *GiteaForge.)

func (*GiteaForge) UpdateReleaseNotes added in v0.8.0

func (g *GiteaForge) UpdateReleaseNotes(ctx context.Context, releaseID, body string) error

func (*GiteaForge) UpdateRepoMetadata added in v0.8.0

func (g *GiteaForge) UpdateRepoMetadata(ctx context.Context, meta RepoMetadata) (MetadataOutcome, error)

UpdateRepoMetadata sets project identity on the Gitea/Forgejo repo: description + website via PATCH, topics via PUT /topics (full replace). The avatar (logo) is a base64 upload handled by the idempotent avatar step. Implements MetadataSetter; also serves Forgejo (which embeds *GiteaForge). Gitea/Forgejo APIs are compatible.

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 MetadataOutcome added in v0.8.0

type MetadataOutcome struct {
	Set      []string // fields applied: "description" | "website" | "topics" | "logo"
	Skipped  []string // "field: reason" — the provider has no such field
	Warnings []string // non-fatal issues (e.g., a topic dropped, a body over cap)
}

MetadataOutcome reports, per repo, what the provider actually did — so the caller can render an honest summary (set / skipped-because-unsupported / warned).

type MetadataSetter added in v0.8.0

type MetadataSetter interface {
	UpdateRepoMetadata(ctx context.Context, meta RepoMetadata) (MetadataOutcome, error)
}

MetadataSetter is the OPTIONAL capability interface a forge implements when it can set repo identity fields. Mirrors registry.Warner: the metadata contributor type-asserts it and skips-with-a-warning where a forge (or provider like Azure DevOps) doesn't implement it — so this stays off the core Forge interface and forces nothing on non-participants.

type PackageVersion added in v0.7.0

type PackageVersion struct {
	ID        string
	Version   string
	CreatedAt time.Time
}

PackageVersion describes one version of a generic package. ID is the stable forge handle used for deletion (e.g. the GitLab package id); Version is the human-facing version label.

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.

func ParseProvider added in v0.7.0

func ParseProvider(s string) Provider

ParseProvider maps a DECLARED provider string (case-insensitive) to a known Provider, or Unknown when unrecognized. Unlike DetectProvider — which guesses the provider from a transport URL — this is the authoritative path: the operator has stated the forge type in config, so it is trusted over any URL heuristic. The git remote is transport identity (how to reach the repo); the provider is forge identity (which API to speak), and the two are not coupled (proxies, SSH aliases, IP remotes).

type PublishPackageOptions added in v0.7.0

type PublishPackageOptions struct {
	PackageName string
	Version     string
	FileName    string
	FilePath    string // local file to upload
}

PublishPackageOptions configures a generic package file publish.

type PublishedPackage added in v0.7.0

type PublishedPackage struct {
	PackageName string
	Version     string
	FileName    string
	PullURL     string // direct download URL (tokenless on public projects)
}

PublishedPackage is the result of publishing a generic package file.

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 ReleaseAsset added in v0.8.0

type ReleaseAsset struct {
	ID     string // platform asset id (for delete/replace)
	Name   string // filename or link name
	Size   int64  // bytes — fallback comparison when Digest is unavailable
	Digest string // content digest if the forge exposes one, else ""
	URL    string // for a file: the download URL; for an external link: the reference URL

	// LinkType is the source link classification when known (GitLab: "image", "package",
	// "runbook", "other"); "" for a native file blob (GitHub/Gitea).
	LinkType string
	// External marks a REFERENCE (a registry/image link, or a URL on a host other than the
	// source forge) that must be re-created on the mirror as a link, NOT downloaded as a
	// file. Derived by the source forge from link_type + host comparison (see gitlab.go).
	External bool
}

ReleaseAsset is one asset attached to a release, as seen on a forge. It is either a downloadable FILE (a binary/archive re-hosted by download+upload) or an EXTERNAL link (a registry/image reference re-created on the mirror as a link — never downloaded). The mirror reconciler compares files by Digest (preferred) or Size (fallback) to converge only what drifted.

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"

	// DirectAssetPath, when set (GitLab only), yields a permanent download URL
	// at /-/releases/<tag>/downloads/<DirectAssetPath> that redirects to URL.
	// Leading-slash relative path (e.g. "/dwiz-windows-amd64.zip"). Ignored by
	// forges whose assets are natively addressable (GitHub/Gitea blobs).
	DirectAssetPath string
}

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
	Type        ReleaseType // semantic intent; each forge lowers it to native flags
}

ReleaseOptions configures a new release.

type ReleaseType added in v0.8.0

type ReleaseType int

ReleaseType is the forge-agnostic INTENT of a release. Each forge backend lowers it to whatever its native API expresses (GitHub: prerelease + make_latest; Gitea: prerelease; GitLab: a plain release). Keeping intent — not GitHub's make_latest flag — in the internal model is the "one semantic IR, many backend realizers" pattern.

const (
	// ReleaseTypeAuto preserves each forge's default behavior: on GitHub it does NOT
	// send make_latest (legacy — GitHub decides), prerelease=false. It is the value for
	// an omitted / "unspecified" config, so existing configs behave identically. A
	// version-inferred prerelease is resolved to ReleaseTypePrerelease upstream, so Auto
	// only ever means "a stable release that does not force Latest."
	ReleaseTypeAuto ReleaseType = iota
	// ReleaseTypeLatest marks the stable, "Latest" release (GitHub: make_latest=true).
	ReleaseTypeLatest
	// ReleaseTypePrerelease marks a pre-release (never Latest on GitHub/Gitea).
	ReleaseTypePrerelease
)

func ReleaseTypeFromPrerelease added in v0.8.0

func ReleaseTypeFromPrerelease(prerelease bool) ReleaseType

ReleaseTypeFromPrerelease maps a legacy prerelease boolean to the semantic type. Used by mirror/sync paths that replicate existing releases and only have the prerelease signal (they can't know Latest intent), so false → Auto (not Latest).

type RepoMetadata added in v0.8.0

type RepoMetadata struct {
	Description string   // short project description ("" = leave unchanged)
	Website     string   // external site URL / homepage ("" = leave unchanged)
	Topics      []string // discovery tags (nil = leave unchanged)
	LogoPath    string   // path to a project-avatar image ("" = leave unchanged)
}

RepoMetadata is the project-identity a `kind: metadata` target pushes to a forge repo. Empty/nil fields are left unchanged. Values are pre-resolved and (for Topics) already normalized by the caller; the forge impl just maps them to its API's capability.

Jump to

Keyboard shortcuts

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