diff --git a/web/README.md b/web/README.md index 8b4f19a..00cccdd 100644 --- a/web/README.md +++ b/web/README.md @@ -6,18 +6,12 @@ Testgrid frontend code uses Lit elements and is written in Typescript. `tsconfig More info about Lit and Typescript can be found in [Lit docs](https://lit.dev/) and [TS docs](https://www.typescriptlang.org/) respectively. ## Development -Local development is done with the help of [Web Dev Server](https://modern-web.dev/docs/dev-server/overview/). Web dev server configurations are defined in `web-dev-server-{env}.config.mjs` file. Depending on the config, frontend will render from the data from either fake or prod API. +Local development is done with the help of [Web Dev Server](https://modern-web.dev/docs/dev-server/overview/). Web dev server configurations are defined in `web-dev-server-{env}.config.mjs` file. Depending on the config, frontend will render from the data from either fake or prod API. -To develop locally: -- Run `npm install`, then: - - To see fake data, run `npm run start:local` - - To see prod data, run `npm run start:k8s` - -More info in the [Scripts](#scripts) section below. - -TIP: If you hit unexpected errors, try running `rm -rf node_modules/`, then `npm install` to refresh dependencies. +To see fake data, run `npm run start:local`. To see prod data, run `npm run start:k8s`. More info in the [Scripts](#scripts) section below. ## Testing +Testing relies on [Web Test Runner](https://modern-web.dev/docs/test-runner/overview/) with the configuration defined in `web-test-runner.config.mjs`. Testing is currently happening across the fake data provided by `json-server`. To run the tests, run `npm run test`. More info in the [Scripts](#scripts) section below. @@ -34,15 +28,7 @@ Most scripts are in `npm run` commands. ## Pulling from upstream -To generate or update the proto definitions: - -- Checkout a local copy of https://github.com/GoogleCloudPlatform/testgrid, ex. `gh repo clone GoogleCloudPlatform/testgrid $HOME/gcp-testgrid` -- Run - ``` - # Path to local GCP/testgrid repo, `$HOME/gcp-testgrid` - TGREPO={{local GCP/testgrid repo}} - bump-protos.sh "$TGREPO" - ``` +Upstream proto definitions can be generated by running `pb/bump-protos.sh` ## Configs and files - Frontend code is located in `src` dir. @@ -52,4 +38,4 @@ To generate or update the proto definitions: - `tsconfig.json` defines how and where will the .ts files compile. - `web-dev-server-*.config.mjs` defines configuration parameters for the web dev server. - `web-test-runner.config.mjs` defined configuration parameters for the web test runner. -- `rollup.config.js` defines how the code will be built and bundled. +- `rollup.config.js` defines how the code will be built and bundled. \ No newline at end of file diff --git a/web/bump-protos.sh b/web/bump-protos.sh index a967ba2..1b11065 100755 --- a/web/bump-protos.sh +++ b/web/bump-protos.sh @@ -17,27 +17,16 @@ set -o errexit set -o nounset set -o pipefail -if [ "$#" -lt 1 ] -then - echo "Usage: $0 [path to local GCP/testgrid repo]" - exit 1 -fi - -# The location of your local https://github.com/GoogleCloudPlatform/testgrid repo, where the proto files live. -TESTGRID_REPO=$1 - -WORKDIR="$(git rev-parse --show-toplevel)" # The root directory of your repository +WORKDIR="${HOME}/github/testgrid" # The root directory of your repository PROTO_DEST="${WORKDIR}/web/src/gen" -echo "Generating protos from source $TESTGRID_REPO to destination $PROTO_DEST..." - cd "${WORKDIR}/web" # See https://github.com/timostamm/protobuf-ts/blob/master/MANUAL.md -npx protoc --ts_out ${PROTO_DEST} --proto_path ${TESTGRID_REPO} --ts_opt long_type_string \ - ${TESTGRID_REPO}/pb/custom_evaluator/custom_evaluator.proto \ - ${TESTGRID_REPO}/pb/state/state.proto \ - ${TESTGRID_REPO}/pb/summary/summary.proto \ - ${TESTGRID_REPO}/pb/config/config.proto \ - ${TESTGRID_REPO}/pb/test_status/test_status.proto \ - ${TESTGRID_REPO}/pb/api/v1/data.proto +npx protoc --ts_out ${PROTO_DEST} --proto_path ${WORKDIR} --ts_opt long_type_string \ + ${WORKDIR}/pb/custom_evaluator/custom_evaluator.proto \ + ${WORKDIR}/pb/state/state.proto \ + ${WORKDIR}/pb/summary/summary.proto \ + ${WORKDIR}/pb/config/config.proto \ + ${WORKDIR}/pb/test_status/test_status.proto \ + ${WORKDIR}/pb/api/v1/data.proto diff --git a/web/custom-elements.json b/web/custom-elements.json index 2de5960..e317e7c 100644 --- a/web/custom-elements.json +++ b/web/custom-elements.json @@ -69,18 +69,6 @@ "text": "TabSummaryInfo | undefined" }, "attribute": "info" - }, - { - "kind": "method", - "name": "changeTab", - "privacy": "private", - "description": "Lets the data content element know that the tab changed", - "parameters": [ - { - "description": "string", - "name": "tabName" - } - ] } ], "attributes": [ @@ -372,73 +360,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/testgrid-failures-summary.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "TestgridFailuresSummary", - "members": [ - { - "kind": "field", - "name": "showFailureSummary", - "type": { - "text": "boolean" - }, - "default": "false" - }, - { - "kind": "field", - "name": "info", - "type": { - "text": "TabSummaryInfo | undefined" - }, - "attribute": "info" - }, - { - "kind": "method", - "name": "dropdownTable", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "info", - "type": { - "text": "TabSummaryInfo | undefined" - }, - "fieldName": "info" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "testgrid-failures-summary", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "TestgridFailuresSummary", - "declaration": { - "name": "TestgridFailuresSummary", - "module": "src/testgrid-failures-summary.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "testgrid-failures-summary", - "declaration": { - "name": "TestgridFailuresSummary", - "module": "src/testgrid-failures-summary.ts" - } - } - ] - }, { "kind": "javascript-module", "path": "src/testgrid-grid-cell.ts", @@ -912,73 +833,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/testgrid-healthiness-summary.ts", - "declarations": [ - { - "kind": "class", - "description": "", - "name": "TestgridTabTable", - "members": [ - { - "kind": "field", - "name": "showHealthinesSummary", - "type": { - "text": "boolean" - }, - "default": "false" - }, - { - "kind": "field", - "name": "info", - "type": { - "text": "TabSummaryInfo | undefined" - }, - "attribute": "info" - }, - { - "kind": "method", - "name": "dropdownTable", - "privacy": "private" - } - ], - "attributes": [ - { - "name": "info", - "type": { - "text": "TabSummaryInfo | undefined" - }, - "fieldName": "info" - } - ], - "superclass": { - "name": "LitElement", - "package": "lit" - }, - "tagName": "testgrid-healthiness-summary", - "customElement": true - } - ], - "exports": [ - { - "kind": "js", - "name": "TestgridTabTable", - "declaration": { - "name": "TestgridTabTable", - "module": "src/testgrid-healthiness-summary.ts" - } - }, - { - "kind": "custom-element-definition", - "name": "testgrid-healthiness-summary", - "declaration": { - "name": "TestgridTabTable", - "module": "src/testgrid-healthiness-summary.ts" - } - } - ] - }, { "kind": "javascript-module", "path": "src/testgrid-index.ts", @@ -1762,7 +1616,7 @@ { "kind": "variable", "name": "TabSummary", - "default": "class TabSummary extends LitElement {\n render() {\n var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;\n return html `\n \n
\n
\n
\n ${(_b = this.info) === null || _b === void 0 ? void 0 : _b.icon}\n
\n
\n
\n
this.changeTab()} class=\"tab-name\">\n ${(_c = this.info) === null || _c === void 0 ? void 0 : _c.name}: ${(_d = this.info) === null || _d === void 0 ? void 0 : _d.overallStatus}\n
\n
${(_e = this.info) === null || _e === void 0 ? void 0 : _e.detailedStatusMsg}
\n
\n
\n
\n Last update: ${(_f = this.info) === null || _f === void 0 ? void 0 : _f.lastUpdateTimestamp}\n
\n
\n Tests last ran: ${(_g = this.info) === null || _g === void 0 ? void 0 : _g.lastRunTimestamp}\n
\n
\n Last green run: ${(_h = this.info) === null || _h === void 0 ? void 0 : _h.latestGreenBuild}\n
\n
\n
\n ${((_j = this.info) === null || _j === void 0 ? void 0 : _j.failuresSummary) !== undefined ?\n html `\n ` : ''}\n ${((_k = this.info) === null || _k === void 0 ? void 0 : _k.healthinessSummary) !== undefined ?\n html `\n ` : ''}\n `;\n }\n /**\n * Lets the data content element know that the tab changed\n *\n * @fires tab-changed\n * @param tabName string\n */\n changeTab() {\n var _a;\n window.dispatchEvent(new CustomEvent('tab-changed', {\n detail: {\n tabName: (_a = this.info) === null || _a === void 0 ? void 0 : _a.name\n },\n }));\n }\n}" + "default": "class TabSummary extends LitElement {\n render() {\n var _a, _b, _c, _d, _e, _f, _g, _h;\n return html `\n \n
\n
\n
\n ${(_b = this.info) === null || _b === void 0 ? void 0 : _b.icon}\n
\n
\n
\n
\n ${(_c = this.info) === null || _c === void 0 ? void 0 : _c.name}: ${(_d = this.info) === null || _d === void 0 ? void 0 : _d.overallStatus}\n
\n
${(_e = this.info) === null || _e === void 0 ? void 0 : _e.detailedStatusMsg}
\n
\n
\n
\n Last update: ${(_f = this.info) === null || _f === void 0 ? void 0 : _f.lastUpdateTimestamp}\n
\n
\n Tests last ran: ${(_g = this.info) === null || _g === void 0 ? void 0 : _g.lastRunTimestamp}\n
\n
\n Last green run: ${(_h = this.info) === null || _h === void 0 ? void 0 : _h.latestGreenBuild}\n
\n
\n
\n `;\n }\n}" } ], "exports": [ @@ -1840,7 +1694,7 @@ { "kind": "variable", "name": "TestgridDataContent", - "default": "class TestgridDataContent extends LitElement {\n constructor() {\n super(...arguments);\n this.tabNames = [];\n this.activeIndex = 0;\n this.showTab = false;\n this.dashboardName = '';\n }\n // set the functionality when any tab is clicked on\n onTabActivated(event) {\n const tabIndex = event.detail.index;\n if (tabIndex === this.activeIndex) {\n return;\n }\n this.tabName = this.tabNames[tabIndex];\n if (this.activeIndex === 0 || tabIndex === 0) {\n this.showTab = !this.showTab;\n }\n this.activeIndex = tabIndex;\n navigateTab(this.dashboardName, this.tabName);\n }\n /**\n * Lit-element lifecycle method.\n * Invoked when a component is added to the document's DOM.\n */\n connectedCallback() {\n super.connectedCallback();\n this.fetchTabNames();\n window.addEventListener('tab-changed', (evt) => {\n this.tabName = evt.detail.tabName;\n this.showTab = !this.showTab;\n this.highlightIndex(this.tabName);\n navigateTab(this.dashboardName, this.tabName);\n });\n window.addEventListener('popstate', () => {\n console.log(location.pathname);\n console.log(location.pathname.split('/'));\n if (location.pathname.split('/').length === 2) {\n this.showTab = false;\n this.tabName = undefined;\n this.highlightIndex(this.tabName);\n navigateTab(this.dashboardName, this.tabName);\n }\n });\n }\n /**\n * Lit-element lifecycle method.\n * Invoked on each update to perform rendering tasks.\n */\n render() {\n var tabBar = html `${\n // make sure we only render the tabs when there are tabs\n when(this.tabNames.length > 0, () => html `\n \n ${map(this.tabNames, (name) => html ``)}\n `)}`;\n return html `\n ${tabBar}\n ${!this.showTab ?\n html `` :\n html ``}\n `;\n }\n // fetch the tab names to populate the tab bar\n async fetchTabNames() {\n try {\n const response = await fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboards/${this.dashboardName}/tabs`);\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`);\n }\n const data = ListDashboardTabsResponse.fromJson(await response.json());\n var tabNames = ['Summary'];\n data.dashboardTabs.forEach(tab => {\n tabNames.push(tab.name);\n });\n this.tabNames = tabNames;\n this.highlightIndex(this.tabName);\n }\n catch (error) {\n console.error(`Could not get dashboard summaries: ${error}`);\n }\n }\n // identify which tab to highlight on the tab bar\n highlightIndex(tabName) {\n if (tabName === undefined) {\n this.activeIndex = 0;\n return;\n }\n var index = this.tabNames.indexOf(tabName);\n if (index > -1) {\n this.activeIndex = index;\n }\n }\n}", + "default": "class TestgridDataContent extends LitElement {\n constructor() {\n super(...arguments);\n this.tabNames = [];\n this.activeIndex = 0;\n this.showTab = false;\n this.dashboardName = '';\n }\n // set the functionality when any tab is clicked on\n onTabActivated(event) {\n const tabIndex = event.detail.index;\n if (tabIndex === this.activeIndex) {\n return;\n }\n this.tabName = this.tabNames[tabIndex];\n if (this.activeIndex === 0 || tabIndex === 0) {\n this.showTab = !this.showTab;\n }\n this.activeIndex = tabIndex;\n navigateTab(this.dashboardName, this.tabName);\n }\n /**\n * Lit-element lifecycle method.\n * Invoked when a component is added to the document's DOM.\n */\n connectedCallback() {\n super.connectedCallback();\n this.fetchTabNames();\n }\n /**\n * Lit-element lifecycle method.\n * Invoked on each update to perform rendering tasks.\n */\n render() {\n var tabBar = html `${\n // make sure we only render the tabs when there are tabs\n when(this.tabNames.length > 0, () => html `\n \n ${map(this.tabNames, (name) => html ``)}\n `)}`;\n return html `\n ${tabBar}\n ${!this.showTab ?\n html `` :\n html ``}\n `;\n }\n // fetch the tab names to populate the tab bar\n async fetchTabNames() {\n try {\n const response = await fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboards/${this.dashboardName}/tabs`);\n if (!response.ok) {\n throw new Error(`HTTP error: ${response.status}`);\n }\n const data = ListDashboardTabsResponse.fromJson(await response.json());\n var tabNames = ['Summary'];\n data.dashboardTabs.forEach(tab => {\n tabNames.push(tab.name);\n });\n this.tabNames = tabNames;\n this.highlightIndex(this.tabName);\n }\n catch (error) {\n console.error(`Could not get dashboard summaries: ${error}`);\n }\n }\n // identify which tab to highlight on the tab bar\n highlightIndex(tabName) {\n if (tabName === undefined) {\n return;\n }\n var index = this.tabNames.indexOf(tabName);\n if (index > -1) {\n this.activeIndex = index;\n }\n }\n}", "description": "Class definition for the `testgrid-data-content` element.\nActs as a container for dashboard summary or grid data." } ], @@ -1855,27 +1709,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "out-tsc/src/testgrid-failures-summary.js", - "declarations": [ - { - "kind": "variable", - "name": "TestgridFailuresSummary", - "default": "class TestgridFailuresSummary extends LitElement {\n constructor() {\n super(...arguments);\n this.showFailureSummary = false;\n }\n render() {\n var _a;\n return html `\n
\n \n ${this.showFailureSummary ? html `\n \n \n \n \n \n \n \n ${map((_a = this.info) === null || _a === void 0 ? void 0 : _a.failuresSummary.topFailingTests, (test) => html `\n \n \n \n \n \n \n `)}\n
Test Name# FailsFirst FailedLast Passed
${test.displayName}${test.failCount}${test.passTimestamp}${test.failTimestamp}
`\n : ''}\n
\n `;\n }\n dropdownTable() {\n this.showFailureSummary = !this.showFailureSummary;\n }\n}" - } - ], - "exports": [ - { - "kind": "js", - "name": "TestgridFailuresSummary", - "declaration": { - "name": "TestgridFailuresSummary", - "module": "out-tsc/src/testgrid-failures-summary.js" - } - } - ] - }, { "kind": "javascript-module", "path": "out-tsc/src/testgrid-grid-cell.js", @@ -1939,6 +1772,27 @@ } ] }, + { + "kind": "javascript-module", + "path": "out-tsc/src/testgrid-grid-row-id.js", + "declarations": [ + { + "kind": "variable", + "name": "TestgridGridRowId", + "default": "class TestgridGridRowId extends LitElement {\n render() {\n return html `${this.name}`;\n }\n}" + } + ], + "exports": [ + { + "kind": "js", + "name": "TestgridGridRowId", + "declaration": { + "name": "TestgridGridRowId", + "module": "out-tsc/src/testgrid-grid-row-id.js" + } + } + ] + }, { "kind": "javascript-module", "path": "out-tsc/src/testgrid-grid-row-name.js", @@ -2024,27 +1878,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "out-tsc/src/testgrid-healthiness-summary.js", - "declarations": [ - { - "kind": "variable", - "name": "TestgridTabTable", - "default": "class TestgridTabTable extends LitElement {\n constructor() {\n super(...arguments);\n this.showHealthinesSummary = false;\n }\n render() {\n var _a;\n return html `\n
\n \n ${this.showHealthinesSummary ? html `\n \n \n \n \n \n \n \n \n \n ${map((_a = this.info) === null || _a === void 0 ? void 0 : _a.healthinessSummary.topFlakyTests, (test) => {\n var _a, _b, _c, _d, _e, _f;\n return html `\n \n \n \n \n \n \n \n \n `;\n })}\n
Test NameFlakiness (Previous)Flakiness (Current)TrendInfra Failure RateFlaky Tests Count
${test.displayName}${(_b = (_a = this.info) === null || _a === void 0 ? void 0 : _a.healthinessSummary) === null || _b === void 0 ? void 0 : _b.healthinessStats.previousFlakiness}${(_d = (_c = this.info) === null || _c === void 0 ? void 0 : _c.healthinessSummary) === null || _d === void 0 ? void 0 : _d.healthinessStats.averageFlakiness}N/A${test.flakiness}${(_f = (_e = this.info) === null || _e === void 0 ? void 0 : _e.healthinessSummary) === null || _f === void 0 ? void 0 : _f.healthinessStats.numFlakyTests}
`\n : ''}\n
\n `;\n }\n dropdownTable() {\n this.showHealthinesSummary = !this.showHealthinesSummary;\n }\n}" - } - ], - "exports": [ - { - "kind": "js", - "name": "TestgridTabTable", - "declaration": { - "name": "TestgridTabTable", - "module": "out-tsc/src/testgrid-healthiness-summary.js" - } - } - ] - }, { "kind": "javascript-module", "path": "out-tsc/src/testgrid-index.js", @@ -2052,7 +1885,7 @@ { "kind": "variable", "name": "TestgridIndex", - "default": "class TestgridIndex extends LitElement {\n constructor() {\n super(...arguments);\n this.dashboards = [];\n this.dashboardGroups = [];\n this.respectiveDashboards = [];\n // toggles between the dashboards of a particular group or a dashboard without a group\n this.show = true;\n }\n /**\n * Lit-element lifecycle method.\n * Invoked when a component is added to the document's DOM.\n */\n connectedCallback() {\n super.connectedCallback();\n this.fetchDashboardGroups();\n this.fetchDashboards();\n }\n /**\n * Lit-element lifecycle method.\n * Invoked on each update to perform rendering tasks.\n */\n render() {\n return html `\n
\n \n \n ${map(this.dashboardGroups, (dash, index) => html `\n this.fetchRespectiveDashboards(dash)}\"\n >\n
\n

${dash}

\n
\n \n `)}\n
\n\n \n ${this.show ? dashboardTemplate(this.dashboards) : ''}\n\n \n ${!this.show ? dashboardTemplate(this.respectiveDashboards) : ''}\n ${!this.show ? html `\n this.show = !this.show}\">X\n `\n : ''}\n
\n `;\n }\n // fetch the the list of dashboards from the API\n async fetchDashboards() {\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboards`).then(async (response) => {\n const resp = ListDashboardsResponse.fromJson(await response.json());\n const dashboards = [];\n resp.dashboards.forEach(db => {\n if (db.dashboardGroupName === \"\") {\n dashboards.push(db.name);\n }\n });\n this.dashboards = dashboards;\n });\n }\n catch (error) {\n console.log(`failed to fetch: ${error}`);\n }\n }\n // fetch the list of dashboard groups from API\n async fetchDashboardGroups() {\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboard-groups`).then(async (response) => {\n const resp = ListDashboardGroupsResponse.fromJson(await response.json());\n const dashboardGroups = [];\n resp.dashboardGroups.forEach(db => {\n dashboardGroups.push(db.name);\n });\n this.dashboardGroups = dashboardGroups;\n });\n }\n catch (error) {\n console.log(`failed to fetch: ${error}`);\n }\n }\n // fetch the list of respective dashboards for a group from API\n async fetchRespectiveDashboards(name) {\n this.show = false;\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboard-groups/${name}`).then(async (response) => {\n const resp = ListDashboardsResponse.fromJson(await response.json());\n const respectiveDashboards = [];\n resp.dashboards.forEach(ts => {\n respectiveDashboards.push(ts.name);\n });\n this.respectiveDashboards = respectiveDashboards;\n });\n }\n catch (error) {\n console.error(`Could not get dashboard summaries: ${error}`);\n }\n }\n}", + "default": "class TestgridIndex extends LitElement {\n constructor() {\n super(...arguments);\n this.dashboards = [];\n this.dashboardGroups = [];\n this.respectiveDashboards = [];\n // toggles between the dashboards of a particular group or a dashboard without a group\n this.show = true;\n }\n /**\n * Lit-element lifecycle method.\n * Invoked when a component is added to the document's DOM.\n */\n connectedCallback() {\n super.connectedCallback();\n this.fetchDashboardGroups();\n this.fetchDashboards();\n }\n /**\n * Lit-element lifecycle method.\n * Invoked on each update to perform rendering tasks.\n */\n render() {\n return html `\n
\n \n \n ${map(this.dashboardGroups, (dash, index) => html `\n this.fetchRespectiveDashboards(dash)}\"\n >\n
\n

${dash}

\n
\n \n `)}\n
\n\n \n ${this.show ? dashboardTemplate(this.dashboards) : ''}\n\n \n ${!this.show ? dashboardTemplate(this.respectiveDashboards) : ''}\n ${!this.show ? html `\n this.show = !this.show}\">X\n `\n : ''}\n
\n `;\n }\n // fetch the the list of dashboards from the API\n async fetchDashboards() {\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboards`).then(async (response) => {\n const resp = ListDashboardsResponse.fromJson(await response.json());\n const dashboards = [];\n resp.dashboards.forEach(db => {\n console.log(db.dashboardGroupName);\n dashboards.push(db.name);\n });\n this.dashboards = dashboards;\n });\n }\n catch (error) {\n console.log(`failed to fetch: ${error}`);\n }\n }\n // fetch the list of dashboard groups from API\n async fetchDashboardGroups() {\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboard-groups`).then(async (response) => {\n const resp = ListDashboardGroupsResponse.fromJson(await response.json());\n const dashboardGroups = [];\n resp.dashboardGroups.forEach(db => {\n dashboardGroups.push(db.name);\n });\n this.dashboardGroups = dashboardGroups;\n });\n }\n catch (error) {\n console.log(`failed to fetch: ${error}`);\n }\n }\n // fetch the list of respective dashboards for a group from API\n async fetchRespectiveDashboards(name) {\n this.show = false;\n try {\n fetch(`http://${process.env.API_HOST}:${process.env.API_PORT}/api/v1/dashboard-groups/${name}`).then(async (response) => {\n const resp = ListDashboardsResponse.fromJson(await response.json());\n const respectiveDashboards = [];\n resp.dashboards.forEach(ts => {\n respectiveDashboards.push(ts.name);\n });\n this.respectiveDashboards = respectiveDashboards;\n });\n }\n catch (error) {\n console.error(`Could not get dashboard summaries: ${error}`);\n }\n }\n}", "description": "Class definition for the `testgrid-index` element.\nRenders the list of dashboards and dashboard groups available." } ], @@ -2446,6 +2279,57 @@ } ] }, + { + "kind": "javascript-module", + "path": "out-tsc/stories/testgrid-grid-row-header.stories.js", + "declarations": [ + { + "kind": "variable", + "name": "Empty" + }, + { + "kind": "variable", + "name": "Short" + }, + { + "kind": "variable", + "name": "Long" + } + ], + "exports": [ + { + "kind": "js", + "name": "default", + "declaration": { + "module": "out-tsc/stories/testgrid-grid-row-header.stories.js" + } + }, + { + "kind": "js", + "name": "Empty", + "declaration": { + "name": "Empty", + "module": "out-tsc/stories/testgrid-grid-row-header.stories.js" + } + }, + { + "kind": "js", + "name": "Short", + "declaration": { + "name": "Short", + "module": "out-tsc/stories/testgrid-grid-row-header.stories.js" + } + }, + { + "kind": "js", + "name": "Long", + "declaration": { + "name": "Long", + "module": "out-tsc/stories/testgrid-grid-row-header.stories.js" + } + } + ] + }, { "kind": "javascript-module", "path": "out-tsc/stories/testgrid-grid-row-name.stories.js", @@ -3104,6 +2988,66 @@ } ] }, + { + "kind": "javascript-module", + "path": "src/gen/pb/custom_evaluator/custom_evaluator.ts", + "declarations": [ + { + "kind": "variable", + "name": "RuleSet", + "default": "new RuleSet$Type()" + }, + { + "kind": "variable", + "name": "Rule", + "default": "new Rule$Type()" + }, + { + "kind": "variable", + "name": "TestResultComparison", + "default": "new TestResultComparison$Type()" + }, + { + "kind": "variable", + "name": "Comparison", + "default": "new Comparison$Type()" + } + ], + "exports": [ + { + "kind": "js", + "name": "RuleSet", + "declaration": { + "name": "RuleSet", + "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" + } + }, + { + "kind": "js", + "name": "Rule", + "declaration": { + "name": "Rule", + "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" + } + }, + { + "kind": "js", + "name": "TestResultComparison", + "declaration": { + "name": "TestResultComparison", + "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" + } + }, + { + "kind": "js", + "name": "Comparison", + "declaration": { + "name": "Comparison", + "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" + } + } + ] + }, { "kind": "javascript-module", "path": "src/gen/pb/state/state.ts", @@ -3268,66 +3212,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "src/gen/pb/custom_evaluator/custom_evaluator.ts", - "declarations": [ - { - "kind": "variable", - "name": "RuleSet", - "default": "new RuleSet$Type()" - }, - { - "kind": "variable", - "name": "Rule", - "default": "new Rule$Type()" - }, - { - "kind": "variable", - "name": "TestResultComparison", - "default": "new TestResultComparison$Type()" - }, - { - "kind": "variable", - "name": "Comparison", - "default": "new Comparison$Type()" - } - ], - "exports": [ - { - "kind": "js", - "name": "RuleSet", - "declaration": { - "name": "RuleSet", - "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" - } - }, - { - "kind": "js", - "name": "Rule", - "declaration": { - "name": "Rule", - "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" - } - }, - { - "kind": "js", - "name": "TestResultComparison", - "declaration": { - "name": "TestResultComparison", - "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" - } - }, - { - "kind": "js", - "name": "Comparison", - "declaration": { - "name": "Comparison", - "module": "src/gen/pb/custom_evaluator/custom_evaluator.ts" - } - } - ] - }, { "kind": "javascript-module", "path": "src/gen/pb/summary/summary.ts", @@ -3849,6 +3733,78 @@ } ] }, + { + "kind": "javascript-module", + "path": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js", + "declarations": [ + { + "kind": "variable", + "name": "Comparison_Operator" + }, + { + "kind": "variable", + "name": "RuleSet", + "default": "new RuleSet$Type()" + }, + { + "kind": "variable", + "name": "Rule", + "default": "new Rule$Type()" + }, + { + "kind": "variable", + "name": "TestResultComparison", + "default": "new TestResultComparison$Type()" + }, + { + "kind": "variable", + "name": "Comparison", + "default": "new Comparison$Type()" + } + ], + "exports": [ + { + "kind": "js", + "name": "Comparison_Operator", + "declaration": { + "name": "Comparison_Operator", + "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" + } + }, + { + "kind": "js", + "name": "RuleSet", + "declaration": { + "name": "RuleSet", + "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" + } + }, + { + "kind": "js", + "name": "Rule", + "declaration": { + "name": "Rule", + "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" + } + }, + { + "kind": "js", + "name": "TestResultComparison", + "declaration": { + "name": "TestResultComparison", + "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" + } + }, + { + "kind": "js", + "name": "Comparison", + "declaration": { + "name": "Comparison", + "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" + } + } + ] + }, { "kind": "javascript-module", "path": "out-tsc/src/gen/pb/state/state.js", @@ -4013,78 +3969,6 @@ } ] }, - { - "kind": "javascript-module", - "path": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js", - "declarations": [ - { - "kind": "variable", - "name": "Comparison_Operator" - }, - { - "kind": "variable", - "name": "RuleSet", - "default": "new RuleSet$Type()" - }, - { - "kind": "variable", - "name": "Rule", - "default": "new Rule$Type()" - }, - { - "kind": "variable", - "name": "TestResultComparison", - "default": "new TestResultComparison$Type()" - }, - { - "kind": "variable", - "name": "Comparison", - "default": "new Comparison$Type()" - } - ], - "exports": [ - { - "kind": "js", - "name": "Comparison_Operator", - "declaration": { - "name": "Comparison_Operator", - "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" - } - }, - { - "kind": "js", - "name": "RuleSet", - "declaration": { - "name": "RuleSet", - "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" - } - }, - { - "kind": "js", - "name": "Rule", - "declaration": { - "name": "Rule", - "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" - } - }, - { - "kind": "js", - "name": "TestResultComparison", - "declaration": { - "name": "TestResultComparison", - "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" - } - }, - { - "kind": "js", - "name": "Comparison", - "declaration": { - "name": "Comparison", - "module": "out-tsc/src/gen/pb/custom_evaluator/custom_evaluator.js" - } - } - ] - }, { "kind": "javascript-module", "path": "out-tsc/src/gen/pb/summary/summary.js", diff --git a/web/src/gen/pb/config/config.ts b/web/src/gen/pb/config/config.ts index 80859d8..b71dda6 100644 --- a/web/src/gen/pb/config/config.ts +++ b/web/src/gen/pb/config/config.ts @@ -571,14 +571,6 @@ export interface TestGroup_ResultSource { * @generated from protobuf field: testgrid.config.GCSConfig gcs_config = 2; */ gcsConfig: GCSConfig; - } | { - oneofKind: "resultstoreConfig"; - /** - * Invocations stored in ResultStore. - * - * @generated from protobuf field: testgrid.config.ResultStoreConfig resultstore_config = 6; - */ - resultstoreConfig: ResultStoreConfig; } | { oneofKind: undefined; }; @@ -680,26 +672,6 @@ export interface GCSConfig { */ pubsubSubscription: string; } -/** - * ResultStoreConfig specifies results stored in ResultStore. - * - * @generated from protobuf message testgrid.config.ResultStoreConfig - */ -export interface ResultStoreConfig { - /** - * Google Cloud Platform project ID where ResultStore results are stored. - * - * @generated from protobuf field: string project = 1; - */ - project: string; - /** - * A simple query to filter for particular results. - * Currently, only allows a query in the form of `target:""`. - * - * @generated from protobuf field: string query = 2; - */ - query: string; -} /** * Options for where to gather linked issues from. * @@ -2289,8 +2261,7 @@ export const TestGroup_KeyValue = new TestGroup_KeyValue$Type(); class TestGroup_ResultSource$Type extends MessageType { constructor() { super("testgrid.config.TestGroup.ResultSource", [ - { no: 2, name: "gcs_config", kind: "message", oneof: "resultSourceConfig", T: () => GCSConfig }, - { no: 6, name: "resultstore_config", kind: "message", oneof: "resultSourceConfig", T: () => ResultStoreConfig } + { no: 2, name: "gcs_config", kind: "message", oneof: "resultSourceConfig", T: () => GCSConfig } ]); } create(value?: PartialMessage): TestGroup_ResultSource { @@ -2311,12 +2282,6 @@ class TestGroup_ResultSource$Type extends MessageType { gcsConfig: GCSConfig.internalBinaryRead(reader, reader.uint32(), options, (message.resultSourceConfig as any).gcsConfig) }; break; - case /* testgrid.config.ResultStoreConfig resultstore_config */ 6: - message.resultSourceConfig = { - oneofKind: "resultstoreConfig", - resultstoreConfig: ResultStoreConfig.internalBinaryRead(reader, reader.uint32(), options, (message.resultSourceConfig as any).resultstoreConfig) - }; - break; default: let u = options.readUnknownField; if (u === "throw") @@ -2332,9 +2297,6 @@ class TestGroup_ResultSource$Type extends MessageType { /* testgrid.config.GCSConfig gcs_config = 2; */ if (message.resultSourceConfig.oneofKind === "gcsConfig") GCSConfig.internalBinaryWrite(message.resultSourceConfig.gcsConfig, writer.tag(2, WireType.LengthDelimited).fork(), options).join(); - /* testgrid.config.ResultStoreConfig resultstore_config = 6; */ - if (message.resultSourceConfig.oneofKind === "resultstoreConfig") - ResultStoreConfig.internalBinaryWrite(message.resultSourceConfig.resultstoreConfig, writer.tag(6, WireType.LengthDelimited).fork(), options).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); @@ -2407,60 +2369,6 @@ class GCSConfig$Type extends MessageType { */ export const GCSConfig = new GCSConfig$Type(); // @generated message type with reflection information, may provide speed optimized methods -class ResultStoreConfig$Type extends MessageType { - constructor() { - super("testgrid.config.ResultStoreConfig", [ - { no: 1, name: "project", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, - { no: 2, name: "query", kind: "scalar", T: 9 /*ScalarType.STRING*/ } - ]); - } - create(value?: PartialMessage): ResultStoreConfig { - const message = { project: "", query: "" }; - globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); - if (value !== undefined) - reflectionMergePartial(this, message, value); - return message; - } - internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ResultStoreConfig): ResultStoreConfig { - let message = target ?? this.create(), end = reader.pos + length; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case /* string project */ 1: - message.project = reader.string(); - break; - case /* string query */ 2: - message.query = reader.string(); - break; - default: - let u = options.readUnknownField; - if (u === "throw") - throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); - let d = reader.skip(wireType); - if (u !== false) - (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); - } - } - return message; - } - internalBinaryWrite(message: ResultStoreConfig, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { - /* string project = 1; */ - if (message.project !== "") - writer.tag(1, WireType.LengthDelimited).string(message.project); - /* string query = 2; */ - if (message.query !== "") - writer.tag(2, WireType.LengthDelimited).string(message.query); - let u = options.writeUnknownFields; - if (u !== false) - (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); - return writer; - } -} -/** - * @generated MessageType for protobuf message testgrid.config.ResultStoreConfig - */ -export const ResultStoreConfig = new ResultStoreConfig$Type(); -// @generated message type with reflection information, may provide speed optimized methods class IssueGatherOptions$Type extends MessageType { constructor() { super("testgrid.config.IssueGatherOptions", []); diff --git a/web/src/gen/pb/state/state.ts b/web/src/gen/pb/state/state.ts index 2527672..0e8e5e9 100644 --- a/web/src/gen/pb/state/state.ts +++ b/web/src/gen/pb/state/state.ts @@ -180,14 +180,6 @@ export interface AlertInfo { * @generated from protobuf field: repeated string email_addresses = 15; */ emailAddresses: string[]; - /** - * Maps (custom column headers name):(custom column headers value) for arbitrary alert properties. - * - * @generated from protobuf field: map custom_column_headers = 16; - */ - customColumnHeaders: { - [key: string]: string; - }; } /** * Info on default test metadata for a dashboard tab. @@ -766,12 +758,11 @@ class AlertInfo$Type extends MessageType { { no: 14, name: "latest_fail_test_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 12, name: "properties", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "scalar", T: 9 /*ScalarType.STRING*/ } }, { no: 13, name: "hotlist_ids", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, - { no: 15, name: "email_addresses", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, - { no: 16, name: "custom_column_headers", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "scalar", T: 9 /*ScalarType.STRING*/ } } + { no: 15, name: "email_addresses", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ } ]); } create(value?: PartialMessage): AlertInfo { - const message = { failCount: 0, failBuildId: "", failTestId: "", passBuildId: "", failureMessage: "", buildLink: "", buildLinkText: "", buildUrlText: "", latestFailBuildId: "", latestFailTestId: "", properties: {}, hotlistIds: [], emailAddresses: [], customColumnHeaders: {} }; + const message = { failCount: 0, failBuildId: "", failTestId: "", passBuildId: "", failureMessage: "", buildLink: "", buildLinkText: "", buildUrlText: "", latestFailBuildId: "", latestFailTestId: "", properties: {}, hotlistIds: [], emailAddresses: [] }; globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); if (value !== undefined) reflectionMergePartial(this, message, value); @@ -827,9 +818,6 @@ class AlertInfo$Type extends MessageType { case /* repeated string email_addresses */ 15: message.emailAddresses.push(reader.string()); break; - case /* map custom_column_headers */ 16: - this.binaryReadMap16(message.customColumnHeaders, reader, options); - break; default: let u = options.readUnknownField; if (u === "throw") @@ -857,22 +845,6 @@ class AlertInfo$Type extends MessageType { } map[key ?? ""] = val ?? ""; } - private binaryReadMap16(map: AlertInfo["customColumnHeaders"], reader: IBinaryReader, options: BinaryReadOptions): void { - let len = reader.uint32(), end = reader.pos + len, key: keyof AlertInfo["customColumnHeaders"] | undefined, val: AlertInfo["customColumnHeaders"][any] | undefined; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case 1: - key = reader.string(); - break; - case 2: - val = reader.string(); - break; - default: throw new globalThis.Error("unknown map entry field for field testgrid.state.AlertInfo.custom_column_headers"); - } - } - map[key ?? ""] = val ?? ""; - } internalBinaryWrite(message: AlertInfo, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* int32 fail_count = 1; */ if (message.failCount !== 0) @@ -919,9 +891,6 @@ class AlertInfo$Type extends MessageType { /* repeated string email_addresses = 15; */ for (let i = 0; i < message.emailAddresses.length; i++) writer.tag(15, WireType.LengthDelimited).string(message.emailAddresses[i]); - /* map custom_column_headers = 16; */ - for (let k of Object.keys(message.customColumnHeaders)) - writer.tag(16, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.LengthDelimited).string(message.customColumnHeaders[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); diff --git a/web/src/gen/pb/summary/summary.ts b/web/src/gen/pb/summary/summary.ts index 90824ae..3bdbed6 100644 --- a/web/src/gen/pb/summary/summary.ts +++ b/web/src/gen/pb/summary/summary.ts @@ -134,14 +134,6 @@ export interface FailingTestSummary { * @generated from protobuf field: repeated string email_addresses = 18; */ emailAddresses: string[]; - /** - * map of custom column headers - * - * @generated from protobuf field: map custom_column_headers = 19; - */ - customColumnHeaders: { - [key: string]: string; - }; } /** * Metrics about a specific test, i.e. passes, fails, total runs, etc. @@ -501,12 +493,11 @@ class FailingTestSummary$Type extends MessageType { { no: 14, name: "latest_fail_build_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, { no: 15, name: "properties", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "scalar", T: 9 /*ScalarType.STRING*/ } }, { no: 16, name: "hotlist_ids", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, - { no: 18, name: "email_addresses", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ }, - { no: 19, name: "custom_column_headers", kind: "map", K: 9 /*ScalarType.STRING*/, V: { kind: "scalar", T: 9 /*ScalarType.STRING*/ } } + { no: 18, name: "email_addresses", kind: "scalar", repeat: 2 /*RepeatType.UNPACKED*/, T: 9 /*ScalarType.STRING*/ } ]); } create(value?: PartialMessage): FailingTestSummary { - const message = { displayName: "", testName: "", failBuildId: "", failTimestamp: 0, passBuildId: "", passTimestamp: 0, failCount: 0, buildLink: "", buildLinkText: "", buildUrlText: "", failureMessage: "", linkedBugs: [], failTestLink: "", latestFailTestLink: "", latestFailBuildId: "", properties: {}, hotlistIds: [], emailAddresses: [], customColumnHeaders: {} }; + const message = { displayName: "", testName: "", failBuildId: "", failTimestamp: 0, passBuildId: "", passTimestamp: 0, failCount: 0, buildLink: "", buildLinkText: "", buildUrlText: "", failureMessage: "", linkedBugs: [], failTestLink: "", latestFailTestLink: "", latestFailBuildId: "", properties: {}, hotlistIds: [], emailAddresses: [] }; globalThis.Object.defineProperty(message, MESSAGE_TYPE, { enumerable: false, value: this }); if (value !== undefined) reflectionMergePartial(this, message, value); @@ -571,9 +562,6 @@ class FailingTestSummary$Type extends MessageType { case /* repeated string email_addresses */ 18: message.emailAddresses.push(reader.string()); break; - case /* map custom_column_headers */ 19: - this.binaryReadMap19(message.customColumnHeaders, reader, options); - break; default: let u = options.readUnknownField; if (u === "throw") @@ -601,22 +589,6 @@ class FailingTestSummary$Type extends MessageType { } map[key ?? ""] = val ?? ""; } - private binaryReadMap19(map: FailingTestSummary["customColumnHeaders"], reader: IBinaryReader, options: BinaryReadOptions): void { - let len = reader.uint32(), end = reader.pos + len, key: keyof FailingTestSummary["customColumnHeaders"] | undefined, val: FailingTestSummary["customColumnHeaders"][any] | undefined; - while (reader.pos < end) { - let [fieldNo, wireType] = reader.tag(); - switch (fieldNo) { - case 1: - key = reader.string(); - break; - case 2: - val = reader.string(); - break; - default: throw new globalThis.Error("unknown map entry field for field testgrid.summary.FailingTestSummary.custom_column_headers"); - } - } - map[key ?? ""] = val ?? ""; - } internalBinaryWrite(message: FailingTestSummary, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { /* string display_name = 1; */ if (message.displayName !== "") @@ -672,9 +644,6 @@ class FailingTestSummary$Type extends MessageType { /* repeated string email_addresses = 18; */ for (let i = 0; i < message.emailAddresses.length; i++) writer.tag(18, WireType.LengthDelimited).string(message.emailAddresses[i]); - /* map custom_column_headers = 19; */ - for (let k of Object.keys(message.customColumnHeaders)) - writer.tag(19, WireType.LengthDelimited).fork().tag(1, WireType.LengthDelimited).string(k).tag(2, WireType.LengthDelimited).string(message.customColumnHeaders[k]).join(); let u = options.writeUnknownFields; if (u !== false) (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);