Fix web lint for current plugin tooling The lint config still loaded ../../eslint.config.js, but Gerrit's shared plugin lint config is plugins/eslint-plugin.config.js. The old path is not present in Bazel runfiles, so lint_test cannot load ESLint. Point the config at the shared plugin config. Also replace the loose any types in change-message parsing with local types and mark the async change processing call with void, so current lint rules pass without suppressions. Verified: ZRS=//plugins/zuul-results-summary/web bazelisk build //plugins/zuul-results-summary:zuul-results-summary bazelisk test :lint_test bazelisk test :zuul-results-summary-ts_typecheck_test bazelisk test :zuul-results-summary-ts_transitive_typecheck_test Change-Id: Ic0b0dc2cfb5cfb77373a399da870f1ef5af02883
diff --git a/web/eslint.config.js b/web/eslint.config.js index 74ce3bf..1d6bfe8 100644 --- a/web/eslint.config.js +++ b/web/eslint.config.js
@@ -9,10 +9,10 @@ // eslint-disable-next-line no-undef __plugindir = 'zuul-results-summary/web'; -const gerritEslint = require('../../eslint.config.js'); +const gerritEslint = require('../../eslint-plugin.config.js'); module.exports = defineConfig([ { extends: [gerritEslint], }, -]); \ No newline at end of file +]);
diff --git a/web/zuul-summary-status-tab.ts b/web/zuul-summary-status-tab.ts index 93c091e..c043376 100644 --- a/web/zuul-summary-status-tab.ts +++ b/web/zuul-summary-status-tab.ts
@@ -18,6 +18,7 @@ import {PluginApi} from '@gerritcodereview/typescript-api/plugin'; import { ChangeInfo, + ChangeMessageInfo, RevisionInfo, } from '@gerritcodereview/typescript-api/rest-api'; import {LitElement, html, css, nothing} from 'lit'; @@ -43,16 +44,23 @@ interface ZuulTableItem { succeeded: boolean; + author_id?: number; author_name: string; - revision: string | number; + revision?: string | number; pipeline: string; - rechecks?: number; + rechecks: number; + date: Date; gr_date: string; results: ZuulJobResult[]; } const ZUUL_PRIORITY = [22348]; +function priority(authorId?: number) { + const index = authorId === undefined ? -1 : ZUUL_PRIORITY.indexOf(authorId); + return index === -1 ? Number.MAX_SAFE_INTEGER : index; +} + @customElement('zuul-summary-status-tab') export class ZuulSummaryStatusTab extends LitElement { @property({type: Object}) @@ -129,7 +137,7 @@ } override updated(changed: Map<string, unknown>) { - if (changed.has('change')) this._processChange(this.change); + if (changed.has('change')) void this._processChange(this.change); } override render() { @@ -199,7 +207,8 @@ `; } - private async _processChange(change: any) { + private async _processChange(change?: ChangeInfo) { + if (!change) return; this._enabled = await this._projectEnabled(change.project); if (this._enabled) this._processMessages(change); } @@ -220,26 +229,28 @@ } } - private _match_message_via_tag(msg: any) { + private _match_message_via_tag(msg: ChangeMessageInfo) { return !!msg.tag?.startsWith('autogenerated:zuul'); } - private _match_message_via_regex(msg: any) { - return /^(.* CI|Zuul)/.test(msg.author.name); + private _match_message_via_regex(msg: ChangeMessageInfo) { + return /^(.* CI|Zuul)/.test(msg.author?.name ?? ''); } - private _get_status_and_pipeline(msg: any): [string, string] | false { + private _get_status_and_pipeline( + msg: ChangeMessageInfo, + ): [string, string] | undefined { const fullMatch = /^Build (\w+) \(([\w]+) pipeline\)\./gm.exec(msg.message); if (fullMatch) return [fullMatch[1], fullMatch[2]]; const simpleMatch = /^Build (\w+)\./gm.exec(msg.message); if (simpleMatch) return [simpleMatch[1], 'unknown']; - return false; + return undefined; } - private _processMessages(change: any) { - const table: any[] = []; + private _processMessages(change: ChangeInfo) { + const table: ZuulTableItem[] = []; - change.messages.forEach((message: any) => { + (change.messages ?? []).forEach((message: ChangeMessageInfo) => { if ( !( this._match_message_via_tag(message) || @@ -250,14 +261,13 @@ const date = new Date(message.date); const revision = message._revision_number; - const [status, pipeline] = this._get_status_and_pipeline(message) || []; - - if (!status) return; + const statusAndPipeline = this._get_status_and_pipeline(message); + if (!statusAndPipeline) return; + const [status, pipeline] = statusAndPipeline; + const authorId = message.author?._account_id; const existingIdx = table.findIndex( - entry => - entry.author_id === message.author._account_id && - entry.pipeline === pipeline, + entry => entry.author_id === authorId && entry.pipeline === pipeline, ); let rechecks = 0; @@ -265,30 +275,32 @@ rechecks = table[existingIdx].rechecks + 1; } - const results: any[] = []; + const results: ZuulJobResult[] = []; const resultRe = /^- (?<job>[^ ]+) (?:(?<link>https?:\/\/[^ ]+)|[^ ]+) : ((ERROR (?<errormsg>.*?) in (?<errtime>.*))|(?<result>[^ ]+)( in (?<time>.*))?)/; message.message.split('\n').forEach((line: string) => { const match = resultRe.exec(line); - if (match?.groups) { - if (match.groups.result === 'SKIPPED') match.groups.link = ''; - if (match.groups.errormsg) { - match.groups.result = 'ERROR'; - match.groups.time = match.groups.errtime; - } - results.push(match.groups); - } + const groups = match?.groups; + if (!groups) return; + const result = groups.errormsg ? 'ERROR' : groups.result; + if (!groups.job || !result) return; + results.push({ + job: groups.job, + link: result === 'SKIPPED' ? '' : groups.link, + result, + errormsg: groups.errormsg, + time: groups.errormsg ? groups.errtime : groups.time, + }); }); - const row = { - author_name: message.author.name, - author_id: message.author._account_id, + const row: ZuulTableItem = { + author_name: message.author?.name ?? '', + author_id: authorId, revision, rechecks, date, gr_date: message.date, - status, succeeded: status === 'succeeded', pipeline, results, @@ -302,9 +314,9 @@ }); this.__table = table.sort((a, b) => { - const pa = ZUUL_PRIORITY.indexOf(a.author_id) >>> 0; - const pb = ZUUL_PRIORITY.indexOf(b.author_id) >>> 0; - return pa - pb || b.date - a.date; + const pa = priority(a.author_id); + const pb = priority(b.author_id); + return pa - pb || b.date.getTime() - a.date.getTime(); }); } }