0
0
mirror of https://github.com/thegeeklab/wp-gitea-release.git synced 2024-06-02 18:29:43 +02:00
wp-gitea-release/plugin/release.go

170 lines
4.3 KiB
Go

package plugin
import (
"errors"
"fmt"
"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")
)
type GiteaClient struct {
client *gitea.Client
Release *GiteaRelease
}
type GiteaRelease struct {
client *gitea.Client
Opt GiteaReleaseOpt
}
type GiteaReleaseOpt struct {
Owner string
Repo string
Tag string
Draft bool
Prerelease bool
FileExists string
Title string
Note string
}
type FileExists string
const (
FileExistsOverwrite FileExists = "overwrite"
FileExistsFail FileExists = "fail"
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{},
},
}
}
// 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 *GiteaRelease) 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 *GiteaRelease) 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 *GiteaRelease) 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 *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
}