From 7118ed856053de06ddcdfba2a2d6fa40f58c17ab Mon Sep 17 00:00:00 2001 From: Jim Myhrberg Date: Sat, 9 Oct 2021 18:04:12 +0100 Subject: [PATCH] feat(release): add description to GitHub Releases The description includes links to the Emacs source repo used, the git ref, commit, tarball download URL, and build log (GitHub Actions Run). --- pkg/cli/release.go | 2 + pkg/plan/create.go | 5 ++- pkg/plan/plan.go | 16 +------- pkg/release/publish.go | 29 ++++++++++++- pkg/release/release_body.go | 80 ++++++++++++++++++++++++++++++++++++ pkg/repository/repository.go | 39 ++++++++++++++++++ pkg/source/source.go | 17 ++++++++ 7 files changed, 171 insertions(+), 17 deletions(-) create mode 100644 pkg/release/release_body.go create mode 100644 pkg/source/source.go diff --git a/pkg/cli/release.go b/pkg/cli/release.go index a2e912f..3d6c71e 100644 --- a/pkg/cli/release.go +++ b/pkg/cli/release.go @@ -185,6 +185,8 @@ func releasePublishAction( } if rOpts.Plan != nil { + rlsOpts.Source = rOpts.Plan.Source + if rOpts.Plan.Release != nil { rlsOpts.ReleaseName = rOpts.Plan.Release.Name rlsOpts.ReleaseTitle = rOpts.Plan.Release.Title diff --git a/pkg/plan/create.go b/pkg/plan/create.go index fbef7eb..2859fdb 100644 --- a/pkg/plan/create.go +++ b/pkg/plan/create.go @@ -13,6 +13,7 @@ import ( "github.com/jimeh/build-emacs-for-macos/pkg/osinfo" "github.com/jimeh/build-emacs-for-macos/pkg/release" "github.com/jimeh/build-emacs-for-macos/pkg/repository" + "github.com/jimeh/build-emacs-for-macos/pkg/source" ) var nonAlphaNum = regexp.MustCompile(`[^\w_-]+`) @@ -85,11 +86,11 @@ func Create(ctx context.Context, opts *Options) (*Plan, error) { Build: &Build{ Name: buildName, }, - Source: &Source{ + Source: &source.Source{ Ref: opts.Ref, Repository: repo, Commit: commitInfo, - Tarball: &Tarball{ + Tarball: &source.Tarball{ URL: repo.TarballURL(commitInfo.SHA), }, }, diff --git a/pkg/plan/plan.go b/pkg/plan/plan.go index e33181a..333da67 100644 --- a/pkg/plan/plan.go +++ b/pkg/plan/plan.go @@ -5,15 +5,14 @@ import ( "io" "os" - "github.com/jimeh/build-emacs-for-macos/pkg/commit" "github.com/jimeh/build-emacs-for-macos/pkg/osinfo" - "github.com/jimeh/build-emacs-for-macos/pkg/repository" + "github.com/jimeh/build-emacs-for-macos/pkg/source" "gopkg.in/yaml.v3" ) type Plan struct { Build *Build `yaml:"build,omitempty"` - Source *Source `yaml:"source,omitempty"` + Source *source.Source `yaml:"source,omitempty"` OS *osinfo.OSInfo `yaml:"os,omitempty"` Release *Release `yaml:"release,omitempty"` Output *Output `yaml:"output,omitempty"` @@ -58,17 +57,6 @@ type Build struct { Name string `yaml:"name,omitempty"` } -type Source struct { - Ref string `yaml:"ref,omitempty"` - Repository *repository.Repository `yaml:"repository,omitempty"` - Commit *commit.Commit `yaml:"commit,omitempty"` - Tarball *Tarball `yaml:"tarball,omitempty"` -} - -type Tarball struct { - URL string `yaml:"url,omitempty"` -} - type Release struct { Name string `yaml:"name"` Title string `yaml:"title,omitempty"` diff --git a/pkg/release/publish.go b/pkg/release/publish.go index 2f6cf0b..8b07f42 100644 --- a/pkg/release/publish.go +++ b/pkg/release/publish.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/go-hclog" "github.com/jimeh/build-emacs-for-macos/pkg/gh" "github.com/jimeh/build-emacs-for-macos/pkg/repository" + "github.com/jimeh/build-emacs-for-macos/pkg/source" ) type releaseType int @@ -40,6 +41,11 @@ type PublishOptions struct { // draft) ReleaseType releaseType + // Source contains the source used to build the asset files. When set a + // release body/description text will be generated based on source commit + // details. + Source *source.Source + // AssetFiles is a list of files which must all exist in the release for // the check to pass. AssetFiles []string @@ -68,6 +74,16 @@ func Publish(ctx context.Context, opts *PublishOptions) error { prerelease := opts.ReleaseType == Prerelease draft := opts.ReleaseType == Draft + body := "" + if opts.Source != nil { + body, err = releaseBody(opts) + if err != nil { + return err + } + logger.Debug("rendered release body", "content", body) + } + + created := false logger.Info("checking release", "tag", tagName) release, resp, err := gh.Repositories.GetReleaseByTag( ctx, opts.Repository.Owner(), opts.Repository.Name(), tagName, @@ -77,6 +93,7 @@ func Publish(ctx context.Context, opts *PublishOptions) error { return err } + created = true logger.Info("creating release", "tag", tagName, "name", name) release, _, err = gh.Repositories.CreateRelease( @@ -87,6 +104,7 @@ func Publish(ctx context.Context, opts *PublishOptions) error { TargetCommitish: &opts.CommitRef, Prerelease: boolPtr(false), Draft: boolPtr(true), + Body: &body, }, ) if err != nil { @@ -158,6 +176,11 @@ func Publish(ctx context.Context, opts *PublishOptions) error { changed = true } + if body != "" && release.GetBody() != body { + release.Body = &body + changed = true + } + if release.GetDraft() != draft { release.Draft = &draft changed = true @@ -178,7 +201,11 @@ func Publish(ctx context.Context, opts *PublishOptions) error { } } - logger.Info("release created", "url", release.GetHTMLURL()) + if created { + logger.Info("release created", "url", release.GetHTMLURL()) + } else { + logger.Info("release updated", "url", release.GetHTMLURL()) + } return nil } diff --git a/pkg/release/release_body.go b/pkg/release/release_body.go new file mode 100644 index 0000000..b014075 --- /dev/null +++ b/pkg/release/release_body.go @@ -0,0 +1,80 @@ +package release + +import ( + "bytes" + "os" + "strings" + "text/template" +) + +var tplFuncs = template.FuncMap{ + "indent": func(n int, s string) string { + pad := strings.Repeat(" ", n) + + return pad + strings.ReplaceAll(s, "\n", "\n"+pad) + }, +} + +var bodyTpl = template.Must(template.New("body").Funcs(tplFuncs).Parse(` +{{- $t := "` + "`" + `" -}} +### Build Details + +{{ with .SourceURL -}} +- Source: {{ . }} +{{- end }} +{{- if and .CommitSHA .CommitURL }} +- Commit: [{{ $t }}{{ .CommitSHA }}{{ $t }}] + {{- if .CommitURL }}({{ .CommitURL }}){{ end }} +{{- else if and .CommitSHA }} +- Commit: {{ $t }}{{ .CommitSHA }}{{ $t }} +{{- end }} +{{- with .TarballURL }} +- Tarball: {{ . }} +{{- end }} +{{- with .BuildLogURL }} +- Build Log: {{ . }} (available for 90 days) +{{- end }}`, +)) + +type bodyData struct { + SourceURL string + CommitSHA string + CommitURL string + BuildLogURL string + TarballURL string +} + +func releaseBody(opts *PublishOptions) (string, error) { + src := opts.Source + + if src.Repository == nil || src.Commit == nil { + return "", nil + } + + data := &bodyData{ + SourceURL: src.Repository.TreeURL(src.Ref), + CommitSHA: src.Commit.SHA, + CommitURL: src.Repository.CommitURL(src.Commit.SHA), + TarballURL: src.Repository.TarballURL(src.Commit.SHA), + } + + // If available, use the exact value from the build plan. + if src.Tarball != nil { + data.TarballURL = src.Tarball.URL + } + + // If running within GitHub Actions, provide link to build log. + if opts.Repository != nil { + if id := os.Getenv("GITHUB_RUN_ID"); id != "" { + data.BuildLogURL = opts.Repository.ActionRunURL(id) + } + } + + var buf bytes.Buffer + err := bodyTpl.Execute(&buf, data) + if err != nil { + return "", err + } + + return buf.String(), nil +} diff --git a/pkg/repository/repository.go b/pkg/repository/repository.go index 98d5eeb..f29c2a1 100644 --- a/pkg/repository/repository.go +++ b/pkg/repository/repository.go @@ -89,3 +89,42 @@ func (s *Repository) TarballURL(ref string) string { return "" } } + +func (s *Repository) CommitURL(ref string) string { + if ref == "" { + return "" + } + + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + "/commit/" + ref + default: + return "" + } +} + +func (s *Repository) TreeURL(ref string) string { + if ref == "" { + return "" + } + + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + "/tree/" + ref + default: + return "" + } +} + +func (s *Repository) ActionRunURL(runID string) string { + if runID == "" { + return "" + } + + switch s.Type { + case GitHub: + return GitHubBaseURL + s.Source + "/actions/runs/" + runID + default: + return "" + } +} diff --git a/pkg/source/source.go b/pkg/source/source.go new file mode 100644 index 0000000..749f8fa --- /dev/null +++ b/pkg/source/source.go @@ -0,0 +1,17 @@ +package source + +import ( + "github.com/jimeh/build-emacs-for-macos/pkg/commit" + "github.com/jimeh/build-emacs-for-macos/pkg/repository" +) + +type Source struct { + Ref string `yaml:"ref,omitempty"` + Repository *repository.Repository `yaml:"repository,omitempty"` + Commit *commit.Commit `yaml:"commit,omitempty"` + Tarball *Tarball `yaml:"tarball,omitempty"` +} + +type Tarball struct { + URL string `yaml:"url,omitempty"` +}