fix(pkg/pull): Route git/GitHub URLs to manifest provider#2681
fix(pkg/pull): Route git/GitHub URLs to manifest provider#2681robaa12 wants to merge 13 commits intounikraft:stagingfrom
Conversation
|
Can you create commit for each fix in the table please? thanks 🙏 |
|
Hi @craciunoiuc , I implemented all the requested changes. Please take another look when you get a chance. Happy to make any further changes if needed. |
There was a problem hiding this comment.
Pull request overview
Fixes kraft pkg pull handling for git/GitHub-style inputs by ensuring they are routed to the manifest provider (instead of being treated as OCI registry/image refs), and prevents a nil-provider dereference during provider selection.
Changes:
- Add git-source heuristics to prevent the OCI manager from claiming git/GitHub inputs and to allow the manifest manager to short-circuit compatibility checks.
- Update
kraft pkg pullarg handling to pass git/GitHub inputs viaWithSource(so the manifest provider resolution path is used). - Improve normalization of SCP-style SSH and bare
github.com/...URLs in git/GitHub parsing and add unit tests for the new behavior.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
oci/manager.go |
Adds isGitSource and uses it to avoid OCI lookups for git/GitHub sources in Catalog/IsCompatible. |
oci/manager_test.go |
Adds unit tests for isGitSource. |
manifest/provider.go |
Adds nil-guard so provider selection never returns a nil provider without error. |
manifest/provider_git.go |
Normalizes bare github.com/... and fixes SCP-style SSH conversion to a parsable ssh:// form. |
manifest/manager.go |
Adds early-compatibility claim for git/GitHub patterns so manifest manager can handle them. |
manifest/manager_test.go |
Adds unit tests for git-source compatibility behavior. |
internal/ghrepo/repo.go |
Normalizes SCP-style SSH and bare github.com/... before url.Parse to correctly extract owner/repo. |
internal/ghrepo/repo_test.go |
Adds unit tests for NewFromURL normalization and parsing. |
internal/cli/kraft/pkg/pull/pull.go |
Routes detected git/GitHub args via WithSource instead of WithName. |
Comments suppressed due to low confidence (1)
oci/manager.go:1001
- In
OCIManager.IsCompatible, the newisGitSourceguard only exists insideisRegistry/isRemoteImage(which are only evaluated whenquery.Remote()is true). WhenRemoteis false (a common/default),isFullyQualifiedNameReferencecan still return true for GitHub-like git inputs (sincename.ParseReferenceaccepts them), so OCI may still claim git sources. Consider applying the git-source guard before running any of the checks (or insideisFullyQualifiedNameReference) so compatibility is consistently false for git sources regardless ofRemote.
// Check if the provided source an OCI Distrubtion Spec capable registry
isRegistry := func(source string) bool {
log.G(ctx).
WithField("source", source).
Tracef("checking if source is registry")
if isGitSource(source) {
return false
}
regName, err := name.NewRegistry(source)
if err != nil {
return false
}
if _, err := transport.Ping(ctx, regName, http.DefaultTransport.(*http.Transport).Clone()); err == nil {
return true
}
return false
}
// Check if the provided source is OCI registry
isRemoteImage := func(source string) bool {
log.G(ctx).
WithField("source", source).
Tracef("checking if source is remote image")
if isGitSource(source) {
return false
}
ref, err := name.ParseReference(source,
name.WithDefaultRegistry(DefaultRegistry),
name.WithDefaultTag(DefaultTag),
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| func isGitSource(source string) bool { | ||
| return strings.HasSuffix(source, ".git") || | ||
| strings.HasPrefix(source, "git@") || | ||
| strings.HasPrefix(source, "github.com/") || | ||
| strings.Contains(source, "://github.com/") | ||
| } |
There was a problem hiding this comment.
isGitSource doesn’t recognize SSH URL forms like ssh://git@github.com/owner/repo (no .git suffix) because it only checks git@ at the start and ://github.com/ (which won’t match ://git@github.com/). This means some valid git sources will still be treated as OCI refs and won’t be routed to the manifest provider. Consider parsing as a URL and matching hostname/user, or extending the checks to cover ssh:// (and ssh+git://, git+ssh://) variants explicitly.
| func isGitSource(source string) bool { | ||
| return strings.HasSuffix(source, ".git") || | ||
| strings.HasPrefix(source, "git@") || | ||
| strings.HasPrefix(source, "github.com/") || | ||
| strings.Contains(source, "://github.com/") | ||
| } |
There was a problem hiding this comment.
The .git suffix check in isGitSource will also return true for valid OCI image references whose repository name ends with .git (e.g. ghcr.io/org/foo.git without an explicit tag). That would prevent the OCI manager from handling those images and may cause a regression. Consider narrowing the heuristic (e.g. require a URL scheme/SSH form, or specifically target known git host patterns) so non-git OCI refs aren’t excluded.
| if strings.HasSuffix(arg, ".git") || | ||
| strings.HasPrefix(arg, "git@") || | ||
| strings.HasPrefix(arg, "github.com/") || | ||
| strings.Contains(arg, "://github.com/") { | ||
| qopts = append(qopts, packmanager.WithSource(arg)) | ||
| } else { | ||
| qopts = append(qopts, packmanager.WithName(arg)) | ||
| } |
There was a problem hiding this comment.
The git/GitHub detection here doesn’t match ssh://git@github.com/owner/repo (no .git suffix), so those sources will still be treated as package names and won’t set WithSource. Consider expanding detection to include SSH URL forms (and/or reusing a shared helper used by the manifest/git provider) so all supported git URL formats are routed consistently.
| if strings.HasSuffix(source, ".git") || | ||
| strings.HasPrefix(source, "git@") || | ||
| strings.HasPrefix(source, "github.com/") || | ||
| strings.Contains(source, "://github.com/") { | ||
| return m, true, nil | ||
| } |
There was a problem hiding this comment.
This early-claim heuristic misses GitHub SSH URL forms like ssh://git@github.com/owner/repo (no .git suffix) for the same reason as isGitSource in the OCI manager. If users pass those forms, the manifest manager may not be selected as compatible. Consider parsing as a URL and matching hostname, or adding explicit handling for ssh://git@github.com/ (and similar SSH variants).
|
I am working on the copilot changes now. Will push an update soon. |
6192ae3 to
3b7c460
Compare
|
Hey @craciunoiuc! I addressed the Copilot feedback by creating a shared What changed
Why did I choose this approach?
|
NewFromURL used url.Parse directly, which cannot handle SCP-style SSH URLs (git@github.com:owner/repo.git) or bare github.com/ paths without a scheme. Both cases result in an empty host, causing the "host is not github.com" error. Normalize both forms to https:// before parsing so the function works for all common GitHub URL formats. Signed-off-by: robaa12 <arobaa23@gmail.com>
NewGitProvider converted SCP-style git@HOST:path URLs to ssh://git@HOST:path (colon kept), which URL parsers (giturl, go-git) reject. The colon must become a slash: ssh://git@HOST/path. Also add explicit https:// normalization for bare github.com/ paths so they resolve without requiring a scheme prefix. Signed-off-by: robaa12 <arobaa23@gmail.com>
When both NewGitProvider and NewGitHubProvider fail, NewProvider returned a nil provider without error, causing a nil pointer dereference in Manifests(). Add a nil guard before the fallback return so the error path is taken instead. Signed-off-by: robaa12 <arobaa23@gmail.com>
ManifestManager.IsCompatible had no recognition of git/GitHub URL patterns, so it never short-circuited to claim them. Sources with a .git suffix, git@ prefix, github.com/ prefix, or ://github.com/ substring were not identified as compatible, causing the manifest manager to be skipped entirely. Add an early-return guard so these sources are claimed before the authentication/registry lookup path runs. Signed-off-by: robaa12 <arobaa23@gmail.com>
google/go-containerregistry's name.ParseReference accepts github.com/ paths as valid OCI references (treating github.com as a registry host), so OCIManager.IsCompatible incorrectly claimed git/GitHub URLs before the manifest manager could handle them. Add isGitSource() to detect .git suffixes, git@ prefixes, github.com/ prefixes, and ://github.com/ substrings, and return early in both the isRegistry and isRemoteImage closures. Also return early from Catalog() for git sources to prevent the entire local OCI image list from leaking into results. Signed-off-by: robaa12 <arobaa23@gmail.com>
git/GitHub args in pull.go were passed as WithName, but the manifest manager's Catalog() only resolves a provider when WithSource is set. As a result, Catalog() tried to glob-match the full URL against manifest names instead of calling NewProvider(ctx, source) to resolve the correct provider. Detect git/GitHub URL shapes (.git suffix, git@ prefix, github.com/ prefix, ://github.com/ substring) and pass them as WithSource so the manifest manager can route them to the correct provider. Signed-off-by: robaa12 <arobaa23@gmail.com>
Add centralized utility to detect git repository URLs vs OCI image references. Handles SSH URLs (ssh://, git@, git+ssh://), HTTPS URLs and bare host/path patterns. Also distinguishes OCI images with .git in the name from actual git sources. Fixes unikraft#1114 Signed-off-by: robaa12 <arobaa23@gmail.com>
Replace inline string matching with centralized IsGitSource to prevent OCI manager from claiming git/GitHub URLs. Also reduce test duplication as core logic is tested in gitutil package. Signed-off-by: robaa12 <arobaa23@gmail.com>
Replace inline git URL detection with centralized IsCompatible check. Add test cases for SSH URL variants. Signed-off-by: robaa12 <arobaa23@gmail.com>
Replace inline detection to properly route git/GitHub arguments via WithSource instead of WithName so manifest provider is used. Signed-off-by: robaa12 <arobaa23@gmail.com>
|
Done, please have another look when u get a chance. |
|
Hey, this did not work for me with these cases, am I doing something wrong? also note that it's showing a wildcard everywhere instead of the URL |
|
reproduced it on my end too. I'm working on a follow-up fix for those exact Also, the I'll push an update soon and drop another comment with exactly what changed. |
When pkg pull uses WithSource without a package name, Query.String fell back to '*', which made progress and error output misleading. Prefer the source field when name is empty so logs show the exact URL being queried. Signed-off-by: robaa12 <arobaa23@gmail.com>
Handle ssh+git@ and ssh://git@...:owner/repo forms consistently in source detection and URL parsing helpers. This prevents valid GitHub SSH-like inputs from being rejected and adds tests covering the additional normalization paths. Signed-off-by: robaa12 <arobaa23@gmail.com>
When probing GitHub sources, using the raw SSH-like input could depend on SSH agent availability and fail for public repositories. Probe via normalized HTTPS and preserve manifest origin as the original input so source-based filtering still matches the requested URL. Signed-off-by: robaa12 <arobaa23@gmail.com>
What was going wrong
What I changed
VerificationI rebuilt and tested |

Prerequisite checklist
Description of changes
Closes #1114
kraft pkg pullfailed to handle git/GitHub URLs such as:github.com/unikraft/lib-nginx.githttps://github.com/unikraft/lib-nginxgit@github.com:unikraft/lib-nginx.gitInstead of routing them to the manifest provider, they were either claimed by the OCI manager or crashed with a nil pointer dereference.
name.ParseReferencetreatsgithub.comas a valid registry host, soOCIManager.IsCompatibleclaimed git/GitHub URLs before the manifest manager couldisGitSource()to reject these URLs early inIsCompatibleandCatalog()pull.gowere passed asWithName, but the manifest manager'sCatalog()only resolves a provider whenWithSourceis setWithSourcefor all git/GitHub argsManifestManager.IsCompatiblehad no recognition of git/GitHub URL patterns, so it never short-circuited to claim them.git,git@,github.com/, and://github.com/NewGitProviderandNewGitHubProviderfailed, a nil provider was returned without error, causing a nil pointer dereference inManifests()NewProviderNewGitProviderconvertedgit@HOST:pathtossh://git@HOST:path(colon kept), which URL parsers rejectssh://git@HOST/path(colon replaced with slash)ghrepo.NewFromURLusedurl.Parsedirectly, which cannot handle SCP-style SSH or baregithub.com/URLs, resulting in an empty hosthttps://before parsing