Skip to content
This repository has been archived by the owner on Nov 22, 2022. It is now read-only.

feat: add new release commands to manage GitLab releases #445

Merged
merged 15 commits into from
May 27, 2021
Prev Previous commit
Next Next commit
feat: release view command
  • Loading branch information
profclems committed May 25, 2021
commit 42a7d4c822a26955c25259ad4c9fdc1afc2413be
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/CHANGELOG.md

# GLab local config dir
/.glab-cli
.glab-cli
/test/testdata/.glab-cli

# Test binary, built with `go test -c`
Expand Down Expand Up @@ -45,4 +45,4 @@ test/testdata-*

coverage*
vendor
log.txt
log.txt.glab-cli
8 changes: 4 additions & 4 deletions commands/release/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
"github.com/xanzy/go-gitlab"
)

type CreateOpts struct {
type DeleteOpts struct {
ForceDelete bool
DeleteTag bool
TagName string
Expand All @@ -28,8 +28,8 @@ type CreateOpts struct {
Config func() (config.Config, error)
}

func NewCmdDelete(f *cmdutils.Factory, runE func(opts *CreateOpts) error) *cobra.Command {
opts := &CreateOpts{
func NewCmdDelete(f *cmdutils.Factory, runE func(opts *DeleteOpts) error) *cobra.Command {
opts := &DeleteOpts{
IO: f.IO,
Config: f.Config,
}
Expand Down Expand Up @@ -77,7 +77,7 @@ func NewCmdDelete(f *cmdutils.Factory, runE func(opts *CreateOpts) error) *cobra
return cmd
}

func deleteRun(opts *CreateOpts) error {
func deleteRun(opts *DeleteOpts) error {
client, err := opts.HTTPClient()
if err != nil {
return err
Expand Down
23 changes: 20 additions & 3 deletions commands/release/list/release_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@ func NewCmdReleaseList(f *cmdutils.Factory) *cobra.Command {
},
}
releaseListCmd.Flags().StringP("tag", "t", "", "Filter releases by tag <name>")
// deprecate in favour of the `release view` command
releaseListCmd.Flags().MarkDeprecated("tag", "use `glab release view <tag>` instead")
// make it hidden but still accessible
// TODO: completely remove before a major release (v2.0.0+)
releaseListCmd.Flags().MarkHidden("tag")
return releaseListCmd
}

func listReleases(cmd *cobra.Command, args []string) error {
c := factory.IO.Color()
l := &gitlab.ListReleasesOptions{}

tag, err := cmd.Flags().GetString("tag")
Expand All @@ -60,7 +64,15 @@ func listReleases(cmd *cobra.Command, args []string) error {

cfg, _ := factory.Config()
glamourStyle, _ := cfg.Get(repo.RepoHost(), "glamour_style")
fmt.Fprintln(factory.IO.StdOut, releaseutils.DisplayRelease(c, release, glamourStyle))
factory.IO.ResolveBackgroundColor(glamourStyle)

err = factory.IO.StartPager()
if err != nil {
return err
}
defer factory.IO.StopPager()

fmt.Fprintln(factory.IO.StdOut, releaseutils.DisplayRelease(factory.IO, release))
} else {
l.PerPage = 30

Expand All @@ -73,8 +85,13 @@ func listReleases(cmd *cobra.Command, args []string) error {
title.RepoName = repo.FullName()
title.Page = 0
title.CurrentPageTotal = len(releases)
err = factory.IO.StartPager()
if err != nil {
return err
}
defer factory.IO.StopPager()

fmt.Fprintf(factory.IO.StdOut, "%s\n%s\n", title.Describe(), releaseutils.DisplayAllReleases(c, releases, repo.FullName()))
fmt.Fprintf(factory.IO.StdOut, "%s\n%s\n", title.Describe(), releaseutils.DisplayAllReleases(factory.IO, releases, repo.FullName()))
}
return nil
}
2 changes: 2 additions & 0 deletions commands/release/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
releaseDeleteCmd "github.com/profclems/glab/commands/release/delete"
releaseListCmd "github.com/profclems/glab/commands/release/list"
releaseUploadCmd "github.com/profclems/glab/commands/release/upload"
releaseViewCmd "github.com/profclems/glab/commands/release/view"
"github.com/spf13/cobra"
)

Expand All @@ -22,6 +23,7 @@ func NewCmdRelease(f *cmdutils.Factory) *cobra.Command {
releaseCmd.AddCommand(releaseCreateCmd.NewCmdCreate(f, nil))
releaseCmd.AddCommand(releaseUploadCmd.NewCmdUpload(f, nil))
releaseCmd.AddCommand(releaseDeleteCmd.NewCmdDelete(f, nil))
releaseCmd.AddCommand(releaseViewCmd.NewCmdView(f, nil))

return releaseCmd
}
15 changes: 9 additions & 6 deletions commands/release/releaseutils/releaseutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (
"github.com/xanzy/go-gitlab"
)

func DisplayAllReleases(c *iostreams.ColorPalette, releases []*gitlab.Release, repoName string) string {
func DisplayAllReleases(io *iostreams.IOStreams, releases []*gitlab.Release, repoName string) string {
c := io.Color()
table := tableprinter.NewTablePrinter()
for _, r := range releases {
table.AddRow(r.Name, r.TagName, c.Gray(utils.TimeToPrettyTimeAgo(*r.CreatedAt)))
Expand All @@ -26,19 +27,21 @@ func DisplayAllReleases(c *iostreams.ColorPalette, releases []*gitlab.Release, r
}

func RenderReleaseAssertLinks(assets []*gitlab.ReleaseLink) string {
var assetsPrint string
if len(assets) == 0 {
return "There are no assets for this release"
}
t := tableprinter.NewTablePrinter()
for _, asset := range assets {
assetsPrint += asset.URL + "\n"
t.AddRow(asset.Name, asset.LinkType, asset.DirectAssetURL)
//assetsPrint += asset.DirectAssetURL + "\n"
}
return assetsPrint
return t.String()
}

func DisplayRelease(c *iostreams.ColorPalette, r *gitlab.Release, glamourStyle string) string {
func DisplayRelease(io *iostreams.IOStreams, r *gitlab.Release) string {
c := io.Color()
duration := utils.TimeToPrettyTimeAgo(*r.CreatedAt)
description, err := utils.RenderMarkdown(r.Description, glamourStyle)
description, err := utils.RenderMarkdown(r.Description, io.BackgroundColor())
if err != nil {
description = r.Description

Expand Down
130 changes: 130 additions & 0 deletions commands/release/view/view.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package view

import (
"fmt"
"github.com/MakeNowJust/heredoc"
"github.com/profclems/glab/commands/cmdutils"
"github.com/profclems/glab/commands/release/releaseutils"
"github.com/profclems/glab/internal/config"
"github.com/profclems/glab/internal/glinstance"
"github.com/profclems/glab/internal/glrepo"
"github.com/profclems/glab/pkg/iostreams"
"github.com/profclems/glab/pkg/utils"
"github.com/spf13/cobra"
"github.com/xanzy/go-gitlab"
)

type ViewOpts struct {
TagName string
OpenInBrowser bool

IO *iostreams.IOStreams
HTTPClient func() (*gitlab.Client, error)
BaseRepo func() (glrepo.Interface, error)
Config func() (config.Config, error)
}

func NewCmdView(f *cmdutils.Factory, runE func(opts *ViewOpts) error) *cobra.Command {
opts := &ViewOpts{
IO: f.IO,
Config: f.Config,
}

cmd := &cobra.Command{
Use: "view <tag>",
Short: "View information about a GitHub Release",
Long: heredoc.Docf(`View information about a GitHub Release.

Without an explicit tag name argument, the latest release in the project is shown.
`, "`"),
Example: heredoc.Doc(`
View the latest release of a GitLab repository
$ glab release view

View a release with specified tag name
$ glab release view v1.0.1
`),
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.HTTPClient = f.HttpClient
opts.BaseRepo = f.BaseRepo

if len(args) == 1 {
opts.TagName = args[0]
}

if runE != nil {
return runE(opts)
}

return deleteRun(opts)
},
}

cmd.Flags().BoolVarP(&opts.OpenInBrowser, "yes", "y", false, "Skip confirmation prompt")

return cmd
}

func deleteRun(opts *ViewOpts) error {
client, err := opts.HTTPClient()
if err != nil {
return err
}

repo, err := opts.BaseRepo()
if err != nil {
return err
}

cfg, _ := opts.Config()

var resp *gitlab.Response

if opts.TagName == "" {
tags, resp, err := client.Tags.ListTags(repo.FullName(), &gitlab.ListTagsOptions{
OrderBy: gitlab.String("updated"),
Sort: gitlab.String("desc"),
})
if err != nil && resp != nil && resp.StatusCode != 404 {
return cmdutils.WrapError(err, "could not fetch tag")
}
if len(tags) < 1 {
return cmdutils.WrapError(err, "no tags found. Create a new tag, push to GitLab and try this command again.")
}
opts.TagName = tags[0].Name
}

release, resp, err := client.Releases.GetRelease(repo.FullName(), opts.TagName)
if err != nil {
if resp != nil && (resp.StatusCode == 404 || resp.StatusCode == 403) {
return cmdutils.WrapError(err, "release does not exist.")
}
return cmdutils.WrapError(err, "failed to fetch release")
}

if opts.OpenInBrowser { //open in browser if --web flag is specified
url := fmt.Sprintf("%s://%s/%s/-/releases/%s",
glinstance.OverridableDefaultProtocol(), glinstance.OverridableDefault(),
repo.FullName(), release.TagName)

if opts.IO.IsOutputTTY() {
opts.IO.Logf("Opening %s in your browser.\n", release)
}

browser, _ := cfg.Get(repo.RepoHost(), "browser")
return utils.OpenInBrowser(url, browser)
}

glamourStyle, _ := cfg.Get(repo.RepoHost(), "glamour_style")
opts.IO.ResolveBackgroundColor(glamourStyle)

err = opts.IO.StartPager()
if err != nil {
return err
}
defer opts.IO.StopPager()

opts.IO.LogInfo(releaseutils.DisplayRelease(opts.IO, release))
return nil
}