-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Pub packages (#20560)
* Added support for Pub packages. * Update docs/content/doc/packages/overview.en-us.md Co-authored-by: Gergely Nagy <algernon@users.noreply.github.com> Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: Gergely Nagy <algernon@users.noreply.github.com> Co-authored-by: Lauris BH <lauris@nix.lv>
- Loading branch information
1 parent
d4326af
commit f55af46
Showing
22 changed files
with
908 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
--- | ||
date: "2022-07-31T00:00:00+00:00" | ||
title: "Pub Packages Repository" | ||
slug: "packages/pub" | ||
draft: false | ||
toc: false | ||
menu: | ||
sidebar: | ||
parent: "packages" | ||
name: "Pub" | ||
weight: 90 | ||
identifier: "pub" | ||
--- | ||
|
||
# Pub Packages Repository | ||
|
||
Publish [Pub](https://dart.dev/guides/packages) packages for your user or organization. | ||
|
||
**Table of Contents** | ||
|
||
{{< toc >}} | ||
|
||
## Requirements | ||
|
||
To work with the Pub package registry, you need to use the tools [dart](https://dart.dev/tools/dart-tool) and/or [flutter](https://docs.flutter.dev/reference/flutter-cli). | ||
|
||
The following examples use dart. | ||
|
||
## Configuring the package registry | ||
|
||
To register the package registry and provide credentials, execute: | ||
|
||
```shell | ||
dart pub token add https://gitea.example.com/api/packages/{owner}/pub | ||
``` | ||
|
||
| Placeholder | Description | | ||
| ------------ | ----------- | | ||
| `owner` | The owner of the package. | | ||
|
||
You need to provide your [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}). | ||
|
||
## Publish a package | ||
|
||
To publish a package, edit the `pubspec.yaml` and add the following line: | ||
|
||
```yaml | ||
publish_to: https://gitea.example.com/api/packages/{owner}/pub | ||
``` | ||
| Placeholder | Description | | ||
| ------------ | ----------- | | ||
| `owner` | The owner of the package. | | ||
|
||
Now you can publish the package by running the following command: | ||
|
||
```shell | ||
dart pub publish | ||
``` | ||
|
||
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. | ||
|
||
## Install a package | ||
|
||
To install a Pub package from the package registry, execute the following command: | ||
|
||
```shell | ||
dart pub add {package_name} --hosted-url=https://gitea.example.com/api/packages/{owner}/pub/ | ||
``` | ||
|
||
| Parameter | Description | | ||
| ----------------- | ----------- | | ||
| `owner` | The owner of the package. | | ||
| `package_name` | The package name. | | ||
|
||
For example: | ||
|
||
```shell | ||
# use latest version | ||
dart pub add mypackage --hosted-url=https://gitea.example.com/api/packages/testuser/pub/ | ||
# specify version | ||
dart pub add mypackage:1.0.8 --hosted-url=https://gitea.example.com/api/packages/testuser/pub/ | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ menu: | |
sidebar: | ||
parent: "packages" | ||
name: "PyPI" | ||
weight: 90 | ||
weight: 100 | ||
identifier: "pypi" | ||
--- | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ menu: | |
sidebar: | ||
parent: "packages" | ||
name: "RubyGems" | ||
weight: 100 | ||
weight: 110 | ||
identifier: "rubygems" | ||
--- | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
// 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" | ||
"io" | ||
"mime/multipart" | ||
"net/http" | ||
"net/http/httptest" | ||
"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" | ||
pub_module "code.gitea.io/gitea/modules/packages/pub" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestPackagePub(t *testing.T) { | ||
defer prepareTestEnv(t)() | ||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}).(*user_model.User) | ||
|
||
token := "Bearer " + getUserToken(t, user.Name) | ||
|
||
packageName := "test_package" | ||
packageVersion := "1.0.1" | ||
packageDescription := "Test Description" | ||
|
||
filename := fmt.Sprintf("%s.tar.gz", packageVersion) | ||
|
||
pubspecContent := `name: ` + packageName + ` | ||
version: ` + packageVersion + ` | ||
description: ` + packageDescription | ||
|
||
var buf bytes.Buffer | ||
zw := gzip.NewWriter(&buf) | ||
archive := tar.NewWriter(zw) | ||
archive.WriteHeader(&tar.Header{ | ||
Name: "pubspec.yaml", | ||
Mode: 0o600, | ||
Size: int64(len(pubspecContent)), | ||
}) | ||
archive.Write([]byte(pubspecContent)) | ||
archive.Close() | ||
zw.Close() | ||
content := buf.Bytes() | ||
|
||
root := fmt.Sprintf("/api/packages/%s/pub", user.Name) | ||
|
||
t.Run("Upload", func(t *testing.T) { | ||
defer PrintCurrentTest(t)() | ||
|
||
uploadURL := root + "/api/packages/versions/new" | ||
|
||
req := NewRequest(t, "GET", uploadURL) | ||
MakeRequest(t, req, http.StatusUnauthorized) | ||
|
||
req = NewRequest(t, "GET", uploadURL) | ||
addTokenAuthHeader(req, token) | ||
resp := MakeRequest(t, req, http.StatusOK) | ||
|
||
type UploadRequest struct { | ||
URL string `json:"url"` | ||
Fields map[string]string `json:"fields"` | ||
} | ||
|
||
var result UploadRequest | ||
DecodeJSON(t, resp, &result) | ||
|
||
assert.Empty(t, result.Fields) | ||
|
||
uploadFile := func(t *testing.T, url string, content []byte, expectedStatus int) *httptest.ResponseRecorder { | ||
body := &bytes.Buffer{} | ||
writer := multipart.NewWriter(body) | ||
part, _ := writer.CreateFormFile("file", "dummy.tar.gz") | ||
_, _ = io.Copy(part, bytes.NewReader(content)) | ||
|
||
_ = writer.Close() | ||
|
||
req := NewRequestWithBody(t, "POST", url, body) | ||
req.Header.Add("Content-Type", writer.FormDataContentType()) | ||
addTokenAuthHeader(req, token) | ||
return MakeRequest(t, req, expectedStatus) | ||
} | ||
|
||
resp = uploadFile(t, result.URL, content, http.StatusNoContent) | ||
|
||
req = NewRequest(t, "GET", resp.Header().Get("Location")) | ||
addTokenAuthHeader(req, token) | ||
MakeRequest(t, req, http.StatusOK) | ||
|
||
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypePub) | ||
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, &pub_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) | ||
|
||
resp = uploadFile(t, result.URL, content, http.StatusBadRequest) | ||
}) | ||
|
||
t.Run("Download", func(t *testing.T) { | ||
defer PrintCurrentTest(t)() | ||
|
||
req := NewRequest(t, "GET", fmt.Sprintf("%s/api/packages/%s/%s", root, packageName, packageVersion)) | ||
resp := MakeRequest(t, req, http.StatusOK) | ||
|
||
type VersionMetadata struct { | ||
Version string `json:"version"` | ||
ArchiveURL string `json:"archive_url"` | ||
Published time.Time `json:"published"` | ||
Pubspec interface{} `json:"pubspec,omitempty"` | ||
} | ||
|
||
var result VersionMetadata | ||
DecodeJSON(t, resp, &result) | ||
|
||
assert.Equal(t, packageVersion, result.Version) | ||
assert.NotNil(t, result.Pubspec) | ||
|
||
req = NewRequest(t, "GET", result.ArchiveURL) | ||
resp = MakeRequest(t, req, http.StatusOK) | ||
|
||
assert.Equal(t, content, resp.Body.Bytes()) | ||
}) | ||
|
||
t.Run("EnumeratePackageVersions", func(t *testing.T) { | ||
defer PrintCurrentTest(t)() | ||
|
||
req := NewRequest(t, "GET", fmt.Sprintf("%s/api/packages/%s", root, packageName)) | ||
resp := MakeRequest(t, req, http.StatusOK) | ||
|
||
type VersionMetadata struct { | ||
Version string `json:"version"` | ||
ArchiveURL string `json:"archive_url"` | ||
Published time.Time `json:"published"` | ||
Pubspec interface{} `json:"pubspec,omitempty"` | ||
} | ||
|
||
type PackageVersions struct { | ||
Name string `json:"name"` | ||
Latest *VersionMetadata `json:"latest"` | ||
Versions []*VersionMetadata `json:"versions"` | ||
} | ||
|
||
var result PackageVersions | ||
DecodeJSON(t, resp, &result) | ||
|
||
assert.Equal(t, packageName, result.Name) | ||
assert.NotNil(t, result.Latest) | ||
assert.Len(t, result.Versions, 1) | ||
assert.Equal(t, result.Latest.Version, result.Versions[0].Version) | ||
assert.Equal(t, packageVersion, result.Latest.Version) | ||
assert.NotNil(t, result.Latest.Pubspec) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.