Skip to content

Commit

Permalink
fix: add support for finally tasks
Browse files Browse the repository at this point in the history
Signed-off-by: mbwhite <[email protected]>
  • Loading branch information
mbwhite committed Jan 9, 2024
1 parent fd4b11f commit 68c503d
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 10 deletions.
55 changes: 55 additions & 0 deletions regression-tests/general/finally.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: cleanup
spec:
params:
- name: taskexample
steps:
- name: ls-build-sources
command: ["ls", "-ltr", "/workspace/source/$(params.taskexample)"]
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: notification
spec:
steps: []
---
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: build-deploy-cleaup-pipeline
spec:
params:
- name: finallyparam
- name: really-unused
workspaces:
- name: shared-workspace
tasks: []

finally:
- name: cleanup
displayName: "Notification from $(params.notdefined)"
taskRef:
name: cleanup
params:
- name: unrequiredparam
value: "blank"
- name: taskexample
value: $(params.finallyparam)
- name: taskexample
value: $(params.undefined)
- name: "???_"
value: wibble
workspaces:
- name: shared-workspace
workspace: shared-workspace
- name: notification-using-context-variable
displayName: "Notification from $(params.finallyparam)"
taskRef:
name: notification
workspaces:
- name: shared-workspace
workspace: unknown-workspace
1 change: 1 addition & 0 deletions regression-tests/general/finally.yaml.expect.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"message":"Duplicate param 'taskexample'","rule":"no-duplicate-param","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[814,825,826],"startLine":42,"startColumn":17,"endLine":42,"endColumn":28}},{"message":"Pipeline 'build-deploy-cleaup-pipeline' references task 'cleanup' (as 'cleanup'), and supplies parameter 'unrequiredparam' to it, but it's not a valid parameter","rule":"no-extra-param","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[683,730,730],"startLine":38,"startColumn":11,"endLine":40,"endColumn":1}},{"message":"Pipeline 'build-deploy-cleaup-pipeline' references task 'cleanup' (as 'cleanup'), and supplies parameter '???_' to it, but it's not a valid parameter","rule":"no-extra-param","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[873,910,910],"startLine":44,"startColumn":11,"endLine":46,"endColumn":1}},{"message":"Pipeline 'build-deploy-cleaup-pipeline' provides workspace 'unknown-workspace' for 'shared-workspace' for Task 'notification-using-context-variable', but 'unknown-workspace' doesn't exists in 'build-deploy-cleaup-pipeline'","rule":"no-missing-workspace","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[1243,1260,1269],"startLine":55,"startColumn":22,"endLine":55,"endColumn":39}},{"message":"Undefined param 'notdefined' at .spec.finally[0].displayName in 'build-deploy-cleaup-pipeline'","rule":"no-undefined-param","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[581,621,622],"startLine":34,"startColumn":20,"endLine":34,"endColumn":60}},{"message":"Undefined param 'undefined' at .spec.finally[0].params[2].value in 'build-deploy-cleaup-pipeline'","rule":"no-undefined-param","level":"error","path":"./regression-tests/general/finally.yaml","loc":{"range":[843,862,863],"startLine":43,"startColumn":18,"endLine":43,"endColumn":37}},{"message":"Pipeline 'build-deploy-cleaup-pipeline' defines parameter 'really-unused', but it's not used anywhere in the spec","rule":"no-unused-param","level":"warning","path":"./regression-tests/general/finally.yaml","loc":{"range":[447,467,467],"startLine":27,"startColumn":7,"endLine":28,"endColumn":1}},{"message":"Invalid name for '???_' at .spec.finally[0].params[3].name in 'build-deploy-cleaup-pipeline'. Names should be in lowercase, alphanumeric, kebab-case format.","rule":"prefer-kebab-case","level":"warning","path":"./regression-tests/general/finally.yaml","loc":{"range":[879,885,886],"startLine":44,"startColumn":17,"endLine":44,"endColumn":23}}]
1 change: 1 addition & 0 deletions src/interfaces/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ interface Tekton {
triggerBindings?: ListResources;
conditions?: ListResources;
externaltasks?: ExternalResource[];
finally?: ListResources;
}

// ref: https://dev.to/ankittanna/how-to-create-a-type-for-complex-json-object-in-typescript-d81
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/pipeline/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Pipeline extends Base {
resources?: PipelineResource[];
workspaces?: Workspace[];
tasks: Task[];
finally?: Task[];
};
}

Expand Down
4 changes: 3 additions & 1 deletion src/rules/no-duplicate-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
checkParams(getParams('Task', task), report);
if (task.taskSpec) {
checkParams(getParams('Task', task.taskSpec), report);
Expand Down
8 changes: 6 additions & 2 deletions src/rules/no-extra-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ function getTaskParams(spec) {

export default (docs, tekton, report) => {
for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (task.taskRef) {
const name = task.taskRef.name;

Expand All @@ -28,7 +30,9 @@ export default (docs, tekton, report) => {
}
}
for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (task.taskSpec) {
const params = getTaskParams(task.taskSpec);
if (task.params == null && params == null) continue;
Expand Down
4 changes: 3 additions & 1 deletion src/rules/no-invalid-param-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ export default (docs, tekton, report) => {

for (const pipeline of Object.values<any>(tekton.pipelines)) {
if (!pipeline.spec || !pipeline.spec.params) continue;
for (const task of Object.values<any>(pipeline.spec.tasks)) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (!task.params) continue;
for (const param of Object.values<any>(task.params)) {
if (typeof param.value == 'undefined') {
Expand Down
4 changes: 3 additions & 1 deletion src/rules/no-missing-hashbang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (!task.taskSpec) continue;
checkSteps(task.taskSpec.steps, report);
}
Expand Down
8 changes: 6 additions & 2 deletions src/rules/no-missing-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ function getTaskParams(spec) {

export default (docs, tekton, report) => {
for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (task.taskRef) {
const name = task.taskRef.name;
if (!tekton.tasks[name]) continue;
Expand All @@ -27,7 +29,9 @@ export default (docs, tekton, report) => {
}
}
for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (task.taskSpec) {
const params = getTaskParams(task.taskSpec);
if (task.params == null && params == null) continue;
Expand Down
8 changes: 6 additions & 2 deletions src/rules/no-missing-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (!task.conditions) continue;
for (const condition of task.conditions) {
if (tekton.conditions[condition.conditionRef]) continue;
Expand All @@ -60,7 +62,9 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (!task.taskRef) continue;
const name = task.taskRef.name;

Expand Down
4 changes: 3 additions & 1 deletion src/rules/no-missing-workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export default (docs, tekton, report) => {

for (const pipeline of Object.values<any>(tekton.pipelines)) {
const pipelineWorkspaces = pipeline.spec.workspaces || [];
for (const task of pipeline.spec.tasks) {
// include any finally tasks if they are present
const tasks = [...pipeline.spec.tasks, ...(pipeline.spec.finally ? pipeline.spec.finally : [])];
for (const task of tasks) {
if (!task.workspaces) continue;
for (const workspace of task.workspaces) {
let matchingWorkspace = false;
Expand Down
5 changes: 5 additions & 0 deletions src/rules/no-undefined-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export default (docs, tekton, report) => {
for (const pipeline of Object.values<any>(tekton.pipelines)) {
const params = getParams(pipeline);
walk(pipeline.spec.tasks, ['spec', 'tasks'], createVisitor(pipeline.metadata.name, params, 'params', report));
walk(
pipeline.spec.finally,
['spec', 'finally'],
createVisitor(pipeline.metadata.name, params, 'params', report),
);
}

for (const task of Object.values<any>(tekton.tasks)) {
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-unused-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ export default (docs, tekton, report) => {
if (!pipeline.spec) continue;
const params = getParams(pipeline.kind, pipeline.spec);
const occurences = Object.fromEntries(params.map((param) => [param.name, 0]));

walk(pipeline.spec.tasks, ['spec', 'tasks'], unused(occurences, 'params'));
walk(pipeline.spec.finally, ['spec', 'finally'], unused(occurences, 'params'));
for (const [param, n] of Object.entries(occurences)) {
if (n) continue;
report(
Expand Down
1 change: 1 addition & 0 deletions src/rules/prefer-kebab-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ const naming = (resource, prefix, report) => (node, path, parent) => {
export default (docs, tekton, report) => {
for (const pipeline of Object.values<any>(tekton.pipelines)) {
walk(pipeline.spec.tasks, ['spec', 'tasks'], naming(pipeline.metadata.name, 'params', report));
walk(pipeline.spec.finally, ['spec', 'finally'], naming(pipeline.metadata.name, 'params', report));
}
};

0 comments on commit 68c503d

Please sign in to comment.