Documentation
¶
Index ¶
- Variables
- func AddCommitAndPushChanges(ctx context.Context, repo *goGit.Repository, workTree *goGit.Worktree, ...) plumbing.Hash
- func BuildPRCompareURL(repo *goGit.Repository, defaultBranch, featureBranch string) string
- func CheckoutToDefaultBranchAndFetchUpdates(ctx context.Context, repo *goGit.Repository, workTree *goGit.Worktree, ...)
- func CloneRepo(ctx context.Context, url string, authMethod transport.AuthMethod, ...) *goGit.Repository
- func CommitSigner(ctx context.Context) goGit.Signer
- func CreateAndCheckoutToBranch(ctx context.Context, repo *goGit.Repository, branch string, ...)
- func GetDefaultBranchName(ctx context.Context, authMethod transport.AuthMethod, repo *goGit.Repository) string
- func GetGitAuthMethod(ctx context.Context) transport.AuthMethod
- func GetRepoDir(parsedURL *giturl.ParsedURL) string
- func HardResetRepoToRef(ctx context.Context, repo *git.Repository, ref string)
- func OperatorAttribution(message string) (*object.Signature, string)
- func ParseURL(url string) (*giturl.ParsedURL, error)
- func SetRemoteHEADRef(ctx context.Context, repo *goGit.Repository, branch string)
- func WaitUntilPRMerged(ctx context.Context, repo *goGit.Repository, defaultBranchName string, ...)
- type CloneRepoOptions
Constants ¶
This section is empty.
Variables ¶
var CommonKnownHosts string
The hosts specified in this file, are know by defaut by ArgoCD. Because, we've picked them up from a argocd-ssh-known-hosts-cm ConfigMap 😉.
Functions ¶
func AddCommitAndPushChanges ¶
func AddCommitAndPushChanges(ctx context.Context, repo *goGit.Repository, workTree *goGit.Worktree, branch string, authMethod transport.AuthMethod, clusterName string, commitMessage string, defaultBranchName string, ) plumbing.Hash
defaultBranchName is the fork's default branch (e.g. "main") — passed in by the caller rather than re-discovered inside this function. The caller already called GetDefaultBranchName once during its own setup (setup_kubeaid_config.go / upgrade_cluster.go); passing the value through avoids a second remote.ListContext call right after the push, which over SSH triggers a separate "look up default branch on <fork>" YubiKey touch on every commit-push cycle.
func BuildPRCompareURL ¶ added in v0.23.0
func BuildPRCompareURL(repo *goGit.Repository, defaultBranch, featureBranch string) string
BuildPRCompareURL returns a clickable "create PR" URL for the given repo's origin, comparing defaultBranch (base) against featureBranch (head). Format is `<https-base>/compare/<base>...<head>`, which is what GitHub, Gitea, and most other forges accept for a same-repo compare page. kubeaid-cli always pushes the feature branch to the operator's own config repo (head == base repo), so we never need the cross-fork URL form.
Panics on internal errors (origin remote unreadable, malformed URL). In practice these are unreachable: callers always invoke this after successfully pushing to origin, so origin must be readable and well- formed. A panic surfaces the bug fast instead of silently degrading to an empty URL the operator can't click.
(Aside: some forges support push options like `git push -o merge_request.create` (GitLab) to open the PR automatically, but GitHub doesn't, so we just print the URL and let the operator click it.)
func CheckoutToDefaultBranchAndFetchUpdates ¶ added in v0.10.0
func CheckoutToDefaultBranchAndFetchUpdates(ctx context.Context, repo *goGit.Repository, workTree *goGit.Worktree, authMethod transport.AuthMethod, )
Removes any unstaged changes in the current branch. Then checks out to the default branch and fetches updates for that branch.
Used by CloneRepo's re-run path for repos where kubeaid-cli walks history on the default branch (kubeaid-config — WaitUntilPRMerged's isCommitPresentInBranch needs the default branch's commit graph). Repos that are read-only-at-a-pinned-ref (kubeaid-fork) take the refreshPinnedRef path instead.
The fetch is scoped to '+refs/heads/<defaultBranch>:refs/heads/<defaultBranch>' — narrow refspec, no tags. The previous '+refs/*:refs/*' + AllTags pulled every ref + every tag from the operator's kubeaid-config on every re-run, which is wasteful (we only check commit presence on the default branch) and turns out to be brittle: when the operator merges a PR with auto-delete-on-merge, refs/heads/<feature-branch> is gone remotely, and a wildcard refspec then surfaces "couldn't find remote ref" / "some refs were not updated" errors even though our actual target — the default branch — fetched fine.
CreateAndCheckoutToBranch deliberately does NOT call this — callers there go through CloneRepo first, so the fetch has already happened; double-fetching back-to-back would just burn a YubiKey touch.
func CloneRepo ¶
func CloneRepo(ctx context.Context, url string, authMethod transport.AuthMethod, opts ...CloneRepoOptions) *goGit.Repository
Clones the given git repository, if that isn't already done. When the repo is already cloned, it checks out to the default branch and fetches the latest changes.
Pass CloneRepoOptions to override the re-run fetch behavior — see CloneRepoOptions doc. Variadic parameter for backward compat with existing callers that don't need the override.
func CommitSigner ¶ added in v0.23.0
CommitSigner returns a go-git Signer suitable for CommitOptions.Signer when ALL of these hold:
- git config commit.gpgsign == "true" (operator opted in);
- git config user.signingkey is set;
- git config gpg.format is empty or "openpgp" (this signer doesn't handle ssh-format signatures);
- gpg is on PATH;
- a GPG smartcard is plugged in (`gpg --card-status` succeeds).
Returns nil otherwise — caller passes nil to leave the commit unsigned. With no card we stay unsigned rather than silently fall back to a software key the operator may not have meant to use for kubeaid-cli's commits.
When commit.gpgsign IS true but a downstream gate fails, we log at Info level so the operator sees why the commit went through unsigned — debug-only logs hid these "I expected signing, why didn't it sign" cases under the default log level.
func CreateAndCheckoutToBranch ¶
func CreateAndCheckoutToBranch(ctx context.Context, repo *goGit.Repository, branch string, workTree *goGit.Worktree, authMethod transport.AuthMethod, )
Discards all the changes in the current branch and checks out to the default branch first. Then, checks out to a new branhc with the given name. If a branch with that name already exists, then panics.
func GetDefaultBranchName ¶
func GetDefaultBranchName(ctx context.Context, authMethod transport.AuthMethod, repo *goGit.Repository, ) string
GetDefaultBranchName returns the default branch of the 'origin' remote.
Reads refs/remotes/origin/HEAD locally first (no network) — set by SetRemoteHEADRef after clone, or lazily cached by this function after a network fallback. Falls back to remote.ListContext only when the symbolic ref is missing — a legacy clone made before the eager-write landed, or one produced by a tool that didn't set the ref. The fallback caches its result so subsequent calls hit the local path.
go-git's PlainCloneContext doesn't write refs/remotes/origin/HEAD (still missing as of v5.x — verified on disk under /tmp/kubeaid-core/...kubeaid-config/.git/refs/remotes/origin/), so the local lookup only succeeds for clones we've cached one way or another. Each successful network fallback writes the cache, so a pre-eager-write legacy clone pays one list-refs touch on first call and zero thereafter.
func GetGitAuthMethod ¶
func GetGitAuthMethod(ctx context.Context) transport.AuthMethod
Returns the Git authentication method which KubeAid CLI will use to interact with the KubeAid Config and / or KubeAid repositories.
The operator-supplied private key (file path) is expected to be UNENCRYPTED — we pass an empty passphrase to gossh.NewPublicKeysFromFile. Encrypted keys (BEGIN OPENSSH ENCRYPTED ...) fail at construction time. Operators who need a passphrased key should use the SSH agent path instead, which holds the decrypted material in memory.
TODO : Support passphrased private keys by prompting the operator at runtime via golang.org/x/term.ReadPassword (no echo) and passing the captured passphrase to gossh.NewPublicKeysFromFile. Setup-time validation in pkg/config/prompt/prompt_helper.go:validateSSHPrivateKey already accepts encrypted keys ("the passphrase will be supplied later") but the runtime never wires up the prompt — encrypted keys pass setup and then fail at first git op. Adding the prompt here closes that gap without storing the passphrase in general.yaml.
func GetRepoDir ¶ added in v0.16.0
GetRepoDir returns the local on-disk path where the given repository will be cloned: <TempDir>/<host>/<owner>/<repo>. Uses HostName so non-default SSH ports (e.g. ":2223") don't leak the colon into the path — tools like docker's -v <src>:<dst> volume spec choke on it.
func HardResetRepoToRef ¶ added in v0.22.2
func HardResetRepoToRef(ctx context.Context, repo *git.Repository, ref string)
func OperatorAttribution ¶ added in v0.23.0
OperatorAttribution returns the Author signature and post- processed commit message kubeaid-cli should use when committing on the operator's behalf.
When the operator has user.name + user.email set in their global git config (~/.gitconfig), the Author is the operator and a `Co-Authored-By: Obmondo <info@obmondo.com>` trailer credits the kubeaid-cli script — same pattern Git uses elsewhere for human-attributed-but-tool-driven commits (and what forges like Gitea/GitHub render as a co-author on the PR page). When global config is missing the script authors directly as Obmondo with no trailer; the trailer would just duplicate the Author line in that case.
We read GlobalScope only — not Local. kubeaid-cli's commits land in the kubeaid-config repo, which the operator only ever interacts with via this script; there's no plausible reason for them to set a per-repo identity there. Reading Global also gives consistent attribution across multiple kubeaid-config repos managed from the same machine.
func ParseURL ¶ added in v0.23.0
ParseURL is a thin wrapper over giturl.Parse, kept here so callers in the git package can use the shorter `git.ParseURL` name and to preserve the previous package layout.
func SetRemoteHEADRef ¶ added in v0.23.0
func SetRemoteHEADRef(ctx context.Context, repo *goGit.Repository, branch string)
SetRemoteHEADRef writes refs/remotes/origin/HEAD as a symbolic ref pointing to refs/remotes/origin/<branch>. Lets GetDefaultBranchName answer locally on subsequent calls, skipping the remote list-refs round-trip (and the YubiKey touch that goes with it). Best-effort — any write failure logs a warning; GetDefaultBranchName's fallback path is the safety net.
func WaitUntilPRMerged ¶
func WaitUntilPRMerged(ctx context.Context, repo *goGit.Repository, defaultBranchName string, commitHash plumbing.Hash, auth transport.AuthMethod, branchToBeMerged string, )
WaitUntilPRMerged blocks until the operator confirms via stdin that they've merged the feature branch into the default branch.
The operator sees the PR URL (printed by AddCommitAndPushChanges before this is called), goes to their forge, merges, comes back, and presses ENTER. We then do ONE fetch + ONE commit-presence check to verify the merge actually happened — if it didn't (operator pressed ENTER too early, or merged the wrong branch), we say so and prompt again.
Earlier this function polled via a 10-second fetch loop. That meant one YubiKey touch every 10 seconds for as long as the PR sat unmerged — easily 30+ touches if the operator took a few minutes. One touch per ENTER press is far better, and the operator is in control of when it fires.
SkipPRWorkflow callers never reach this function — they push directly to the default branch. So this function always runs in interactive mode; no headless variant is needed.
Types ¶
type CloneRepoOptions ¶ added in v0.23.0
type CloneRepoOptions struct {
// PinnedRef is the tag or branch name the caller will hard-reset
// to after CloneRepo returns. When set, the re-run path narrows
// its fetch to just this ref instead of the default branch +
// everything else. Commit-hash values are rejected by
// validateKubeAidForkVersion at config parse time, so this is
// guaranteed to be a tag or branch name.
PinnedRef string
}
CloneRepoOptions controls CloneRepo's re-run-path fetch scope. The default behavior (no options, or PinnedRef empty) is for repos where kubeaid-cli walks history on the default branch — kubeaid- config, where isCommitPresentInBranch in WaitUntilPRMerged needs the default branch's commit history. Set PinnedRef for repos where kubeaid-cli only ever HardResetRepoToRef to a fixed tag/ branch (kubeaid-fork): the re-run path skips the default-branch dance and fetches only the pinned ref, saving network on every re-run.