func NewCmdStatus()

in commands/ci/status/status.go [21:187]


func NewCmdStatus(f *cmdutils.Factory) *cobra.Command {
	pipelineStatusCmd := &cobra.Command{
		Use:     "status [flags]",
		Short:   `View a running CI/CD pipeline on current or other branch specified.`,
		Aliases: []string{"stats"},
		Example: heredoc.Doc(`
			$ glab ci status --live

			# A more compact view
			$ glab ci status --compact

			# Get the pipeline for the main branch
			$ glab ci status --branch=main

			# Get the pipeline for the current branch
			$ glab ci status
		`),
		Long: ``,
		Args: cobra.ExactArgs(0),
		RunE: func(cmd *cobra.Command, args []string) error {
			var err error
			c := f.IO.Color()

			apiClient, err := f.HttpClient()
			if err != nil {
				return err
			}

			branch, _ := cmd.Flags().GetString("branch")
			live, _ := cmd.Flags().GetBool("live")
			compact, _ := cmd.Flags().GetBool("compact")

			if branch == "" {
				branch, err = git.CurrentBranch()
				if err != nil {
					return err
				}
				dbg.Debug("Current branch:", branch)
			}

			var repo glrepo.Interface
			branchConfig := git.ReadBranchConfig(branch)
			if branchConfig.RemoteName == "" {
				repo, err = f.BaseRepo()
				if err != nil {
					return err
				}
			} else {
				remotes, err := f.Remotes()
				if err != nil {
					return err
				}
				repo, err = remotes.FindByName(branchConfig.RemoteName)
				if err != nil {
					redCheck := c.Red("x")
					fmt.Fprintf(f.IO.StdOut, "%s Remote '%s' for branch '%s' is gone.\n", redCheck, branchConfig.RemoteName, branch)
					return err
				}
			}
			repoName := repo.FullName()
			dbg.Debug("Repository:", repoName)

			runningPipeline, err := api.GetLatestPipeline(apiClient, repoName, branch)
			if err != nil {
				redCheck := c.Red("✘")
				fmt.Fprintf(f.IO.StdOut, "%s No pipelines running or available on branch: %s\n", redCheck, branch)
				return err
			}

			writer := uilive.New()

			// start listening for updates and render
			writer.Start()
			defer writer.Stop()
			for {
				jobs, err := api.GetPipelineJobs(apiClient, runningPipeline.ID, repoName)
				if err != nil {
					return err
				}
				for _, job := range jobs {
					end := time.Now()
					if job.FinishedAt != nil {
						end = *job.FinishedAt
					}
					var duration string
					if job.StartedAt != nil {
						duration = utils.FmtDuration(end.Sub(*job.StartedAt))
					} else {
						duration = "not started"
					}
					var status string
					switch s := job.Status; s {
					case "failed":
						if job.AllowFailure {
							status = c.Yellow(s)
						} else {
							status = c.Red(s)
						}
					case "success":
						status = c.Green(s)
					default:
						status = c.Gray(s)
					}
					// fmt.Println(job.Tag)
					if compact {
						fmt.Fprintf(writer, "(%s) • %s [%s]\n", status, job.Name, job.Stage)
					} else {
						fmt.Fprintf(writer, "(%s) • %s\t%s\t\t%s\n", status, c.Gray(duration), job.Stage, job.Name)
					}
				}

				if !compact {
					fmt.Fprintf(writer.Newline(), "\n%s\n", runningPipeline.WebURL)
					fmt.Fprintf(writer.Newline(), "SHA: %s\n", runningPipeline.SHA)
				}
				fmt.Fprintf(writer.Newline(), "Pipeline state: %s\n\n", runningPipeline.Status)

				if (runningPipeline.Status == "pending" || runningPipeline.Status == "running") && live {
					runningPipeline, err = api.GetLatestPipeline(apiClient, repoName, branch)
					if err != nil {
						return err
					}
				} else if f.IO.IsInputTTY() && f.IO.PromptEnabled() {
					prompt := &survey.Select{
						Message: "Choose an action:",
						Options: []string{"View logs", "Retry", "Exit"},
						Default: "Exit",
					}
					var answer string
					_ = survey.AskOne(prompt, &answer)
					if answer == "View logs" {
						return ciutils.TraceJob(&ciutils.JobInputs{
							Branch: branch,
						}, &ciutils.JobOptions{
							Repo:      repo,
							ApiClient: apiClient,
							IO:        f.IO,
						})
					} else if answer == "Retry" {
						_, err = api.RetryPipeline(apiClient, runningPipeline.ID, repoName)
						if err != nil {
							return err
						}
						runningPipeline, err = api.GetLatestPipeline(apiClient, repoName, branch)
						if err != nil {
							return err
						}
					} else {
						break
					}
				} else {
					break
				}
			}
			if runningPipeline.Status == "failed" {
				return cmdutils.SilentError
			}
			return nil
		},
	}

	pipelineStatusCmd.Flags().BoolP("live", "l", false, "Show status in real time until the pipeline ends.")
	pipelineStatusCmd.Flags().BoolP("compact", "c", false, "Show status in compact format.")
	pipelineStatusCmd.Flags().StringP("branch", "b", "", "Check pipeline status for a branch. (default current branch)")

	return pipelineStatusCmd
}