180 lines
4.4 KiB
Go
180 lines
4.4 KiB
Go
package src
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
"git.beisel.it/florian/gitea-release-drafter/src/config"
|
|
"github.com/sethvargo/go-githubactions"
|
|
)
|
|
|
|
type Action struct {
|
|
config *config.DrafterConfig
|
|
|
|
globalContext context.Context
|
|
client *gitea.Client
|
|
}
|
|
|
|
// NewAction factory for a new action
|
|
func NewAction(ctx *context.Context, cfg *config.DrafterConfig) (*Action, error) {
|
|
gitea, err := gitea.NewClient(cfg.ApiUrl, gitea.SetToken(cfg.Token))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Action{
|
|
config: cfg,
|
|
globalContext: *ctx,
|
|
client: gitea,
|
|
}, nil
|
|
}
|
|
|
|
// updateOrCreateDraftRelease
|
|
func updateOrCreateDraftRelease(a *Action, cfg *config.RepoConfig) (*gitea.Release, error) {
|
|
draft, last, err := FindReleases(a.client, a.config.RepoOwner, a.config.RepoName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
changelog, err := GenerateChangelog(a.client, a.config.RepoOwner, a.config.RepoName, last)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(*changelog) == 0 {
|
|
githubactions.Infof("No updates found")
|
|
return nil, nil
|
|
}
|
|
|
|
// Create a map to hold categorized PRs
|
|
categorizedPRs := make(map[string][]*gitea.PullRequest)
|
|
|
|
for _, prs := range *changelog {
|
|
for _, pr := range prs {
|
|
categorized := false
|
|
for _, category := range cfg.Categories {
|
|
if !categorized && prHasLabel(pr, category.Labels) {
|
|
categorizedPRs[category.Title] = append(categorizedPRs[category.Title], pr)
|
|
categorized = true
|
|
break // Break out of the category loop
|
|
}
|
|
}
|
|
if !categorized {
|
|
// Add to a default category if not categorized
|
|
categorizedPRs["Other Changes"] = append(categorizedPRs["Other Changes"], pr)
|
|
}
|
|
if categorized {
|
|
break // Break out of the PR loop once categorized
|
|
}
|
|
}
|
|
}
|
|
|
|
// Build the changelog string
|
|
var b strings.Builder
|
|
b.WriteString("# What's Changed\n\n")
|
|
|
|
for _, category := range cfg.Categories {
|
|
prs, exists := categorizedPRs[category.Title]
|
|
if exists && len(prs) > 0 {
|
|
fmt.Fprintf(&b, "## %s\n\n", category.Title)
|
|
for _, pr := range prs {
|
|
fmt.Fprintf(&b, "* %s (#%d) @%s\n", pr.Title, pr.Index, pr.Poster.UserName)
|
|
}
|
|
b.WriteString("\n")
|
|
}
|
|
}
|
|
|
|
nextVersion, err := ResolveVersion(cfg, last, changelog)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
title := FillVariables(cfg.NameTemplate, TemplateVariables{
|
|
ReleaseVersion: nextVersion.String(),
|
|
})
|
|
|
|
// FIXME: require RESOLVED_VERSION to be set?
|
|
tag := FillVariables(cfg.TagTemplate, TemplateVariables{
|
|
ReleaseVersion: nextVersion.String(),
|
|
})
|
|
|
|
if draft != nil {
|
|
updatedDraft, err := UpdateExistingDraft(a.client, a.config.RepoOwner, a.config.RepoName, draft, title, tag, b.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return updatedDraft, nil
|
|
}
|
|
|
|
newDraft, err := CreateDraftRelease(a.client, a.config.RepoOwner, a.config.RepoName, cfg.DefaultBranch, title, tag, b.String())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return newDraft, nil
|
|
}
|
|
|
|
// GetConfigFile reads the local configuration file in `.gitea/` in the ref branch (probably main/master)
|
|
func (a *Action) GetConfigFile(ref string) (*bytes.Reader, error) {
|
|
data, _, err := a.client.GetFile(a.config.RepoOwner, a.config.RepoName, ref, a.config.ConfigPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return bytes.NewReader(data), err
|
|
}
|
|
|
|
// Run builds the configuration and executes the action logic
|
|
func (a *Action) Run() error {
|
|
// fetch the repo to retrieve the default branch to be set as the config default
|
|
repo, err := GetRepo(a.client, a.config.RepoOwner, a.config.RepoName)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
githubactions.Debugf("Found default branch %s", repo.DefaultBranch)
|
|
|
|
// build repo config
|
|
configReader, err := a.GetConfigFile(repo.DefaultBranch)
|
|
if err != nil {
|
|
if err.Error() != "404 Not Found" {
|
|
return err
|
|
} else {
|
|
// no config file found
|
|
githubactions.Warningf("No such config file: .gitea/%s", a.config.ConfigPath)
|
|
configReader = bytes.NewReader([]byte{})
|
|
}
|
|
}
|
|
|
|
config, err := config.ReadRepoConfig(configReader, repo.DefaultBranch)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
draft, err := updateOrCreateDraftRelease(a, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if draft != nil {
|
|
githubactions.Infof("created draft release %s", draft.Title)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func prHasLabel(pr *gitea.PullRequest, labels []string) bool {
|
|
for _, prLabel := range pr.Labels {
|
|
for _, label := range labels {
|
|
if prLabel.Name == label {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|