github.com/gfleury/gobbs@v0.0.0-20200831213239-44ca2b94c1a1/pullrequests/info.go (about)

     1  package pullrequests
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"net"
     8  	"net/http"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/gfleury/gobbs/common"
    13  	"github.com/gfleury/gobbs/common/log"
    14  
    15  	bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  // Info is the cmd implementation for Merging Pull Requests
    20  var Info = &cobra.Command{
    21  	Use:     "info pullRequestID",
    22  	Aliases: []string{"inf"},
    23  	Short:   "Info pull requests for repository",
    24  	Args:    cobra.MinimumNArgs(1),
    25  	RunE: func(cmd *cobra.Command, args []string) error {
    26  		prID, err := strconv.Atoi(args[0])
    27  		if err != nil {
    28  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
    29  			return err
    30  		}
    31  
    32  		apiClient, cancel, err := common.APIClient(cmd)
    33  		defer cancel()
    34  
    35  		if err != nil {
    36  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
    37  			return err
    38  		}
    39  
    40  		stashInfo := cmd.Context().Value(common.StashInfoKey).(*common.StashInfo)
    41  		err = mustHaveProjectRepo(stashInfo)
    42  		if err != nil {
    43  			return err
    44  		}
    45  
    46  		response, err := apiClient.DefaultApi.GetPullRequest(*stashInfo.Project(), *stashInfo.Repo(), prID)
    47  
    48  		if netError, ok := err.(net.Error); (!ok || (ok && !netError.Timeout())) &&
    49  			!errors.Is(err, context.Canceled) &&
    50  			!errors.Is(err, context.DeadlineExceeded) &&
    51  			response != nil && response.Response != nil &&
    52  			response.Response.StatusCode >= http.StatusMultipleChoices {
    53  			common.PrintApiError(response.Values)
    54  			return err
    55  		} else if err != nil {
    56  			cmd.SilenceUsage = true
    57  			return err
    58  		}
    59  
    60  		if response.StatusCode == http.StatusNoContent {
    61  			log.Infof("Pull request ID: %v sucessfully GOT.", prID)
    62  		}
    63  
    64  		pr, err := bitbucketv1.GetPullRequestResponse(response)
    65  		if err != nil {
    66  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
    67  			return err
    68  		}
    69  
    70  		// Get Build Status
    71  		apiClient, cancel, err = common.APIClient(cmd)
    72  		defer cancel()
    73  
    74  		if err != nil {
    75  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
    76  			return err
    77  		}
    78  
    79  		response, err = apiClient.DefaultApi.GetCommitBuildStatuses(pr.FromRef.LatestCommit)
    80  
    81  		if netError, ok := err.(net.Error); (!ok || (ok && !netError.Timeout())) &&
    82  			!errors.Is(err, context.Canceled) &&
    83  			!errors.Is(err, context.DeadlineExceeded) &&
    84  			response != nil && response.Response != nil &&
    85  			response.Response.StatusCode >= http.StatusMultipleChoices {
    86  			common.PrintApiError(response.Values)
    87  			cmd.SilenceUsage = true
    88  			log.Debugf(err.Error())
    89  			return fmt.Errorf("Unable to process request, API Error")
    90  		} else if err != nil {
    91  			cmd.SilenceUsage = true
    92  			return err
    93  		}
    94  
    95  		if response.StatusCode == http.StatusNoContent {
    96  			log.Infof("Build Status for commit ID: %v sucessfully GOT.", pr.FromRef.LatestCommit)
    97  		}
    98  
    99  		buildStatuses, err := bitbucketv1.GetBuildStatusesResponse(response)
   100  		if err != nil {
   101  			log.Critical("Argument must be a pull request ID. Err: %s", err.Error())
   102  			return err
   103  		}
   104  
   105  		header := []string{"ID", "State", "Updated", "Builds", "Tasks Resolv. / Done", "Short Desc.", "Reviewers"}
   106  		table := common.Table(header)
   107  
   108  		table.Append([]string{
   109  			fmt.Sprintf("%d", pr.ID),
   110  			pr.State,
   111  			fmt.Sprint(time.Unix(pr.UpdatedDate/1000, 0).Format("2006-01-02T15:04:05-0700")),
   112  			func() (r string) {
   113  				for _, buildStatus := range buildStatuses {
   114  					r = fmt.Sprintf("%sName: %s\n\tState: %s\n\tURL: %s\n\tDesc.:  %s\n\tAdded: %s\n",
   115  						r,
   116  						buildStatus.Name,
   117  						buildStatus.State,
   118  						buildStatus.Url,
   119  						buildStatus.Description,
   120  						time.Unix(buildStatus.DateAdded/1000, 0).Format("2006-01-02T15:04:05-0700"))
   121  				}
   122  				return
   123  			}(),
   124  			fmt.Sprintf("%d / %d", pr.Properties.OpenTaskCount, pr.Properties.ResolvedTaskCount),
   125  			fmt.Sprintf("[%s -> %s] %s", pr.FromRef.DisplayID, pr.ToRef.DisplayID, pr.Title),
   126  			func() (r string) {
   127  				for _, reviewer := range pr.Reviewers {
   128  					r = fmt.Sprintf("%s%s %s\n", r, reviewer.User.Name,
   129  						func() string {
   130  							if reviewer.Approved {
   131  								return "(A)"
   132  							}
   133  							return "( )"
   134  						}())
   135  				}
   136  				return
   137  			}(),
   138  		})
   139  		table.Render()
   140  
   141  		return nil
   142  	},
   143  }