Skip to content

Commit b2861a8

Browse files
committed
Merge remote-tracking branch 'upstream/main'
* upstream/main: Fix typo (go-gitea#20993) fix broken insecureskipverify handling in rediss connection uris (go-gitea#20967) Redirect if user does not exist (go-gitea#20981) fix hard-coded timeout and error panic in API archive download endpoint (go-gitea#20925) Add support for Vagrant packages (go-gitea#20930)
2 parents 87257f4 + e4addac commit b2861a8

File tree

29 files changed

+905
-77
lines changed

29 files changed

+905
-77
lines changed

cmd/migrate_storage.go

+2-5
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,8 @@ func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) e
112112

113113
func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error {
114114
return db.IterateObjects(ctx, func(archiver *repo_model.RepoArchiver) error {
115-
p, err := archiver.RelativePath()
116-
if err != nil {
117-
return err
118-
}
119-
_, err = storage.Copy(dstStorage, p, storage.RepoArchives, p)
115+
p := archiver.RelativePath()
116+
_, err := storage.Copy(dstStorage, p, storage.RepoArchives, p)
120117
return err
121118
})
122119
}

docs/content/doc/packages/overview.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ The following package managers are currently supported:
3737
| [Pub]({{< relref "doc/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` |
3838
| [PyPI]({{< relref "doc/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` |
3939
| [RubyGems]({{< relref "doc/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` |
40+
| [Vagrant]({{< relref "doc/packages/vagrant.en-us.md" >}}) | - | `vagrant` |
4041

4142
**The following paragraphs only apply if Packages are not globally disabled!**
4243

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
---
2+
date: "2022-08-23T00:00:00+00:00"
3+
title: "Vagrant Packages Repository"
4+
slug: "packages/vagrant"
5+
draft: false
6+
toc: false
7+
menu:
8+
sidebar:
9+
parent: "packages"
10+
name: "vagrant"
11+
weight: 120
12+
identifier: "vagrant"
13+
---
14+
15+
# Vagrant Packages Repository
16+
17+
Publish [Vagrant](https://www.vagrantup.com/) packages for your user or organization.
18+
19+
**Table of Contents**
20+
21+
{{< toc >}}
22+
23+
## Requirements
24+
25+
To work with the Vagrant package registry, you need [Vagrant](https://www.vagrantup.com/downloads) and a tool to make HTTP requests like `curl`.
26+
27+
## Publish a package
28+
29+
Publish a Vagrant box by performing a HTTP PUT request to the registry:
30+
31+
```
32+
PUT https://gitea.example.com/api/packages/{owner}/vagrant/{package_name}/{package_version}/{provider}.box
33+
```
34+
35+
| Parameter | Description |
36+
| ----------------- | ----------- |
37+
| `owner` | The owner of the package. |
38+
| `package_name` | The package name. |
39+
| `package_version` | The package version, semver compatible. |
40+
| `provider` | One of the [supported provider names](https://www.vagrantup.com/docs/providers). |
41+
42+
Example for uploading a Hyper-V box:
43+
44+
```shell
45+
curl --user your_username:your_password_or_token \
46+
--upload-file path/to/your/vagrant.box \
47+
https://gitea.example.com/api/packages/testuser/vagrant/test_system/1.0.0/hyperv.box
48+
```
49+
50+
You cannot publish a box if a box of the same name, version and provider already exists. You must delete the existing package first.
51+
52+
## Install a package
53+
54+
To install a box from the package registry, execute the following command:
55+
56+
```shell
57+
vagrant box add "https://gitea.example.com/api/packages/{owner}/vagrant/{package_name}"
58+
```
59+
60+
| Parameter | Description |
61+
| -------------- | ----------- |
62+
| `owner` | The owner of the package. |
63+
| `package_name` | The package name. |
64+
65+
For example:
66+
67+
```shell
68+
vagrant box add "https://gitea.example.com/api/packages/testuser/vagrant/test_system"
69+
```
70+
71+
This will install the latest version of the package. To add a specific version, use the `--box-version` parameter.
72+
If the registry is private you can pass your [personal access token]({{< relref "doc/developers/api-usage.en-us.md#authentication" >}}) in the `VAGRANT_CLOUD_TOKEN` environment variable.
73+
74+
## Supported commands
75+
76+
```
77+
vagrant box add
78+
```

docs/content/doc/usage/https-support.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ACME_DIRECTORY=https
7272
7373
```
7474

75-
Minimumg setup using a [smallstep CA](https://github.com/smallstep/certificates), refer to [their tutorial](https://smallstep.com/docs/tutorials/acme-challenge) for more information.
75+
Minimum setup using a [smallstep CA](https://github.com/smallstep/certificates), refer to [their tutorial](https://smallstep.com/docs/tutorials/acme-challenge) for more information.
7676

7777
```ini
7878
[server]
+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
// Copyright 2022 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package integrations
6+
7+
import (
8+
"archive/tar"
9+
"bytes"
10+
"compress/gzip"
11+
"fmt"
12+
"net/http"
13+
"strings"
14+
"testing"
15+
16+
"code.gitea.io/gitea/models/db"
17+
"code.gitea.io/gitea/models/packages"
18+
"code.gitea.io/gitea/models/unittest"
19+
user_model "code.gitea.io/gitea/models/user"
20+
"code.gitea.io/gitea/modules/json"
21+
vagrant_module "code.gitea.io/gitea/modules/packages/vagrant"
22+
23+
"github.com/stretchr/testify/assert"
24+
)
25+
26+
func TestPackageVagrant(t *testing.T) {
27+
defer prepareTestEnv(t)()
28+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
29+
30+
token := "Bearer " + getUserToken(t, user.Name)
31+
32+
packageName := "test_package"
33+
packageVersion := "1.0.1"
34+
packageDescription := "Test Description"
35+
packageProvider := "virtualbox"
36+
37+
filename := fmt.Sprintf("%s.box", packageProvider)
38+
39+
infoContent, _ := json.Marshal(map[string]string{
40+
"description": packageDescription,
41+
})
42+
43+
var buf bytes.Buffer
44+
zw := gzip.NewWriter(&buf)
45+
archive := tar.NewWriter(zw)
46+
archive.WriteHeader(&tar.Header{
47+
Name: "info.json",
48+
Mode: 0o600,
49+
Size: int64(len(infoContent)),
50+
})
51+
archive.Write(infoContent)
52+
archive.Close()
53+
zw.Close()
54+
content := buf.Bytes()
55+
56+
root := fmt.Sprintf("/api/packages/%s/vagrant", user.Name)
57+
58+
t.Run("Authenticate", func(t *testing.T) {
59+
defer PrintCurrentTest(t)()
60+
61+
authenticateURL := fmt.Sprintf("%s/authenticate", root)
62+
63+
req := NewRequest(t, "GET", authenticateURL)
64+
MakeRequest(t, req, http.StatusUnauthorized)
65+
66+
req = NewRequest(t, "GET", authenticateURL)
67+
addTokenAuthHeader(req, token)
68+
MakeRequest(t, req, http.StatusOK)
69+
})
70+
71+
boxURL := fmt.Sprintf("%s/%s", root, packageName)
72+
73+
t.Run("Upload", func(t *testing.T) {
74+
defer PrintCurrentTest(t)()
75+
76+
req := NewRequest(t, "HEAD", boxURL)
77+
MakeRequest(t, req, http.StatusNotFound)
78+
79+
uploadURL := fmt.Sprintf("%s/%s/%s", boxURL, packageVersion, filename)
80+
81+
req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader(content))
82+
MakeRequest(t, req, http.StatusUnauthorized)
83+
84+
req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader(content))
85+
addTokenAuthHeader(req, token)
86+
MakeRequest(t, req, http.StatusCreated)
87+
88+
req = NewRequest(t, "HEAD", boxURL)
89+
resp := MakeRequest(t, req, http.StatusOK)
90+
assert.True(t, strings.HasPrefix(resp.HeaderMap.Get("Content-Type"), "application/json"))
91+
92+
pvs, err := packages.GetVersionsByPackageType(db.DefaultContext, user.ID, packages.TypeVagrant)
93+
assert.NoError(t, err)
94+
assert.Len(t, pvs, 1)
95+
96+
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
97+
assert.NoError(t, err)
98+
assert.NotNil(t, pd.SemVer)
99+
assert.IsType(t, &vagrant_module.Metadata{}, pd.Metadata)
100+
assert.Equal(t, packageName, pd.Package.Name)
101+
assert.Equal(t, packageVersion, pd.Version.Version)
102+
103+
pfs, err := packages.GetFilesByVersionID(db.DefaultContext, pvs[0].ID)
104+
assert.NoError(t, err)
105+
assert.Len(t, pfs, 1)
106+
assert.Equal(t, filename, pfs[0].Name)
107+
assert.True(t, pfs[0].IsLead)
108+
109+
pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID)
110+
assert.NoError(t, err)
111+
assert.Equal(t, int64(len(content)), pb.Size)
112+
113+
req = NewRequestWithBody(t, "PUT", uploadURL, bytes.NewReader(content))
114+
addTokenAuthHeader(req, token)
115+
MakeRequest(t, req, http.StatusConflict)
116+
})
117+
118+
t.Run("Download", func(t *testing.T) {
119+
defer PrintCurrentTest(t)()
120+
121+
req := NewRequest(t, "GET", fmt.Sprintf("%s/%s/%s", boxURL, packageVersion, filename))
122+
resp := MakeRequest(t, req, http.StatusOK)
123+
124+
assert.Equal(t, content, resp.Body.Bytes())
125+
})
126+
127+
t.Run("EnumeratePackageVersions", func(t *testing.T) {
128+
defer PrintCurrentTest(t)()
129+
130+
req := NewRequest(t, "GET", boxURL)
131+
resp := MakeRequest(t, req, http.StatusOK)
132+
133+
type providerData struct {
134+
Name string `json:"name"`
135+
URL string `json:"url"`
136+
Checksum string `json:"checksum"`
137+
ChecksumType string `json:"checksum_type"`
138+
}
139+
140+
type versionMetadata struct {
141+
Version string `json:"version"`
142+
Status string `json:"status"`
143+
DescriptionHTML string `json:"description_html,omitempty"`
144+
DescriptionMarkdown string `json:"description_markdown,omitempty"`
145+
Providers []*providerData `json:"providers"`
146+
}
147+
148+
type packageMetadata struct {
149+
Name string `json:"name"`
150+
Description string `json:"description,omitempty"`
151+
ShortDescription string `json:"short_description,omitempty"`
152+
Versions []*versionMetadata `json:"versions"`
153+
}
154+
155+
var result packageMetadata
156+
DecodeJSON(t, resp, &result)
157+
158+
assert.Equal(t, packageName, result.Name)
159+
assert.Equal(t, packageDescription, result.Description)
160+
assert.Len(t, result.Versions, 1)
161+
version := result.Versions[0]
162+
assert.Equal(t, packageVersion, version.Version)
163+
assert.Equal(t, "active", version.Status)
164+
assert.Len(t, version.Providers, 1)
165+
provider := version.Providers[0]
166+
assert.Equal(t, packageProvider, provider.Name)
167+
assert.Equal(t, "sha512", provider.ChecksumType)
168+
assert.Equal(t, "259bebd6160acad695016d22a45812e26f187aaf78e71a4c23ee3201528346293f991af3468a8c6c5d2a21d7d9e1bdc1bf79b87110b2fddfcc5a0d45963c7c30", provider.Checksum)
169+
})
170+
}

models/packages/descriptor.go

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"code.gitea.io/gitea/modules/packages/pub"
2323
"code.gitea.io/gitea/modules/packages/pypi"
2424
"code.gitea.io/gitea/modules/packages/rubygems"
25+
"code.gitea.io/gitea/modules/packages/vagrant"
2526

2627
"github.com/hashicorp/go-version"
2728
)
@@ -150,6 +151,8 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
150151
metadata = &pypi.Metadata{}
151152
case TypeRubyGems:
152153
metadata = &rubygems.Metadata{}
154+
case TypeVagrant:
155+
metadata = &vagrant.Metadata{}
153156
default:
154157
panic(fmt.Sprintf("unknown package type: %s", string(p.Type)))
155158
}

models/packages/package.go

+5
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242
TypePub Type = "pub"
4343
TypePyPI Type = "pypi"
4444
TypeRubyGems Type = "rubygems"
45+
TypeVagrant Type = "vagrant"
4546
)
4647

4748
// Name gets the name of the package type
@@ -69,6 +70,8 @@ func (pt Type) Name() string {
6970
return "PyPI"
7071
case TypeRubyGems:
7172
return "RubyGems"
73+
case TypeVagrant:
74+
return "Vagrant"
7275
}
7376
panic(fmt.Sprintf("unknown package type: %s", string(pt)))
7477
}
@@ -98,6 +101,8 @@ func (pt Type) SVGName() string {
98101
return "gitea-python"
99102
case TypeRubyGems:
100103
return "gitea-rubygems"
104+
case TypeVagrant:
105+
return "gitea-vagrant"
101106
}
102107
panic(fmt.Sprintf("unknown package type: %s", string(pt)))
103108
}

models/repo.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
218218

219219
archivePaths := make([]string, 0, len(archives))
220220
for _, v := range archives {
221-
p, _ := v.RelativePath()
222-
archivePaths = append(archivePaths, p)
221+
archivePaths = append(archivePaths, v.RelativePath())
223222
}
224223

225224
if _, err := db.DeleteByBean(ctx, &repo_model.RepoArchiver{RepoID: repoID}); err != nil {

models/repo/archiver.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ func init() {
3939
db.RegisterModel(new(RepoArchiver))
4040
}
4141

42-
// RelativePath returns relative path
43-
func (archiver *RepoArchiver) RelativePath() (string, error) {
44-
return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String()), nil
42+
// RelativePath returns the archive path relative to the archive storage root.
43+
func (archiver *RepoArchiver) RelativePath() string {
44+
return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String())
4545
}
4646

4747
var delRepoArchiver = new(RepoArchiver)

modules/nosql/manager_redis.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ func getRedisTLSOptions(uri *url.URL) *tls.Config {
245245

246246
if len(skipverify) > 0 {
247247
skipverify, err := strconv.ParseBool(skipverify)
248-
if err != nil {
248+
if err == nil {
249249
tlsConfig.InsecureSkipVerify = skipverify
250250
}
251251
}
@@ -254,7 +254,7 @@ func getRedisTLSOptions(uri *url.URL) *tls.Config {
254254

255255
if len(insecureskipverify) > 0 {
256256
insecureskipverify, err := strconv.ParseBool(insecureskipverify)
257-
if err != nil {
257+
if err == nil {
258258
tlsConfig.InsecureSkipVerify = insecureskipverify
259259
}
260260
}

modules/nosql/manager_redis_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@ func TestRedisPasswordOpt(t *testing.T) {
2727
}
2828
}
2929

30+
func TestSkipVerifyOpt(t *testing.T) {
31+
uri, _ := url.Parse("rediss://myredis/0?skipverify=true")
32+
tlsConfig := getRedisTLSOptions(uri)
33+
34+
if !tlsConfig.InsecureSkipVerify {
35+
t.Fail()
36+
}
37+
}
38+
39+
func TestInsecureSkipVerifyOpt(t *testing.T) {
40+
uri, _ := url.Parse("rediss://myredis/0?insecureskipverify=true")
41+
tlsConfig := getRedisTLSOptions(uri)
42+
43+
if !tlsConfig.InsecureSkipVerify {
44+
t.Fail()
45+
}
46+
}
47+
3048
func TestRedisSentinelUsernameOpt(t *testing.T) {
3149
uri, _ := url.Parse("redis+sentinel://redis:password@myredis/0?sentinelusername=suser&sentinelpassword=spass")
3250
opts := getRedisOptions(uri).Failover()

0 commit comments

Comments
 (0)