[#466] adm: Allow to download contracts from Gitea, with tests

Signed-off-by: Olga Konstantinova <kola43843@gmail.com>
This commit is contained in:
Olga Konstantinova 2024-06-25 22:19:09 +03:00
parent 80b581d499
commit 0530f04670
4 changed files with 227 additions and 11 deletions

View file

@ -41,15 +41,46 @@ func downloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) {
return resp.Body, nil
}
func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error) {
client, err := gitea.NewClient("https://git.frostfs.info")
if err != nil {
return nil, fmt.Errorf("can't initialize repository client: %w", err)
}
type GiteaGlient interface {
ListReleases(owner, repo string, opt gitea.ListReleasesOptions) ([]*gitea.Release, *gitea.Response, error)
}
releases, _, err := client.ListReleases("TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{})
type GiteaRepo struct {
client GiteaGlient
}
func New() GiteaRepo {
client, _ := gitea.NewClient("https://git.frostfs.info")
return GiteaRepo{
client: client,
}
}
func (g *GiteaRepo) ListReleases(owner, repo string, opt gitea.ListReleasesOptions) ([]*gitea.Release, *gitea.Response, error) {
return g.client.ListReleases(owner, repo, opt)
}
type Downloader interface {
DownloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error)
}
type ContractDownloader struct{}
func (d *ContractDownloader) DownloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) {
return downloadContracts(cmd, url)
}
func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error) {
giteaRepo := new(GiteaRepo)
downloader := new(ContractDownloader)
return downloadContractsFromGitea(cmd, giteaRepo, downloader)
}
func downloadContractsFromGitea(cmd *cobra.Command, giteaRepo *GiteaRepo, downloader Downloader) (io.ReadCloser, error) {
releases, _, err := giteaRepo.ListReleases("TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{})
if err != nil {
return nil, fmt.Errorf("can't fetch release information: %w", err)
}
var latestRelease *gitea.Release
@ -61,11 +92,9 @@ func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error)
}
if latestRelease == nil {
return nil, fmt.Errorf("attempt to fetch contracts archive from the offitial repository failed: no releases found")
return nil, fmt.Errorf("attempt to fetch contracts archive from the official repository failed: no releases found")
}
cmd.Printf("Found release %s (%s)\n", latestRelease.TagName, latestRelease.Title)
var url string
for _, a := range latestRelease.Attachments {
if strings.HasPrefix(a.Name, "frostfs-contract") {
@ -77,5 +106,5 @@ func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error)
return nil, errors.New("can't find contracts archive in the latest release")
}
return downloadContracts(cmd, url)
return downloader.DownloadContracts(cmd, url)
}

View file

@ -0,0 +1,186 @@
package morph
import (
"bytes"
"code.gitea.io/sdk/gitea"
"fmt"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
"io"
"testing"
)
type MockGiteaRepo struct {
mock.Mock
*gitea.Client
}
func (m *MockGiteaRepo) ListReleases(owner, repo string, opt gitea.ListReleasesOptions) ([]*gitea.Release, *gitea.Response, error) {
args := m.Called(owner, repo, opt)
return args.Get(0).([]*gitea.Release), args.Get(1).(*gitea.Response), args.Error(2)
}
type MockDownloader struct {
mock.Mock
}
func (m *MockDownloader) DownloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) {
args := m.Called(cmd, url)
return args.Get(0).(io.ReadCloser), args.Error(1)
}
func TestGiteaRepo_DownloadContracts_ListReleasesFailure(t *testing.T) {
m := MockGiteaRepo{}
giteaRepo := GiteaRepo{
client: &m,
}
m.On("ListReleases", "TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}).
Return([]*gitea.Release{}, &gitea.Response{Response: nil}, fmt.Errorf("failed"))
res, err := downloadContractsFromGitea(nil, &giteaRepo, nil)
assert.Nil(t, res, "result must be nil")
require.Error(t, err, "error must be provided")
assert.EqualError(t, err, "can't fetch release information: failed")
}
func TestGiteaRepo_DownloadContracts_ListReleasesEmpty(t *testing.T) {
m := MockGiteaRepo{}
giteaRepo := GiteaRepo{
client: &m,
}
m.On("ListReleases", "TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}).
Return([]*gitea.Release{}, &gitea.Response{Response: nil}, nil)
res, err := downloadContractsFromGitea(nil, &giteaRepo, nil)
assert.Nil(t, res, "result must be nil")
require.Error(t, err, "error must be provided")
assert.EqualError(t, err, "attempt to fetch contracts archive from the official repository failed: no releases found")
}
func TestGiteaRepo_DownloadContracts_ListReleasesOnlyDraftsAndPrereleases(t *testing.T) {
mockRepo := MockGiteaRepo{}
giteaRepo := GiteaRepo{
client: &mockRepo,
}
mockDownloader := MockDownloader{}
attachment := gitea.Attachment{
ID: 1,
DownloadURL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/download/v0.19.2/frostfs-contract-v0.19.2.tar.gz",
Name: "frostfs-contract",
}
draft := gitea.Release{
ID: 1,
Title: "Draft",
URL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.19.2",
IsDraft: true,
IsPrerelease: false,
Attachments: []*gitea.Attachment{&attachment},
}
prerelease := gitea.Release{
ID: 2,
Title: "Prerelease",
URL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.20.1",
IsDraft: false,
IsPrerelease: true,
}
cmd := cobra.Command{}
mockRepo.On("ListReleases", "TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}).
Return([]*gitea.Release{&draft, &prerelease}, &gitea.Response{Response: nil}, nil)
mockDownloader.On("DownloadContracts", &cmd, attachment.DownloadURL).
Return(io.NopCloser(bytes.NewReader([]byte("data"))), nil)
res, err := downloadContractsFromGitea(&cmd, &giteaRepo, &mockDownloader)
assert.Nil(t, res, "result must be nil")
require.Error(t, err, "error must be provided")
assert.EqualError(t, err, "attempt to fetch contracts archive from the offitial repository failed: no releases found")
}
func TestGiteaRepo_DownloadContracts_ListReleasesWrongAttachments(t *testing.T) {
mockRepo := MockGiteaRepo{}
giteaRepo := GiteaRepo{
client: &mockRepo,
}
attachment1 := gitea.Attachment{
ID: 1,
DownloadURL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/download/v0.19.2/incorrect-name-v0.19.2.tar.gz",
Name: "incorrect-name-1",
}
attachment2 := gitea.Attachment{
ID: 2,
DownloadURL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/download/v0.19.2/incorrect-name-v0.19.3.tar.gz",
Name: "incorrect-name-2",
}
release := gitea.Release{
ID: 1,
Title: "Title",
URL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.19.2",
IsDraft: false,
IsPrerelease: false,
Attachments: []*gitea.Attachment{&attachment1, &attachment2},
}
cmd := cobra.Command{}
mockRepo.On("ListReleases", "TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}).
Return([]*gitea.Release{&release}, &gitea.Response{Response: nil}, nil)
res, err := downloadContractsFromGitea(&cmd, &giteaRepo, nil)
assert.Nil(t, res, "result must be nil")
require.Error(t, err, "error must be provided")
assert.EqualError(t, err, "can't find contracts archive in the latest release")
}
func TestGiteaRepo_DownloadContracts_Success(t *testing.T) {
mockRepo := MockGiteaRepo{}
giteaRepo := GiteaRepo{
client: &mockRepo,
}
mockDownloader := MockDownloader{}
attachment1 := gitea.Attachment{
ID: 1,
DownloadURL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/download/v0.19.2/incorrect-name-v0.19.2.tar.gz",
Name: "incorrect-name-1",
}
attachment2 := gitea.Attachment{
ID: 2,
DownloadURL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/download/v0.19.2/frostfs-contract-v0.19.2.tar.gz",
Name: "frostfs-contract",
}
release := gitea.Release{
ID: 1,
Title: "Title",
URL: "https://git.frostfs.info/TrueCloudLab/frostfs-contract/releases/tag/v0.19.2",
IsDraft: false,
IsPrerelease: false,
Attachments: []*gitea.Attachment{&attachment1, &attachment2},
}
cmd := cobra.Command{}
mockRepo.On("ListReleases", "TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{}).
Return([]*gitea.Release{&release}, &gitea.Response{Response: nil}, nil)
mockDownloader.On("DownloadContracts", &cmd, attachment2.DownloadURL).
Return(io.NopCloser(bytes.NewReader([]byte("data"))), nil)
res, err := downloadContractsFromGitea(&cmd, &giteaRepo, &mockDownloader)
assert.NotNil(t, res, "result must not be nil")
require.NoError(t, err, "error must not be provided")
mockDownloader.AssertCalled(t, "DownloadContracts", &cmd, attachment2.DownloadURL)
}

3
go.mod
View file

@ -30,7 +30,7 @@ require (
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
go.etcd.io/bbolt v1.3.8
go.opentelemetry.io/otel v1.22.0
go.opentelemetry.io/otel/trace v1.22.0
@ -107,6 +107,7 @@ require (
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/twmb/murmur3 v1.1.8 // indirect

BIN
go.sum

Binary file not shown.