gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package integration
  4. import (
  5. "bytes"
  6. "compress/gzip"
  7. "encoding/base64"
  8. "encoding/xml"
  9. "fmt"
  10. "io"
  11. "net/http"
  12. "net/http/httptest"
  13. "strings"
  14. "testing"
  15. "code.gitea.io/gitea/models/packages"
  16. "code.gitea.io/gitea/models/unittest"
  17. user_model "code.gitea.io/gitea/models/user"
  18. rpm_module "code.gitea.io/gitea/modules/packages/rpm"
  19. "code.gitea.io/gitea/modules/setting"
  20. "code.gitea.io/gitea/modules/util"
  21. "code.gitea.io/gitea/tests"
  22. "github.com/ProtonMail/go-crypto/openpgp"
  23. "github.com/sassoftware/go-rpmutils"
  24. "github.com/stretchr/testify/assert"
  25. "github.com/stretchr/testify/require"
  26. )
  27. func TestPackageRpm(t *testing.T) {
  28. defer tests.PrepareTestEnv(t)()
  29. packageName := "gitea-test"
  30. packageVersion := "1.0.2-1"
  31. packageArchitecture := "x86_64"
  32. user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
  33. base64RpmPackageContent := `H4sICFayB2QCAGdpdGVhLXRlc3QtMS4wLjItMS14ODZfNjQucnBtAO2YV4gTQRjHJzl7wbNhhxVF
  34. VNwk2zd2PdvZ9Sxnd3Z3NllNsmF3o6congVFsWFHRWwIImIXfRER0QcRfPBJEXvvBQvWSfZTT0VQ
  35. 8TF/MuU33zcz3+zOJGEe73lyuQBRBWKWRzDrEddjuVAkxLMc+lsFUOWfm5bvvReAalWECg/TsivU
  36. dyKa0U61aVnl6wj0Uxe4nc8F92hZiaYE8CO/P0r7/Quegr0c7M/AvoCaGZEIWNGUqMHrhhGROIUT
  37. Zc7gOAOraoQzCNZ0WdU0HpEI5jiB4zlek3gT85wqCBomhomxoGCs8wImWMImbxqKgXVNUKKaqShR
  38. STKVKK9glFUNcf2g+/t27xs16v5x/eyOKftVGlIhyiuvvPLKK6+88sorr7zyyiuvvPKCO5HPnz+v
  39. pGVhhXsTsFVeSstuWR9anwU+Bk3Vch5wTwL3JkHg+8C1gR8A169wj1KdpobAj4HbAT+Be5VewE+h
  40. fz/g52AvBX4N9vHAb4AnA7+F8ePAH8BuA38ELgf+BLzQ50oIeBlw0OdAOXAlP57AGuCsbwGtbgCu
  41. DrwRuAb4bwau6T/PwFbgWsDXgWuD/y3gOmC/B1wI/Bi4AcT3Arih3z9YCNzI9w9m/YKUG4Nd9N9z
  42. pSZgHwrcFPgccFt//OADGE+F/q+Ao+D/FrijzwV1gbv4/QvaAHcFDgF3B5aB+wB3Be7rz1dQCtwP
  43. eDxwMcw3GbgU7AasdwzYE8DjwT4L/CeAvRx4IvBCYA3iWQds+FzpDjABfghsAj8BTgA/A/b8+StX
  44. A84A1wKe5s9fuRB4JpzHZv55rL8a/Dv49vpn/PErR4BvQX8Z+Db4l2W5CH2/f0W5+1fEoeFDBzFp
  45. rE/FMcK4mWQSOzN+aDOIqztW2rPsFKIyqh7sQERR42RVMSKihnzVHlQ8Ag0YLBYNEIajkhmuR5Io
  46. 7nlpt2M4nJs0ZNkoYaUyZahMlSfJImr1n1WjFVNCPCaTZgYNGdGL8YN2mX8WHfA/C7ViHJK0pxHG
  47. SrkeTiSI4T+7ubf85yrzRCQRQ5EVxVAjvIBVRY/KRFAVReIkhfARSddNSceayQkGliIKb0q8RAxJ
  48. 5QWNVxHIsW3Pz369bw+5jh5y0klE9Znqm0dF57b0HbGy2A5lVUBTZZrqZjdUjYoprFmpsBtHP5d0
  49. +ISltS2yk2mHuC4x+lgJMhgnidvuqy3b0suK0bm+tw3FMxI2zjm7/fA0MtQhplX2s7nYLZ2ZC0yg
  50. CxJZDokhORTJlrlcCvG5OieGBERlVCs7CfuS6WzQ/T2j+9f92BWxTFEcp2IkYccYGp2LYySEfreq
  51. irue4WRF5XkpKovw2wgpq2rZBI8bQZkzxEkiYaNwxnXCCVvHidzIiB3CM2yMYdNWmjDsaLovaE4c
  52. x3a6mLaTxB7rEj3jWN4M2p7uwPaa1GfI8BHFfcZMKhkycnhR7y781/a+A4t7FpWWTupRUtKbegwZ
  53. XMKwJinTSe70uhRcj55qNu3YHtE922Fdz7FTMTq9Q3TbMdiYrrPudMvT44S6u2miu138eC0tTN9D
  54. 2CFGHHtQsHHsGCRFDFbXuT9wx6mUTZfseydlkWZeJkW6xOgYjqXT+LA7I6XHaUx2xmUzqelWymA9
  55. rCXI9+D1BHbjsITssqhBNysw0tOWjcpmIh6+aViYPfftw8ZSGfRVPUqKiosZj5R5qGmk/8AjjRbZ
  56. d8b3vvngdPHx3HvMeCarIk7VVSwbgoZVkceEVyOmyUmGxBGNYDVKSFSOGlIkGqWnUZFkiY/wsmhK
  57. Mu0UFYgZ/bYnuvn/vz4wtCz8qMwsHUvP0PX3tbYFUctAPdrY6tiiDtcCddDECahx7SuVNP5dpmb5
  58. 9tMDyaXb7OAlk5acuPn57ss9mw6Wym0m1Fq2cej7tUt2LL4/b8enXU2fndk+fvv57ndnt55/cQob
  59. 7tpp/pEjDS7cGPZ6BY430+7danDq6f42Nw49b9F7zp6BiKpJb9s5P0AYN2+L159cnrur636rx+v1
  60. 7ae1K28QbMMcqI8CqwIrgwg9nTOp8Oj9q81plUY7ZuwXN8Vvs8wbAAA=`
  61. rpmPackageContent, err := base64.StdEncoding.DecodeString(base64RpmPackageContent)
  62. assert.NoError(t, err)
  63. zr, err := gzip.NewReader(bytes.NewReader(rpmPackageContent))
  64. assert.NoError(t, err)
  65. content, err := io.ReadAll(zr)
  66. assert.NoError(t, err)
  67. rootURL := fmt.Sprintf("/api/packages/%s/rpm", user.Name)
  68. for _, group := range []string{"", "el9", "el9/stable"} {
  69. t.Run(fmt.Sprintf("[Group:%s]", group), func(t *testing.T) {
  70. var groupParts []string
  71. if group != "" {
  72. groupParts = strings.Split(group, "/")
  73. }
  74. groupURL := strings.Join(append([]string{rootURL}, groupParts...), "/")
  75. t.Run("RepositoryConfig", func(t *testing.T) {
  76. defer tests.PrintCurrentTest(t)()
  77. req := NewRequest(t, "GET", groupURL+".repo")
  78. resp := MakeRequest(t, req, http.StatusOK)
  79. expected := fmt.Sprintf(`[gitea-%s]
  80. name=%s
  81. baseurl=%s
  82. enabled=1
  83. gpgcheck=1
  84. gpgkey=%sapi/packages/%s/rpm/repository.key`,
  85. strings.Join(append([]string{user.LowerName}, groupParts...), "-"),
  86. strings.Join(append([]string{user.Name, setting.AppName}, groupParts...), " - "),
  87. util.URLJoin(setting.AppURL, groupURL),
  88. setting.AppURL,
  89. user.Name,
  90. )
  91. assert.Equal(t, expected, resp.Body.String())
  92. })
  93. t.Run("RepositoryKey", func(t *testing.T) {
  94. defer tests.PrintCurrentTest(t)()
  95. req := NewRequest(t, "GET", rootURL+"/repository.key")
  96. resp := MakeRequest(t, req, http.StatusOK)
  97. assert.Equal(t, "application/pgp-keys", resp.Header().Get("Content-Type"))
  98. assert.Contains(t, resp.Body.String(), "-----BEGIN PGP PUBLIC KEY BLOCK-----")
  99. })
  100. t.Run("Upload", func(t *testing.T) {
  101. url := groupURL + "/upload"
  102. req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content))
  103. MakeRequest(t, req, http.StatusUnauthorized)
  104. req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
  105. AddBasicAuth(user.Name)
  106. MakeRequest(t, req, http.StatusCreated)
  107. pvs, err := packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeRpm)
  108. assert.NoError(t, err)
  109. assert.Len(t, pvs, 1)
  110. pd, err := packages.GetPackageDescriptor(t.Context(), pvs[0])
  111. assert.NoError(t, err)
  112. assert.Nil(t, pd.SemVer)
  113. assert.IsType(t, &rpm_module.VersionMetadata{}, pd.Metadata)
  114. assert.Equal(t, packageName, pd.Package.Name)
  115. assert.Equal(t, packageVersion, pd.Version.Version)
  116. pfs, err := packages.GetFilesByVersionID(t.Context(), pvs[0].ID)
  117. assert.NoError(t, err)
  118. assert.Len(t, pfs, 1)
  119. assert.Equal(t, fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture), pfs[0].Name)
  120. assert.True(t, pfs[0].IsLead)
  121. pb, err := packages.GetBlobByID(t.Context(), pfs[0].BlobID)
  122. assert.NoError(t, err)
  123. assert.Equal(t, int64(len(content)), pb.Size)
  124. req = NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
  125. AddBasicAuth(user.Name)
  126. MakeRequest(t, req, http.StatusConflict)
  127. })
  128. t.Run("Download", func(t *testing.T) {
  129. defer tests.PrintCurrentTest(t)()
  130. // download the package without the file name
  131. req := NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture))
  132. resp := MakeRequest(t, req, http.StatusOK)
  133. assert.Equal(t, content, resp.Body.Bytes())
  134. // download the package with a file name (it can be anything)
  135. req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s/any-file-name", groupURL, packageName, packageVersion, packageArchitecture))
  136. resp = MakeRequest(t, req, http.StatusOK)
  137. assert.Equal(t, content, resp.Body.Bytes())
  138. })
  139. t.Run("Repository", func(t *testing.T) {
  140. defer tests.PrintCurrentTest(t)()
  141. url := groupURL + "/repodata"
  142. req := NewRequest(t, "HEAD", url+"/dummy.xml")
  143. MakeRequest(t, req, http.StatusNotFound)
  144. req = NewRequest(t, "GET", url+"/dummy.xml")
  145. MakeRequest(t, req, http.StatusNotFound)
  146. t.Run("repomd.xml", func(t *testing.T) {
  147. defer tests.PrintCurrentTest(t)()
  148. req = NewRequest(t, "HEAD", url+"/repomd.xml")
  149. MakeRequest(t, req, http.StatusOK)
  150. req = NewRequest(t, "GET", url+"/repomd.xml")
  151. resp := MakeRequest(t, req, http.StatusOK)
  152. type Repomd struct {
  153. XMLName xml.Name `xml:"repomd"`
  154. Xmlns string `xml:"xmlns,attr"`
  155. XmlnsRpm string `xml:"xmlns:rpm,attr"`
  156. Data []struct {
  157. Type string `xml:"type,attr"`
  158. Checksum struct {
  159. Value string `xml:",chardata"`
  160. Type string `xml:"type,attr"`
  161. } `xml:"checksum"`
  162. OpenChecksum struct {
  163. Value string `xml:",chardata"`
  164. Type string `xml:"type,attr"`
  165. } `xml:"open-checksum"`
  166. Location struct {
  167. Href string `xml:"href,attr"`
  168. } `xml:"location"`
  169. Timestamp int64 `xml:"timestamp"`
  170. Size int64 `xml:"size"`
  171. OpenSize int64 `xml:"open-size"`
  172. } `xml:"data"`
  173. }
  174. var result Repomd
  175. decodeXML(t, resp, &result)
  176. assert.Len(t, result.Data, 3)
  177. for _, d := range result.Data {
  178. assert.Equal(t, "sha256", d.Checksum.Type)
  179. assert.NotEmpty(t, d.Checksum.Value)
  180. assert.Equal(t, "sha256", d.OpenChecksum.Type)
  181. assert.NotEmpty(t, d.OpenChecksum.Value)
  182. assert.NotEqual(t, d.Checksum.Value, d.OpenChecksum.Value)
  183. assert.Greater(t, d.OpenSize, d.Size)
  184. switch d.Type {
  185. case "primary":
  186. assert.EqualValues(t, 722, d.Size)
  187. assert.EqualValues(t, 1759, d.OpenSize)
  188. assert.Equal(t, "repodata/primary.xml.gz", d.Location.Href)
  189. case "filelists":
  190. assert.EqualValues(t, 257, d.Size)
  191. assert.EqualValues(t, 326, d.OpenSize)
  192. assert.Equal(t, "repodata/filelists.xml.gz", d.Location.Href)
  193. case "other":
  194. assert.EqualValues(t, 306, d.Size)
  195. assert.EqualValues(t, 394, d.OpenSize)
  196. assert.Equal(t, "repodata/other.xml.gz", d.Location.Href)
  197. }
  198. }
  199. })
  200. t.Run("repomd.xml.asc", func(t *testing.T) {
  201. defer tests.PrintCurrentTest(t)()
  202. req = NewRequest(t, "GET", url+"/repomd.xml.asc")
  203. resp := MakeRequest(t, req, http.StatusOK)
  204. assert.Contains(t, resp.Body.String(), "-----BEGIN PGP SIGNATURE-----")
  205. })
  206. decodeGzipXML := func(t testing.TB, resp *httptest.ResponseRecorder, v any) {
  207. t.Helper()
  208. zr, err := gzip.NewReader(resp.Body)
  209. assert.NoError(t, err)
  210. assert.NoError(t, xml.NewDecoder(zr).Decode(v))
  211. }
  212. t.Run("primary.xml.gz", func(t *testing.T) {
  213. defer tests.PrintCurrentTest(t)()
  214. req = NewRequest(t, "GET", url+"/primary.xml.gz")
  215. resp := MakeRequest(t, req, http.StatusOK)
  216. type EntryList struct {
  217. Entries []*rpm_module.Entry `xml:"entry"`
  218. }
  219. type Metadata struct {
  220. XMLName xml.Name `xml:"metadata"`
  221. Xmlns string `xml:"xmlns,attr"`
  222. XmlnsRpm string `xml:"xmlns:rpm,attr"`
  223. PackageCount int `xml:"packages,attr"`
  224. Packages []struct {
  225. XMLName xml.Name `xml:"package"`
  226. Type string `xml:"type,attr"`
  227. Name string `xml:"name"`
  228. Architecture string `xml:"arch"`
  229. Version struct {
  230. Epoch string `xml:"epoch,attr"`
  231. Version string `xml:"ver,attr"`
  232. Release string `xml:"rel,attr"`
  233. } `xml:"version"`
  234. Checksum struct {
  235. Checksum string `xml:",chardata"`
  236. Type string `xml:"type,attr"`
  237. Pkgid string `xml:"pkgid,attr"`
  238. } `xml:"checksum"`
  239. Summary string `xml:"summary"`
  240. Description string `xml:"description"`
  241. Packager string `xml:"packager"`
  242. URL string `xml:"url"`
  243. Time struct {
  244. File uint64 `xml:"file,attr"`
  245. Build uint64 `xml:"build,attr"`
  246. } `xml:"time"`
  247. Size struct {
  248. Package int64 `xml:"package,attr"`
  249. Installed uint64 `xml:"installed,attr"`
  250. Archive uint64 `xml:"archive,attr"`
  251. } `xml:"size"`
  252. Location struct {
  253. Href string `xml:"href,attr"`
  254. } `xml:"location"`
  255. Format struct {
  256. License string `xml:"license"`
  257. Vendor string `xml:"vendor"`
  258. Group string `xml:"group"`
  259. Buildhost string `xml:"buildhost"`
  260. Sourcerpm string `xml:"sourcerpm"`
  261. Provides EntryList `xml:"provides"`
  262. Requires EntryList `xml:"requires"`
  263. Conflicts EntryList `xml:"conflicts"`
  264. Obsoletes EntryList `xml:"obsoletes"`
  265. Files []*rpm_module.File `xml:"file"`
  266. } `xml:"format"`
  267. } `xml:"package"`
  268. }
  269. var result Metadata
  270. decodeGzipXML(t, resp, &result)
  271. assert.Equal(t, 1, result.PackageCount)
  272. assert.Len(t, result.Packages, 1)
  273. p := result.Packages[0]
  274. assert.Equal(t, "rpm", p.Type)
  275. assert.Equal(t, packageName, p.Name)
  276. assert.Equal(t, packageArchitecture, p.Architecture)
  277. assert.Equal(t, "YES", p.Checksum.Pkgid)
  278. assert.Equal(t, "sha256", p.Checksum.Type)
  279. assert.Equal(t, "f1d5d2ffcbe4a7568e98b864f40d923ecca084e9b9bcd5977ed6521c46d3fa4c", p.Checksum.Checksum)
  280. assert.Equal(t, "https://gitea.io", p.URL)
  281. assert.EqualValues(t, len(content), p.Size.Package)
  282. assert.EqualValues(t, 13, p.Size.Installed)
  283. assert.EqualValues(t, 272, p.Size.Archive)
  284. 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)
  285. f := p.Format
  286. assert.Equal(t, "MIT", f.License)
  287. assert.Len(t, f.Provides.Entries, 2)
  288. assert.Len(t, f.Requires.Entries, 7)
  289. assert.Empty(t, f.Conflicts.Entries)
  290. assert.Empty(t, f.Obsoletes.Entries)
  291. assert.Len(t, f.Files, 1)
  292. })
  293. t.Run("filelists.xml.gz", func(t *testing.T) {
  294. defer tests.PrintCurrentTest(t)()
  295. req = NewRequest(t, "GET", url+"/filelists.xml.gz")
  296. resp := MakeRequest(t, req, http.StatusOK)
  297. type Filelists struct {
  298. XMLName xml.Name `xml:"filelists"`
  299. Xmlns string `xml:"xmlns,attr"`
  300. PackageCount int `xml:"packages,attr"`
  301. Packages []struct {
  302. Pkgid string `xml:"pkgid,attr"`
  303. Name string `xml:"name,attr"`
  304. Architecture string `xml:"arch,attr"`
  305. Version struct {
  306. Epoch string `xml:"epoch,attr"`
  307. Version string `xml:"ver,attr"`
  308. Release string `xml:"rel,attr"`
  309. } `xml:"version"`
  310. Files []*rpm_module.File `xml:"file"`
  311. } `xml:"package"`
  312. }
  313. var result Filelists
  314. decodeGzipXML(t, resp, &result)
  315. assert.Equal(t, 1, result.PackageCount)
  316. assert.Len(t, result.Packages, 1)
  317. p := result.Packages[0]
  318. assert.NotEmpty(t, p.Pkgid)
  319. assert.Equal(t, packageName, p.Name)
  320. assert.Equal(t, packageArchitecture, p.Architecture)
  321. assert.Len(t, p.Files, 1)
  322. f := p.Files[0]
  323. assert.Equal(t, "/usr/local/bin/hello", f.Path)
  324. })
  325. t.Run("other.xml.gz", func(t *testing.T) {
  326. defer tests.PrintCurrentTest(t)()
  327. req = NewRequest(t, "GET", url+"/other.xml.gz")
  328. resp := MakeRequest(t, req, http.StatusOK)
  329. type Other struct {
  330. XMLName xml.Name `xml:"otherdata"`
  331. Xmlns string `xml:"xmlns,attr"`
  332. PackageCount int `xml:"packages,attr"`
  333. Packages []struct {
  334. Pkgid string `xml:"pkgid,attr"`
  335. Name string `xml:"name,attr"`
  336. Architecture string `xml:"arch,attr"`
  337. Version struct {
  338. Epoch string `xml:"epoch,attr"`
  339. Version string `xml:"ver,attr"`
  340. Release string `xml:"rel,attr"`
  341. } `xml:"version"`
  342. Changelogs []*rpm_module.Changelog `xml:"changelog"`
  343. } `xml:"package"`
  344. }
  345. var result Other
  346. decodeGzipXML(t, resp, &result)
  347. assert.Equal(t, 1, result.PackageCount)
  348. assert.Len(t, result.Packages, 1)
  349. p := result.Packages[0]
  350. assert.NotEmpty(t, p.Pkgid)
  351. assert.Equal(t, packageName, p.Name)
  352. assert.Equal(t, packageArchitecture, p.Architecture)
  353. assert.Len(t, p.Changelogs, 1)
  354. c := p.Changelogs[0]
  355. assert.Equal(t, "KN4CK3R <dummy@gitea.io>", c.Author)
  356. assert.EqualValues(t, 1678276800, c.Date)
  357. assert.Equal(t, "- Changelog message.", c.Text)
  358. })
  359. })
  360. t.Run("Delete", func(t *testing.T) {
  361. defer tests.PrintCurrentTest(t)()
  362. req := NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture))
  363. MakeRequest(t, req, http.StatusUnauthorized)
  364. req = NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture)).
  365. AddBasicAuth(user.Name)
  366. MakeRequest(t, req, http.StatusNoContent)
  367. pvs, err := packages.GetVersionsByPackageType(t.Context(), user.ID, packages.TypeRpm)
  368. assert.NoError(t, err)
  369. assert.Empty(t, pvs)
  370. req = NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture)).
  371. AddBasicAuth(user.Name)
  372. MakeRequest(t, req, http.StatusNotFound)
  373. })
  374. t.Run("UploadSign", func(t *testing.T) {
  375. defer tests.PrintCurrentTest(t)()
  376. url := groupURL + "/upload?sign=true"
  377. req := NewRequestWithBody(t, "PUT", url, bytes.NewReader(content)).
  378. AddBasicAuth(user.Name)
  379. MakeRequest(t, req, http.StatusCreated)
  380. gpgReq := NewRequest(t, "GET", rootURL+"/repository.key")
  381. gpgResp := MakeRequest(t, gpgReq, http.StatusOK)
  382. pub, err := openpgp.ReadArmoredKeyRing(gpgResp.Body)
  383. require.NoError(t, err)
  384. rpmFileName := fmt.Sprintf("%s-%s.%s.rpm", packageName, packageVersion, packageArchitecture)
  385. req = NewRequest(t, "GET", fmt.Sprintf("%s/package/%s/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture, rpmFileName))
  386. resp := MakeRequest(t, req, http.StatusOK)
  387. _, sigs, err := rpmutils.Verify(resp.Body, pub)
  388. require.NoError(t, err)
  389. require.NotEmpty(t, sigs)
  390. req = NewRequest(t, "DELETE", fmt.Sprintf("%s/package/%s/%s/%s", groupURL, packageName, packageVersion, packageArchitecture)).
  391. AddBasicAuth(user.Name)
  392. MakeRequest(t, req, http.StatusNoContent)
  393. })
  394. })
  395. }
  396. }