github.com/saucelabs/saucectl@v0.175.1/internal/cmd/artifacts/list.go (about) 1 package artifacts 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "os" 8 9 "github.com/jedib0t/go-pretty/v6/table" 10 "github.com/jedib0t/go-pretty/v6/text" 11 "github.com/saucelabs/saucectl/internal/artifacts" 12 cmds "github.com/saucelabs/saucectl/internal/cmd" 13 "github.com/saucelabs/saucectl/internal/http" 14 "github.com/saucelabs/saucectl/internal/segment" 15 "github.com/saucelabs/saucectl/internal/usage" 16 "github.com/spf13/cobra" 17 "golang.org/x/text/cases" 18 "golang.org/x/text/language" 19 ) 20 21 var defaultTableStyle = table.Style{ 22 Name: "saucy", 23 Box: table.BoxStyle{ 24 BottomLeft: "└", 25 BottomRight: "┘", 26 BottomSeparator: "", 27 EmptySeparator: text.RepeatAndTrim(" ", text.RuneCount("+")), 28 Left: "│", 29 LeftSeparator: "", 30 MiddleHorizontal: "─", 31 MiddleSeparator: "", 32 MiddleVertical: "", 33 PaddingLeft: " ", 34 PaddingRight: " ", 35 PageSeparator: "\n", 36 Right: "│", 37 RightSeparator: "", 38 TopLeft: "┌", 39 TopRight: "┐", 40 TopSeparator: "", 41 UnfinishedRow: " ...", 42 }, 43 Color: table.ColorOptionsDefault, 44 Format: table.FormatOptions{ 45 Footer: text.FormatDefault, 46 Header: text.FormatDefault, 47 Row: text.FormatDefault, 48 }, 49 HTML: table.DefaultHTMLOptions, 50 Options: table.Options{ 51 DrawBorder: true, 52 SeparateColumns: false, 53 SeparateFooter: true, 54 SeparateHeader: true, 55 SeparateRows: false, 56 }, 57 Title: table.TitleOptionsDefault, 58 } 59 60 func ListCommand() *cobra.Command { 61 var out string 62 63 cmd := &cobra.Command{ 64 Use: "list <jobID>", 65 Aliases: []string{ 66 "ls", 67 }, 68 Short: "Returns the list of artifacts for the specified job.", 69 SilenceUsage: true, 70 Args: func(cmd *cobra.Command, args []string) error { 71 if len(args) == 0 || args[0] == "" { 72 return errors.New("no job ID specified") 73 } 74 75 return nil 76 }, 77 PreRunE: func(cmd *cobra.Command, args []string) error { 78 err := http.CheckProxy() 79 if err != nil { 80 return fmt.Errorf("invalid HTTP_PROXY value") 81 } 82 83 tracker := segment.DefaultTracker 84 85 go func() { 86 tracker.Collect( 87 cases.Title(language.English).String(cmds.FullName(cmd)), 88 usage.Properties{}.SetFlags(cmd.Flags()), 89 ) 90 _ = tracker.Close() 91 }() 92 return nil 93 }, 94 RunE: func(cmd *cobra.Command, args []string) error { 95 return list(args[0], out) 96 }, 97 } 98 flags := cmd.PersistentFlags() 99 flags.StringVarP(&out, "out", "o", "text", "Output format to the console. Options: text, json.") 100 101 return cmd 102 } 103 104 func list(jobID, outputFormat string) error { 105 lst, err := artifactSvc.List(jobID) 106 if err != nil { 107 return fmt.Errorf("failed to get artifacts list: %w", err) 108 } 109 110 switch outputFormat { 111 case "json": 112 if err := renderJSON(lst); err != nil { 113 return fmt.Errorf("failed to render output: %w", err) 114 } 115 case "text": 116 renderTable(lst) 117 default: 118 return errors.New("unknown output format") 119 } 120 121 return nil 122 } 123 124 func renderTable(lst artifacts.List) { 125 if len(lst.Items) == 0 { 126 println("No artifacts for this job.") 127 return 128 } 129 130 t := table.NewWriter() 131 t.SetStyle(defaultTableStyle) 132 t.SuppressEmptyColumns() 133 134 t.AppendHeader(table.Row{"Items"}) 135 t.SetColumnConfigs([]table.ColumnConfig{ 136 { 137 Name: "Items", 138 }, 139 }) 140 141 for _, item := range lst.Items { 142 // the order of values must match the order of the header 143 t.AppendRow(table.Row{item}) 144 } 145 t.SuppressEmptyColumns() 146 147 fmt.Println(t.Render()) 148 } 149 150 func renderJSON(val any) error { 151 return json.NewEncoder(os.Stdout).Encode(val) 152 }