Changes
24 changed files (+679/-21)
-
-
@@ -0,0 +1,67 @@--- date: "2022-04-14T00:00:00+00:00" title: "Helm Chart Registry" slug: "packages/helm" draft: false toc: false menu: sidebar: parent: "packages" name: "Helm" weight: 50 identifier: "helm" --- # Helm Chart Registry Publish [Helm](https://helm.sh/) charts for your user or organization. **Table of Contents** {{< toc >}} ## Requirements To work with the Helm Chart registry use a simple HTTP client like `curl` or the [`helm cm-push`](https://github.com/chartmuseum/helm-push/) plugin. ## Publish a package Publish a package by running the following command: ```shell curl --user {username}:{password} -X POST --upload-file ./{chart_file}.tgz https://gitea.example.com/api/packages/{owner}/helm/api/charts ``` or with the `helm cm-push` plugin: ```shell helm repo add --username {username} --password {password} {repo} https://gitea.example.com/api/packages/{owner}/helm helm cm-push ./{chart_file}.tgz {repo} ``` | Parameter | Description | | ------------ | ----------- | | `username` | Your Gitea username. | | `password` | Your Gitea password or a personal access token. | | `repo` | The name for the repository. | | `chart_file` | The Helm Chart archive. | | `owner` | The owner of the package. | ## Install a package To install a Helm char from the registry, execute the following command: ```shell helm repo add --username {username} --password {password} {repo} https://gitea.example.com/api/packages/{owner}/helm helm repo update helm install {name} {repo}/{chart} ``` | Parameter | Description | | ---------- | ----------- | | `username` | Your Gitea username. | | `password` | Your Gitea password or a personal access token. | | `repo` | The name for the repository. | | `owner` | The owner of the package. | | `name` | The local name. | | `chart` | The name Helm Chart. |
-
-
-
@@ -8,7 +8,7 @@ menu:sidebar: parent: "packages" name: "Maven" weight: 50 weight: 60 identifier: "maven" ---
-
-
-
@@ -8,7 +8,7 @@ menu:sidebar: parent: "packages" name: "npm" weight: 60 weight: 70 identifier: "npm" ---
-
-
-
@@ -8,7 +8,7 @@ menu:sidebar: parent: "packages" name: "NuGet" weight: 70 weight: 80 identifier: "nuget" ---
-
-
-
@@ -30,6 +30,7 @@ The following package managers are currently supported:| [Conan]({{< relref "doc/packages/conan.en-us.md" >}}) | C++ | `conan` | | [Container]({{< relref "doc/packages/container.en-us.md" >}}) | - | any OCI compliant client | | [Generic]({{< relref "doc/packages/generic.en-us.md" >}}) | - | any HTTP client | | [Helm]({{< relref "doc/packages/helm.en-us.md" >}}) | - | any HTTP client, `cm-push` | | [Maven]({{< relref "doc/packages/maven.en-us.md" >}}) | Java | `mvn`, `gradle` | | [npm]({{< relref "doc/packages/npm.en-us.md" >}}) | JavaScript | `npm`, `yarn` | | [NuGet]({{< relref "doc/packages/nuget.en-us.md" >}}) | .NET | `nuget` |
-
-
-
@@ -8,7 +8,7 @@ menu:sidebar: parent: "packages" name: "PyPI" weight: 80 weight: 90 identifier: "pypi" ---
-
-
-
@@ -8,7 +8,7 @@ menu:sidebar: parent: "packages" name: "RubyGems" weight: 90 weight: 100 identifier: "rubygems" ---
-
-
-
@@ -0,0 +1,166 @@// Copyright 2022 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package integrations import ( "archive/tar" "bytes" "compress/gzip" "fmt" "net/http" "testing" "time" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" helm_module "code.gitea.io/gitea/modules/packages/helm" "code.gitea.io/gitea/modules/setting" "github.com/stretchr/testify/assert" "gopkg.in/yaml.v2" ) func TestPackageHelm(t *testing.T) { defer prepareTestEnv(t)() user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) packageName := "test-chart" packageVersion := "1.0.3" packageAuthor := "KN4CK3R" packageDescription := "Gitea Test Package" filename := fmt.Sprintf("%s-%s.tgz", packageName, packageVersion) chartContent := `apiVersion: v2 description: ` + packageDescription + ` name: ` + packageName + ` type: application version: ` + packageVersion + ` maintainers: - name: ` + packageAuthor + ` dependencies: - name: dep1 repository: https://example.com/ version: 1.0.0` var buf bytes.Buffer zw := gzip.NewWriter(&buf) archive := tar.NewWriter(zw) archive.WriteHeader(&tar.Header{ Name: fmt.Sprintf("%s/Chart.yaml", packageName), Mode: 0o600, Size: int64(len(chartContent)), }) archive.Write([]byte(chartContent)) archive.Close() zw.Close() content := buf.Bytes() url := fmt.Sprintf("/api/packages/%s/helm", user.Name) t.Run("Upload", func(t *testing.T) { defer PrintCurrentTest(t)() uploadURL := url + "/api/charts" req := NewRequestWithBody(t, "POST", uploadURL, bytes.NewReader(content)) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusCreated) pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeHelm) assert.NoError(t, err) assert.Len(t, pvs, 1) pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) assert.NoError(t, err) assert.NotNil(t, pd.SemVer) assert.IsType(t, &helm_module.Metadata{}, pd.Metadata) assert.Equal(t, packageName, pd.Package.Name) assert.Equal(t, packageVersion, pd.Version.Version) pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID) assert.NoError(t, err) assert.Len(t, pfs, 1) assert.Equal(t, filename, pfs[0].Name) assert.True(t, pfs[0].IsLead) pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID) assert.NoError(t, err) assert.Equal(t, int64(len(content)), pb.Size) req = NewRequestWithBody(t, "POST", uploadURL, bytes.NewReader(content)) req = AddBasicAuthHeader(req, user.Name) MakeRequest(t, req, http.StatusCreated) }) t.Run("Download", func(t *testing.T) { defer PrintCurrentTest(t)() checkDownloadCount := func(count int64) { pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeHelm) assert.NoError(t, err) assert.Len(t, pvs, 1) assert.Equal(t, count, pvs[0].DownloadCount) } checkDownloadCount(0) req := NewRequest(t, "GET", fmt.Sprintf("%s/%s", url, filename)) req = AddBasicAuthHeader(req, user.Name) resp := MakeRequest(t, req, http.StatusOK) assert.Equal(t, content, resp.Body.Bytes()) checkDownloadCount(1) }) t.Run("Index", func(t *testing.T) { defer PrintCurrentTest(t)() req := NewRequest(t, "GET", fmt.Sprintf("%s/index.yaml", url)) req = AddBasicAuthHeader(req, user.Name) resp := MakeRequest(t, req, http.StatusOK) type ChartVersion struct { helm_module.Metadata `yaml:",inline"` URLs []string `yaml:"urls"` Created time.Time `yaml:"created,omitempty"` Removed bool `yaml:"removed,omitempty"` Digest string `yaml:"digest,omitempty"` } type ServerInfo struct { ContextPath string `yaml:"contextPath,omitempty"` } type Index struct { APIVersion string `yaml:"apiVersion"` Entries map[string][]*ChartVersion `yaml:"entries"` Generated time.Time `yaml:"generated,omitempty"` ServerInfo *ServerInfo `yaml:"serverInfo,omitempty"` } var result Index assert.NoError(t, yaml.NewDecoder(resp.Body).Decode(&result)) assert.NotEmpty(t, result.Entries) assert.Contains(t, result.Entries, packageName) cvs := result.Entries[packageName] assert.Len(t, cvs, 1) cv := cvs[0] assert.Equal(t, packageName, cv.Name) assert.Equal(t, packageVersion, cv.Version) assert.Equal(t, packageDescription, cv.Description) assert.Len(t, cv.Maintainers, 1) assert.Equal(t, packageAuthor, cv.Maintainers[0].Name) assert.Len(t, cv.Dependencies, 1) assert.ElementsMatch(t, []string{fmt.Sprintf("%s%s/%s", setting.AppURL, url[1:], filename)}, cv.URLs) assert.Equal(t, url, result.ServerInfo.ContextPath) }) }
-
-
-
@@ -15,6 +15,7 @@ import ("code.gitea.io/gitea/modules/packages/composer" "code.gitea.io/gitea/modules/packages/conan" "code.gitea.io/gitea/modules/packages/container" "code.gitea.io/gitea/modules/packages/helm" "code.gitea.io/gitea/modules/packages/maven" "code.gitea.io/gitea/modules/packages/npm" "code.gitea.io/gitea/modules/packages/nuget"
-
@@ -129,6 +130,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDescmetadata = &container.Metadata{} case TypeGeneric: // generic packages have no metadata case TypeHelm: metadata = &helm.Metadata{} case TypeNuGet: metadata = &nuget.Metadata{} case TypeNpm:
-
-
-
@@ -35,9 +35,10 @@ const (TypeConan Type = "conan" TypeContainer Type = "container" TypeGeneric Type = "generic" TypeNuGet Type = "nuget" TypeNpm Type = "npm" TypeHelm Type = "helm" TypeMaven Type = "maven" TypeNpm Type = "npm" TypeNuGet Type = "nuget" TypePyPI Type = "pypi" TypeRubyGems Type = "rubygems" )
-
@@ -53,12 +54,14 @@ func (pt Type) Name() string {return "Container" case TypeGeneric: return "Generic" case TypeNuGet: return "NuGet" case TypeNpm: return "npm" case TypeHelm: return "Helm" case TypeMaven: return "Maven" case TypeNpm: return "npm" case TypeNuGet: return "NuGet" case TypePyPI: return "PyPI" case TypeRubyGems:
-
@@ -78,12 +81,14 @@ func (pt Type) SVGName() string {return "octicon-container" case TypeGeneric: return "octicon-package" case TypeNuGet: return "gitea-nuget" case TypeNpm: return "gitea-npm" case TypeHelm: return "gitea-helm" case TypeMaven: return "gitea-maven" case TypeNpm: return "gitea-npm" case TypeNuGet: return "gitea-nuget" case TypePyPI: return "gitea-python" case TypeRubyGems:
-
-
-
@@ -0,0 +1,131 @@// Copyright 2022 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package helm import ( "archive/tar" "compress/gzip" "errors" "io" "strings" "code.gitea.io/gitea/modules/validation" "github.com/hashicorp/go-version" "gopkg.in/yaml.v2" ) var ( // ErrMissingChartFile indicates a missing Chart.yaml file ErrMissingChartFile = errors.New("Chart.yaml file is missing") // ErrInvalidName indicates an invalid package name ErrInvalidName = errors.New("package name is invalid") // ErrInvalidVersion indicates an invalid package version ErrInvalidVersion = errors.New("package version is invalid") // ErrInvalidChart indicates an invalid chart ErrInvalidChart = errors.New("chart is invalid") ) // Metadata for a Chart file. This models the structure of a Chart.yaml file. type Metadata struct { APIVersion string `json:"api_version" yaml:"apiVersion"` Type string `json:"type,omitempty" yaml:"type,omitempty"` Name string `json:"name" yaml:"name"` Version string `json:"version" yaml:"version"` AppVersion string `json:"app_version,omitempty" yaml:"appVersion,omitempty"` Home string `json:"home,omitempty" yaml:"home,omitempty"` Sources []string `json:"sources,omitempty" yaml:"sources,omitempty"` Description string `json:"description,omitempty" yaml:"description,omitempty"` Keywords []string `json:"keywords,omitempty" yaml:"keywords,omitempty"` Maintainers []*Maintainer `json:"maintainers,omitempty" yaml:"maintainers,omitempty"` Icon string `json:"icon,omitempty" yaml:"icon,omitempty"` Condition string `json:"condition,omitempty" yaml:"condition,omitempty"` Tags string `json:"tags,omitempty" yaml:"tags,omitempty"` Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"` Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"` KubeVersion string `json:"kube_version,omitempty" yaml:"kubeVersion,omitempty"` Dependencies []*Dependency `json:"dependencies,omitempty" yaml:"dependencies,omitempty"` } type Maintainer struct { Name string `json:"name,omitempty" yaml:"name,omitempty"` Email string `json:"email,omitempty" yaml:"email,omitempty"` URL string `json:"url,omitempty" yaml:"url,omitempty"` } type Dependency struct { Name string `json:"name" yaml:"name"` Version string `json:"version,omitempty" yaml:"version,omitempty"` Repository string `json:"repository" yaml:"repository"` Condition string `json:"condition,omitempty" yaml:"condition,omitempty"` Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"` Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"` ImportValues []interface{} `json:"import_values,omitempty" yaml:"import-values,omitempty"` Alias string `json:"alias,omitempty" yaml:"alias,omitempty"` } // ParseChartArchive parses the metadata of a Helm archive func ParseChartArchive(r io.Reader) (*Metadata, error) { gzr, err := gzip.NewReader(r) if err != nil { return nil, err } defer gzr.Close() tr := tar.NewReader(gzr) for { hd, err := tr.Next() if err == io.EOF { break } if err != nil { return nil, err } if hd.Typeflag != tar.TypeReg { continue } if hd.FileInfo().Name() == "Chart.yaml" { if strings.Count(hd.Name, "/") != 1 { continue } return ParseChartFile(tr) } } return nil, ErrMissingChartFile } // ParseChartFile parses a Chart.yaml file to retrieve the metadata of a Helm chart func ParseChartFile(r io.Reader) (*Metadata, error) { var metadata *Metadata if err := yaml.NewDecoder(r).Decode(&metadata); err != nil { return nil, err } if metadata.APIVersion == "" { return nil, ErrInvalidChart } if metadata.Type != "" && metadata.Type != "application" && metadata.Type != "library" { return nil, ErrInvalidChart } if metadata.Name == "" { return nil, ErrInvalidName } if _, err := version.NewSemver(metadata.Version); err != nil { return nil, ErrInvalidVersion } if !validation.IsValidURL(metadata.Home) { metadata.Home = "" } return metadata, nil }
-
-
-
@@ -3051,6 +3051,9 @@ container.labels.key = Keycontainer.labels.value = Value generic.download = Download package from the command line: generic.documentation = For more information on the generic registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/generic">the documentation</a>. helm.registry = Setup this registry from the command line: helm.install = To install the package, run the following command: helm.documentation = For more information on the Helm registry, see <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/packages/helm/">the documentation</a>. maven.registry = Setup this registry in your project <code>pom.xml</code> file: maven.install = To use the package include the following in the <code>dependencies</code> block in the <code>pom.xml</code> file: maven.install2 = Run via command line:
-
-
-
@@ -0,0 +1,1 @@<svg viewBox="0 0 62 65" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" class="svg gitea-helm" width="16" height="16" aria-hidden="true"><path fill="#3f7a9c" d="m41.868 16.659.248.19a19.17 19.17 0 0 1 3.919 4.128l.9 1.414 2.774-1.601-1.05-1.65a22.373 22.373 0 0 0-3.304-3.748 17.143 17.143 0 0 0 2.215-2.403c2.158-2.813 3.141-5.657 2.204-6.376s-3.43.966-5.589 3.779a17.048 17.048 0 0 0-1.748 2.762 22.297 22.297 0 0 0-10.308-3.48c.189-.957.298-2.076.298-3.273 0-3.546-.951-6.4-2.133-6.4S28.16 2.854 28.16 6.4c0 1.198.109 2.317.298 3.273a22.293 22.293 0 0 0-10.308 3.48 17.117 17.117 0 0 0-1.748-2.762c-2.158-2.813-4.651-4.498-5.589-3.779s.045 3.563 2.204 6.376a17.203 17.203 0 0 0 2.215 2.403 22.373 22.373 0 0 0-3.304 3.748 22.33 22.33 0 0 0-1.05 1.65l2.774 1.601a19.13 19.13 0 0 1 .9-1.414 19.21 19.21 0 0 1 3.919-4.128l.248-.19c3.214-2.424 7.221-3.859 11.574-3.859s8.36 1.435 11.574 3.859zM14.551 43.023A19.15 19.15 0 0 0 30.293 51.2a19.15 19.15 0 0 0 15.742-8.177l2.624 1.837a22.373 22.373 0 0 1-3.304 3.748 17.143 17.143 0 0 1 2.215 2.403c2.158 2.813 3.141 5.657 2.204 6.376s-3.43-.966-5.589-3.779a17.048 17.048 0 0 1-1.748-2.762 22.297 22.297 0 0 1-10.308 3.48c.189.957.298 2.076.298 3.273 0 3.546-.951 6.4-2.133 6.4s-2.133-2.854-2.133-6.4c0-1.198.109-2.317.298-3.273a22.293 22.293 0 0 1-10.308-3.48 17.117 17.117 0 0 1-1.748 2.762c-2.158 2.813-4.651 4.498-5.589 3.779s.045-3.563 2.204-6.376a17.203 17.203 0 0 1 2.215-2.403 22.373 22.373 0 0 1-3.304-3.748zm30.249-2.49V24.32h4.693l3.413 9.813 3.413-9.813h4.267v16.213h-3.84v-5.12l.853-5.973-3.84 9.813h-2.133l-3.84-9.813.853 5.973v5.12zM31.147 24.32v16.213h10.667V37.12h-6.4v-12.8zm-14.08 0v16.213H28.16V37.12h-6.827v-2.987h5.547V30.72h-5.547v-2.987h6.4V24.32zm-12.8 16.213v-6.4h5.12v6.4h4.267V24.32H9.387v5.973h-5.12V24.32H0v16.213z" stroke="none"/></svg>
-
-
-
@@ -17,6 +17,7 @@ import ("code.gitea.io/gitea/routers/api/packages/conan" "code.gitea.io/gitea/routers/api/packages/container" "code.gitea.io/gitea/routers/api/packages/generic" "code.gitea.io/gitea/routers/api/packages/helm" "code.gitea.io/gitea/routers/api/packages/maven" "code.gitea.io/gitea/routers/api/packages/npm" "code.gitea.io/gitea/routers/api/packages/nuget"
-
@@ -162,6 +163,11 @@ func Routes() *web.Route {}, reqPackageAccess(perm.AccessModeWrite)) }) }) r.Group("/helm", func() { r.Get("/index.yaml", helm.Index) r.Get("/{filename}", helm.DownloadPackageFile) r.Post("/api/charts", reqPackageAccess(perm.AccessModeWrite), helm.UploadPackage) }) r.Group("/maven", func() { r.Put("/*", reqPackageAccess(perm.AccessModeWrite), maven.UploadPackageFile) r.Get("/*", maven.DownloadPackageFile)
-
-
-
@@ -0,0 +1,205 @@// Copyright 2022 The Gitea Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. package helm import ( "fmt" "io" "net/http" "net/url" "strings" "time" packages_model "code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" packages_module "code.gitea.io/gitea/modules/packages" helm_module "code.gitea.io/gitea/modules/packages/helm" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/routers/api/packages/helper" packages_service "code.gitea.io/gitea/services/packages" "gopkg.in/yaml.v2" ) func apiError(ctx *context.Context, status int, obj interface{}) { helper.LogAndProcessError(ctx, status, obj, func(message string) { type Error struct { Error string `json:"error"` } ctx.JSON(status, Error{ Error: message, }) }) } // Index generates the Helm charts index func Index(ctx *context.Context) { pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ OwnerID: ctx.Package.Owner.ID, Type: packages_model.TypeHelm, }) if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } baseURL := setting.AppURL + "api/packages/" + url.PathEscape(ctx.Package.Owner.Name) + "/helm" type ChartVersion struct { helm_module.Metadata `yaml:",inline"` URLs []string `yaml:"urls"` Created time.Time `yaml:"created,omitempty"` Removed bool `yaml:"removed,omitempty"` Digest string `yaml:"digest,omitempty"` } type ServerInfo struct { ContextPath string `yaml:"contextPath,omitempty"` } type Index struct { APIVersion string `yaml:"apiVersion"` Entries map[string][]*ChartVersion `yaml:"entries"` Generated time.Time `yaml:"generated,omitempty"` ServerInfo *ServerInfo `yaml:"serverInfo,omitempty"` } entries := make(map[string][]*ChartVersion) for _, pv := range pvs { metadata := &helm_module.Metadata{} if err := json.Unmarshal([]byte(pv.MetadataJSON), &metadata); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } entries[metadata.Name] = append(entries[metadata.Name], &ChartVersion{ Metadata: *metadata, Created: pv.CreatedUnix.AsTime(), URLs: []string{fmt.Sprintf("%s/%s", baseURL, url.PathEscape(createFilename(metadata)))}, }) } ctx.Resp.WriteHeader(http.StatusOK) if err := yaml.NewEncoder(ctx.Resp).Encode(&Index{ APIVersion: "v1", Entries: entries, Generated: time.Now(), ServerInfo: &ServerInfo{ ContextPath: setting.AppSubURL + "/api/packages/" + url.PathEscape(ctx.Package.Owner.Name) + "/helm", }, }); err != nil { log.Error("YAML encode failed: %v", err) } } // DownloadPackageFile serves the content of a package func DownloadPackageFile(ctx *context.Context) { filename := ctx.Params("filename") pvs, _, err := packages_model.SearchVersions(ctx, &packages_model.PackageSearchOptions{ OwnerID: ctx.Package.Owner.ID, Type: packages_model.TypeHelm, Name: packages_model.SearchValue{ ExactMatch: true, Value: ctx.Params("package"), }, HasFileWithName: filename, }) if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } if len(pvs) != 1 { apiError(ctx, http.StatusNotFound, nil) return } s, pf, err := packages_service.GetFileStreamByPackageVersion( ctx, pvs[0], &packages_service.PackageFileInfo{ Filename: filename, }, ) if err != nil { if err == packages_model.ErrPackageFileNotExist { apiError(ctx, http.StatusNotFound, err) return } apiError(ctx, http.StatusInternalServerError, err) return } defer s.Close() ctx.ServeStream(s, pf.Name) } // UploadPackage creates a new package func UploadPackage(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, 32*1024*1024) if err != nil { apiError(ctx, http.StatusInternalServerError, err) return } defer buf.Close() metadata, err := helm_module.ParseChartArchive(buf) if err != nil { apiError(ctx, http.StatusBadRequest, err) return } if _, err := buf.Seek(0, io.SeekStart); err != nil { apiError(ctx, http.StatusInternalServerError, err) return } _, _, err = packages_service.CreatePackageOrAddFileToExisting( &packages_service.PackageCreationInfo{ PackageInfo: packages_service.PackageInfo{ Owner: ctx.Package.Owner, PackageType: packages_model.TypeHelm, Name: metadata.Name, Version: metadata.Version, }, SemverCompatible: true, Creator: ctx.Doer, Metadata: metadata, }, &packages_service.PackageFileCreationInfo{ PackageFileInfo: packages_service.PackageFileInfo{ Filename: createFilename(metadata), }, Data: buf, IsLead: true, OverwriteExisting: true, }, ) if err != nil { if err == packages_model.ErrDuplicatePackageVersion { apiError(ctx, http.StatusConflict, err) return } 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)) }
-
-
-
@@ -40,7 +40,7 @@ func ListPackages(ctx *context.APIContext) {// in: query // description: package type filter // type: string // enum: [composer, conan, generic, maven, npm, nuget, pypi, rubygems] // enum: [composer, conan, container, generic, helm, maven, npm, nuget, pypi, rubygems] // - name: q // in: query // description: name filter
-
-
-
@@ -17,6 +17,7 @@<option value="conan" {{if eq .PackageType "conan"}}selected="selected"{{end}}>Conan</option> <option value="container" {{if eq .PackageType "container"}}selected="selected"{{end}}>Container</option> <option value="generic" {{if eq .PackageType "generic"}}selected="selected"{{end}}>Generic</option> <option value="helm" {{if eq .PackageType "helm"}}selected="selected"{{end}}>Helm</option> <option value="maven" {{if eq .PackageType "maven"}}selected="selected"{{end}}>Maven</option> <option value="npm" {{if eq .PackageType "npm"}}selected="selected"{{end}}>npm</option> <option value="nuget" {{if eq .PackageType "nuget"}}selected="selected"{{end}}>NuGet</option>
-
-
-
@@ -0,0 +1,57 @@{{if eq .PackageDescriptor.Package.Type "helm"}} <h4 class="ui top attached header">{{.i18n.Tr "packages.installation"}}</h4> <div class="ui attached segment"> <div class="ui form"> <div class="field"> <label>{{svg "octicon-terminal"}} {{.i18n.Tr "packages.helm.registry"}}</label> <div class="markup"><pre class="code-block"><code>helm repo add gitea {{AppUrl}}api/packages/{{.PackageDescriptor.Owner.Name}}/helm helm repo update</code></pre></div> </div> <div class="field"> <label>{{svg "octicon-terminal"}} {{.i18n.Tr "packages.helm.install"}}</label> <div class="markup"><pre class="code-block"><code>helm install {{.PackageDescriptor.Package.Name}} gitea/{{.PackageDescriptor.Package.Name}}</code></pre></div> </div> <div class="field"> <label>{{.i18n.Tr "packages.helm.documentation" | Safe}}</label> </div> </div> </div> {{if .PackageDescriptor.Metadata.Description}} <h4 class="ui top attached header">{{.i18n.Tr "packages.about"}}</h4> <div class="ui attached segment"> {{.PackageDescriptor.Metadata.Description}} </div> {{end}} {{if .PackageDescriptor.Metadata.Dependencies}} <h4 class="ui top attached header">{{.i18n.Tr "packages.dependencies"}}</h4> <div class="ui attached segment"> <table class="ui single line very basic table"> <thead> <tr> <th class="ten wide">{{.i18n.Tr "packages.dependency.id"}}</th> <th class="six wide">{{.i18n.Tr "packages.dependency.version"}}</th> </tr> </thead> <tbody> {{range .PackageDescriptor.Metadata.Dependencies}} <tr> <td>{{.Name}}</td> <td>{{.Version}}</td> </tr> {{end}} </tbody> </table> </div> {{end}} {{if .PackageDescriptor.Metadata.Keywords}} <h4 class="ui top attached header">{{.i18n.Tr "packages.keywords"}}</h4> <div class="ui attached segment"> {{range .PackageDescriptor.Metadata.Keywords}} {{.}} {{end}} </div> {{end}} {{end}}
-
-
-
@@ -45,7 +45,7 @@</div> {{end}} {{if or .PackageDescriptor.Metadata.Keywords}} {{if .PackageDescriptor.Metadata.Keywords}} <h4 class="ui top attached header">{{.i18n.Tr "packages.keywords"}}</h4> <div class="ui attached segment"> {{range .PackageDescriptor.Metadata.Keywords}}
-
-
-
@@ -0,0 +1,4 @@{{if eq .PackageDescriptor.Package.Type "helm"}} {{range .PackageDescriptor.Metadata.Maintainers}}<div class="item" title="{{$.i18n.Tr "packages.details.author"}}">{{svg "octicon-person" 16 "mr-3"}} {{.Name}}</div>{{end}} {{if .PackageDescriptor.Metadata.Home}}<div class="item">{{svg "octicon-link-external" 16 "mr-3"}} <a href="{{.PackageDescriptor.Metadata.Home}}" target="_blank" rel="noopener noreferrer me">{{.i18n.Tr "packages.details.project_site"}}</a></div>{{end}} {{end}}
-
-
-
@@ -10,6 +10,7 @@<option value="conan" {{if eq .PackageType "conan"}}selected="selected"{{end}}>Conan</option> <option value="container" {{if eq .PackageType "container"}}selected="selected"{{end}}>Container</option> <option value="generic" {{if eq .PackageType "generic"}}selected="selected"{{end}}>Generic</option> <option value="helm" {{if eq .PackageType "helm"}}selected="selected"{{end}}>Helm</option> <option value="maven" {{if eq .PackageType "maven"}}selected="selected"{{end}}>Maven</option> <option value="npm" {{if eq .PackageType "npm"}}selected="selected"{{end}}>npm</option> <option value="nuget" {{if eq .PackageType "nuget"}}selected="selected"{{end}}>NuGet</option>
-
-
-
@@ -23,9 +23,10 @@{{template "package/content/conan" .}} {{template "package/content/container" .}} {{template "package/content/generic" .}} {{template "package/content/nuget" .}} {{template "package/content/npm" .}} {{template "package/content/helm" .}} {{template "package/content/maven" .}} {{template "package/content/npm" .}} {{template "package/content/nuget" .}} {{template "package/content/pypi" .}} {{template "package/content/rubygems" .}} </div>
-
@@ -43,9 +44,10 @@{{template "package/metadata/conan" .}} {{template "package/metadata/container" .}} {{template "package/metadata/generic" .}} {{template "package/metadata/nuget" .}} {{template "package/metadata/npm" .}} {{template "package/metadata/helm" .}} {{template "package/metadata/maven" .}} {{template "package/metadata/npm" .}} {{template "package/metadata/nuget" .}} {{template "package/metadata/pypi" .}} {{template "package/metadata/rubygems" .}} </div>
-
-
-
@@ -1904,7 +1904,9 @@"enum": [ "composer", "conan", "container", "generic", "helm", "maven", "npm", "nuget",
-
-
-
@@ -0,0 +1,3 @@<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 62 65" fill="#fff" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round"> <g><path fill="#3f7a9c" d="M41.868 16.659l.248.19c1.503 1.172 2.825 2.564 3.919 4.128l.9 1.414 2.774-1.601-1.05-1.65c-.959-1.37-2.068-2.628-3.304-3.748.728-.642 1.491-1.459 2.215-2.403 2.158-2.813 3.141-5.657 2.204-6.376s-3.43.966-5.589 3.779c-.725.944-1.317 1.892-1.748 2.762-3.013-1.94-6.525-3.176-10.308-3.48.189-.957.298-2.076.298-3.273 0-3.546-.951-6.4-2.133-6.4S28.16 2.854 28.16 6.4c0 1.198.109 2.317.298 3.273-3.783.304-7.296 1.54-10.308 3.48-.431-.87-1.024-1.818-1.748-2.762-2.158-2.813-4.651-4.498-5.589-3.779s.045 3.563 2.204 6.376c.725.944 1.487 1.761 2.215 2.403-1.236 1.12-2.345 2.378-3.304 3.748a22.33 22.33 0 0 0-1.05 1.65l2.774 1.601a19.13 19.13 0 0 1 .9-1.414 19.21 19.21 0 0 1 3.919-4.128l.248-.19c3.214-2.424 7.221-3.859 11.574-3.859s8.36 1.435 11.574 3.859zM14.551 43.023A19.15 19.15 0 0 0 30.293 51.2a19.15 19.15 0 0 0 15.742-8.177l2.624 1.837c-.959 1.37-2.068 2.628-3.304 3.748.728.642 1.491 1.459 2.215 2.403 2.158 2.813 3.141 5.657 2.204 6.376s-3.43-.966-5.589-3.779c-.725-.944-1.317-1.892-1.748-2.762-3.013 1.94-6.525 3.176-10.308 3.48.189.957.298 2.076.298 3.273 0 3.546-.951 6.4-2.133 6.4s-2.133-2.854-2.133-6.4c0-1.198.109-2.317.298-3.273-3.783-.304-7.296-1.54-10.308-3.48-.431.87-1.024 1.818-1.748 2.762-2.158 2.813-4.651 4.498-5.589 3.779s.045-3.563 2.204-6.376c.725-.944 1.487-1.761 2.215-2.403-1.236-1.12-2.345-2.378-3.304-3.748zM44.8 40.533V24.32h4.693l3.413 9.813 3.413-9.813h4.267v16.213h-3.84v-5.12l.853-5.973-3.84 9.813h-2.133l-3.84-9.813.853 5.973v5.12zM31.147 24.32v16.213h10.667V37.12h-6.4v-12.8zm-14.08 0v16.213H28.16V37.12h-6.827v-2.987h5.547V30.72h-5.547v-2.987h6.4V24.32zm-12.8 16.213v-6.4h5.12v6.4h4.267V24.32H9.387v5.973h-5.12V24.32H0v16.213z" stroke="none"/></g> </svg>
-