mirror of
https://github.com/thegeeklab/wp-gitea-release.git
synced 2024-11-24 13:00:40 +00:00
176 lines
4.4 KiB
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
|
|
}
|