-
Notifications
You must be signed in to change notification settings - Fork 1
feat: [AH-2542]: added readme api for nuget #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| // Copyright 2023 Harness, Inc. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| package nuget | ||
|
|
||
| import ( | ||
| "context" | ||
| "fmt" | ||
|
|
||
| "github.com/harness/gitness/registry/app/pkg" | ||
| "github.com/harness/gitness/registry/app/pkg/base" | ||
| "github.com/harness/gitness/registry/app/pkg/commons" | ||
| "github.com/harness/gitness/registry/app/pkg/nuget" | ||
| "github.com/harness/gitness/registry/app/pkg/response" | ||
| nugettype "github.com/harness/gitness/registry/app/pkg/types/nuget" | ||
| registrytypes "github.com/harness/gitness/registry/types" | ||
| ) | ||
|
|
||
| func (c *controller) GetReadme( | ||
| ctx context.Context, | ||
| info nugettype.ArtifactInfo, | ||
| ) *GetReadmeResponse { | ||
| f := func(registry registrytypes.Registry, a pkg.Artifact) response.Response { | ||
| info.RegIdentifier = registry.Name | ||
| info.RegistryID = registry.ID | ||
| nugetRegistry, ok := a.(nuget.Registry) | ||
| if !ok { | ||
| return &GetReadmeResponse{ | ||
| BaseResponse{ | ||
| fmt.Errorf("invalid registry type: expected nuget.Registry"), | ||
| nil, | ||
| }, "", | ||
| } | ||
| } | ||
| readmeContent, err := nugetRegistry.GetReadme(ctx, info) | ||
| if err != nil { | ||
| return &GetReadmeResponse{ | ||
| BaseResponse{ | ||
| err, | ||
| nil, | ||
| }, "", | ||
| } | ||
| } | ||
|
|
||
| headers := &commons.ResponseHeaders{ | ||
| Headers: map[string]string{ | ||
| "Content-Type": "text/markdown; charset=utf-8", | ||
| }, | ||
| } | ||
|
|
||
| return &GetReadmeResponse{ | ||
| BaseResponse{ | ||
| nil, | ||
| headers, | ||
| }, readmeContent, | ||
| } | ||
| } | ||
|
|
||
| result, err := base.NoProxyWrapper(ctx, c.registryDao, f, info) | ||
|
|
||
| if err != nil { | ||
| return &GetReadmeResponse{ | ||
| BaseResponse{ | ||
| err, | ||
| nil, | ||
| }, "", | ||
| } | ||
| } | ||
| readmeResponse, ok := result.(*GetReadmeResponse) | ||
| if !ok { | ||
| return &GetReadmeResponse{ | ||
| BaseResponse{ | ||
| fmt.Errorf("invalid response type: expected GetReadmeResponse"), | ||
| nil, | ||
| }, "", | ||
| } | ||
| } | ||
| return readmeResponse | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| package nuget | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "net/http" | ||
| "strings" | ||
|
|
||
|
|
@@ -33,6 +34,7 @@ type Handler interface { | |
| UploadSymbolPackage(writer http.ResponseWriter, request *http.Request) | ||
| DownloadPackage(http.ResponseWriter, *http.Request) | ||
| DeletePackage(writer http.ResponseWriter, request *http.Request) | ||
| GetReadme(writer http.ResponseWriter, request *http.Request) | ||
| GetServiceEndpoint(http.ResponseWriter, *http.Request) | ||
| GetServiceEndpointV2(http.ResponseWriter, *http.Request) | ||
| ListPackageVersion(http.ResponseWriter, *http.Request) | ||
|
|
@@ -92,3 +94,36 @@ func (h *handler) GetPackageArtifactInfo(r *http.Request) (pkg.PackageArtifactIn | |
| NestedPath: strings.TrimSuffix(r.PathValue("*"), "/"), | ||
| }, nil | ||
| } | ||
|
|
||
| func (h *handler) GetReadme(writer http.ResponseWriter, request *http.Request) { | ||
| ctx := request.Context() | ||
|
|
||
| // Get artifact info from request | ||
| info, err := h.GetPackageArtifactInfo(request) | ||
| if err != nil { | ||
| h.HandleErrors(ctx, []error{err}, writer) | ||
| return | ||
| } | ||
|
|
||
| nugetInfo, ok := info.(*nugettype.ArtifactInfo) | ||
| if !ok { | ||
| h.HandleErrors(ctx, []error{fmt.Errorf("failed to fetch info from context")}, writer) | ||
| return | ||
| } | ||
|
|
||
| // Call controller to get readme | ||
| response := h.controller.GetReadme(ctx, *nugetInfo) | ||
| if response.Error != nil { | ||
| h.HandleError(ctx, writer, response.Error) | ||
| return | ||
| } | ||
|
|
||
| // Write response headers | ||
| if response.ResponseHeaders != nil { | ||
| response.ResponseHeaders.WriteHeadersToResponse(writer) | ||
| } | ||
|
|
||
| // Write readme content | ||
| writer.WriteHeader(http.StatusOK) | ||
| _, _ = writer.Write([]byte(response.ReadmeContent)) | ||
| } | ||
|
Comment on lines
+98
to
+129
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # Find ResponseHeaders type definition and WriteHeadersToResponse implementation
rg -n "type ResponseHeaders|WriteHeadersToResponse" -C 5 --type=goRepository: abhinavcode/harness Length of output: 8039 🏁 Script executed: # Search for other NuGet handlers to see standard error handling patterns
rg -n "func \(h \*handler\) Get" -C 3 --type=go | head -100Repository: abhinavcode/harness Length of output: 7184 🏁 Script executed: # Look for standard error mapping patterns in NuGet handlers
rg -n "TranslatedUserError|StatusCodeMapper|GetPackageMetadata|GetServiceEndpoint" -C 3 --type=go | head -150Repository: abhinavcode/harness Length of output: 10135 🏁 Script executed: # Find the response type/structure for GetReadme
rg -n "GetReadme" -C 5 --type=go | grep -A 20 "func.*GetReadme"Repository: abhinavcode/harness Length of output: 6266 🏁 Script executed: # Find GetReadmeResponse type definition
rg -n "type GetReadmeResponse|ReadmeContent|ResponseHeaders" registry/app/api/controller/pkg/nuget/ -C 3 --type=goRepository: abhinavcode/harness Length of output: 4914 🏁 Script executed: # Look at GetPackageMetadata handler implementation to see standard pattern
cat -n registry/app/api/handler/nuget/package_metadata.goRepository: abhinavcode/harness Length of output: 1860 🏁 Script executed: # Check GetServiceEndpoint handler implementation
cat -n registry/app/api/handler/nuget/service_endpoint.goRepository: abhinavcode/harness Length of output: 1847 🏁 Script executed: # Find how other handlers map controller responses to HTTP responses
rg -n "controller\." registry/app/api/handler/nuget/ -A 5 --type=go | head -200Repository: abhinavcode/harness Length of output: 9256 🏁 Script executed: # Check WriteToResponse vs WriteHeadersToResponse difference
rg -n "func.*WriteToResponse|func.*WriteHeadersToResponse" registry/app/pkg/commons/request.go -A 10Repository: abhinavcode/harness Length of output: 551 🏁 Script executed: # Find HandleError implementation
rg -n "func.*HandleError" registry/app/api/handler/nuget/ -A 8 --type=goRepository: abhinavcode/harness Length of output: 45 🏁 Script executed: # Look at the complete get_readme.go controller to see full flow
cat -n registry/app/api/controller/pkg/nuget/get_readme.goRepository: abhinavcode/harness Length of output: 2962 🏁 Script executed: # Search for HandleError in the handler base class
rg -n "HandleError" registry/app/api/handler/ -C 3 --type=go | head -100Repository: abhinavcode/harness Length of output: 6677 🏁 Script executed: # Check the handler base implementation
find registry/app/api/handler -name "handler.go" -o -name "base.go" | xargs grep -l "HandleError" 2>/dev/nullRepository: abhinavcode/harness Length of output: 195 🏁 Script executed: # Look at the handler struct definition in nuget
rg -n "type handler struct" registry/app/api/handler/nuget/ -A 10 --type=goRepository: abhinavcode/harness Length of output: 770 🏁 Script executed: # Find HandleError in packages.Handler
cat -n registry/app/api/handler/packages/handler.go | grep -A 15 "func.*HandleError"Repository: abhinavcode/harness Length of output: 1901 Use standard error handling pattern consistent with other NuGet handlers.
Follow the pattern used by 🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -517,6 +517,14 @@ func (r *proxy) GetPackageTypes() []artifact.PackageType { | |
| return []artifact.PackageType{artifact.PackageTypeNUGET} | ||
| } | ||
|
|
||
| func (r *proxy) GetReadme( | ||
| ctx context.Context, | ||
| _ nugettype.ArtifactInfo, | ||
| ) (string, error) { | ||
| log.Error().Ctx(ctx).Msg("Not implemented") | ||
| return "", errcode.ErrCodeInvalidRequest.WithDetail(fmt.Errorf("not implemented")) | ||
| } | ||
|
Comment on lines
+520
to
+526
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Readme retrieval always fails for proxy registries. The new endpoint is now routable for NuGet, but the proxy implementation hard-fails with “not implemented,” which means readme fetches for upstream/proxy registries will consistently error. If proxy registries are meant to support readmes, this needs a real upstream fetch; if not, consider explicitly signaling “not supported” and hiding readme URLs for proxy metadata to avoid broken links. 🤖 Prompt for AI Agents |
||
|
|
||
| func (r *proxy) putFileToLocal( | ||
| ctx context.Context, info *nugettype.ArtifactInfo, | ||
| remote RemoteRegistryHelper, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 158
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 1338
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 545
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 4402
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 520
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 1912
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 156
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 6438
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 45
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 233
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 45
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 233
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 1008
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 502
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 45
🏁 Script executed:
# Look at the nuget handler to see how it processes responses cat -n registry/app/api/handler/nuget/handler.goRepository: abhinavcode/harness
Length of output: 4976
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 2596
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 45
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 45
🏁 Script executed:
# Also check the commons package for these methods cat -n registry/app/pkg/commons/request.goRepository: abhinavcode/harness
Length of output: 3184
🏁 Script executed:
Repository: abhinavcode/harness
Length of output: 585
Set
Code: 200explicitly for clarity and consistency with other handler patterns.The handler layer does write HTTP 200 OK (via
writer.WriteHeader(http.StatusOK)on line 127 ofregistry/app/api/handler/nuget/handler.go), so the current code functions correctly. However, theCodefield is left at zero, which creates confusion given thatResponseHeaders.WriteToResponse()only writes the status ifCode != 0. Other handlers likeDownloadPackageuse theWriteToResponse()pattern, which would fail silently ifCoderemained zero. For consistency and clarity, explicitly setCode: 200in the controller response.🤖 Prompt for AI Agents