forked from actions/release-action
229 lines
5.8 KiB
Go
229 lines
5.8 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"code.gitea.io/sdk/gitea"
|
|
gha "github.com/sethvargo/go-githubactions"
|
|
)
|
|
|
|
func main() {
|
|
ctx, err := gha.Context()
|
|
if err != nil {
|
|
gha.Fatalf("failed to get context: %v", err)
|
|
}
|
|
|
|
if !strings.HasPrefix(ctx.Ref, "refs/tags/") {
|
|
gha.Fatalf("ref %s is not a tag", ctx.Ref)
|
|
}
|
|
|
|
files := gha.GetInput("files")
|
|
title := gha.GetInput("title")
|
|
body := gha.GetInput("body")
|
|
note := gha.GetInput("note")
|
|
apiKey := gha.GetInput("api_key")
|
|
preRelease, _ := strconv.ParseBool(gha.GetInput("pre_release"))
|
|
draft, _ := strconv.ParseBool(gha.GetInput("draft"))
|
|
if title == "" {
|
|
title = ctx.RefName
|
|
}
|
|
if apiKey == "" {
|
|
apiKey = os.Getenv("GITHUB_TOKEN")
|
|
}
|
|
insecure, _ := strconv.ParseBool(gha.GetInput("insecure"))
|
|
|
|
client := http.DefaultClient
|
|
if insecure {
|
|
tr := &http.Transport{
|
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
|
}
|
|
client = &http.Client{Transport: tr}
|
|
}
|
|
|
|
c, err := gitea.NewClient(ctx.ServerURL, gitea.SetToken(apiKey), gitea.SetHTTPClient(client))
|
|
if err != nil {
|
|
gha.Fatalf("failed to create gitea client: %v", err)
|
|
}
|
|
|
|
owner := ctx.RepositoryOwner
|
|
repo := strings.Split(ctx.Repository, "/")[1]
|
|
|
|
// 获取上一个 tag 的 SHA
|
|
tags, _, err := c.ListRepoTags(owner, repo, gitea.ListRepoTagsOptions{
|
|
ListOptions: gitea.ListOptions{
|
|
Page: 1,
|
|
PageSize: 100,
|
|
},
|
|
})
|
|
if err != nil {
|
|
gha.Fatalf("failed to get tags: %v", err)
|
|
}
|
|
previewTagSHA := ""
|
|
if len(tags) > 1 {
|
|
previewTagSHA = tags[1].Commit.SHA
|
|
}
|
|
|
|
// 获取上一个 tag 至当前 tag 之间的所有 commit 信息,列出提交信息
|
|
commits, _, err := c.ListRepoCommits(owner, repo, gitea.ListCommitOptions{})
|
|
if err != nil {
|
|
gha.Fatalf("failed to get commits: %v", err)
|
|
}
|
|
commitCount := 1
|
|
commitHistory := ""
|
|
for _, commit := range commits {
|
|
if previewTagSHA == commit.SHA {
|
|
break
|
|
}
|
|
commitHistory += fmt.Sprintf("%d. %s\n", commitCount, commit.RepoCommit.Message)
|
|
commitCount++
|
|
}
|
|
|
|
if body == "" {
|
|
body = "\n## 内容\n" + commitHistory
|
|
}
|
|
body += "## 提示\n" + note
|
|
|
|
fmt.Printf("Creating release for %s/%s with tag %s\n", owner, repo, ctx.RefName)
|
|
fmt.Printf("Title: %s\n", title)
|
|
fmt.Printf("Note: %s\n", body)
|
|
|
|
rel, err := createOrGetRelease(ctx, c, owner, repo, gitea.CreateReleaseOption{
|
|
TagName: ctx.RefName,
|
|
IsDraft: draft,
|
|
IsPrerelease: preRelease,
|
|
Title: title,
|
|
Target: ctx.SHA,
|
|
Note: body,
|
|
})
|
|
if err != nil {
|
|
gha.Fatalf("failed to create release: %v", err)
|
|
}
|
|
|
|
matchedFiles, err := getFiles(ctx.Workspace, files)
|
|
if err != nil {
|
|
gha.Fatalf("failed to get files: %v", err)
|
|
}
|
|
|
|
if err := uploadFiles(ctx, c, owner, repo, rel.ID, matchedFiles); err != nil {
|
|
gha.Fatalf("Failed to upload files: %v", err)
|
|
}
|
|
|
|
gha.SetOutput("status", "success")
|
|
}
|
|
|
|
func getDirFiles(dir string) ([]string, error) {
|
|
d, err := os.Open(dir)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer d.Close()
|
|
info, err := d.Stat()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !info.IsDir() {
|
|
return []string{dir}, nil
|
|
}
|
|
list, err := d.Readdirnames(0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res := make([]string, 0, len(list))
|
|
for _, f := range list {
|
|
subs, err := getDirFiles(filepath.Join(dir, f))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res = append(res, subs...)
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func getFiles(parentDir, files string) ([]string, error) {
|
|
var fileList []string
|
|
lines := strings.Split(files, "\n")
|
|
for _, line := range lines {
|
|
line = strings.Trim(line, "'")
|
|
line = strings.TrimSpace(strings.Trim(line, `"`))
|
|
if line == "" {
|
|
continue
|
|
}
|
|
if filepath.IsAbs(line) {
|
|
return nil, fmt.Errorf("file path %s is absolute", line)
|
|
}
|
|
line = filepath.Join(parentDir, line)
|
|
matches, err := filepath.Glob(line)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, match := range matches {
|
|
files, err := getDirFiles(match)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fileList = append(fileList, files...)
|
|
}
|
|
}
|
|
return fileList, nil
|
|
}
|
|
|
|
func createOrGetRelease(ctx *gha.GitHubContext, c *gitea.Client, owner, repo string, opts gitea.CreateReleaseOption) (*gitea.Release, error) {
|
|
// Get the release by tag
|
|
release, resp, err := c.GetReleaseByTag(owner, repo, opts.TagName)
|
|
if err == nil {
|
|
return release, nil
|
|
}
|
|
errMessage := fmt.Errorf("failed to get release for tag: %s with error: %w", opts.TagName, err)
|
|
if resp.StatusCode != 404 {
|
|
return nil, errMessage
|
|
}
|
|
fmt.Printf("%s trying to create it\n", errMessage)
|
|
// Create the release
|
|
release, _, err = c.CreateRelease(owner, repo, opts)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to create release: %w and %s", err, errMessage)
|
|
}
|
|
return release, nil
|
|
}
|
|
|
|
func uploadFiles(ctx *gha.GitHubContext, c *gitea.Client, owner, repo string, releaseID int64, files []string) error {
|
|
attachments, _, err := c.ListReleaseAttachments(owner, repo, releaseID, gitea.ListReleaseAttachmentsOptions{})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to fetch existing release attachments: %w", err)
|
|
}
|
|
|
|
for _, file := range files {
|
|
f, err := os.Open(file)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to open release attachment %s: %w", file, err)
|
|
}
|
|
|
|
for _, attachment := range attachments {
|
|
if attachment.Name == filepath.Base(file) {
|
|
if _, err := c.DeleteReleaseAttachment(owner, repo, releaseID, attachment.ID); err != nil {
|
|
f.Close()
|
|
return fmt.Errorf("failed to delete release attachment %s: %w", file, err)
|
|
}
|
|
|
|
fmt.Printf("Successfully deleted old release attachment %s\n", attachment.Name)
|
|
}
|
|
}
|
|
|
|
if _, _, err = c.CreateReleaseAttachment(owner, repo, releaseID, f, filepath.Base(file)); err != nil {
|
|
f.Close()
|
|
return fmt.Errorf("failed to upload release attachment %s: %w", file, err)
|
|
}
|
|
f.Close()
|
|
|
|
fmt.Printf("Successfully uploaded release attachment %s\n", file)
|
|
}
|
|
|
|
return nil
|
|
}
|