0
0
mirror of https://github.com/thegeeklab/wp-gitea-release.git synced 2024-11-24 13:00:40 +00:00
wp-gitea-release/gitea/gitea.go

176 lines
4.4 KiB
Go

package gitea
import (
"errors"
"fmt"
"net/http"
"os"
"path"
"code.gitea.io/sdk/gitea"
"github.com/rs/zerolog/log"
)
var (
ErrReleaseNotFound = errors.New("release not found")
ErrFileExists = errors.New("asset file already exist")
)
const (
FileExistsOverwrite FileExists = "overwrite"
FileExistsFail FileExists = "fail"
FileExistsSkip FileExists = "skip"
)
type Client struct {
client APIClient
Release *Release
}
type Release struct {
client APIClient
Opt ReleaseOptions
}
type ReleaseOptions struct {
Owner string
Repo string
Tag string
Draft bool
Prerelease bool
FileExists string
Title string
Note string
}
type FileExists string
// NewClient creates a new Client instance with the provided Gitea client.
func NewClient(url, key string, client *http.Client) (*Client, error) {
c, err := gitea.NewClient(url, gitea.SetToken(key), gitea.SetHTTPClient(client))
if err != nil {
return nil, err
}
return &Client{
client: c,
Release: &Release{
client: c,
Opt: ReleaseOptions{},
},
}, nil
}
// Find retrieves the release with the specified tag name from the repository.
// If the release is not found, it returns an ErrReleaseNotFound error.
func (r *Release) Find() (*gitea.Release, error) {
releases, _, err := r.client.ListReleases(r.Opt.Owner, r.Opt.Repo, gitea.ListReleasesOptions{})
if err != nil {
return nil, err
}
for _, release := range releases {
if release.TagName == r.Opt.Tag {
log.Info().Msgf("found release: %s", r.Opt.Tag)
return release, nil
}
}
return nil, fmt.Errorf("%w: %s", ErrReleaseNotFound, r.Opt.Tag)
}
// Create creates a new release on the Gitea repository with the specified options.
// It returns the created release or an error if the creation failed.
func (r *Release) Create() (*gitea.Release, error) {
opts := gitea.CreateReleaseOption{
TagName: r.Opt.Tag,
IsDraft: r.Opt.Draft,
IsPrerelease: r.Opt.Prerelease,
Title: r.Opt.Title,
Note: r.Opt.Note,
}
release, _, err := r.client.CreateRelease(r.Opt.Owner, r.Opt.Repo, opts)
if err != nil {
return nil, fmt.Errorf("failed to create release: %w", err)
}
log.Info().Msgf("created release: %s", r.Opt.Tag)
return release, nil
}
// 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,
// and handles them according to the FileExists option:
//
// - "overwrite": overwrites the existing attachment
// - "fail": returns an error if the file already exists
// - "skip": skips uploading the file and logs a warning
//
// If there are no conflicts, it uploads the new files as attachments to the release.
func (r *Release) AddAttachments(releaseID int64, files []string) error {
attachments, _, err := r.client.ListReleaseAttachments(
r.Opt.Owner,
r.Opt.Repo,
releaseID,
gitea.ListReleaseAttachmentsOptions{},
)
if err != nil {
return fmt.Errorf("failed to fetch attachments: %w", err)
}
existingAttachments := make(map[string]bool)
attachmentsMap := make(map[string]*gitea.Attachment)
for _, attachment := range attachments {
attachmentsMap[attachment.Name] = attachment
existingAttachments[attachment.Name] = true
}
for _, file := range files {
fileName := path.Base(file)
if existingAttachments[fileName] {
switch FileExists(r.Opt.FileExists) {
case FileExistsOverwrite:
_, err := r.client.DeleteReleaseAttachment(r.Opt.Owner, r.Opt.Repo, releaseID, attachmentsMap[fileName].ID)
if err != nil {
return fmt.Errorf("failed to delete artifact: %s: %w", fileName, err)
}
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
}
}
if err := r.uploadFile(releaseID, file); err != nil {
return err
}
}
return nil
}
func (r *Release) 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
}