forked from hinterland/hearth
feat: vendor gitea 1.16.2
This commit is contained in:
@@ -12,15 +12,16 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/packages"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
rpm_module "code.gitea.io/gitea/modules/packages/rpm"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/ProtonMail/go-crypto/openpgp"
|
||||
@@ -31,14 +32,24 @@ import (
|
||||
|
||||
func TestPackageRpm(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
packageName := "gitea-test"
|
||||
packageVersion := "1.0.2-1"
|
||||
packageArchitecture := "x86_64"
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
base64RpmPackageContent := `H4sICFayB2QCAGdpdGVhLXRlc3QtMS4wLjItMS14ODZfNjQucnBtAO2YV4gTQRjHJzl7wbNhhxVF
|
||||
// To build an RPM package, it needs tools lik "cpio", it's not easy to do in Golang.
|
||||
// So here we only use pre-built package contents. And to save space, the content is gzipped and base64 encoded.
|
||||
rpmContentFromGzipBase64 := func(t testing.TB, s string) []byte {
|
||||
b, err := base64.StdEncoding.DecodeString(s)
|
||||
require.NoError(t, err)
|
||||
zr, err := gzip.NewReader(bytes.NewReader(b))
|
||||
require.NoError(t, err)
|
||||
content, err := io.ReadAll(zr)
|
||||
require.NoError(t, err)
|
||||
return content
|
||||
}
|
||||
packageRpmGzipBase64 := `H4sICFayB2QCAGdpdGVhLXRlc3QtMS4wLjItMS14ODZfNjQucnBtAO2YV4gTQRjHJzl7wbNhhxVF
|
||||
VNwk2zd2PdvZ9Sxnd3Z3NllNsmF3o6congVFsWFHRWwIImIXfRER0QcRfPBJEXvvBQvWSfZTT0VQ
|
||||
8TF/MuU33zcz3+zOJGEe73lyuQBRBWKWRzDrEddjuVAkxLMc+lsFUOWfm5bvvReAalWECg/TsivU
|
||||
dyKa0U61aVnl6wj0Uxe4nc8F92hZiaYE8CO/P0r7/Quegr0c7M/AvoCaGZEIWNGUqMHrhhGROIUT
|
||||
@@ -66,14 +77,17 @@ Mu0UFYgZ/bYnuvn/vz4wtCz8qMwsHUvP0PX3tbYFUctAPdrY6tiiDtcCddDECahx7SuVNP5dpmb5
|
||||
9tMDyaXb7OAlk5acuPn57ss9mw6Wym0m1Fq2cej7tUt2LL4/b8enXU2fndk+fvv57ndnt55/cQob
|
||||
7tpp/pEjDS7cGPZ6BY430+7danDq6f42Nw49b9F7zp6BiKpJb9s5P0AYN2+L159cnrur636rx+v1
|
||||
7ae1K28QbMMcqI8CqwIrgwg9nTOp8Oj9q81plUY7ZuwXN8Vvs8wbAAA=`
|
||||
rpmPackageContent, err := base64.StdEncoding.DecodeString(base64RpmPackageContent)
|
||||
assert.NoError(t, err)
|
||||
|
||||
zr, err := gzip.NewReader(bytes.NewReader(rpmPackageContent))
|
||||
assert.NoError(t, err)
|
||||
packageRpmContent := rpmContentFromGzipBase64(t, packageRpmGzipBase64)
|
||||
|
||||
content, err := io.ReadAll(zr)
|
||||
assert.NoError(t, err)
|
||||
decodeGzipXML := func(t testing.TB, resp *httptest.ResponseRecorder, v any) {
|
||||
t.Helper()
|
||||
|
||||
zr, err := gzip.NewReader(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, xml.NewDecoder(zr).Decode(v))
|
||||
}
|
||||
|
||||
rootURL := fmt.Sprintf("/api/packages/%s/rpm", user.Name)
|
||||
|
||||
@@ -99,7 +113,7 @@ gpgcheck=1
|
||||
gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
strings.Join(append([]string{user.LowerName}, groupParts...), "-"),
|
||||
strings.Join(append([]string{user.Name, setting.AppName}, groupParts...), " - "),
|
||||
util.URLJoin(setting.AppURL, groupURL),
|
||||
strings.TrimSuffix(setting.AppURL, "/")+groupURL,
|
||||
setting.AppURL,
|
||||
user.Name,
|
||||
)
|
||||
@@ -120,10 +134,10 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
t.Run("Upload", func(t *testing.T) {
|
||||
url := groupURL + "/upload"
|
||||
|
||||
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content))
|
||||
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(packageRpmContent))
|
||||
MakeRequest(t, req, http.StatusUnauthorized)
|
||||
|
||||
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
|
||||
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(packageRpmContent)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
@@ -146,9 +160,9 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
|
||||
pb, err := packages.GetBlobByID(t.Context(), pfs[0].BlobID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(len(content)), pb.Size)
|
||||
assert.Equal(t, int64(len(packageRpmContent)), pb.Size)
|
||||
|
||||
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
|
||||
req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(packageRpmContent)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusConflict)
|
||||
})
|
||||
@@ -159,12 +173,12 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
// download the package without the file name
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture))
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
assert.Equal(t, content, resp.Body.Bytes())
|
||||
assert.Equal(t, packageRpmContent, resp.Body.Bytes())
|
||||
|
||||
// download the package with a file name (it can be anything)
|
||||
req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s/any-file-name", groupURL, packageName, packageVersion, packageArchitecture))
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
assert.Equal(t, content, resp.Body.Bytes())
|
||||
assert.Equal(t, packageRpmContent, resp.Body.Bytes())
|
||||
})
|
||||
|
||||
t.Run("Repository", func(t *testing.T) {
|
||||
@@ -248,15 +262,6 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNATURE-----")
|
||||
})
|
||||
|
||||
decodeGzipXML := func(t testing.TB, resp *httptest.ResponseRecorder, v any) {
|
||||
t.Helper()
|
||||
|
||||
zr, err := gzip.NewReader(resp.Body)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, xml.NewDecoder(zr).Decode(v))
|
||||
}
|
||||
|
||||
t.Run("primary.xml.gz", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
@@ -331,7 +336,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
assert.Equal(t, "sha256", p.Checksum.Type)
|
||||
assert.Equal(t, "f1d5d2ffcbe4a7568e98b864f40d923ecca084e9b9bcd5977ed6521c46d3fa4c", p.Checksum.Checksum)
|
||||
assert.Equal(t, "https://gitea.io", p.URL)
|
||||
assert.EqualValues(t, len(content), p.Size.Package)
|
||||
assert.EqualValues(t, len(packageRpmContent), p.Size.Package)
|
||||
assert.EqualValues(t, 13, p.Size.Installed)
|
||||
assert.EqualValues(t, 272, p.Size.Archive)
|
||||
assert.Equal(t, fmt.Sprintf("package/%s/%s/%s/%s", packageName, packageVersion, packageArchitecture, fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture)), p.Location.Href)
|
||||
@@ -421,6 +426,417 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Errata", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
type updateInfo struct {
|
||||
XMLName xml.Name `xml:"updates"`
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
Updates []*rpm_module.Update `xml:"update"`
|
||||
}
|
||||
|
||||
errataURL := fmt.Sprintf("%s/package/%s/%s/errata", groupURL, packageName, packageVersion)
|
||||
|
||||
advisory := rpm_module.Update{
|
||||
From: "security@example.com",
|
||||
Status: "stable",
|
||||
Type: "security",
|
||||
Version: "1.0",
|
||||
ID: "CVE-2023-1234",
|
||||
Title: "Test Security Update",
|
||||
Severity: "Important",
|
||||
Description: "This is a test security update.",
|
||||
References: []*rpm_module.Reference{
|
||||
{
|
||||
Href: "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-1234",
|
||||
ID: "CVE-2023-1234",
|
||||
Title: "CVE-2023-1234",
|
||||
Type: "cve",
|
||||
},
|
||||
},
|
||||
PkgList: []*rpm_module.Collection{
|
||||
{
|
||||
Short: "el9",
|
||||
Packages: []*rpm_module.UpdatePackage{
|
||||
{
|
||||
Arch: packageArchitecture,
|
||||
Name: packageName,
|
||||
Release: "1",
|
||||
Src: "gitea-test-1.0.2-1.src.rpm",
|
||||
Version: "1.0.2",
|
||||
Filename: fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("Success", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
updates := []*rpm_module.Update{&advisory}
|
||||
body, err := json.Marshal(updates)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req := NewRequestWithBody(t, "POST", errataURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
url := groupURL + "/repodata"
|
||||
|
||||
// Check repomd.xml contains updateinfo
|
||||
req = NewRequest(t, "GET", url+"/repomd.xml")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
type testRepoData struct {
|
||||
Type string `xml:"type,attr"`
|
||||
}
|
||||
var repomd struct {
|
||||
Data []*testRepoData `xml:"data"`
|
||||
}
|
||||
err = xml.NewDecoder(resp.Body).Decode(&repomd)
|
||||
require.NoError(t, err)
|
||||
|
||||
found := slices.IndexFunc(repomd.Data, func(s *testRepoData) bool {
|
||||
return s.Type == "updateinfo"
|
||||
}) >= 0
|
||||
assert.True(t, found, "updateinfo not found in repomd.xml")
|
||||
|
||||
// Now check updateinfo.xml.gz
|
||||
req = NewRequest(t, "GET", url+"/updateinfo.xml.gz")
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result updateInfo
|
||||
decodeGzipXML(t, resp, &result)
|
||||
|
||||
assert.Equal(t, "http://linux.duke.edu/metadata/updateinfo", result.Xmlns)
|
||||
assert.Len(t, result.Updates, 1)
|
||||
assert.Equal(t, "CVE-2023-1234", result.Updates[0].ID)
|
||||
assert.NotEmpty(t, result.Updates[0].Issued.Date)
|
||||
assert.NotEmpty(t, result.Updates[0].Updated.Date)
|
||||
})
|
||||
|
||||
t.Run("InvalidJSON", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequestWithBody(t, "POST", errataURL, strings.NewReader("invalid json")).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusBadRequest)
|
||||
})
|
||||
|
||||
t.Run("NullElementsInJSON", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Send a payload with null inside arrays
|
||||
payload := `[
|
||||
{
|
||||
"id": "CVE-2023-5678",
|
||||
"from": "security@example.com",
|
||||
"status": "stable",
|
||||
"type": "security",
|
||||
"version": "1.0",
|
||||
"title": "Test Null Elements",
|
||||
"severity": "Important",
|
||||
"description": "Test null elements",
|
||||
"pkg_list": [
|
||||
null,
|
||||
{
|
||||
"short": "el9",
|
||||
"packages": [
|
||||
null,
|
||||
{
|
||||
"arch": "x86_64",
|
||||
"name": "gitea",
|
||||
"release": "1",
|
||||
"src": "gitea-1.0.0-1.src.rpm",
|
||||
"version": "1.0.0",
|
||||
"filename": "gitea-1.0.0-1.x86_64.rpm"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]`
|
||||
|
||||
req := NewRequestWithBody(t, "POST", errataURL, strings.NewReader(payload)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Verify it was stored correctly (skipping nulls)
|
||||
url := groupURL + "/repodata"
|
||||
req = NewRequest(t, "GET", url+"/updateinfo.xml.gz")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result updateInfo
|
||||
decodeGzipXML(t, resp, &result)
|
||||
|
||||
// We need to find the new advisory CVE-2023-5678
|
||||
var newAdvisory *rpm_module.Update
|
||||
for _, u := range result.Updates {
|
||||
if u.ID == "CVE-2023-5678" {
|
||||
newAdvisory = u
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, newAdvisory)
|
||||
assert.Len(t, newAdvisory.PkgList, 1)
|
||||
assert.Equal(t, "el9", newAdvisory.PkgList[0].Short)
|
||||
assert.Len(t, newAdvisory.PkgList[0].Packages, 1)
|
||||
assert.Equal(t, "gitea", newAdvisory.PkgList[0].Packages[0].Name)
|
||||
})
|
||||
|
||||
t.Run("PackageNotFound", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
badURL := fmt.Sprintf("%s/package/%s/non-existent-version/errata", groupURL, packageName)
|
||||
updates := []*rpm_module.Update{&advisory}
|
||||
body, err := json.Marshal(updates)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req := NewRequestWithBody(t, "POST", badURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
})
|
||||
|
||||
t.Run("MergeAdvisories", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Upload a second advisory with the same ID but a different package
|
||||
advisory2 := advisory
|
||||
advisory2.PkgList = []*rpm_module.Collection{
|
||||
{
|
||||
Short: "el9",
|
||||
Packages: []*rpm_module.UpdatePackage{
|
||||
{
|
||||
Arch: packageArchitecture,
|
||||
Name: "another-package",
|
||||
Release: "1",
|
||||
Src: "another-package-1.0.0-1.src.rpm",
|
||||
Version: "1.0.0",
|
||||
Filename: "another-package-1.0.0-1.x86_64.rpm",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
updates := []*rpm_module.Update{&advisory2}
|
||||
body, err := json.Marshal(updates)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req := NewRequestWithBody(t, "POST", errataURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Check updateinfo.xml.gz again
|
||||
url := groupURL + "/repodata"
|
||||
req = NewRequest(t, "GET", url+"/updateinfo.xml.gz")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result updateInfo
|
||||
decodeGzipXML(t, resp, &result)
|
||||
|
||||
var targetUpdate *rpm_module.Update
|
||||
for _, u := range result.Updates {
|
||||
if u.ID == "CVE-2023-1234" {
|
||||
targetUpdate = u
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, targetUpdate)
|
||||
// Verify that package lists are merged into the same collection
|
||||
assert.Len(t, targetUpdate.PkgList, 1)
|
||||
assert.Len(t, targetUpdate.PkgList[0].Packages, 2)
|
||||
assert.Equal(t, "another-package", result.Updates[0].PkgList[0].Packages[1].Name)
|
||||
})
|
||||
|
||||
t.Run("NewCollection", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
// Upload a third advisory with the same ID but a different collection
|
||||
advisory3 := advisory
|
||||
advisory3.PkgList = []*rpm_module.Collection{
|
||||
{
|
||||
Short: "el8",
|
||||
Packages: []*rpm_module.UpdatePackage{
|
||||
{
|
||||
Arch: packageArchitecture,
|
||||
Name: packageName,
|
||||
Release: "1",
|
||||
Src: "gitea-test-1.0.2-1.src.rpm",
|
||||
Version: "1.0.2",
|
||||
Filename: fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
updates := []*rpm_module.Update{&advisory3}
|
||||
body, err := json.Marshal(updates)
|
||||
assert.NoError(t, err)
|
||||
|
||||
req := NewRequestWithBody(t, "POST", errataURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Check updateinfo.xml.gz again
|
||||
url := groupURL + "/repodata"
|
||||
req = NewRequest(t, "GET", url+"/updateinfo.xml.gz")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result updateInfo
|
||||
decodeGzipXML(t, resp, &result)
|
||||
|
||||
var targetUpdate *rpm_module.Update
|
||||
for _, u := range result.Updates {
|
||||
if u.ID == "CVE-2023-1234" {
|
||||
targetUpdate = u
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, targetUpdate)
|
||||
// Verify that we now have 2 collections
|
||||
assert.Len(t, targetUpdate.PkgList, 2)
|
||||
// We need to be careful with order, map iteration is random
|
||||
// Let's check both exist
|
||||
shorts := []string{targetUpdate.PkgList[0].Short, targetUpdate.PkgList[1].Short}
|
||||
assert.Contains(t, shorts, "el9")
|
||||
assert.Contains(t, shorts, "el8")
|
||||
})
|
||||
|
||||
t.Run("Idempotency", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
updates := []*rpm_module.Update{&advisory}
|
||||
body, err := json.Marshal(updates)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Post twice
|
||||
req := NewRequestWithBody(t, "POST", errataURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
req = NewRequestWithBody(t, "POST", errataURL, bytes.NewReader(body)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// Check updateinfo.xml.gz
|
||||
url := groupURL + "/repodata"
|
||||
req = NewRequest(t, "GET", url+"/updateinfo.xml.gz")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var result updateInfo
|
||||
decodeGzipXML(t, resp, &result)
|
||||
|
||||
var targetUpdate *rpm_module.Update
|
||||
for _, u := range result.Updates {
|
||||
if u.ID == "CVE-2023-1234" {
|
||||
targetUpdate = u
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, targetUpdate)
|
||||
assert.Len(t, targetUpdate.PkgList, 2)
|
||||
|
||||
var el9Coll *rpm_module.Collection
|
||||
for _, coll := range targetUpdate.PkgList {
|
||||
if coll.Short == "el9" {
|
||||
el9Coll = coll
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotNil(t, el9Coll)
|
||||
assert.Len(t, el9Coll.Packages, 2)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("NoArch", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
noarchPackageName := "gitea-noarch-test"
|
||||
noarchPackageVersion := "1.0.0-1"
|
||||
noarchPackageGzipBase64 := `H4sICKC05mkAA2dpdGVhLW5vYXJjaC10ZXN0LTEuMC4wLTEubm9hcmNoLnJwbQDtmLtrFEEcx+dy` +
|
||||
`p0ZROYliFMUTLJJiz53HPgbBBwZR0Jgiglo5sztzLt6Lu0uIYmEhFhFUsBUJahd8gHZWKvgnpLES` +
|
||||
`VIwYo43a6Dm7+zvfhbXsF+ZmP/N7zM5y03wXZt89yyOjbiXqKGHVG6IVnLQ6qt2xcNku2xZG/6wc` +
|
||||
`WvL70qXbr3PwuAyh4gMz74TnW2YumqJVZl76vQPKrQEeTjn/2swFM6rAb9N61Ezr84sQPwfx9xA/` +
|
||||
`b8Il6nEpWSgwVz7lrqOZ9oWjqKZSShIQT/k4cHWIAtcJHNsR1OGKSp8w5QcMM+4SiSV1OSY293wi` +
|
||||
`TAMmmBauL1XoeJ7mXAqhafL6BXzzSd+N2eFP9x8/nHt25u7CBbN49t8/YKZMmTJlypQpU6ZMmTJl` +
|
||||
`ypTpP1biiXS73Sso8TR+8U1KCOU+mHkXSnyN3HPICc3oh5yeTxL7Jn3A88Brgd8Ab0Q/fJTlZmwC` +
|
||||
`XgC2gd+h1FfZDbwI9SPAHyB+EPgjxMeAP0O/ceAvED8B/BVYp1xYC1wDXg/nuww8CPvFvlHePG6A` +
|
||||
`+D3gjcBd4KG0X24d1B9N63Nw3sKxND9XApaQPwQcAm8HVsAMWANz4CrwjpQHrsJ+8D0GnkIcvsfA` +
|
||||
`C9j/OPBLyL8GPA/xmZj3oj/8OZT4cwij0WStFK+VmiI4JSoKjf8EZdMgevVgRjbqqg1/mEMHxtGR` +
|
||||
`erupgkhHKkTVqD4xhdLuf27VswLL7VZQbjVrf3mZ9KVX9IZJqkZyaG+j1mypdluF+6KqGhU11R5G` +
|
||||
`EItXRqKKKf6xNiZOVxsiSW7vF5NqrKV0NDWMqNmfWRixsptYkgx+iV1O/Mn+nldpHSYlq4KCZtRA` +
|
||||
`lTNRE3E4lDWp6mGjZaUHTWomOtrykdCUKxxgLjTzfKG0J2wqFfeVFjyMzT1CfC255lRRn5HQDT2J` +
|
||||
`mcDMdQRzeNqL0NBmhEimlTDpnoeV7xGPYSmpZ3vcljQIbYf6SmjJXEwoVT6xpc+k4wkS/7fSC97t` +
|
||||
`xvcCFbdcTO92X57apoHNSquLs6s3b3s0uHXPpes77+yZnp5eaa7m3PxbJ3YYvwFme3wbyRUAAA==`
|
||||
noarchRpmPackageContent := rpmContentFromGzipBase64(t, noarchPackageGzipBase64)
|
||||
// Upload the noarch RPM
|
||||
req := NewRequestWithBody(t, "PUT", groupURL+"/upload", bytes.NewReader(noarchRpmPackageContent)).AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
// The noarch package should appear in primary.xml when any arch is requested.
|
||||
// At this point the group contains the existing x86_64 package + this noarch one.
|
||||
req = NewRequest(t, "GET", groupURL+"/repodata/primary.xml.gz")
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
type PackageSummary struct {
|
||||
Name string `xml:"name"`
|
||||
Architecture string `xml:"arch"`
|
||||
}
|
||||
type PrimaryMetadata struct {
|
||||
XMLName xml.Name `xml:"metadata"`
|
||||
PackageCount int `xml:"packages,attr"`
|
||||
Packages []PackageSummary `xml:"package"`
|
||||
}
|
||||
|
||||
var primary PrimaryMetadata
|
||||
decodeGzipXML(t, resp, &primary)
|
||||
|
||||
// Both the arch-specific package uploaded earlier and the noarch one must be present.
|
||||
assert.Equal(t, 2, primary.PackageCount)
|
||||
assert.Len(t, primary.Packages, 2)
|
||||
|
||||
archNames := make([]string, 0, len(primary.Packages))
|
||||
for _, p := range primary.Packages {
|
||||
archNames = append(archNames, p.Architecture)
|
||||
}
|
||||
assert.Contains(t, archNames, packageArchitecture) // x86_64 from the Upload subtest
|
||||
assert.Contains(t, archNames, "noarch")
|
||||
|
||||
// noarch package must be downloadable regardless of the arch path used.
|
||||
for _, arch := range []string{"noarch", "x86_64", "aarch64", "my_arch"} {
|
||||
req = NewRequest(t, "GET", fmt.Sprintf(
|
||||
"%s/package/%s/%s/%s",
|
||||
groupURL, noarchPackageName, noarchPackageVersion, arch,
|
||||
))
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
// Clean up: delete via the canonical noarch path.
|
||||
req = NewRequest(t, "DELETE", fmt.Sprintf(
|
||||
"%s/package/%s/%s/noarch",
|
||||
groupURL, noarchPackageName, noarchPackageVersion,
|
||||
)).AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusNoContent)
|
||||
|
||||
// After deletion, the noarch package must no longer be reachable via any arch.
|
||||
for _, arch := range []string{"noarch", "x86_64", "aarch64"} {
|
||||
req = NewRequest(t, "GET", fmt.Sprintf(
|
||||
"%s/package/%s/%s/%s",
|
||||
groupURL, noarchPackageName, noarchPackageVersion, arch,
|
||||
))
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
// The x86_64 package from the Upload subtest must still be present.
|
||||
req = NewRequest(t, "GET", groupURL+"/repodata/primary.xml.gz")
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
var primaryAfter PrimaryMetadata
|
||||
decodeGzipXML(t, resp, &primaryAfter)
|
||||
assert.Equal(t, 1, primaryAfter.PackageCount)
|
||||
assert.Equal(t, packageArchitecture, primaryAfter.Packages[0].Architecture)
|
||||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
@@ -442,7 +858,7 @@ gpgkey=%sapi/packages/%s/rpm/repository.key`,
|
||||
t.Run("UploadSign", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
url := groupURL + "/upload?sign=true"
|
||||
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
|
||||
req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(packageRpmContent)).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user