VCS¶
The pkg/vcs/ directory is split into focused subpackages. Each has a distinct responsibility and can be used independently.
Package Overview¶
| Package | Import path | Purpose |
|---|---|---|
| Release | pkg/vcs/release |
Backend-agnostic Provider/Release/ReleaseAsset interfaces, sentinel errors, and the provider registry |
| Repo | pkg/vcs/repo |
Git repository operations (local and in-memory) via go-git |
| GitHub | pkg/vcs/github |
GitHub Enterprise API client and GitHub release provider |
| GitLab | pkg/vcs/gitlab |
GitLab (and self-managed) release provider |
| Bitbucket | pkg/vcs/bitbucket |
Bitbucket Cloud Downloads-based release provider (filename-pattern version detection) |
| Gitea / Codeberg | pkg/vcs/gitea |
Gitea, Forgejo, and Codeberg REST API release provider |
| Direct HTTP | pkg/vcs/direct |
Direct HTTP release provider for arbitrary download servers |
The root pkg/vcs package contains only auth.go โ the shared ResolveToken helper used by the GitHub and GitLab subpackages.
Provider Registry¶
All built-in release providers register themselves at package init time. Consuming code looks up a provider by source type string rather than importing platform packages directly:
Blank imports in pkg/setup/providers.go wire all built-in providers automatically โ no manual registration is required when using setup.NewUpdater. See Release Provider for the full registry API and how to register a custom provider.
Authentication¶
vcs.ResolveTokenContext(ctx context.Context, cfg config.Containable, fallbackEnv string) string resolves a token from a config subtree in this order:
auth.envโ reads the named environment variableauth.keychainโ"<service>/<account>"reference resolved viacredentials.Retrieve; silently skipped when no keychain-capableBackendis registeredauth.valueโ uses the literal value stored in configfallbackEnvโ falls back to a well-known environment variable (e.g."GITHUB_TOKEN")
Returns an empty string when nothing is found. Callers decide whether that is an error โ public repositories can operate without a token; private repositories will receive a 401. The context is propagated to the credentials backend so remote secret stores (Vault, AWS SSM, 1Password Connect) honour the caller's deadline and cancellation.
import (
"context"
"gitlab.com/phpboyscout/go-tool-base/pkg/vcs"
)
// Resolve a GitHub token from props.Config.Sub("github") with the
// cobra command's context.
token := vcs.ResolveTokenContext(cmd.Context(), props.Config.Sub("github"), "GITHUB_TOKEN")
The context-free form vcs.ResolveToken(cfg, fallbackEnv) is preserved as a compatibility shim that internally calls ResolveTokenContext(context.Background(), โฆ). Prefer the context-aware variant anywhere a context is already in scope.
Design Goals¶
- Interface segregation
RepoLike(repo operations) andGitHubClient(API operations) are separate interfaces. Most features only need one of them.- Backend agnosticism for releases
- All release providers implement
release.Provider. Consuming code (e.g. the auto-update command) depends only on that interface and never imports a platform-specific package directly. - Extensibility
- Custom providers can be registered at startup via
release.Register. The registry is backed by async.RWMutexand safe for concurrent use. See the how-to guide for a full walkthrough. - Testability
- All public interfaces have generated mocks in
mocks/pkg/vcs/. In-memory git storage (SourceMemory) enables offline integration-style tests. HTTP-based providers usehttptest.NewServerfor network-free unit tests. aferointegrationRepo.AddToFSbridgesgo-gitobject storage into anyafero.Fs, so file operations are consistent between production (OS filesystem) and tests (memory-mapped filesystem).
Related Documentation¶
- VCS Concepts โ architectural rationale and usage patterns
- Auto-Update Lifecycle โ how
release.Provideris used for version checks - Interface Design โ
RepoLikeandGitHubClientin the interface hierarchy - Custom Release Source โ register your own provider implementation