github.com/abdfnx/gh-api@v0.0.0-20210414084727-f5432eec23b8/pkg/cmd/run/list/list.go (about)

     1  package list
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"github.com/abdfnx/gh-api/api"
     8  	"github.com/abdfnx/gh-api/internal/ghrepo"
     9  	"github.com/abdfnx/gh-api/pkg/cmd/run/shared"
    10  	workflowShared "github.com/abdfnx/gh-api/pkg/cmd/workflow/shared"
    11  	"github.com/abdfnx/gh-api/pkg/cmdutil"
    12  	"github.com/abdfnx/gh-api/pkg/iostreams"
    13  	"github.com/abdfnx/gh-api/utils"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  const (
    18  	defaultLimit = 10
    19  )
    20  
    21  type ListOptions struct {
    22  	IO         *iostreams.IOStreams
    23  	HttpClient func() (*http.Client, error)
    24  	BaseRepo   func() (ghrepo.Interface, error)
    25  
    26  	PlainOutput bool
    27  
    28  	Limit            int
    29  	WorkflowSelector string
    30  }
    31  
    32  func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
    33  	opts := &ListOptions{
    34  		IO:         f.IOStreams,
    35  		HttpClient: f.HttpClient,
    36  	}
    37  
    38  	cmd := &cobra.Command{
    39  		Use:    "list",
    40  		Short:  "List recent workflow runs",
    41  		Args:   cobra.NoArgs,
    42  		Hidden: true,
    43  		RunE: func(cmd *cobra.Command, args []string) error {
    44  			// support `-R, --repo` override
    45  			opts.BaseRepo = f.BaseRepo
    46  
    47  			terminal := opts.IO.IsStdoutTTY() && opts.IO.IsStdinTTY()
    48  			opts.PlainOutput = !terminal
    49  
    50  			if opts.Limit < 1 {
    51  				return &cmdutil.FlagError{Err: fmt.Errorf("invalid limit: %v", opts.Limit)}
    52  			}
    53  
    54  			if runF != nil {
    55  				return runF(opts)
    56  			}
    57  
    58  			return listRun(opts)
    59  		},
    60  	}
    61  
    62  	cmd.Flags().IntVarP(&opts.Limit, "limit", "L", defaultLimit, "Maximum number of runs to fetch")
    63  	cmd.Flags().StringVarP(&opts.WorkflowSelector, "workflow", "w", "", "Filter runs by workflow")
    64  
    65  	return cmd
    66  }
    67  
    68  func listRun(opts *ListOptions) error {
    69  	baseRepo, err := opts.BaseRepo()
    70  	if err != nil {
    71  		return fmt.Errorf("failed to determine base repo: %w", err)
    72  	}
    73  
    74  	c, err := opts.HttpClient()
    75  	if err != nil {
    76  		return fmt.Errorf("failed to create http client: %w", err)
    77  	}
    78  	client := api.NewClientFromHTTP(c)
    79  
    80  	var runs []shared.Run
    81  	var workflow *workflowShared.Workflow
    82  
    83  	opts.IO.StartProgressIndicator()
    84  	if opts.WorkflowSelector != "" {
    85  		states := []workflowShared.WorkflowState{workflowShared.Active}
    86  		workflow, err = workflowShared.ResolveWorkflow(
    87  			opts.IO, client, baseRepo, false, opts.WorkflowSelector, states)
    88  		if err == nil {
    89  			runs, err = shared.GetRunsByWorkflow(client, baseRepo, opts.Limit, workflow.ID)
    90  		}
    91  	} else {
    92  		runs, err = shared.GetRuns(client, baseRepo, opts.Limit)
    93  	}
    94  	opts.IO.StopProgressIndicator()
    95  	if err != nil {
    96  		return fmt.Errorf("failed to get runs: %w", err)
    97  	}
    98  
    99  	tp := utils.NewTablePrinter(opts.IO)
   100  
   101  	cs := opts.IO.ColorScheme()
   102  
   103  	if len(runs) == 0 {
   104  		if !opts.PlainOutput {
   105  			fmt.Fprintln(opts.IO.ErrOut, "No runs found")
   106  		}
   107  		return nil
   108  	}
   109  
   110  	out := opts.IO.Out
   111  
   112  	for _, run := range runs {
   113  		if opts.PlainOutput {
   114  			tp.AddField(string(run.Status), nil, nil)
   115  			tp.AddField(string(run.Conclusion), nil, nil)
   116  		} else {
   117  			symbol, symbolColor := shared.Symbol(cs, run.Status, run.Conclusion)
   118  			tp.AddField(symbol, nil, symbolColor)
   119  		}
   120  
   121  		tp.AddField(run.CommitMsg(), nil, cs.Bold)
   122  
   123  		tp.AddField(run.Name, nil, nil)
   124  		tp.AddField(run.HeadBranch, nil, cs.Bold)
   125  		tp.AddField(string(run.Event), nil, nil)
   126  
   127  		if opts.PlainOutput {
   128  			elapsed := run.UpdatedAt.Sub(run.CreatedAt)
   129  			if elapsed < 0 {
   130  				elapsed = 0
   131  			}
   132  			tp.AddField(elapsed.String(), nil, nil)
   133  		}
   134  
   135  		tp.AddField(fmt.Sprintf("%d", run.ID), nil, cs.Cyan)
   136  
   137  		tp.EndRow()
   138  	}
   139  
   140  	err = tp.Render()
   141  	if err != nil {
   142  		return err
   143  	}
   144  
   145  	if !opts.PlainOutput {
   146  		fmt.Fprintln(out)
   147  		fmt.Fprintln(out, "For details on a run, try: gh run view <run-id>")
   148  	}
   149  
   150  	return nil
   151  }