Skip to content

Commit

Permalink
Use displayName if set for showing task status
Browse files Browse the repository at this point in the history
The displayName field has been introduced since Tekton Pipeline 0.47.x, use this
when showing the task breakdown status.

Signed-off-by: Chmouel Boudjnah <chmouel@redhat.com>
  • Loading branch information
chmouel committed Sep 5, 2023
1 parent cd017c5 commit bb48c6e
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 29 deletions.
7 changes: 7 additions & 0 deletions .tekton/linter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ spec:
workspace: source

- name: generate-release-yaml
displayName: "Generate release.yaml"
runAfter:
- fetchit
taskSpec:
Expand All @@ -50,6 +51,7 @@ spec:
workspace: source

- name: gitlint
displayName: "Git commit linter"
runAfter:
- fetchit
workspaces:
Expand All @@ -67,6 +69,7 @@ spec:
gitlint --commit "$(git log --format=format:%H --no-merges -1)"
- name: yamllint
generateName: "YAML Linter"
runAfter:
- generate-release-yaml
taskSpec:
Expand All @@ -84,6 +87,7 @@ spec:
workspace: source

- name: pylint
generateName: "Python Linter"
runAfter:
- fetchit
taskSpec:
Expand All @@ -100,6 +104,7 @@ spec:
workspace: source

- name: black
generateName: "Python Formatter check"
runAfter:
- pylint
taskSpec:
Expand All @@ -116,6 +121,7 @@ spec:
workspace: source

- name: markdownlint
generateName: "Markdown Linter"
runAfter:
- fetchit
taskSpec:
Expand All @@ -132,6 +138,7 @@ spec:
workspace: source

- name: vale
generateName: "Spelling and Grammar"
runAfter:
- fetchit
taskSpec:
Expand Down
14 changes: 10 additions & 4 deletions docs/content/docs/guide/statuses.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
title: PipelineRun status
weight: 6
---

# Status

## GitHub apps

After the pipeline has finished, its status will be shown in the GitHub Check
tabs, along with a concise overview of the duration of each task in the
pipeline. If any step fails, a small portion of the log from that step will
After the `PipelineRun` has finished, its status will be
shown in the GitHub Check tabs, along with a concise overview
of the status the name and the duration of each task in the pipeline. If the task has a
[displayName](https://tekton.dev/docs/pipelines/tasks/#specifying-a-display-name)
it will use it as the description of the task or otherwise just the task
name.

If any step fails, a small portion of the log from that step will
also be included in the output.

In case an error is encountered while creating the `PipelineRun` on the cluster,
Expand Down Expand Up @@ -104,7 +110,7 @@ NAME URL
pipelines-as-code-ci https://github.com/openshift-pipelines/pipelines-as-code pipelines-as-code-ci True Succeeded 59m 56m
```

Using the tkn pac describe command from the [cli](../cli/) you can easily view
Using the tkn pac describe command from the [cli](../cli/) you can easily view
all of the statuses of the PipelineRuns associated with your repository, as
well as their metadata.

Expand Down
1 change: 1 addition & 0 deletions pkg/apis/pipelinesascode/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type TaskInfos struct {
Message string
LogSnippet string
Reason string
DisplayName string
CompletionTime *metav1.Time
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/cmd/tknpac/describe/describe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ func TestDescribe(t *testing.T) {
},
CollectedTaskInfos: &map[string]v1alpha1.TaskInfos{
"task1": {
Reason: tektonv1.PipelineRunReasonFailed.String(),
LogSnippet: "Error error miss robinson",
Reason: tektonv1.PipelineRunReasonFailed.String(),
DisplayName: "And here's to you, Mrs. Robinson",
LogSnippet: "We'd like to help you learn to help yourself",
},

"task2": {
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/tknpac/describe/templates/describe.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

{{ $.ColorScheme.Underline "Failures:" }}
{{ range $taskName, $task := $status.CollectedTaskInfos }}
{{ $.ColorScheme.Bold "•" }} {{ $taskName }}:{{if ne $task.Reason "Failed"}} {{$.ColorScheme.Dimmed $task.Reason}}{{end}}
{{ $.ColorScheme.Bold "•" }} {{if ne $task.DisplayName ""}}{{ $task.DisplayName }}{{ else }}{{ $taskName }}{{ end }}:{{if ne $task.Reason "Failed"}} {{$.ColorScheme.Dimmed $task.Reason}}{{end}}
{{ if eq $task.LogSnippet ""}} {{ $task.Message }}{{ else }}{{ formatError $.ColorScheme $task.LogSnippet }}{{end}}
{{ end }}
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ Duration: 1 minute

Failures:

task1:
Error error miss robinson
And here's to you, Mrs. Robinson:
We'd like to help you learn to help yourself

• task2: PipelineRunTimeout
I was sleeping and I forgot to wake up
Expand Down
13 changes: 13 additions & 0 deletions pkg/kubeinteraction/status/task_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ func GetStatusFromTaskStatusOrFromAsking(ctx context.Context, pr *tektonv1.Pipel
run.Clients.Log.Warnf("cannot get taskrun status pr %s ns: %s err: %w", pr.GetName(), pr.GetNamespace(), err)
continue
}
if ts == nil {
run.Clients.Log.Warnf("cannot get taskrun status pr %s ns: %s, ts come back nil?", pr.GetName(), pr.GetNamespace(), err)
continue
}
// search in taskSpecs if there is a displayName for that status
if pr.Spec.PipelineSpec != nil && pr.Spec.PipelineSpec.Tasks != nil {
for _, taskSpec := range pr.Spec.PipelineSpec.Tasks {
if ts.TaskSpec != nil && taskSpec.Name == cr.PipelineTaskName {
ts.TaskSpec.DisplayName = taskSpec.DisplayName
}
}
}
trStatus[cr.Name] = &tektonv1.PipelineRunTaskRunStatus{
PipelineTaskName: cr.PipelineTaskName,
Status: ts,
Expand Down Expand Up @@ -77,6 +89,7 @@ func CollectFailedTasksLogSnippet(ctx context.Context, cs *params.Run, kinteract
Message: reasonMessageReplacementRegexp.ReplaceAllString(task.Status.Conditions[0].Message, ""),
CompletionTime: task.Status.CompletionTime,
Reason: task.Status.Conditions[0].Reason,
DisplayName: task.Status.TaskSpec.DisplayName,
}
if ti.Reason == "TaskRunValidationFailed" || ti.Reason == tektonv1.TaskRunReasonCancelled.String() || ti.Reason == tektonv1.TaskRunReasonTimedOut.String() || ti.Reason == tektonv1.TaskRunReasonImagePullFailed.String() {
failureReasons[task.PipelineTaskName] = ti
Expand Down
100 changes: 92 additions & 8 deletions pkg/kubeinteraction/status/task_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ func TestCollectFailedTasksLogSnippet(t *testing.T) {
clock := clockwork.NewFakeClock()

tests := []struct {
name string
message, status string
wantFailure int
podOutput string
name, displayName string
message, status string
wantFailure int
podOutput string
}{
{
name: "no failures",
Expand All @@ -42,6 +42,7 @@ func TestCollectFailedTasksLogSnippet(t *testing.T) {
message: "i am gonna to make you fail",
podOutput: "hahah i am the devil of the pod",
wantFailure: 1,
displayName: "A task",
},
}
for _, tt := range tests {
Expand All @@ -63,7 +64,8 @@ func TestCollectFailedTasksLogSnippet(t *testing.T) {
}

taskStatus := tektonv1.TaskRunStatusFields{
PodName: "task1",
PodName: "task1",
TaskSpec: &tektonv1.TaskSpec{DisplayName: tt.displayName},
Steps: []tektonv1.StepState{
{
Name: "step1",
Expand Down Expand Up @@ -106,6 +108,9 @@ func TestCollectFailedTasksLogSnippet(t *testing.T) {
if tt.podOutput != "" {
assert.Equal(t, tt.podOutput, got["task1"].LogSnippet)
}
if tt.displayName != "" {
assert.Equal(t, tt.displayName, got["task1"].DisplayName)
}
})
}
}
Expand All @@ -118,7 +123,72 @@ func TestGetStatusFromTaskStatusOrFromAsking(t *testing.T) {
numStatus int
expectedLogSnippet string
taskRuns []*tektonv1.TaskRun
displayNames []string
}{
{
name: "get status with displayName",
numStatus: 2,
displayNames: []string{"Hello Moto", ""},
pr: &tektonv1.PipelineRun{
ObjectMeta: metav1.ObjectMeta{
Namespace: testNS,
},
Spec: tektonv1.PipelineRunSpec{
PipelineSpec: &tektonv1.PipelineSpec{
Tasks: []tektonv1.PipelineTask{
{
Name: "hello",
DisplayName: "Hello Moto",
},
},
},
},
Status: tektonv1.PipelineRunStatus{
PipelineRunStatusFields: tektonv1.PipelineRunStatusFields{
ChildReferences: []tektonv1.ChildStatusReference{
{
TypeMeta: runtime.TypeMeta{
Kind: "TaskRun",
},
Name: "hello",
PipelineTaskName: "hello",
},
{
TypeMeta: runtime.TypeMeta{
Kind: "TaskRun",
},
Name: "yolo",
PipelineTaskName: "yolo",
},
},
},
},
},
taskRuns: []*tektonv1.TaskRun{
{
ObjectMeta: metav1.ObjectMeta{
Name: "hello",
Namespace: testNS,
},
Status: tektonv1.TaskRunStatus{
TaskRunStatusFields: tektonv1.TaskRunStatusFields{
TaskSpec: &tektonv1.TaskSpec{},
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "yolo",
Namespace: testNS,
},
Status: tektonv1.TaskRunStatus{
TaskRunStatusFields: tektonv1.TaskRunStatusFields{
TaskSpec: &tektonv1.TaskSpec{},
},
},
},
},
},
{
name: "get status from child references post tektoncd/pipelines 0.44",
numStatus: 2,
Expand Down Expand Up @@ -151,14 +221,22 @@ func TestGetStatusFromTaskStatusOrFromAsking(t *testing.T) {
Name: "hello",
Namespace: testNS,
},
Status: tektonv1.TaskRunStatus{},
Status: tektonv1.TaskRunStatus{
TaskRunStatusFields: tektonv1.TaskRunStatusFields{
TaskSpec: &tektonv1.TaskSpec{},
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "yolo",
Namespace: testNS,
},
Status: tektonv1.TaskRunStatus{},
Status: tektonv1.TaskRunStatus{
TaskRunStatusFields: tektonv1.TaskRunStatusFields{
TaskSpec: &tektonv1.TaskSpec{},
},
},
},
},
},
Expand Down Expand Up @@ -210,7 +288,13 @@ func TestGetStatusFromTaskStatusOrFromAsking(t *testing.T) {
}
statuses := GetStatusFromTaskStatusOrFromAsking(ctx, tt.pr, run)
assert.Equal(t, len(statuses), tt.numStatus)

displayNames := []string{}
if tt.displayNames != nil {
for _, prtrs := range statuses {
displayNames = append(displayNames, prtrs.Status.TaskSpec.DisplayName)
}
assert.DeepEqual(t, tt.displayNames, displayNames)
}
if tt.expectedLogSnippet != "" {
logmsg := obslog.FilterMessageSnippet(tt.expectedLogSnippet).TakeAll()
assert.Assert(t, len(logmsg) > 0, "log messages", logmsg, tt.expectedLogSnippet)
Expand Down
6 changes: 5 additions & 1 deletion pkg/reconciler/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,11 @@ func (r *Reconciler) getFailureSnippet(ctx context.Context, pr *tektonv1.Pipelin
if text == "" {
text = sortedTaskInfos[0].Message
}
return fmt.Sprintf("task <b>%s</b> has the status <b>\"%s\"</b>:\n<pre>%s</pre>", sortedTaskInfos[0].Name, sortedTaskInfos[0].Reason, text)
name := sortedTaskInfos[0].Name
if sortedTaskInfos[0].DisplayName != "" {
name = strings.ToLower(sortedTaskInfos[0].DisplayName)
}
return fmt.Sprintf("task <b>%s</b> has the status <b>\"%s\"</b>:\n<pre>%s</pre>", name, sortedTaskInfos[0].Reason, text)
}

func (r *Reconciler) postFinalStatus(ctx context.Context, logger *zap.SugaredLogger, vcx provider.Interface, event *info.Event, createdPR *tektonv1.PipelineRun) (*tektonv1.PipelineRun, error) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/sort/task_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ type tkr struct {
}

func (t tkr) ConsoleLogURL() string {
return fmt.Sprintf("[%s](%s)", t.PipelineTaskName, t.taskLogURL)
name := t.PipelineTaskName
if t.Status != nil && t.Status.TaskSpec != nil && t.Status.TaskSpec.DisplayName != "" {
name = t.Status.TaskSpec.DisplayName
}
return fmt.Sprintf("[%s](%s)", name, t.taskLogURL)
}

type taskrunList []tkr
Expand Down
28 changes: 19 additions & 9 deletions pkg/sort/task_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,39 @@ func TestStatusTmpl(t *testing.T) {
wantErr: true,
tmpl: "{{.XXX}}",
prTaskRunStatus: map[string]*tektonv1.PipelineRunTaskRunStatus{
"first": tektontest.MakePrTrStatus("first", 5),
"last": tektontest.MakePrTrStatus("last", 15),
"middle": tektontest.MakePrTrStatus("middle", 10),
"first": tektontest.MakePrTrStatus("first", "", 5),
"last": tektontest.MakePrTrStatus("last", "", 15),
"middle": tektontest.MakePrTrStatus("middle", "", 10),
},
},
{
name: "sorted",
wantRegexp: regexp.MustCompile(".*first.*middle.*last.*"),
tmpl: flattedTmpl,
prTaskRunStatus: map[string]*tektonv1.PipelineRunTaskRunStatus{
"first": tektontest.MakePrTrStatus("first", 5),
"last": tektontest.MakePrTrStatus("last", 15),
"middle": tektontest.MakePrTrStatus("middle", 10),
"first": tektontest.MakePrTrStatus("first", "", 5),
"last": tektontest.MakePrTrStatus("last", "", 15),
"middle": tektontest.MakePrTrStatus("middle", "", 10),
},
},
{
name: "sorted with displayname",
wantRegexp: regexp.MustCompile(".*Primo.*Median.*Ultimo"),
tmpl: flattedTmpl,
prTaskRunStatus: map[string]*tektonv1.PipelineRunTaskRunStatus{
"first": tektontest.MakePrTrStatus("first", "Primo", 5),
"last": tektontest.MakePrTrStatus("last", "Ultimo", 15),
"middle": tektontest.MakePrTrStatus("middle", "Median", 10),
},
},
{
name: "not completed yet come first",
wantRegexp: regexp.MustCompile(".*notcompleted.*first.*last.*"),
tmpl: flattedTmpl,
prTaskRunStatus: map[string]*tektonv1.PipelineRunTaskRunStatus{
"first": tektontest.MakePrTrStatus("first", 5),
"last": tektontest.MakePrTrStatus("last", 15),
"middle": tektontest.MakePrTrStatus("notcompleted", -1),
"first": tektontest.MakePrTrStatus("first", "", 5),
"last": tektontest.MakePrTrStatus("last", "", 15),
"middle": tektontest.MakePrTrStatus("notcompleted", "", -1),
},
},
{
Expand Down

0 comments on commit bb48c6e

Please sign in to comment.