Documentation
¶
Index ¶
- Constants
- Variables
- func BuildDepsCommitMessage(bumps []DepBump, rootCause string) string
- func CompareVersions(v1, v2 string) int
- func EnsureGHSession(runner Runner, secretStore SecretStore) error
- func FormatCommitMessage(message string) string
- func ValidateCommitMessage(message string) error
- func ValidateShellSafeMessage(message string) string
- func WorkTreeDirtyBeyond(git GitClient, allowed ...string) (bool, error)
- type DepBump
- type Git
- func (g *Git) Add() error
- func (g *Git) CheckRemoteAccess() error
- func (g *Git) Clone(repoURL string) (alreadyPresent bool, err error)
- func (g *Git) Commit(message string) (bool, error)
- func (g *Git) CommitPaths(message string, paths ...string) (bool, error)
- func (g *Git) CreateTag(tag string) (bool, error)
- func (g *Git) DiffShortStat() (string, error)
- func (g *Git) Fetch() error
- func (g *Git) GenerateNextTag() (string, error)
- func (g *Git) GetConfigUserEmail() (string, error)
- func (g *Git) GetConfigUserName() (string, error)
- func (g *Git) GetLatestTag() (string, error)
- func (g *Git) GitIgnoreAdd(entry string) error
- func (g *Git) HasChanges() (bool, error)
- func (g *Git) HasPendingChanges() (bool, error)
- func (g *Git) HasUpstream() (bool, error)
- func (g *Git) IncrementTag(tag string) (string, error)
- func (g *Git) InitRepo(dir string) error
- func (g *Git) IsAheadOfRemote() (bool, error)
- func (g *Git) ObjectsToPublish(_ PublishContext) (PublishAction, string)
- func (g *Git) Pull() error
- func (g *Git) Push(message, tag string) (PushResult, error)
- func (g *Git) PushWithTags(tag string) (bool, error)
- func (g *Git) PushWithoutTags() (bool, error)
- func (g *Git) SetAuthRetrier(a GitHubAuthenticator)
- func (g *Git) SetLog(fn func(...any))
- func (g *Git) SetRootDir(path string)
- func (g *Git) SetShouldWrite(f func() bool)
- func (g *Git) SetUserConfig(name, email string) error
- func (g *Git) StatusPorcelain() (string, error)
- func (g *Git) TagExists(tag string) (bool, error)
- type GitClient
- type GitHub
- func (gh *GitHub) CreateRelease(tag string, assets []string, targetRepo string) (string, error)
- func (gh *GitHub) CreateRepo(owner, name, description, visibility string) error
- func (gh *GitHub) DeleteRepo(owner, name string) error
- func (gh *GitHub) DeleteSecret(repo, name string) error
- func (gh *GitHub) GetCurrentUser() (string, error)
- func (gh *GitHub) GetHelpfulErrorMessage(err error) string
- func (gh *GitHub) IsNetworkError(err error) bool
- func (gh *GitHub) ListSecrets(repo string) ([]string, error)
- func (gh *GitHub) RepoExists(owner, name string) (bool, error)
- func (gh *GitHub) RepoInfo(repoRef string) (owner, name, visibility string, err error)
- func (gh *GitHub) SetLog(fn func(...any))
- func (gh *GitHub) SetSecret(repo, name, value string) error
- func (gh *GitHub) SetSecretWithScope(repo, name, value, org, visibility string) error
- type GitHubAuthHandler
- type GitHubAuthenticator
- type GitHubClient
- type GitHubOAuth
- func (a *GitHubOAuth) DeviceFlowAuth() (string, error)
- func (a *GitHubOAuth) EnsureGitHubAuth() error
- func (a *GitHubOAuth) Name() string
- func (a *GitHubOAuth) SetHTTPClient(client *http.Client)
- func (a *GitHubOAuth) SetLog(fn func(...any))
- func (a *GitHubOAuth) SetStore(store SecretStore)
- func (a *GitHubOAuth) SetTokenValidator(fn func(token string) TokenValidationResult)
- type GitHubPATAuth
- type HTTPSumDB
- type MockGitHubAuth
- type PublishAction
- type PublishContext
- type PublishObjector
- type PushResult
- type RealRunner
- type Runner
- type SecretRunner
- type SecretStore
- type SumDBClient
- type TestCache
- func (tc *TestCache) GetCacheKey() (string, error)
- func (tc *TestCache) GetCachePath() (string, error)
- func (tc *TestCache) GetCachedMessage() string
- func (tc *TestCache) GetGitState() (string, error)
- func (tc *TestCache) InvalidateCache() error
- func (tc *TestCache) IsCacheValid() bool
- func (tc *TestCache) SaveCache(message string) error
- type TokenValidationResult
Constants ¶
const ( // DepsCommitPrefix is the prefix for dependency update commit messages DepsCommitPrefix = "deps: " // CauseLinePrefix is the prefix for the root cause line in commit messages CauseLinePrefix = "cause: " )
const ( ObjectionCodejobSession = "codejob session active" ObjectionOtherReplaces = "other replaces exist" ObjectionPlanPending = "docs/PLAN.md pending" ObjectionDirtyTree = "dirty tree" )
const DevflowOAuthClientID = "Ov23lijHU2vxBCpShn1Q"
DevflowOAuthClientID is the OAuth App Client ID for devflow.
IMPORTANT: This Client ID is intentionally hardcoded and is NOT a secret. OAuth Client IDs are public identifiers (like a username, not a password). The Client Secret is NEVER included in the code - Device Flow doesn't need it. This is the standard approach used by CLI tools like gh, goreleaser, hub, etc.
The OAuth App is registered under a personal GitHub account (not organization). Manage the app at: https://github.com/settings/developers -> OAuth Apps -> devflow
Variables ¶
var ErrDirtyWorkTree = errors.New("cannot pull: working tree has uncommitted changes")
ErrDirtyWorkTree is returned by Pull when the working tree has uncommitted changes.
Functions ¶
func BuildDepsCommitMessage ¶ added in v0.0.2
BuildDepsCommitMessage constructs a standard dependency update commit message. rootCause is the original commit message that triggered the cascade.
func CompareVersions ¶ added in v0.0.2
CompareVersions compares two semantic version strings (e.g., "v1.2.3"). It returns -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2. It handles "v" prefix gracefully.
func EnsureGHSession ¶ added in v0.0.2
func EnsureGHSession(runner Runner, secretStore SecretStore) error
EnsureGHSession verifies the gh session and, if expired, restores it non-interactively from the PAT stored in secretStore via `gh auth login --with-token`. No-op when the session is healthy. The probe and verification run through runner so tests can inject a double and never touch a real gh CLI; restore itself always uses the real process (only reached when the probe genuinely fails, i.e. never under an injected test Runner that reports success).
func FormatCommitMessage ¶ added in v0.0.2
FormatCommitMessage ensures the message is trimmed.
func ValidateCommitMessage ¶ added in v0.0.2
ValidateCommitMessage ensures that a commit message is provided and is valid. It trims whitespace and returns an error if the message is empty.
func ValidateShellSafeMessage ¶ added in v0.0.2
ValidateShellSafeMessage provides a warning if the message contains characters that might need escaping in certain shells (like backticks, dollar signs, or single quotes) if it were to be used in a shell script, even though exec.Command is safe.
Types ¶
type Git ¶
type Git struct {
// contains filtered or unexported fields
}
Git handler for Git operations
func (*Git) CheckRemoteAccess ¶ added in v0.0.2
CheckRemoteAccess verifies connectivity to the remote repository. If an auth error is detected and an authRetrier is configured, it triggers the Device Flow auth automatically and retries once.
func (*Git) Clone ¶ added in v0.0.2
Clone clones repoURL into the working copy. If the destination already contains a repository, it is NOT an error: it does nothing and returns alreadyPresent == true, so an unattended publisher can call Clone unconditionally at startup.
func (*Git) Commit ¶ added in v0.0.2
Commit creates a commit with the given message Returns true if a commit was created
func (*Git) CommitPaths ¶ added in v0.0.2
CommitPaths adds specific paths and creates a commit. It returns true if a commit was created, false if no changes in those paths. This is safer than Add() + Commit() as it only touches specific files.
func (*Git) DiffShortStat ¶ added in v0.0.2
DiffShortStat returns the output of git diff HEAD --shortstat
func (*Git) Fetch ¶ added in v0.0.2
Fetch fetches refs from remote without touching the working tree.
func (*Git) GenerateNextTag ¶ added in v0.0.2
GenerateNextTag calculates the next semantic version
func (*Git) GetConfigUserEmail ¶ added in v0.0.2
GetConfigUserEmail gets the git user.email
func (*Git) GetConfigUserName ¶ added in v0.0.2
GetConfigUserName gets the git user.name
func (*Git) GetLatestTag ¶ added in v0.0.2
GetLatestTag gets the latest release tag (vMAJOR.MINOR.PATCH).
func (*Git) GitIgnoreAdd ¶ added in v0.0.2
GitIgnoreAdd adds entry to .gitignore if shouldWrite allows and entry not present. Creates .gitignore if it doesn't exist.
func (*Git) HasChanges ¶ added in v0.0.2
HasChanges checks if there are staged changes
func (*Git) HasPendingChanges ¶ added in v0.0.2
HasPendingChanges returns true if there are uncommitted or unpushed changes. Used by CodeJob to ensure the file is visible to Jules before dispatching. It ignores changes to .env and .gitignore files.
func (*Git) HasUpstream ¶ added in v0.0.2
HasUpstream checks if the branch has upstream
func (*Git) IncrementTag ¶ added in v0.0.2
IncrementTag increments a specific tag (e.g., v0.0.12 -> v0.0.13)
func (*Git) IsAheadOfRemote ¶ added in v0.0.2
IsAheadOfRemote checks if local branch is ahead of remote
func (*Git) ObjectsToPublish ¶ added in v0.0.2
func (g *Git) ObjectsToPublish(_ PublishContext) (PublishAction, string)
func (*Git) Pull ¶ added in v0.0.2
Pull updates the working copy from upstream. Returns ErrDirtyWorkTree if the working tree has uncommitted changes.
func (*Git) Push ¶ added in v0.0.2
func (g *Git) Push(message, tag string) (PushResult, error)
Push executes the complete push workflow (add, commit, tag, push) Returns a PushResult and error if any.
func (*Git) PushWithTags ¶ added in v0.0.2
PushWithTags pushes commits and tag
func (*Git) PushWithoutTags ¶ added in v0.0.2
PushWithoutTags pushes commits without pushing tags
func (*Git) SetAuthRetrier ¶ added in v0.0.2
func (g *Git) SetAuthRetrier(a GitHubAuthenticator)
SetAuthRetrier injects an authenticator to use for auto-recovery on access errors
func (*Git) SetRootDir ¶ added in v0.0.2
SetRootDir sets the root directory for git operations
func (*Git) SetShouldWrite ¶ added in v0.0.2
SetShouldWrite sets a function that determines if Git write operations (like updating .gitignore) should be allowed.
func (*Git) SetUserConfig ¶ added in v0.0.2
SetUserConfig sets git user name and email
func (*Git) StatusPorcelain ¶ added in v0.0.2
StatusPorcelain returns the output of git status --porcelain
type GitClient ¶ added in v0.0.2
type GitClient interface {
CheckRemoteAccess() error
Push(message, tag string) (PushResult, error)
GetLatestTag() (string, error)
SetLog(fn func(...any))
SetShouldWrite(fn func() bool)
SetRootDir(path string)
GitIgnoreAdd(entry string) error
GetConfigUserName() (string, error)
GetConfigUserEmail() (string, error)
InitRepo(dir string) error
Add() error
Commit(message string) (bool, error)
CommitPaths(message string, paths ...string) (bool, error)
CreateTag(tag string) (bool, error)
PushWithTags(tag string) (bool, error)
PushWithoutTags() (bool, error)
HasPendingChanges() (bool, error)
StatusPorcelain() (string, error)
DiffShortStat() (string, error)
GenerateNextTag() (string, error)
IncrementTag(tag string) (string, error)
Clone(repoURL string) (alreadyPresent bool, err error)
Pull() error
Fetch() error
}
GitClient defines the interface for Git operations.
type GitHub ¶ added in v0.0.2
type GitHub struct {
SecretRunner SecretRunner
// contains filtered or unexported fields
}
GitHub handler for GitHub operations
func NewGitHub ¶ added in v0.0.2
func NewGitHub(logFn func(...any), secretStore SecretStore, auth ...GitHubAuthenticator) (*GitHub, error)
NewGitHub creates handler and verifies gh CLI availability. logFn is used to display authentication messages during Device Flow. secretStore is injected into the default OAuth authenticator (ignored when an authenticator is passed explicitly). If not authenticated, it initiates OAuth Device Flow automatically.
func (*GitHub) CreateRelease ¶ added in v0.0.2
CreateRelease creates a GitHub Release and uploads assets. If targetRepo is not empty, it uses the --repo flag to publish to that repository.
func (*GitHub) CreateRepo ¶ added in v0.0.2
CreateRepo creates a new empty repository on GitHub If owner is provided, creates repo under that organization
func (*GitHub) DeleteRepo ¶ added in v0.0.2
DeleteRepo deletes a repository on GitHub. WARNING: This permanently deletes the repository and cannot be undone. Use with caution, primarily for test cleanup.
func (*GitHub) DeleteSecret ¶ added in v0.0.2
DeleteSecret removes a GitHub Actions secret. gh secret delete NAME --repo=OWNER/REPO
func (*GitHub) GetCurrentUser ¶ added in v0.0.2
GetCurrentUser gets the current authenticated user
func (*GitHub) GetHelpfulErrorMessage ¶ added in v0.0.2
GetHelpfulErrorMessage returns a helpful message for common errors
func (*GitHub) IsNetworkError ¶ added in v0.0.2
IsNetworkError checks if an error is likely a network error
func (*GitHub) ListSecrets ¶ added in v0.0.2
ListSecrets returns the names of secrets registered in the repo. Values are never accessible via API — GitHub only exposes names. gh secret list --repo=OWNER/REPO --json name --jq '[.[].name]'
func (*GitHub) RepoExists ¶ added in v0.0.2
RepoExists checks if a repository exists
func (*GitHub) RepoInfo ¶ added in v0.0.3
repoInfo returns basic information about a repository. If repoRef is empty, it queries the repository in the current directory.
func (*GitHub) SetSecret ¶ added in v0.0.2
SetSecret registers a secret in GitHub Actions via gh CLI. The value is passed via stdin — gh CLI encrypts it with the repo's public key before transmitting it. It does not appear in system ps/logs.
func (*GitHub) SetSecretWithScope ¶ added in v0.0.2
SetSecretWithScope registers a secret either at the repository level or organization level.
type GitHubAuthHandler ¶ added in v0.0.2
type GitHubAuthHandler interface {
GitHubAuthenticator
Name() string
}
GitHubAuthHandler defines the interface for GitHub auth as a TUI handler.
type GitHubAuthenticator ¶ added in v0.0.2
GitHubAuthenticator defines the interface for GitHub authentication. This allows mocking authentication in tests.
type GitHubClient ¶ added in v0.0.2
type GitHubClient interface {
SetLog(fn func(...any))
GetCurrentUser() (string, error)
RepoExists(owner, name string) (bool, error)
CreateRepo(owner, name, description, visibility string) error
DeleteRepo(owner, name string) error
IsNetworkError(err error) bool
GetHelpfulErrorMessage(err error) string
CreateRelease(tag string, assets []string, targetRepo string) (string, error)
}
GitHubClient defines the interface for GitHub operations. This allows mocking the GitHub dependency in tests.
type GitHubOAuth ¶ added in v0.0.2
type GitHubOAuth struct {
// contains filtered or unexported fields
}
GitHubOAuth handles GitHub authentication and token management via Device Flow
func NewGitHubOAuth ¶ added in v0.0.2
func NewGitHubOAuth() *GitHubOAuth
NewGitHubOAuth creates a new GitHub authentication handler
func (*GitHubOAuth) DeviceFlowAuth ¶ added in v0.0.2
func (a *GitHubOAuth) DeviceFlowAuth() (string, error)
DeviceFlowAuth initiates GitHub OAuth Device Flow and returns an access token
func (*GitHubOAuth) EnsureGitHubAuth ¶ added in v0.0.2
func (a *GitHubOAuth) EnsureGitHubAuth() error
EnsureGitHubAuth checks if GitHub is authenticated via the SecretStore, and if not, initiates Device Flow
func (*GitHubOAuth) Name ¶ added in v0.0.2
func (a *GitHubOAuth) Name() string
Name returns the handler name for TUI display.
func (*GitHubOAuth) SetHTTPClient ¶ added in v0.0.5
func (a *GitHubOAuth) SetHTTPClient(client *http.Client)
SetHTTPClient overrides the HTTP client used for GitHub API calls. Tests inject a client that never leaves the machine; nil (the default) uses a client with a 30s timeout.
func (*GitHubOAuth) SetLog ¶ added in v0.0.2
func (a *GitHubOAuth) SetLog(fn func(...any))
SetLog sets the logger function
func (*GitHubOAuth) SetStore ¶ added in v0.0.4
func (a *GitHubOAuth) SetStore(store SecretStore)
SetStore injects the SecretStore used to persist the OAuth token. Without a store, EnsureGitHubAuth and DeviceFlowAuth report a clear error (they can only authenticate interactively if they can store the result).
func (*GitHubOAuth) SetTokenValidator ¶ added in v0.0.5
func (a *GitHubOAuth) SetTokenValidator(fn func(token string) TokenValidationResult)
SetTokenValidator overrides how a stored token is validated. Tests inject a fake validator so no real GitHub API call happens; nil (the default) uses the real check against the GitHub API.
type GitHubPATAuth ¶ added in v0.0.2
type GitHubPATAuth struct {
// contains filtered or unexported fields
}
GitHubPATAuth manages the GitHub PAT via an injected SecretStore. It is used to recover the gh CLI session non-interactively.
func NewGitHubPATAuth ¶ added in v0.0.2
func NewGitHubPATAuth(store SecretStore) *GitHubPATAuth
NewGitHubPATAuth creates a GitHubPATAuth over the given store. The store may be nil: the auth flow then falls back to the GH_TOKEN environment variable and reports a clear error when neither exists.
func (*GitHubPATAuth) EnsureGitHubAuth ¶ added in v0.0.2
func (a *GitHubPATAuth) EnsureGitHubAuth() error
EnsureGitHubAuth fulfills the GitHubAuthenticator interface.
func (*GitHubPATAuth) EnsureToken ¶ added in v0.0.2
func (a *GitHubPATAuth) EnsureToken() (string, error)
EnsureToken returns the PAT from the environment or SecretStore; if absent, prompts once and persists.
func (*GitHubPATAuth) HasToken ¶ added in v0.0.2
func (a *GitHubPATAuth) HasToken() bool
HasToken returns true if the GitHub PAT is already stored in the environment or SecretStore.
func (*GitHubPATAuth) Reset ¶ added in v0.0.2
func (a *GitHubPATAuth) Reset() error
Reset removes the GitHub PAT from the SecretStore.
func (*GitHubPATAuth) SetLog ¶ added in v0.0.2
func (a *GitHubPATAuth) SetLog(fn func(...any))
SetLog sets the logging function.
type HTTPSumDB ¶ added in v0.0.6
HTTPSumDB is the real SumDBClient, backed by sum.golang.org's lookup endpoint (https://go.dev/design/25530-sumdb#lookup).
type MockGitHubAuth ¶ added in v0.0.2
type MockGitHubAuth struct {
EnsureAuthError error // Set this to simulate auth failure
// contains filtered or unexported fields
}
MockGitHubAuth is a mock implementation of GitHubAuthenticator for testing.
func NewMockGitHubAuth ¶ added in v0.0.2
func NewMockGitHubAuth() *MockGitHubAuth
NewMockGitHubAuth creates a new mock authenticator.
func (*MockGitHubAuth) EnsureGitHubAuth ¶ added in v0.0.2
func (m *MockGitHubAuth) EnsureGitHubAuth() error
EnsureGitHubAuth simulates the authentication process.
func (*MockGitHubAuth) Name ¶ added in v0.0.2
func (m *MockGitHubAuth) Name() string
Name returns the handler name for TUI display.
func (*MockGitHubAuth) SetLog ¶ added in v0.0.2
func (m *MockGitHubAuth) SetLog(fn func(...any))
SetLog sets the logger function.
type PublishAction ¶ added in v0.0.2
type PublishAction int
const ( ActionNone PublishAction = iota // no objection: full publication (tag + cascade) ActionDepsOnly // commit go.mod/go.sum, push without tag, no cascade ActionSkip // do not touch the repo at all )
func ResolvePublishAction ¶ added in v0.0.2
func ResolvePublishAction(objectors []PublishObjector, ctx PublishContext) (PublishAction, string)
ResolvePublishAction returns the strongest action any objector requires (Skip > DepsOnly > None) and the reason of the objector that set it.
type PublishContext ¶ added in v0.0.2
type PublishObjector ¶ added in v0.0.2
type PublishObjector interface {
ObjectsToPublish(ctx PublishContext) (PublishAction, string) // action + readable reason
}
type PushResult ¶ added in v0.0.2
type PushResult struct {
Summary string // Human-readable summary of operations performed
Tag string // The tag that was created and pushed
}
PushResult contains the results of a Git push operation
type SecretRunner ¶ added in v0.0.2
type SecretRunner interface {
Run(name string, args ...string) (string, error)
RunSilent(name string, args ...string) (string, error)
RunWithStdin(input, name string, args ...string) (string, error)
}
SecretRunner abstracts command execution for testability. Exported to be implemented in external tests.
type SecretStore ¶ added in v0.0.4
type SecretStore interface {
// Set stores value under key.
Set(key, value string) error
// Get returns the value stored under key.
Get(key string) (string, error)
// Delete removes key.
Delete(key string) error
}
SecretStore abstracts credential persistence for the GitHub auth flows.
tinywasm/git deliberately depends on no concrete backend: inject the store that fits your environment — the OS keyring (github.com/tinywasm/keyring) for interactive CLIs, an in-memory map for tests/CI, or no store at all when GH_TOKEN is set. The auth flows degrade gracefully when store is nil.
type SumDBClient ¶ added in v0.0.6
SumDBClient reports whether a module version was ever indexed by the public Go checksum database (sum.golang.org). A version that appears there was consulted by someone, at some point, possibly with different content than what is about to be tagged now — reusing it risks a "SECURITY ERROR: checksum mismatch" for any consumer building outside GOPRIVATE.
type TestCache ¶ added in v0.0.2
TestCache provides git-based test caching to avoid re-running tests when the code hasn't changed since the last successful test run.
func NewTestCache ¶ added in v0.0.2
NewTestCache creates a new TestCache instance
func (*TestCache) GetCacheKey ¶ added in v0.0.2
GetCacheKey returns a unique key for the current module based on its path
func (*TestCache) GetCachePath ¶ added in v0.0.2
GetCachePath returns the full path to the cache file
func (*TestCache) GetCachedMessage ¶ added in v0.0.2
GetCachedMessage returns the cached test output message
func (*TestCache) GetGitState ¶ added in v0.0.2
GetGitState returns current git state: commit hash + diff hash This uniquely identifies the exact state of the code
func (*TestCache) InvalidateCache ¶ added in v0.0.2
InvalidateCache removes the cache file
func (*TestCache) IsCacheValid ¶ added in v0.0.2
IsCacheValid checks if tests were already run successfully with the current code
type TokenValidationResult ¶ added in v0.0.5
type TokenValidationResult uint8
TokenValidationResult distingue los tres desenlaces posibles de la validación de un token contra la API de GitHub. Sin esta distinción, cualquier tropiezo de una herramienta externa se interpretaba como "credencial inválida" y borraba el token.
const ( TokenValid TokenValidationResult = iota // GitHub aceptó el token TokenRejected // GitHub devolvió 401: el token ya no sirve TokenUnverifiable // no se pudo comprobar: red, gh, llavero… )