mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-24 08:02:18 +02:00
Cli fix pipeline logs (#3913)
Co-authored-by: Thomas Anderson <127358482+zc-devs@users.noreply.github.com> Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
parent
7b7c83d040
commit
49c2029cad
@ -161,3 +161,47 @@ func ParseKeyPair(p []string) map[string]string {
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
/*
|
||||
ParseStep parses the step id form a string which may either be the step PID (step number) or a step name.
|
||||
These rules apply:
|
||||
|
||||
- Step ID take precedence over step name when searching for a match.
|
||||
- First match is used, when there are multiple steps with the same name.
|
||||
|
||||
Strictly speaking, this is not parsing, but a lookup.
|
||||
|
||||
TODO: Use PID instead of StepID
|
||||
*/
|
||||
func ParseStep(client woodpecker.Client, repoID, number int64, stepArg string) (stepID int64, err error) {
|
||||
pipeline, err := client.Pipeline(repoID, number)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
stepID, err = strconv.ParseInt(stepArg, 10, 64)
|
||||
// TODO: for 3.0 do "stepPID, err := strconv.ParseInt(stepArg, 10, 64)"
|
||||
if err == nil {
|
||||
return stepID, nil
|
||||
/*
|
||||
// TODO: for 3.0
|
||||
for _, wf := range pipeline.Workflows {
|
||||
for _, step := range wf.Children {
|
||||
if int64(step.PID) == stepPID {
|
||||
return step.ID, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
for _, wf := range pipeline.Workflows {
|
||||
for _, step := range wf.Children {
|
||||
if step.Name == stepArg {
|
||||
return step.ID, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0, fmt.Errorf("no step with number or name '%s' found", stepArg)
|
||||
}
|
||||
|
@ -17,18 +17,22 @@ package pipeline
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
||||
"github.com/urfave/cli/v3"
|
||||
|
||||
"go.woodpecker-ci.org/woodpecker/v2/cli/internal"
|
||||
"go.woodpecker-ci.org/woodpecker/v2/woodpecker-go/woodpecker"
|
||||
)
|
||||
|
||||
var pipelineLogsCmd = &cli.Command{
|
||||
Name: "logs",
|
||||
Usage: "show pipeline logs",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline] [stepID]",
|
||||
Action: pipelineLogs,
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline> [step-id|step-name]",
|
||||
// TODO: for v3.0 do `ArgsUsage: "<repo-id|repo-full-name> <pipeline> [step-number|step-name]",`
|
||||
Action: pipelineLogs,
|
||||
}
|
||||
|
||||
func pipelineLogs(ctx context.Context, c *cli.Command) error {
|
||||
@ -37,31 +41,73 @@ func pipelineLogs(ctx context.Context, c *cli.Command) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(repoIDOrFullName) == 0 {
|
||||
return fmt.Errorf("missing required argument repo-id / repo-full-name")
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid repo '%s': %w ", repoIDOrFullName, err)
|
||||
}
|
||||
|
||||
numberArgIndex := 1
|
||||
number, err := strconv.ParseInt(c.Args().Get(numberArgIndex), 10, 64)
|
||||
pipelineArg := c.Args().Get(1)
|
||||
if len(pipelineArg) == 0 {
|
||||
return fmt.Errorf("missing required argument pipeline")
|
||||
}
|
||||
number, err := strconv.ParseInt(pipelineArg, 10, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid pipeline '%s': %w", pipelineArg, err)
|
||||
}
|
||||
|
||||
stepArg := c.Args().Get(2) //nolint:mnd
|
||||
if len(stepArg) == 0 {
|
||||
return showPipelineLog(client, repoID, number)
|
||||
}
|
||||
|
||||
step, err := internal.ParseStep(client, repoID, number, stepArg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid step '%s': %w", stepArg, err)
|
||||
}
|
||||
return showStepLog(client, repoID, number, step)
|
||||
}
|
||||
|
||||
func showPipelineLog(client woodpecker.Client, repoID, number int64) error {
|
||||
pipeline, err := client.Pipeline(repoID, number)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stepArgIndex := 2
|
||||
step, err := strconv.ParseInt(c.Args().Get(stepArgIndex), 10, 64)
|
||||
tmpl, err := template.New("_").Parse(tmplPipelineLogs + "\n")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, workflow := range pipeline.Workflows {
|
||||
for _, step := range workflow.Children {
|
||||
if err := tmpl.Execute(os.Stdout, map[string]any{"workflow": workflow, "step": step}); err != nil {
|
||||
return err
|
||||
}
|
||||
err := showStepLog(client, repoID, number, step.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func showStepLog(client woodpecker.Client, repoID, number, step int64) error {
|
||||
logs, err := client.StepLogEntries(repoID, number, step)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, log := range logs {
|
||||
fmt.Print(string(log.Data))
|
||||
fmt.Println(string(log.Data))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// template for pipeline ps information.
|
||||
var tmplPipelineLogs = "\x1b[33m{{ .workflow.Name }} > {{ .step.Name }} (#{{ .step.PID }}):\x1b[0m"
|
||||
|
@ -16,6 +16,7 @@ package pipeline
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"text/template"
|
||||
@ -29,7 +30,7 @@ import (
|
||||
var pipelinePsCmd = &cli.Command{
|
||||
Name: "ps",
|
||||
Usage: "show pipeline steps",
|
||||
ArgsUsage: "<repo-id|repo-full-name> [pipeline]",
|
||||
ArgsUsage: "<repo-id|repo-full-name> <pipeline>",
|
||||
Action: pipelinePs,
|
||||
Flags: []cli.Flag{common.FormatFlag(tmplPipelinePs)},
|
||||
}
|
||||
@ -42,7 +43,7 @@ func pipelinePs(ctx context.Context, c *cli.Command) error {
|
||||
}
|
||||
repoID, err := internal.ParseRepo(client, repoIDOrFullName)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid repo '%s': %w", repoIDOrFullName, err)
|
||||
}
|
||||
|
||||
pipelineArg := c.Args().Get(1)
|
||||
@ -59,7 +60,7 @@ func pipelinePs(ctx context.Context, c *cli.Command) error {
|
||||
} else {
|
||||
number, err = strconv.ParseInt(pipelineArg, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("invalid pipeline '%s': %w", pipelineArg, err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,9 +74,9 @@ func pipelinePs(ctx context.Context, c *cli.Command) error {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, step := range pipeline.Workflows {
|
||||
for _, child := range step.Children {
|
||||
if err := tmpl.Execute(os.Stdout, child); err != nil {
|
||||
for _, workflow := range pipeline.Workflows {
|
||||
for _, step := range workflow.Children {
|
||||
if err := tmpl.Execute(os.Stdout, map[string]any{"workflow": workflow, "step": step}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -84,8 +85,11 @@ func pipelinePs(ctx context.Context, c *cli.Command) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Template for pipeline ps information.
|
||||
var tmplPipelinePs = "\x1b[33mStep #{{ .PID }} \x1b[0m" + `
|
||||
Step: {{ .Name }}
|
||||
State: {{ .State }}
|
||||
// template for pipeline ps information.
|
||||
var tmplPipelinePs = "\x1b[33m{{ .workflow.Name }} > {{ .step.Name }} (#{{ .step.PID }}):\x1b[0m" + `
|
||||
Step: {{ .step.Name }}
|
||||
Started: {{ .step.Started }}
|
||||
Stopped: {{ .step.Stopped }}
|
||||
Type: {{ .step.Type }}
|
||||
State: {{ .step.State }}
|
||||
`
|
||||
|
@ -345,9 +345,12 @@ Message: {{ .Message }}
|
||||
|
||||
show pipeline steps
|
||||
|
||||
**--format**="": format output (default: [33mStep #{{ .PID }} [0m
|
||||
Step: {{ .Name }}
|
||||
State: {{ .State }}
|
||||
**--format**="": format output (default: [33m{{ .workflow.Name }} > {{ .step.Name }} (#{{ .step.PID }}):[0m
|
||||
Step: {{ .step.Name }}
|
||||
Started: {{ .step.Started }}
|
||||
Stopped: {{ .step.Stopped }}
|
||||
Type: {{ .step.Type }}
|
||||
State: {{ .step.State }}
|
||||
)
|
||||
|
||||
### create
|
||||
|
Loading…
Reference in New Issue
Block a user