Skip to content

Commit

Permalink
fix: handle missing specs
Browse files Browse the repository at this point in the history
Signed-off-by: mbwhite <whitemat@uk.ibm.com>
  • Loading branch information
mbwhite committed Jan 4, 2024
1 parent f08793d commit 70f0988
Show file tree
Hide file tree
Showing 15 changed files with 64 additions and 16 deletions.
17 changes: 17 additions & 0 deletions src/interfaces/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Document } from 'yaml';

interface Base {
apiVersion: string;
metadata: {
Expand Down Expand Up @@ -42,4 +44,19 @@ interface Tekton {
externaltasks?: ExternalResource[];
}

// ref: https://dev.to/ankittanna/how-to-create-a-type-for-complex-json-object-in-typescript-d81
type JSONValue = string | number | boolean | { [x: string]: JSONValue } | Array<JSONValue>;

export interface Doc {
content: JSONValue;
doc: Document;
path: string;
raw: string;
no_report: boolean;
}

export type RuleReportFn = (message: string, node, prop) => void;

export type RuleFn = (docs, tekton: Tekton, report: RuleReportFn) => void;

export { Tekton, Base, Param, BaseName, ValueParam, ExternalResource };
9 changes: 7 additions & 2 deletions src/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { toolConfig } from './config.js';
import run from './runner.js';
import logProblems from './log-problems.js';

import { logger } from './logger.js';
import { logger, usingLogfile } from './logger.js';

const p = path.resolve(path.dirname(new url.URL(import.meta.url).pathname), '..', 'package.json');
const pkg = JSON.parse(fs.readFileSync(p, 'utf-8'));
Expand Down Expand Up @@ -67,7 +67,12 @@ const parser = yargs(process.argv.slice(2))
process.exitCode = 0;
}
} catch (e) {
logger.error((e as Error).message);
if (usingLogfile()) {
logger.error(e as Error);
} else {
logger.error((e as Error).message);
}

process.exitCode = 1;
}
})();
11 changes: 10 additions & 1 deletion src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,13 @@ if (logfile) {
});
}

export const logger = pino.pino(transports);
export const logger = pino.pino(
{
serializers: {
err: pino.stdSerializers.err,
},
},
transports,
);

export const usingLogfile = () => logfile;
14 changes: 8 additions & 6 deletions src/reporter.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
function getLine(chars, n) {
import { Doc } from './interfaces/common.js';

function getLine(chars: string[], n: number): number {
let l = 1;
for (let i = 0; i < n; i++) {
if (chars[i] === '\n') l++;
}
return l;
}

function getCol(chars, n) {
function getCol(chars: string[], n: number): number {
let c = 1;
for (let i = 0; i < n; i++) {
if (chars[i] === '\n') c = 0;
Expand All @@ -19,7 +21,7 @@ function getLocation(m, node, prop) {
if (!m.has(node)) return {};
const k = m.get(node);

const chars = Array.from(k.doc.raw);
const chars: string[] = Array.from(k.doc.raw);
let n = prop ? k.node.get(prop, true) : k.node;
if (!n) n = k.node.items.find((pair) => pair.key.value === prop).key;
return {
Expand Down Expand Up @@ -51,11 +53,11 @@ function walk(node, path, visitor) {
}
}

function instrument(docs) {
function instrument(docs: Doc[]) {
const m = new Map();
for (const doc of docs) {
walk(doc.content, [], (node, path) => {
if (node != null && typeof node == 'object') {
if (node != null && typeof node == 'object') {
m.set(node, {
node: path.length ? doc.doc.getIn(path, true) : doc.doc,
path,
Expand All @@ -71,7 +73,7 @@ class Reporter {
private m: any;
problems: any[];

constructor(docs = []) {
constructor(docs: Doc[] = []) {
this.m = instrument(docs);
this.problems = [];
}
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-duplicate-env.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
export default (docs, tekton, report) => {
for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;

if (task.spec.stepTemplate && task.spec.stepTemplate.env) {
const templateEnvVars = new Set();
for (const env of task.spec.stepTemplate.env) {
Expand Down
2 changes: 2 additions & 0 deletions src/rules/no-invalid-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ function getTaskParams(spec) {

function checkInvalidParameterName(resources, report) {
for (const resource of Object.values<any>(resources)) {
if (!resource.spec) continue;

let params;
if (resource.kind === 'Task') {
params = getTaskParams(resource.spec);
Expand Down
7 changes: 4 additions & 3 deletions src/rules/no-invalid-param-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,24 @@ export default (docs, tekton, report) => {
}

for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
const params = getTaskParams(task.spec);
if (!params) continue;
checkParameterValues(task.metadata.name, task.kind, params, report);
}

for (const template of Object.values<any>(tekton.triggerTemplates)) {
if (!template.spec.params) continue;
if (!template.spec || !template.spec.params) continue;
checkParameterValues(template.metadata.name, template.kind, template.spec.params, report);
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
if (!pipeline.spec.params) continue;
if (!pipeline.spec || !pipeline.spec.params) continue;
checkParameterValues(pipeline.metadata.name, pipeline.kind, pipeline.spec.params, report);
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
if (!pipeline.spec.params) continue;
if (!pipeline.spec || !pipeline.spec.params) continue;
for (const task of Object.values<any>(pipeline.spec.tasks)) {
if (!task.params) continue;
for (const param of Object.values<any>(task.params)) {
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-latest-image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default (docs, tekton, report) => {
}

for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
check(task.spec.stepTemplate);
for (const step of Object.values(task.spec.steps)) {
check(step);
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-missing-hashbang.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const checkSteps = (steps, report) => {

export default (docs, tekton, report) => {
for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
checkSteps(task.spec.steps, report);
}

Expand Down
4 changes: 2 additions & 2 deletions src/rules/no-missing-workspace.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export default (docs, tekton, report) => {
for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec.workspaces) continue;
if (!task.spec || !task.spec.workspaces) continue;
const taskName = task.metadata.name;
const requiredWorkspaces = task.spec.workspaces.filter((ws) => !ws.optional).map((ws) => ws.name);

Expand Down Expand Up @@ -42,7 +42,7 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
if (!pipeline.spec.workspaces) continue;
if (!pipeline.spec || !pipeline.spec.workspaces) continue;
const required = pipeline.spec.workspaces.map((ws) => ws.name);

for (const template of Object.values<any>(tekton.triggerTemplates)) {
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-undefined-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default (docs, tekton, report) => {
}

for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
const params = getTaskParams(task);
for (const prefix of ['inputs.params', 'params']) {
for (const prop of ['steps', 'volumes', 'stepTemplate', 'sidecars']) {
Expand Down
1 change: 1 addition & 0 deletions src/rules/no-undefined-volume.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export default (docs, tekton, report) => {
for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
const volumes = (task.spec.volumes || []).map((volume) => volume.name);

for (const step of task.spec.steps) {
Expand Down
4 changes: 4 additions & 0 deletions src/rules/no-unused-param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function getParams(kind, spec) {

export default (docs, tekton, report) => {
for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
const params = getParams(task.kind, task.spec);
const occurences = Object.fromEntries(params.map((param) => [param.name, 0]));
for (const prefix of ['inputs.params', 'params']) {
Expand All @@ -41,6 +42,7 @@ export default (docs, tekton, report) => {
}

for (const condition of Object.values<any>(tekton.conditions)) {
if (!condition.spec) continue;
const params = getParams(condition.kind, condition.spec);
const occurences = Object.fromEntries(params.map((param) => [param.name, 0]));
walk(condition.spec.check, ['spec', 'check'], unused(occurences, 'params'));
Expand All @@ -54,6 +56,7 @@ export default (docs, tekton, report) => {
}

for (const template of Object.values<any>(tekton.triggerTemplates)) {
if (!template.spec) continue;
const params = getParams(template.kind, template.spec);
const occurences = Object.fromEntries(params.map((param) => [param.name, 0]));
walk(template.spec, ['spec'], unused(occurences, 'params'));
Expand All @@ -67,6 +70,7 @@ export default (docs, tekton, report) => {
}

for (const pipeline of Object.values<any>(tekton.pipelines)) {
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'));
Expand Down
3 changes: 2 additions & 1 deletion src/rules/prefer-beta.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export default (docs, tekton, report) => {
for (const pipeline of Object.values<any>(tekton.pipelines)) {
if (!pipeline.spec) continue;
for (const task of pipeline.spec.tasks) {
if (!task.taskSpec) continue;
switch (pipeline.apiVersion) {
case 'tekton.dev/v1alpha1':
if (task.taskSpec.params)
Expand All @@ -22,6 +22,7 @@ export default (docs, tekton, report) => {
}

for (const task of Object.values<any>(tekton.tasks)) {
if (!task.spec) continue;
switch (task.apiVersion) {
case 'tekton.dev/v1alpha1':
if (task.spec.params)
Expand Down
3 changes: 2 additions & 1 deletion src/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import yaml from 'yaml';
import fs from 'node:fs';
import { collectAllExternal } from './external.js';
import { logger } from './logger.js';
import { Doc } from './interfaces/common.js';

/* Collect paths based on the glob pattern passed in */
const collector = async (paths: string[], cfg: ToolConfig) => {
const docs: any = [];
const docs: Doc[] = [];
const files = await glob(paths);
logger.info('Found these files %j', files);
for (const file of files) {
Expand Down

0 comments on commit 70f0988

Please sign in to comment.