mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-12 03:38:40 +00:00
feat(packages): add support for uploading helm provenance files (#36695)
Adds `POST helm/api/prov` endpoint for helm repository allowing for upload of provenance files. Tested manually to a degree but I really didn't want to mess with gpg again so I'm not sure if helm will correctly verify the chart. Initial draft made by gemini 3 flash but was finetuned somewhat. Additionally there's an route that allows for upload of both files via /api/charts - as separate files in form. If there's any interest in that I guess it can be added but I think helm is moving to OCI anyway which we support. Fixes: https://github.com/go-gitea/gitea/issues/36678 Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
@@ -359,6 +359,7 @@ func CommonRoutes() *web.Router {
|
||||
r.Get("/index.yaml", helm.Index)
|
||||
r.Get("/{filename}", helm.DownloadPackageFile)
|
||||
r.Post("/api/charts", reqPackageAccess(perm.AccessModeWrite), helm.UploadPackage)
|
||||
r.Post("/api/prov", reqPackageAccess(perm.AccessModeWrite), helm.UploadProvenanceFile)
|
||||
}, reqPackageAccess(perm.AccessModeRead))
|
||||
r.Group("/maven", func() {
|
||||
r.Put("/*", reqPackageAccess(perm.AccessModeWrite), maven.UploadPackageFile)
|
||||
|
||||
@@ -209,6 +209,76 @@ func UploadPackage(ctx *context.Context) {
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
// UploadProvenanceFile uploads and attaches the provenance file to existing helm chart
|
||||
func UploadProvenanceFile(ctx *context.Context) {
|
||||
upload, needToClose, err := ctx.UploadStream()
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if needToClose {
|
||||
defer upload.Close()
|
||||
}
|
||||
|
||||
buf, err := packages_module.CreateHashedBufferFromReader(upload)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
defer buf.Close()
|
||||
|
||||
metadata, err := helm_module.ParseProvenanceFile(buf)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrInvalidArgument) || errors.Is(err, io.EOF) {
|
||||
apiError(ctx, http.StatusBadRequest, err)
|
||||
} else {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := buf.Seek(0, io.SeekStart); err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = packages_service.AddFileToExistingPackage(
|
||||
ctx,
|
||||
&packages_service.PackageInfo{
|
||||
Owner: ctx.Package.Owner,
|
||||
PackageType: packages_model.TypeHelm,
|
||||
Name: metadata.Name,
|
||||
Version: metadata.Version,
|
||||
},
|
||||
&packages_service.PackageFileCreationInfo{
|
||||
PackageFileInfo: packages_service.PackageFileInfo{
|
||||
Filename: createProvenanceFilename(metadata),
|
||||
},
|
||||
Creator: ctx.Doer,
|
||||
Data: buf,
|
||||
IsLead: false,
|
||||
OverwriteExisting: true,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
switch err {
|
||||
case packages_model.ErrPackageNotExist:
|
||||
apiError(ctx, http.StatusNotFound, err)
|
||||
case packages_service.ErrQuotaTotalCount, packages_service.ErrQuotaTypeSize, packages_service.ErrQuotaTotalSize:
|
||||
apiError(ctx, http.StatusForbidden, err)
|
||||
default:
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Status(http.StatusCreated)
|
||||
}
|
||||
|
||||
func createFilename(metadata *helm_module.Metadata) string {
|
||||
return strings.ToLower(fmt.Sprintf("%s-%s.tgz", metadata.Name, metadata.Version))
|
||||
}
|
||||
|
||||
func createProvenanceFilename(metadata *helm_module.Metadata) string {
|
||||
return strings.ToLower(fmt.Sprintf("%s-%s.tgz.prov", metadata.Name, metadata.Version))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user