Skip to content

Commit c97c8d2

Browse files
committed
feat: add TaskRun controller notices
1 parent 8bf0710 commit c97c8d2

18 files changed

Lines changed: 494 additions & 4 deletions

‎config/300-crds/300-pipelinerun.yaml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,8 @@ spec:
23642364
type: boolean
23652365
enableKubernetesSidecar:
23662366
type: boolean
2367+
enableNotices:
2368+
type: boolean
23672369
enableParamEnum:
23682370
type: boolean
23692371
enableProvenanceInStatus:
@@ -2744,6 +2746,8 @@ spec:
27442746
type: boolean
27452747
enableKubernetesSidecar:
27462748
type: boolean
2749+
enableNotices:
2750+
type: boolean
27472751
enableParamEnum:
27482752
type: boolean
27492753
enableProvenanceInStatus:
@@ -3017,6 +3021,8 @@ spec:
30173021
type: boolean
30183022
enableKubernetesSidecar:
30193023
type: boolean
3024+
enableNotices:
3025+
type: boolean
30203026
enableParamEnum:
30213027
type: boolean
30223028
enableProvenanceInStatus:
@@ -5463,6 +5469,8 @@ spec:
54635469
type: boolean
54645470
enableKubernetesSidecar:
54655471
type: boolean
5472+
enableNotices:
5473+
type: boolean
54665474
enableParamEnum:
54675475
type: boolean
54685476
enableProvenanceInStatus:

‎config/300-crds/300-taskrun.yaml‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1879,6 +1879,8 @@ spec:
18791879
type: boolean
18801880
enableKubernetesSidecar:
18811881
type: boolean
1882+
enableNotices:
1883+
type: boolean
18821884
enableParamEnum:
18831885
type: boolean
18841886
enableProvenanceInStatus:
@@ -2152,6 +2154,8 @@ spec:
21522154
type: boolean
21532155
enableKubernetesSidecar:
21542156
type: boolean
2157+
enableNotices:
2158+
type: boolean
21552159
enableParamEnum:
21562160
type: boolean
21572161
enableProvenanceInStatus:
@@ -3996,6 +4000,48 @@ spec:
39964000
type:
39974001
description: Type of condition.
39984002
type: string
4003+
notices:
4004+
description: Notices are structured messages emitted by controllers that do not affect the task's success/failure status.
4005+
type: array
4006+
items:
4007+
description: Notice represents a structured message emitted by a controller that does not affect the run's success/failure status.
4008+
type: object
4009+
required:
4010+
- level
4011+
- message
4012+
properties:
4013+
file:
4014+
description: |-
4015+
File is the source file path related to this notice.
4016+
Used by VCS integrations to create inline annotations.
4017+
Maximum length: 256 characters.
4018+
type: string
4019+
maxLength: 256
4020+
level:
4021+
description: |-
4022+
Level indicates the severity of the notice.
4023+
Valid values: "info", "warning".
4024+
type: string
4025+
enum:
4026+
- info
4027+
- warning
4028+
message:
4029+
description: |-
4030+
Message is the human-readable notice text.
4031+
Maximum length: 1024 characters.
4032+
type: string
4033+
maxLength: 1024
4034+
startLine:
4035+
description: |-
4036+
StartLine is the starting line number in the source file (1-based).
4037+
Pointer type so that absence (nil) is distinguishable from line 0.
4038+
type: integer
4039+
step:
4040+
description: |-
4041+
Step is the name of the step that emitted this notice.
4042+
Empty for controller-emitted notices.
4043+
type: string
4044+
x-kubernetes-list-type: atomic
39994045
observedGeneration:
40004046
description: |-
40014047
ObservedGeneration is the 'Generation' of the Service that
@@ -4033,6 +4079,8 @@ spec:
40334079
type: boolean
40344080
enableKubernetesSidecar:
40354081
type: boolean
4082+
enableNotices:
4083+
type: boolean
40364084
enableParamEnum:
40374085
type: boolean
40384086
enableProvenanceInStatus:
@@ -4298,6 +4346,8 @@ spec:
42984346
type: boolean
42994347
enableKubernetesSidecar:
43004348
type: boolean
4349+
enableNotices:
4350+
type: boolean
43014351
enableParamEnum:
43024352
type: boolean
43034353
enableProvenanceInStatus:

‎config/config-feature-flags.yaml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ data:
118118
# Setting this flag to "true" will enable the use of Artifacts in Steps
119119
# This feature is in preview mode and not implemented yet. Please check #7693 for updates.
120120
enable-artifacts: "false"
121+
# Setting this flag to "true" will enable controller notices in TaskRun status.
122+
enable-notices: "false"
121123
# Setting this flag to "true" will enable the built-in param input validation via param enum.
122124
enable-param-enum: "false"
123125
# Setting this flag to "pipeline,pipelinerun,taskrun" will prevent users from creating

‎docs/pipeline-api.md‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,44 @@ _Appears in:_
424424
| `params` _[Params](#params)_ | Params is a list of parameters used to fan out the pipelineTask<br />Params takes only `Parameters` of type `"array"`<br />Each array element is supplied to the `PipelineTask` by substituting `params` of type `"string"` in the underlying `Task`.<br />The names of the `params` in the `Matrix` must match the names of the `params` in the underlying `Task` that they will be substituting. | | |
425425

426426

427+
#### Notice
428+
429+
430+
431+
Notice represents a structured message emitted by a controller that does not affect the run's success/failure status.
432+
433+
434+
435+
_Appears in:_
436+
- [TaskRunStatus](#taskrunstatus)
437+
- [TaskRunStatusFields](#taskrunstatusfields)
438+
439+
| Field | Description | Default | Validation |
440+
| --- | --- | --- | --- |
441+
| `level` _[NoticeLevel](#noticelevel)_ | Level indicates the severity of the notice.<br />Valid values: "info", "warning". | | Enum: [info warning] <br /> |
442+
| `message` _string_ | Message is the human-readable notice text.<br />Maximum length: 1024 characters. | | MaxLength: 1024 <br /> |
443+
| `step` _string_ | Step is the name of the step that emitted this notice.<br />Empty for controller-emitted notices. | | Optional: \{\} <br /> |
444+
| `file` _string_ | File is the source file path related to this notice.<br />Used by VCS integrations to create inline annotations.<br />Maximum length: 256 characters. | | MaxLength: 256 <br />Optional: \{\} <br /> |
445+
| `startLine` _integer_ | StartLine is the starting line number in the source file (1-based).<br />Pointer type so that absence (nil) is distinguishable from line 0. | | Optional: \{\} <br /> |
446+
447+
448+
#### NoticeLevel
449+
450+
_Underlying type:_ _string_
451+
452+
NoticeLevel indicates the severity of a notice.
453+
454+
455+
456+
_Appears in:_
457+
- [Notice](#notice)
458+
459+
| Field | Description |
460+
| --- | --- |
461+
| `info` | NoticeLevelInfo represents an informational message, no action needed.<br /> |
462+
| `warning` | NoticeLevelWarning represents something to address, but not blocking.<br /> |
463+
464+
427465
#### OnErrorType
428466

429467
_Underlying type:_ _string_
@@ -1578,6 +1616,7 @@ _Appears in:_
15781616
| `retriesStatus` _[RetriesStatus](#retriesstatus)_ | RetriesStatus contains the history of TaskRunStatus in case of a retry in order to keep record of failures.<br />All TaskRunStatus stored in RetriesStatus will have no date within the RetriesStatus as is redundant. | | Schemaless: \{\} <br />Optional: \{\} <br /> |
15791617
| `results` _[TaskRunResult](#taskrunresult) array_ | Results are the list of results written out by the task's containers | | Optional: \{\} <br /> |
15801618
| `artifacts` _[Artifacts](#artifacts)_ | Artifacts are the list of artifacts written out by the task's containers | | Optional: \{\} <br /> |
1619+
| `notices` _[Notice](#notice) array_ | Notices are structured messages emitted by controllers that do not affect the task's success/failure status. | | Optional: \{\} <br /> |
15811620
| `sidecars` _[SidecarState](#sidecarstate) array_ | The list has one entry per sidecar in the manifest. Each entry is<br />represents the imageid of the corresponding sidecar. | | |
15821621
| `taskSpec` _[TaskSpec](#taskspec)_ | TaskSpec contains the Spec from the dereferenced Task definition used to instantiate this TaskRun. | | |
15831622
| `provenance` _[Provenance](#provenance)_ | Provenance contains some key authenticated metadata about how a software artifact was built (what sources, what inputs/outputs, etc.). | | Optional: \{\} <br /> |
@@ -1606,6 +1645,7 @@ _Appears in:_
16061645
| `retriesStatus` _[RetriesStatus](#retriesstatus)_ | RetriesStatus contains the history of TaskRunStatus in case of a retry in order to keep record of failures.<br />All TaskRunStatus stored in RetriesStatus will have no date within the RetriesStatus as is redundant. | | Schemaless: \{\} <br />Optional: \{\} <br /> |
16071646
| `results` _[TaskRunResult](#taskrunresult) array_ | Results are the list of results written out by the task's containers | | Optional: \{\} <br /> |
16081647
| `artifacts` _[Artifacts](#artifacts)_ | Artifacts are the list of artifacts written out by the task's containers | | Optional: \{\} <br /> |
1648+
| `notices` _[Notice](#notice) array_ | Notices are structured messages emitted by controllers that do not affect the task's success/failure status. | | Optional: \{\} <br /> |
16091649
| `sidecars` _[SidecarState](#sidecarstate) array_ | The list has one entry per sidecar in the manifest. Each entry is<br />represents the imageid of the corresponding sidecar. | | |
16101650
| `taskSpec` _[TaskSpec](#taskspec)_ | TaskSpec contains the Spec from the dereferenced Task definition used to instantiate this TaskRun. | | |
16111651
| `provenance` _[Provenance](#provenance)_ | Provenance contains some key authenticated metadata about how a software artifact was built (what sources, what inputs/outputs, etc.). | | Optional: \{\} <br /> |

‎pkg/apis/config/feature_flags.go‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ const (
101101
EnableCELInWhenExpression = "enable-cel-in-whenexpression"
102102
// EnableArtifacts is the flag to enable the use of Artifacts in Steps
103103
EnableArtifacts = "enable-artifacts"
104+
// EnableNotices is the flag to enable controller notices in TaskRun status
105+
EnableNotices = "enable-notices"
104106
// EnableParamEnum is the flag to enabled enum in params
105107
EnableParamEnum = "enable-param-enum"
106108
// EnableConciseResolverSyntax is the flag to enable concise resolver syntax
@@ -172,6 +174,13 @@ var (
172174
Enabled: DefaultAlphaFeatureEnabled,
173175
}
174176

177+
// DefaultEnableNotices is the default PerFeatureFlag value for EnableNotices
178+
DefaultEnableNotices = PerFeatureFlag{
179+
Name: EnableNotices,
180+
Stability: AlphaAPIFields,
181+
Enabled: DefaultAlphaFeatureEnabled,
182+
}
183+
175184
// DefaultEnableParamEnum is the default PerFeatureFlag value for EnableParamEnum
176185
DefaultEnableParamEnum = PerFeatureFlag{
177186
Name: EnableParamEnum,
@@ -230,6 +239,7 @@ type FeatureFlags struct {
230239
EnableStepActions bool `json:"enableStepActions,omitempty"`
231240
EnableParamEnum bool `json:"enableParamEnum,omitempty"`
232241
EnableArtifacts bool `json:"enableArtifacts,omitempty"`
242+
EnableNotices bool `json:"enableNotices,omitempty"`
233243
DisableInlineSpec string `json:"disableInlineSpec,omitempty"`
234244
EnableConciseResolverSyntax bool `json:"enableConciseResolverSyntax,omitempty"`
235245
EnableKubernetesSidecar bool `json:"enableKubernetesSidecar,omitempty"`
@@ -335,6 +345,9 @@ func NewFeatureFlagsFromMap(cfgMap map[string]string) (*FeatureFlags, error) {
335345
if err := setPerFeatureFlag(EnableArtifacts, DefaultEnableArtifacts, &tc.EnableArtifacts); err != nil {
336346
return nil, err
337347
}
348+
if err := setPerFeatureFlag(EnableNotices, DefaultEnableNotices, &tc.EnableNotices); err != nil {
349+
return nil, err
350+
}
338351

339352
if err := setFeatureInlineSpec(cfgMap, DisableInlineSpec, DefaultDisableInlineSpec, &tc.DisableInlineSpec); err != nil {
340353
return nil, err

‎pkg/apis/config/feature_flags_test.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func TestNewFeatureFlagsFromConfigMap(t *testing.T) {
7676
Coschedule: config.CoscheduleDisabled,
7777
EnableCELInWhenExpression: true,
7878
EnableArtifacts: true,
79+
EnableNotices: true,
7980
EnableParamEnum: true,
8081
DisableInlineSpec: "pipeline,pipelinerun,taskrun",
8182
EnableConciseResolverSyntax: true,
@@ -294,6 +295,9 @@ func TestNewFeatureFlagsConfigMapErrors(t *testing.T) {
294295
}, {
295296
fileName: "feature-flags-invalid-enable-artifacts",
296297
want: `failed parsing feature flags config "invalid": strconv.ParseBool: parsing "invalid": invalid syntax for feature enable-artifacts`,
298+
}, {
299+
fileName: "feature-flags-invalid-enable-notices",
300+
want: `failed parsing feature flags config "invalid": strconv.ParseBool: parsing "invalid": invalid syntax for feature enable-notices`,
297301
}, {
298302
fileName: "feature-flags-invalid-enable-concise-resolver-syntax",
299303
want: `failed parsing feature flags config "invalid": strconv.ParseBool: parsing "invalid": invalid syntax for feature enable-concise-resolver-syntax`,

‎pkg/apis/config/testdata/feature-flags-all-flags-set.yaml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ data:
3535
enable-cel-in-whenexpression: "true"
3636
enable-param-enum: "true"
3737
enable-artifacts: "true"
38+
enable-notices: "true"
3839
disable-inline-spec: "pipeline,pipelinerun,taskrun"
3940
enable-concise-resolver-syntax: "true"
4041
enable-kubernetes-sidecar: "true"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Copyright 2026 The Tekton Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: v1
16+
kind: ConfigMap
17+
metadata:
18+
name: feature-flags
19+
namespace: tekton-pipelines
20+
data:
21+
enable-notices: "invalid"
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
Copyright 2026 The Tekton Authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1
18+
19+
const (
20+
maxControllerNotices = 10
21+
maxNoticeMessageLen = 1024
22+
maxNoticeFileLen = 256
23+
)
24+
25+
// NoticeLevel indicates the severity of a notice.
26+
type NoticeLevel string
27+
28+
const (
29+
// NoticeLevelInfo represents an informational message, no action needed.
30+
NoticeLevelInfo NoticeLevel = "info"
31+
// NoticeLevelWarning represents something to address, but not blocking.
32+
NoticeLevelWarning NoticeLevel = "warning"
33+
)
34+
35+
// AllNoticeLevels can be used for NoticeLevel validation.
36+
var AllNoticeLevels = []NoticeLevel{NoticeLevelInfo, NoticeLevelWarning}
37+
38+
// Notice represents a structured message emitted by a controller that does not affect the run's success/failure status.
39+
type Notice struct {
40+
// Level indicates the severity of the notice.
41+
// Valid values: "info", "warning".
42+
// +kubebuilder:validation:Enum=info;warning
43+
Level NoticeLevel `json:"level"`
44+
45+
// Message is the human-readable notice text.
46+
// Maximum length: 1024 characters.
47+
// +kubebuilder:validation:MaxLength=1024
48+
Message string `json:"message"`
49+
50+
// Step is the name of the step that emitted this notice.
51+
// Empty for controller-emitted notices.
52+
// +optional
53+
Step string `json:"step,omitempty"`
54+
55+
// File is the source file path related to this notice.
56+
// Used by VCS integrations to create inline annotations.
57+
// Maximum length: 256 characters.
58+
// +optional
59+
// +kubebuilder:validation:MaxLength=256
60+
File string `json:"file,omitempty"`
61+
62+
// StartLine is the starting line number in the source file (1-based).
63+
// Pointer type so that absence (nil) is distinguishable from line 0.
64+
// +optional
65+
StartLine *int `json:"startLine,omitempty"`
66+
}
67+
68+
// AddControllerNotice appends a bounded, deduplicated controller notice to TaskRun status.
69+
func (trs *TaskRunStatus) AddControllerNotice(notice Notice) {
70+
if notice.Level != NoticeLevelInfo && notice.Level != NoticeLevelWarning {
71+
return
72+
}
73+
notice.Message = truncateString(notice.Message, maxNoticeMessageLen)
74+
notice.File = truncateString(notice.File, maxNoticeFileLen)
75+
notice.Step = ""
76+
77+
for _, existing := range trs.Notices {
78+
if existing.Level == notice.Level && existing.Message == notice.Message {
79+
return
80+
}
81+
}
82+
if len(trs.Notices) >= maxControllerNotices {
83+
return
84+
}
85+
trs.Notices = append(trs.Notices, notice)
86+
}
87+
88+
func truncateString(value string, limit int) string {
89+
runes := []rune(value)
90+
if len(runes) <= limit {
91+
return value
92+
}
93+
return string(runes[:limit])
94+
}

0 commit comments

Comments
 (0)