Skip to content

Commit a283464

Browse files
committed
Adding v1 ApiVersioning compatibility for catlins pre-commit hooks
1 parent 3f51bad commit a283464

File tree

5 files changed

+501
-41
lines changed

5 files changed

+501
-41
lines changed

pkg/linter/script.go

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/tektoncd/catlin/pkg/parser"
2424
"github.com/tektoncd/catlin/pkg/validator"
25+
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
2526
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
2627
)
2728

@@ -88,20 +89,20 @@ func NewScriptLinter(r *parser.Resource) *taskLinter {
8889
}
8990

9091
// nolint: staticcheck
91-
func (t *taskLinter) validateScript(taskName string, s v1beta1.Step, configs []config) validator.Result {
92+
func (t *taskLinter) validateScript(taskName string, script string, configs []config, stepName string) validator.Result {
9293
result := validator.Result{}
9394

9495
// use /bin/sh by default if no shbang
95-
if s.Script[0:2] != "#!" {
96-
s.Script = "#!/usr/bin/env sh\n" + s.Script
96+
if script[0:2] != "#!" {
97+
script = "#!/usr/bin/env sh\n" + script
9798
} else { // using a shbang, check if we have /usr/bin/env
98-
if s.Script[0:14] != "#!/usr/bin/env" {
99+
if script[0:14] != "#!/usr/bin/env" {
99100
result.Warn("step: %s is not using #!/usr/bin/env ", taskName)
100101
}
101102
}
102103

103104
for _, config := range configs {
104-
matched, err := regexp.MatchString(`^#!`+config.regexp+`\n`, s.Script)
105+
matched, err := regexp.MatchString(`^#!`+config.regexp+`\n`, script)
105106
if err != nil {
106107
result.Error("Invalid regexp: %s", config.regexp)
107108
return result
@@ -123,7 +124,7 @@ func (t *taskLinter) validateScript(taskName string, s v1beta1.Step, configs []c
123124
return result
124125
}
125126
defer os.Remove(tmpfile.Name()) // clean up
126-
if _, err := tmpfile.Write([]byte(s.Script)); err != nil {
127+
if _, err := tmpfile.Write([]byte(script)); err != nil {
127128
result.Error("Cannot write to temporary files")
128129
return result
129130
}
@@ -138,7 +139,7 @@ func (t *taskLinter) validateScript(taskName string, s v1beta1.Step, configs []c
138139
cmd := exec.Command(execpath, append(linter.args, tmpfile.Name())...)
139140
out, err := cmd.CombinedOutput()
140141
if err != nil {
141-
outt := strings.ReplaceAll(string(out), tmpfile.Name(), taskName+"-"+s.Name)
142+
outt := strings.ReplaceAll(string(out), tmpfile.Name(), taskName+"-"+stepName)
142143
result.Error("%s, %s failed:\n%s", execpath, linter.args, outt)
143144
}
144145
}
@@ -148,10 +149,18 @@ func (t *taskLinter) validateScript(taskName string, s v1beta1.Step, configs []c
148149
}
149150

150151
// nolint: staticcheck
151-
func (t *taskLinter) collectOverSteps(steps []v1beta1.Step, name string, result *validator.Result) {
152-
for _, step := range steps {
153-
if step.Script != "" {
154-
result.Append(t.validateScript(name, step, t.configs))
152+
func (t *taskLinter) collectOverSteps(steps interface{}, name string, result *validator.Result) {
153+
if s, ok := steps.([]v1beta1.Step); ok {
154+
for _, step := range s {
155+
if step.Script != "" {
156+
result.Append(t.validateScript(name, step.Script, t.configs, step.Name))
157+
}
158+
}
159+
} else if s, ok := steps.([]v1.Step); ok {
160+
for _, step := range s {
161+
if step.Script != "" {
162+
result.Append(t.validateScript(name, step.Script, t.configs, step.Name))
163+
}
155164
}
156165
}
157166
}
@@ -167,11 +176,17 @@ func (t *taskLinter) Validate() validator.Result {
167176

168177
switch strings.ToLower(t.res.Kind) {
169178
case "task":
170-
task := res.(*v1beta1.Task)
171-
t.collectOverSteps(task.Spec.Steps, task.ObjectMeta.Name, &result)
179+
if res.(*v1.Task) != nil {
180+
task := res.(*v1.Task)
181+
t.collectOverSteps(task.Spec.Steps, task.ObjectMeta.Name, &result)
182+
} else {
183+
task := res.(*v1beta1.Task)
184+
t.collectOverSteps(task.Spec.Steps, task.ObjectMeta.Name, &result)
185+
}
186+
172187
case "clustertask":
173-
task := res.(*v1beta1.ClusterTask)
174-
t.collectOverSteps(task.Spec.Steps, task.ObjectMeta.Name, &result)
188+
task := res.(*v1beta1.ClusterTask)
189+
t.collectOverSteps(task.Spec.Steps, task.ObjectMeta.Name, &result)
175190
}
176191
return result
177192
}

pkg/linter/script_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ spec:
4040
echo "hello moto"
4141
`
4242

43+
const taskScriptValidatorGoodV1 = `
44+
apiVersion: tekton.dev/v1
45+
kind: Task
46+
metadata:
47+
name: hello-moto
48+
spec:
49+
steps:
50+
- name: s1
51+
image: image1
52+
script: |
53+
#!/usr/bin/env sh
54+
echo "Hello world"
55+
script: |
56+
#!/bin/sh
57+
echo "hello moto"
58+
`
59+
4360
const taskScriptValidatorNoGood = `
4461
apiVersion: tekton.dev/v1beta1
4562
kind: Task
@@ -58,6 +75,24 @@ spec:
5875
#!/bin/sh
5976
echo "hello world"
6077
`
78+
const taskScriptValidatorNoGoodV1 = `
79+
apiVersion: tekton.dev/v1
80+
kind: Task
81+
metadata:
82+
name: hello-moto
83+
spec:
84+
steps:
85+
- name: nogood
86+
image: image1
87+
script: |
88+
#!/usr/bin/env sh
89+
'
90+
- name: warn
91+
image: image1
92+
script: |
93+
#!/bin/sh
94+
echo "hello world"
95+
`
6196

6297
const clusterTaskTest = `
6398
apiVersion: tekton.dev/v1beta1
@@ -84,6 +119,17 @@ spec:
84119
taskRef:
85120
name: task-1`
86121

122+
const pipelineWithTaskRefV1 = `
123+
apiVersion: tekton.dev/v1
124+
kind: Pipeline
125+
metadata:
126+
name: pipelien-1
127+
spec:
128+
tasks:
129+
- name: pipeline-1
130+
taskRef:
131+
name: task-1`
132+
87133
var configSh = []config{
88134
{
89135
regexp: `(/usr/bin/env |/bin/)sh`,
@@ -110,6 +156,20 @@ func TestTaskLint_Script_good(t *testing.T) {
110156
result := tl.Validate()
111157
assert.Equal(t, 0, result.Errors)
112158
}
159+
func TestTaskLint_Script_goodV1(t *testing.T) {
160+
r := strings.NewReader(taskScriptValidatorGoodV1)
161+
parser := parser.ForReader(r)
162+
163+
res, err := parser.Parse()
164+
assert.NilError(t, err)
165+
166+
tl := &taskLinter{
167+
res: res,
168+
configs: configSh,
169+
}
170+
result := tl.Validate()
171+
assert.Equal(t, 0, result.Errors)
172+
}
113173

114174
func TestTaskLint_Script_no_good(t *testing.T) {
115175
r := strings.NewReader(taskScriptValidatorNoGood)
@@ -125,6 +185,20 @@ func TestTaskLint_Script_no_good(t *testing.T) {
125185
result := tl.Validate()
126186
assert.Equal(t, 1, result.Errors)
127187
}
188+
func TestTaskLint_Script_no_goodV1(t *testing.T) {
189+
r := strings.NewReader(taskScriptValidatorNoGoodV1)
190+
parser := parser.ForReader(r)
191+
192+
res, err := parser.Parse()
193+
assert.NilError(t, err)
194+
195+
tl := &taskLinter{
196+
res: res,
197+
configs: configSh,
198+
}
199+
result := tl.Validate()
200+
assert.Equal(t, 1, result.Errors)
201+
}
128202

129203
func Test_Pipeline_skip(t *testing.T) {
130204
r := strings.NewReader(pipelineWithTaskRef)
@@ -140,6 +214,20 @@ func Test_Pipeline_skip(t *testing.T) {
140214
result := tl.Validate()
141215
assert.Assert(t, is.Nil(result.Lints))
142216
}
217+
func Test_Pipeline_skipV1(t *testing.T) {
218+
r := strings.NewReader(pipelineWithTaskRefV1)
219+
parser := parser.ForReader(r)
220+
221+
res, err := parser.Parse()
222+
assert.NilError(t, err)
223+
224+
tl := &taskLinter{
225+
res: res,
226+
configs: configSh,
227+
}
228+
result := tl.Validate()
229+
assert.Assert(t, is.Nil(result.Lints))
230+
}
143231

144232
func Test_ClusterTaskParse(t *testing.T) {
145233
r := strings.NewReader(clusterTaskTest)

pkg/parser/parser.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,14 @@ import (
2929
"knative.dev/pkg/apis"
3030

3131
"github.com/tektoncd/catlin/pkg/consts"
32+
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
3233
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
3334
)
3435

3536
func registerSchema() {
37+
v1 := runtime.NewSchemeBuilder(v1.AddToScheme)
38+
_ = v1.AddToScheme(scheme.Scheme)
39+
3640
beta1 := runtime.NewSchemeBuilder(v1beta1.AddToScheme)
3741
_ = beta1.AddToScheme(scheme.Scheme)
3842
}
@@ -152,12 +156,19 @@ type tektonResource interface {
152156

153157
// nolint: staticcheck
154158
func typeForKind(kind string) (tektonResource, error) {
159+
isV1 := (&v1.Task{} != nil)
155160
switch kind {
156161
case "Task":
162+
if isV1 {
163+
return &v1.Task{}, nil
164+
}
157165
return &v1beta1.Task{}, nil
158166
case "ClusterTask":
159167
return &v1beta1.ClusterTask{}, nil
160168
case "Pipeline":
169+
if isV1 {
170+
return &v1.Pipeline{}, nil
171+
}
161172
return &v1beta1.Pipeline{}, nil
162173
}
163174

@@ -166,5 +177,5 @@ func typeForKind(kind string) (tektonResource, error) {
166177

167178
func isTektonKind(gvk *schema.GroupVersionKind) bool {
168179
id := gvk.GroupVersion().Identifier()
169-
return id == v1beta1.SchemeGroupVersion.Identifier()
180+
return id == v1.SchemeGroupVersion.Identifier() || id == v1beta1.SchemeGroupVersion.Identifier()
170181
}

0 commit comments

Comments
 (0)