mirror of
https://github.com/thegeeklab/wp-gitea-release.git
synced 2024-11-14 09:00:44 +00:00
refactor: rework gitea client and add tests (#44)
This commit is contained in:
parent
8b057ea06b
commit
a196e5f4ac
@ -23,7 +23,6 @@ linters:
|
|||||||
- errchkjson
|
- errchkjson
|
||||||
- errname
|
- errname
|
||||||
- errorlint
|
- errorlint
|
||||||
- execinquery
|
|
||||||
- exhaustive
|
- exhaustive
|
||||||
- exportloopref
|
- exportloopref
|
||||||
- forcetypeassert
|
- forcetypeassert
|
||||||
@ -37,12 +36,12 @@ linters:
|
|||||||
- gocyclo
|
- gocyclo
|
||||||
- godot
|
- godot
|
||||||
- godox
|
- godox
|
||||||
- goerr113
|
- err113
|
||||||
- gofmt
|
- gofmt
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- goheader
|
- goheader
|
||||||
- goimports
|
- goimports
|
||||||
- gomnd
|
- mnd
|
||||||
- gomoddirectives
|
- gomoddirectives
|
||||||
- gomodguard
|
- gomodguard
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
@ -95,3 +94,9 @@ run:
|
|||||||
linters-settings:
|
linters-settings:
|
||||||
gofumpt:
|
gofumpt:
|
||||||
extra-rules: true
|
extra-rules: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: "_test.go"
|
||||||
|
linters:
|
||||||
|
- err113
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -70,19 +69,17 @@ func (p *Plugin) Validate() error {
|
|||||||
|
|
||||||
// Execute provides the implementation of the plugin.
|
// Execute provides the implementation of the plugin.
|
||||||
func (p *Plugin) Execute() error {
|
func (p *Plugin) Execute() error {
|
||||||
httpClient := &http.Client{}
|
gitea, err := gitea.NewClient(
|
||||||
|
|
||||||
client, err := gitea.NewClient(
|
|
||||||
p.Settings.baseURL.String(),
|
p.Settings.baseURL.String(),
|
||||||
gitea.SetToken(p.Settings.APIKey),
|
gitea.SetToken(p.Settings.APIKey),
|
||||||
gitea.SetHTTPClient(httpClient),
|
gitea.SetHTTPClient(p.Network.Client),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r := &Release{
|
client := NewGiteaClient(gitea)
|
||||||
Client: client,
|
client.Release.Opt = GiteaReleaseOpt{
|
||||||
Owner: p.Metadata.Repository.Owner,
|
Owner: p.Metadata.Repository.Owner,
|
||||||
Repo: p.Metadata.Repository.Name,
|
Repo: p.Metadata.Repository.Name,
|
||||||
Tag: strings.TrimPrefix(p.Settings.CommitRef, "refs/tags/"),
|
Tag: strings.TrimPrefix(p.Settings.CommitRef, "refs/tags/"),
|
||||||
@ -93,12 +90,20 @@ func (p *Plugin) Execute() error {
|
|||||||
Note: p.Settings.Note,
|
Note: p.Settings.Note,
|
||||||
}
|
}
|
||||||
|
|
||||||
release, err := r.buildRelease()
|
release, err := client.Release.Find()
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, ErrReleaseNotFound) {
|
||||||
return fmt.Errorf("failed to create the release: %w", err)
|
return fmt.Errorf("failed to retrieve release: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := r.uploadFiles(release.ID, p.Settings.files); err != nil {
|
// If no release was found by that tag, create a new one.
|
||||||
|
if release == nil {
|
||||||
|
release, err = client.Release.Create()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create release: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.Release.AddAttachments(release.ID, p.Settings.files); err != nil {
|
||||||
return fmt.Errorf("failed to upload the files: %w", err)
|
return fmt.Errorf("failed to upload the files: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,9 +15,17 @@ var (
|
|||||||
ErrFileExists = errors.New("asset file already exist")
|
ErrFileExists = errors.New("asset file already exist")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Release represents a release for a Gitea repository.
|
type GiteaClient struct {
|
||||||
type Release struct {
|
client *gitea.Client
|
||||||
*gitea.Client
|
Release *GiteaRelease
|
||||||
|
}
|
||||||
|
|
||||||
|
type GiteaRelease struct {
|
||||||
|
client *gitea.Client
|
||||||
|
Opt GiteaReleaseOpt
|
||||||
|
}
|
||||||
|
|
||||||
|
type GiteaReleaseOpt struct {
|
||||||
Owner string
|
Owner string
|
||||||
Repo string
|
Repo string
|
||||||
Tag string
|
Tag string
|
||||||
@ -28,65 +36,66 @@ type Release struct {
|
|||||||
Note string
|
Note string
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildRelease attempts to retrieve an existing release by the specified tag name.
|
type FileExists string
|
||||||
func (rc *Release) buildRelease() (*gitea.Release, error) {
|
|
||||||
// first attempt to get a release by that tag
|
|
||||||
release, err := rc.getRelease()
|
|
||||||
|
|
||||||
if err != nil && release == nil {
|
const (
|
||||||
fmt.Println(err)
|
FileExistsOverwrite FileExists = "overwrite"
|
||||||
} else if release != nil {
|
FileExistsFail FileExists = "fail"
|
||||||
return release, nil
|
FileExistsSkip FileExists = "skip"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewGiteaClient creates a new GiteaClient instance with the provided Gitea client.
|
||||||
|
func NewGiteaClient(client *gitea.Client) *GiteaClient {
|
||||||
|
return &GiteaClient{
|
||||||
|
client: client,
|
||||||
|
Release: &GiteaRelease{
|
||||||
|
client: client,
|
||||||
|
Opt: GiteaReleaseOpt{},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no release was found by that tag, create a new one
|
|
||||||
release, err = rc.newRelease()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to retrieve or create a release: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return release, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRelease retrieves the release with the specified tag name from the repository.
|
// Find retrieves the release with the specified tag name from the repository.
|
||||||
func (rc *Release) getRelease() (*gitea.Release, error) {
|
// If the release is not found, it returns an ErrReleaseNotFound error.
|
||||||
releases, _, err := rc.Client.ListReleases(rc.Owner, rc.Repo, gitea.ListReleasesOptions{})
|
func (r *GiteaRelease) Find() (*gitea.Release, error) {
|
||||||
|
releases, _, err := r.client.ListReleases(r.Opt.Owner, r.Opt.Repo, gitea.ListReleasesOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, release := range releases {
|
for _, release := range releases {
|
||||||
if release.TagName == rc.Tag {
|
if release.TagName == r.Opt.Tag {
|
||||||
log.Info().Msgf("successfully retrieved %s release", rc.Tag)
|
log.Info().Msgf("found release: %s", r.Opt.Tag)
|
||||||
|
|
||||||
return release, nil
|
return release, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("%w: %s", ErrReleaseNotFound, rc.Tag)
|
return nil, fmt.Errorf("%w: %s", ErrReleaseNotFound, r.Opt.Tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRelease creates a new release on the repository with the specified options.
|
// Create creates a new release on the Gitea repository with the specified options.
|
||||||
func (rc *Release) newRelease() (*gitea.Release, error) {
|
// It returns the created release or an error if the creation failed.
|
||||||
r := gitea.CreateReleaseOption{
|
func (r *GiteaRelease) Create() (*gitea.Release, error) {
|
||||||
TagName: rc.Tag,
|
opts := gitea.CreateReleaseOption{
|
||||||
IsDraft: rc.Draft,
|
TagName: r.Opt.Tag,
|
||||||
IsPrerelease: rc.Prerelease,
|
IsDraft: r.Opt.Draft,
|
||||||
Title: rc.Title,
|
IsPrerelease: r.Opt.Prerelease,
|
||||||
Note: rc.Note,
|
Title: r.Opt.Title,
|
||||||
|
Note: r.Opt.Note,
|
||||||
}
|
}
|
||||||
|
|
||||||
release, _, err := rc.Client.CreateRelease(rc.Owner, rc.Repo, r)
|
release, _, err := r.client.CreateRelease(r.Opt.Owner, r.Opt.Repo, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create release: %w", err)
|
return nil, fmt.Errorf("failed to create release: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msgf("successfully created %s release", rc.Tag)
|
log.Info().Msgf("created release: %s", r.Opt.Tag)
|
||||||
|
|
||||||
return release, nil
|
return release, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// uploadFiles uploads the specified files as attachments to the release with the given ID.
|
// AddAttachments uploads the specified files as attachments to the release with the given ID.
|
||||||
// It first checks for any existing attachments with the same names,
|
// It first checks for any existing attachments with the same names,
|
||||||
// and handles them according to the FileExists option:
|
// and handles them according to the FileExists option:
|
||||||
//
|
//
|
||||||
@ -95,61 +104,66 @@ func (rc *Release) newRelease() (*gitea.Release, error) {
|
|||||||
// - "skip": skips uploading the file and logs a warning
|
// - "skip": skips uploading the file and logs a warning
|
||||||
//
|
//
|
||||||
// If there are no conflicts, it uploads the new files as attachments to the release.
|
// If there are no conflicts, it uploads the new files as attachments to the release.
|
||||||
func (rc *Release) uploadFiles(releaseID int64, files []string) error {
|
func (r *GiteaRelease) AddAttachments(releaseID int64, files []string) error {
|
||||||
attachments, _, err := rc.Client.ListReleaseAttachments(
|
attachments, _, err := r.client.ListReleaseAttachments(
|
||||||
rc.Owner,
|
r.Opt.Owner,
|
||||||
rc.Repo,
|
r.Opt.Repo,
|
||||||
releaseID,
|
releaseID,
|
||||||
gitea.ListReleaseAttachmentsOptions{},
|
gitea.ListReleaseAttachmentsOptions{},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to fetch existing assets: %w", err)
|
return fmt.Errorf("failed to fetch attachments: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uploadFiles []string
|
existingAttachments := make(map[string]bool)
|
||||||
|
attachmentsMap := make(map[string]*gitea.Attachment)
|
||||||
|
|
||||||
|
for _, attachment := range attachments {
|
||||||
|
attachmentsMap[attachment.Name] = attachment
|
||||||
|
existingAttachments[attachment.Name] = true
|
||||||
|
}
|
||||||
|
|
||||||
files:
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
for _, attachment := range attachments {
|
fileName := path.Base(file)
|
||||||
if attachment.Name == path.Base(file) {
|
if existingAttachments[fileName] {
|
||||||
switch rc.FileExists {
|
switch FileExists(r.Opt.FileExists) {
|
||||||
case "overwrite":
|
case FileExistsOverwrite:
|
||||||
// do nothing
|
_, err := r.client.DeleteReleaseAttachment(r.Opt.Owner, r.Opt.Repo, releaseID, attachmentsMap[fileName].ID)
|
||||||
case "fail":
|
if err != nil {
|
||||||
return fmt.Errorf("%w: %s", ErrFileExists, path.Base(file))
|
return fmt.Errorf("failed to delete artifact: %s: %w", fileName, err)
|
||||||
case "skip":
|
|
||||||
log.Warn().Msgf("skipping pre-existing %s artifact", attachment.Name)
|
|
||||||
|
|
||||||
continue files
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info().Msgf("deleted artifact: %s", fileName)
|
||||||
|
case FileExistsFail:
|
||||||
|
return fmt.Errorf("%w: %s", ErrFileExists, fileName)
|
||||||
|
case FileExistsSkip:
|
||||||
|
log.Warn().Msgf("skip existing artifact: %s", fileName)
|
||||||
|
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadFiles = append(uploadFiles, file)
|
if err := r.uploadFile(releaseID, file); err != nil {
|
||||||
}
|
return err
|
||||||
|
|
||||||
for _, file := range uploadFiles {
|
|
||||||
handle, err := os.Open(file)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read %s artifact: %w", file, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, attachment := range attachments {
|
|
||||||
if attachment.Name == path.Base(file) {
|
|
||||||
if _, err := rc.Client.DeleteReleaseAttachment(rc.Owner, rc.Repo, releaseID, attachment.ID); err != nil {
|
|
||||||
return fmt.Errorf("failed to delete %s artifact: %w", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Msgf("successfully deleted old %s artifact", attachment.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, _, err = rc.Client.CreateReleaseAttachment(rc.Owner, rc.Repo, releaseID, handle, path.Base(file)); err != nil {
|
|
||||||
return fmt.Errorf("failed to upload %s artifact: %w", file, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Info().Msgf("successfully uploaded %s artifact", file)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *GiteaRelease) uploadFile(releaseID int64, file string) error {
|
||||||
|
handle, err := os.Open(file)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read artifact: %s: %w", file, err)
|
||||||
|
}
|
||||||
|
defer handle.Close()
|
||||||
|
|
||||||
|
_, _, err = r.client.CreateReleaseAttachment(r.Opt.Owner, r.Opt.Repo, releaseID, handle, path.Base(file))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to upload artifact: %s: %w", file, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Msgf("uploaded artifact: %s", path.Base(file))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
356
plugin/release_test.go
Normal file
356
plugin/release_test.go
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
|
||||||
|
"code.gitea.io/sdk/gitea"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func giteaMockHandler(t *testing.T, opt GiteaReleaseOpt) func(http.ResponseWriter, *http.Request) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
fmt.Println(r.RequestURI)
|
||||||
|
|
||||||
|
switch r.RequestURI {
|
||||||
|
case "/api/v1/version":
|
||||||
|
_, err := io.WriteString(w, `{"version":"1.21.0"}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
case "/api/v1/repos/test-owner/test-repo/releases?limit=0&page=1":
|
||||||
|
_, err := io.WriteString(w, `[{
|
||||||
|
"id": 1,
|
||||||
|
"tag_name": "v1.0.0",
|
||||||
|
"name": "Release v1.0.0",
|
||||||
|
"body": "This is the release notes for v1.0.0",
|
||||||
|
"draft": false,
|
||||||
|
"prerelease": false,
|
||||||
|
"created_at": "2023-05-01T12:00:00Z",
|
||||||
|
"published_at": "2023-05-01T12:30:00Z"
|
||||||
|
}]`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
case "/api/v1/repos/test-owner/test-repo/releases":
|
||||||
|
_, err := io.WriteString(w, fmt.Sprintf(`{
|
||||||
|
"id": 1,
|
||||||
|
"tag_name": "%s",
|
||||||
|
"name": "Release %s",
|
||||||
|
"body": "This is the release notes for %s",
|
||||||
|
"draft": %t,
|
||||||
|
"prerelease": %t,
|
||||||
|
"created_at": "2023-05-01T12:00:00Z",
|
||||||
|
"published_at": "2023-05-01T12:30:00Z"
|
||||||
|
}`, opt.Tag, opt.Tag, opt.Tag, opt.Draft, opt.Prerelease))
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
case "/api/v1/repos/test-owner/test-repo/releases/1/assets?limit=0&page=1":
|
||||||
|
_, err := io.WriteString(w, `[{
|
||||||
|
"id": 1,
|
||||||
|
"name": "file1.txt",
|
||||||
|
"size": 1024,
|
||||||
|
"created_at": "2023-05-01T12:30:00Z"
|
||||||
|
}]`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
case "/api/v1/repos/test-owner/test-repo/releases/1/assets":
|
||||||
|
_, err := io.WriteString(w, `{
|
||||||
|
"id": 1,
|
||||||
|
"name": "file1.txt",
|
||||||
|
"size": 1024,
|
||||||
|
"created_at": "2023-05-01T12:30:00Z"
|
||||||
|
}`)
|
||||||
|
if err != nil {
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGiteaReleaseFind(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
opt GiteaReleaseOpt
|
||||||
|
want *gitea.Release
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "find release by tag",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v1.0.0",
|
||||||
|
},
|
||||||
|
want: &gitea.Release{
|
||||||
|
TagName: "v1.0.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "release not found",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v1.1.0",
|
||||||
|
},
|
||||||
|
want: nil,
|
||||||
|
wantErr: ErrReleaseNotFound,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
giteaMockHandler(t, tt.opt)(w, r)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
g, _ := gitea.NewClient(ts.URL)
|
||||||
|
client := NewGiteaClient(g)
|
||||||
|
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
client.Release.Opt = tt.opt
|
||||||
|
release, err := client.Release.Find()
|
||||||
|
|
||||||
|
if tt.want == nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, release)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want.TagName, release.TagName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGiteaReleaseCreate(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
opt GiteaReleaseOpt
|
||||||
|
want *gitea.Release
|
||||||
|
wantErr error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "create release",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v1.1.0",
|
||||||
|
Title: "Release v1.1.0",
|
||||||
|
Note: "This is the release notes for v1.1.0",
|
||||||
|
Draft: false,
|
||||||
|
Prerelease: false,
|
||||||
|
},
|
||||||
|
want: &gitea.Release{
|
||||||
|
TagName: "v1.1.0",
|
||||||
|
Title: "Release v1.1.0",
|
||||||
|
Note: "This is the release notes for v1.1.0",
|
||||||
|
IsDraft: false,
|
||||||
|
IsPrerelease: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "create draft release",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v1.2.0",
|
||||||
|
Title: "Release v1.2.0",
|
||||||
|
Note: "This is the release notes for v1.2.0",
|
||||||
|
Draft: true,
|
||||||
|
Prerelease: false,
|
||||||
|
},
|
||||||
|
want: &gitea.Release{
|
||||||
|
TagName: "v1.2.0",
|
||||||
|
Title: "Release v1.2.0",
|
||||||
|
Note: "This is the release notes for v1.2.0",
|
||||||
|
IsDraft: true,
|
||||||
|
IsPrerelease: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "create prerelease",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v1.3.0-rc1",
|
||||||
|
Title: "Release v1.3.0-rc1",
|
||||||
|
Note: "This is the release notes for v1.3.0-rc1",
|
||||||
|
Draft: false,
|
||||||
|
Prerelease: true,
|
||||||
|
},
|
||||||
|
want: &gitea.Release{
|
||||||
|
TagName: "v1.3.0-rc1",
|
||||||
|
Title: "Release v1.3.0-rc1",
|
||||||
|
Note: "This is the release notes for v1.3.0-rc1",
|
||||||
|
IsDraft: false,
|
||||||
|
IsPrerelease: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
giteaMockHandler(t, tt.opt)(w, r)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
g, _ := gitea.NewClient(ts.URL)
|
||||||
|
client := NewGiteaClient(g)
|
||||||
|
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
client.Release.Opt = tt.opt
|
||||||
|
release, err := client.Release.Create()
|
||||||
|
|
||||||
|
if tt.wantErr != nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, release)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.want.TagName, release.TagName)
|
||||||
|
assert.Equal(t, tt.want.Title, release.Title)
|
||||||
|
assert.Equal(t, tt.want.Note, release.Note)
|
||||||
|
assert.Equal(t, tt.want.IsDraft, release.IsDraft)
|
||||||
|
assert.Equal(t, tt.want.IsPrerelease, release.IsPrerelease)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGiteaReleaseAddAttachments(t *testing.T) {
|
||||||
|
logBuffer := &bytes.Buffer{}
|
||||||
|
logger := zerolog.New(logBuffer)
|
||||||
|
log.Logger = logger
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
opt GiteaReleaseOpt
|
||||||
|
files []string
|
||||||
|
fileExists string
|
||||||
|
wantErr error
|
||||||
|
wantLogs []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "add new attachments",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v2.0.0",
|
||||||
|
Title: "Release v2.0.0",
|
||||||
|
FileExists: "overwrite",
|
||||||
|
},
|
||||||
|
files: []string{createTempFile(t, "file1.txt"), createTempFile(t, "file2.txt")},
|
||||||
|
wantLogs: []string{"uploaded artifact: file1.txt", "uploaded artifact: file2.txt"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fail on existing attachments",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v2.0.0",
|
||||||
|
Title: "Release v2.0.0",
|
||||||
|
FileExists: "fail",
|
||||||
|
},
|
||||||
|
files: []string{createTempFile(t, "file1.txt"), createTempFile(t, "file2.txt")},
|
||||||
|
wantErr: ErrFileExists,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "overwrite on existing attachments",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v2.0.0",
|
||||||
|
Title: "Release v2.0.0",
|
||||||
|
FileExists: "overwrite",
|
||||||
|
},
|
||||||
|
files: []string{createTempFile(t, "file1.txt"), createTempFile(t, "file2.txt")},
|
||||||
|
wantErr: nil,
|
||||||
|
wantLogs: []string{"deleted artifact: file1.txt", "uploaded artifact: file1.txt"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "skip on existing attachments",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v2.0.0",
|
||||||
|
Title: "Release v2.0.0",
|
||||||
|
FileExists: "skip",
|
||||||
|
},
|
||||||
|
files: []string{createTempFile(t, "file1.txt"), createTempFile(t, "file2.txt")},
|
||||||
|
wantErr: nil,
|
||||||
|
wantLogs: []string{"skip existing artifact: file1"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fail on invalid file",
|
||||||
|
opt: GiteaReleaseOpt{
|
||||||
|
Owner: "test-owner",
|
||||||
|
Repo: "test-repo",
|
||||||
|
Tag: "v2.0.0",
|
||||||
|
Title: "Release v2.0.0",
|
||||||
|
FileExists: "overwrite",
|
||||||
|
},
|
||||||
|
files: []string{"testdata/file1.txt", "testdata/invalid.txt"},
|
||||||
|
wantErr: errors.New("no such file or directory"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
giteaMockHandler(t, tt.opt)(w, r)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
logBuffer.Reset()
|
||||||
|
|
||||||
|
g, _ := gitea.NewClient(ts.URL)
|
||||||
|
client := NewGiteaClient(g)
|
||||||
|
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
client.Release.Opt = tt.opt
|
||||||
|
release, _ := client.Release.Create()
|
||||||
|
|
||||||
|
err := client.Release.AddAttachments(release.ID, tt.files)
|
||||||
|
|
||||||
|
// Assert log output.
|
||||||
|
for _, l := range tt.wantLogs {
|
||||||
|
assert.Contains(t, logBuffer.String(), l)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tt.wantErr != nil {
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.ErrorContains(t, err, tt.wantErr.Error())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.NoError(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTempFile(t *testing.T, name string) string {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
name = filepath.Join(t.TempDir(), name)
|
||||||
|
_ = os.WriteFile(name, []byte("hello"), 0o600)
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user