Skip to content

Commit b81079a

Browse files
chmouelsavitaashture
authored andcommitted
Add small snippet of the error log in status
We detect if there is an error and add a small snippet into the checks. Due of git provider API limitation, this will only show last five lines of the first error task Signed-off-by: Chmouel Boudjnah <[email protected]>
1 parent 44c1781 commit b81079a

File tree

18 files changed

+318
-58
lines changed

18 files changed

+318
-58
lines changed

config/302-pac-configmap.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ data:
3333
# PipelineRun on the Tekton dashboard
3434
tekton-dashboard-url: ""
3535

36+
# Enable or disable the feature to show a log snippet of the failed task when there is
37+
# an error in a Pipeline
38+
#
39+
# It will show the last 3 lines of the first container of the first task
40+
# that has error in the pipeline.
41+
#
42+
# you may want to disable this if you think your pipeline may leak some value
43+
error-log-snippet: "true"
44+
45+
# alpha feature: disabled by default
46+
#
3647
# Enable or disable the inspection of container logs to detect error message
3748
# and expose them as annotations on Pull Request. Only Github apps is supported
3849
#

docs/content/docs/guide/statuses.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ When the pipeline finishes, the status will be added in the GitHub Check tabs
1010
with a short recap of how long each task of your pipeline took and the output of
1111
`tkn pr describe`.
1212

13+
## Log error snippet
14+
15+
When we detect an error in one of the task of the Pipeline we will show a small
16+
snippet of the last 3 lines in the task breakdown.
17+
18+
This will only show the output of the first task that failed (due of the limitation of the API not allowing to have many characters).
19+
20+
![log snippet](/images/snippet-failure-message.png)
21+
1322
### Annotations (alpha feature)
1423

1524
If you set `error-detection-from-container-logs` to `true` in the

docs/content/docs/install/settings.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,29 +72,39 @@ There is a few things you can configure through the config map
7272
for your repository and create a Repository CR.
7373

7474
This feature is disabled by default and is only supported with GitHub App.
75-
75+
7676
****NOTE****: If you have a GitHub App already setup then verify if `Repository` event is subscribed.
7777

7878
* `auto-configure-repo-namespace-template`
7979

8080
If `auto-configure-new-github-repo` is enabled then you can provide a template for generating the namespace for your new repository.
8181
By default, the namespace will be generated using this format `{{repo_name}}-pipelines`.
82-
82+
8383
You can override the default using the following variables
84-
84+
8585
* `{{repo_owner}}`: The repository owner.
8686
* `{{repo_name}}`: The repository name.
87-
87+
8888
for example. if the template is defined as `{{repo_owner}}-{{repo_name}}-ci`, then the namespace generated for repository
8989
`https://github.com/owner/repo` will be `owner-repo-ci`
9090

91+
* `error-log-snippet`
92+
93+
Enable or disable the feature to show a log snippet of the failed task when there is
94+
an error in a Pipeline
95+
96+
It will show the last 3 lines of the first container of the first task
97+
that has error in the pipeline.
98+
99+
***NOTE***: You may want to disable this if you think your pipeline may leak some value
100+
91101
## Pipelines-As-Code Info
92102

93103
There are a settings exposed through a config map which any authenticated user can access to know about
94104
Pipeline as Code.
95105

96106
* `version`
97-
107+
98108
The version of Pipelines As Code installed.
99109

100110
* `controller-url`
116 KB
Loading

pkg/apis/pipelinesascode/v1alpha1/types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ type RepositoryRunStatus struct {
6161
}
6262

6363
type TaskInfos struct {
64-
Reason string
65-
LogSnippet string
64+
Name string
65+
Message string
66+
LogSnippet string
67+
Reason string
68+
CompletionTime *metav1.Time
6669
}
6770

6871
// RepositorySpec is the spec of a repo

pkg/cli/status/status.go

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,24 @@ package status
33
import (
44
"context"
55
"regexp"
6-
"strings"
76

87
"github.com/google/go-github/v47/github"
98
pacv1alpha1 "github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
109
"github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction"
10+
kstatus "github.com/openshift-pipelines/pipelines-as-code/pkg/kubeinteraction/status"
1111
"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
1212
sortrepostatus "github.com/openshift-pipelines/pipelines-as-code/pkg/sort"
1313
tektonv1beta1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
1414
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1515
)
1616

17-
var reasonMessageReplacementRegexp = regexp.MustCompile(`\(image: .*`)
18-
1917
// snatched from prow
2018
// https://github.com/kubernetes/test-infra/blob/3c8cbed65c421670a7d37239b8ffceb91e0eb16b/prow/spyglass/lenses/buildlog/lens.go#L95
2119
var (
2220
ErorrRE = regexp.MustCompile(`timed out|ERROR:|(FAIL|Failure \[)\b|panic\b|^E\d{4} \d\d:\d\d:\d\d\.\d\d\d]`)
2321
defaultNumLinesOfLogsInContainersToGrabForErr = int64(10)
2422
)
2523

26-
// CollectTaskInfos collects all tasks information we are interested in.
27-
// TODO: move to a better package than cli since used by watcher too
28-
func CollectTaskInfos(ctx context.Context, cs *params.Run, pr tektonv1beta1.PipelineRun, numLines int64) map[string]pacv1alpha1.TaskInfos {
29-
failureReasons := map[string]pacv1alpha1.TaskInfos{}
30-
kinteract, _ := kubeinteraction.NewKubernetesInteraction(cs)
31-
for _, task := range pr.Status.TaskRuns {
32-
if task.Status != nil && len(task.Status.Conditions) > 0 && task.Status.Conditions[0].Reason == tektonv1beta1.PipelineRunReasonFailed.String() {
33-
ti := pacv1alpha1.TaskInfos{
34-
Reason: reasonMessageReplacementRegexp.ReplaceAllString(task.Status.Conditions[0].Message, ""),
35-
}
36-
37-
if kinteract != nil {
38-
for _, step := range task.Status.Steps {
39-
if step.Terminated != nil && step.Terminated.ExitCode != 0 {
40-
log, err := kinteract.GetPodLogs(ctx, pr.GetNamespace(), task.Status.PodName, step.ContainerName, numLines)
41-
if err != nil {
42-
cs.Clients.Log.Errorf("cannot get pod logs: %w", err)
43-
continue
44-
}
45-
// see if a pattern match from errRe
46-
ti.LogSnippet = strings.TrimSpace(log)
47-
}
48-
}
49-
}
50-
failureReasons[task.PipelineTaskName] = ti
51-
}
52-
}
53-
return failureReasons
54-
}
55-
5624
// RepositoryRunStatusRemoveSameSHA remove an existing status with the same
5725
// SHA. This would come from repo pipelinerun_status. We don't want the doublons
5826
// and we rather use the ones from the live PR on cluster.
@@ -68,7 +36,8 @@ func RepositoryRunStatusRemoveSameSHA(rs []pacv1alpha1.RepositoryRunStatus, live
6836
}
6937

7038
func convertPrStatusToRepositoryStatus(ctx context.Context, cs *params.Run, pr tektonv1beta1.PipelineRun, logurl string) pacv1alpha1.RepositoryRunStatus {
71-
failurereasons := CollectTaskInfos(ctx, cs, pr, defaultNumLinesOfLogsInContainersToGrabForErr)
39+
kinteract, _ := kubeinteraction.NewKubernetesInteraction(cs)
40+
failurereasons := kstatus.CollectFailedTasksLogSnippet(ctx, cs, kinteract, &pr, defaultNumLinesOfLogsInContainersToGrabForErr)
7241
prSHA := pr.GetLabels()["pipelinesascode.tekton.dev/sha"]
7342
return pacv1alpha1.RepositoryRunStatus{
7443
Status: pr.Status.Status,

pkg/cmd/tknpac/describe/describe_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ func TestDescribe(t *testing.T) {
166166
Reason: tektonv1beta1.PipelineRunReasonFailed.String(),
167167
LogSnippet: "Error error miss robinson",
168168
},
169+
170+
"task2": {
171+
Message: "I was sleeping and I forgot to wake up",
172+
Reason: tektonv1beta1.PipelineRunReasonTimedOut.String(),
173+
},
169174
},
170175
PipelineRunName: "pipelinerun1",
171176
LogURL: github.String("https://everywhere.anwywhere"),

pkg/cmd/tknpac/describe/templates/describe.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424

2525
{{ $.ColorScheme.Underline "Failures:" }}
2626
{{ range $taskName, $task := $status.CollectedTaskInfos }}
27-
{{- $.ColorScheme.Red "•" }} {{ $taskName }}: {{ $task.Reason }}
28-
{{ formatError $.ColorScheme $task.LogSnippet }}
27+
{{ $.ColorScheme.Bold "•" }} {{ $taskName }}:{{if ne $task.Reason "Failed"}} {{$.ColorScheme.Dimmed $task.Reason}}{{end}}
28+
{{ if eq $task.LogSnippet ""}} {{ $task.Message }}{{ else }}{{ formatError $.ColorScheme $task.LogSnippet }}{{end}}
2929
{{ end }}
3030
{{- end }}
3131
{{- if (gt (len .Statuses) 1) }}

pkg/cmd/tknpac/describe/testdata/TestDescribe-collect_failures.golden

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ StartTime: 16 minutes ago
1212
Duration: 1 minute
1313

1414
Failures:
15-
• task1: Failed
15+
16+
• task1:
1617
Error error miss robinson
1718

19+
• task2: PipelineRunTimeout
20+
I was sleeping and I forgot to wake up
21+

pkg/kubeinteraction/kubeinteraction.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Interface interface {
2121
CreateBasicAuthSecret(context.Context, *zap.SugaredLogger, *info.Event, string, string) error
2222
DeleteBasicAuthSecret(context.Context, *zap.SugaredLogger, string, string) error
2323
GetSecret(context.Context, GetSecretOpt) (string, error)
24+
GetPodLogs(context.Context, string, string, string, int64) (string, error)
2425
}
2526

2627
type Interaction struct {

0 commit comments

Comments
 (0)