From 636f4d39f8badc873b53bddb44a5eb6242626729 Mon Sep 17 00:00:00 2001 From: Tre' Seymour Date: Tue, 8 Sep 2020 12:42:56 -0600 Subject: [PATCH] [QA][Code Coverage] Coverage teams lookup --- .ci/Jenkinsfile_coverage | 9 +- ...gnment.js => generate_team_assignments.js} | 2 +- .../ingest_coverage/__tests__/either.test.js | 16 +- .../__tests__/enumerate_patterns.test.js | 51 +++++ .../__tests__/enumeration_helpers.test.js | 50 +++++ .../__tests__/ingest_helpers.test.js | 25 +-- .../__tests__/mocks/team_assign_mock.json | 3 - .../__tests__/mocks/team_assign_mock.txt | 194 ++++++++++++++++++ .../__tests__/team_assignment.test.js | 45 ---- .../__tests__/transforms.test.js | 22 +- .../ingest_coverage/constants.js | 2 - .../code_coverage/ingest_coverage/either.js | 6 + .../code_coverage/ingest_coverage/index.js | 9 +- .../code_coverage/ingest_coverage/ingest.js | 12 +- .../ingest_coverage/ingest_helpers.js | 7 - .../integration_tests/ingest_coverage.test.js | 21 ++ .../coverage-summary-qa-research-job.json | 28 +++ .../code_coverage/ingest_coverage/process.js | 11 +- .../team_assignment/enumerate_patterns.js | 79 +++++++ .../team_assignment/enumeration_helpers.js | 46 +++++ .../{update_ingest_pipeline.js => flush.js} | 35 ++-- .../ingest_coverage/team_assignment/index.js | 63 +++--- .../ingestion_pipeline_painless.json | 1 - .../team_assignment/parse_owners.js | 48 +++++ .../team_assignment/parse_owners_helpers.js | 48 +++++ .../{get_data.js => parsing_helpers.js} | 19 +- .../ingest_coverage/transforms.js | 54 ++++- .../code_coverage/ingest_coverage/utils.js | 5 +- .../shell_scripts/assign_teams.sh | 15 -- ...e_team_assignments_and_ingest_coverage.sh} | 9 +- vars/kibanaCoverage.groovy | 12 +- vars/kibanaTeamAssign.groovy | 26 ++- 32 files changed, 768 insertions(+), 205 deletions(-) rename scripts/{load_team_assignment.js => generate_team_assignments.js} (96%) create mode 100644 src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js create mode 100644 src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js delete mode 100644 src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json create mode 100644 src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt delete mode 100644 src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js create mode 100644 src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json create mode 100644 src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js create mode 100644 src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js rename src/dev/code_coverage/ingest_coverage/team_assignment/{update_ingest_pipeline.js => flush.js} (51%) delete mode 100644 src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json create mode 100644 src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js create mode 100644 src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js rename src/dev/code_coverage/ingest_coverage/team_assignment/{get_data.js => parsing_helpers.js} (64%) delete mode 100644 src/dev/code_coverage/shell_scripts/assign_teams.sh rename src/dev/code_coverage/shell_scripts/{ingest_coverage.sh => generate_team_assignments_and_ingest_coverage.sh} (78%) diff --git a/.ci/Jenkinsfile_coverage b/.ci/Jenkinsfile_coverage index ebb9c3dc86dd2..339f436e75b75 100644 --- a/.ci/Jenkinsfile_coverage +++ b/.ci/Jenkinsfile_coverage @@ -13,7 +13,6 @@ kibanaPipeline(timeoutMinutes: 240) { workers.base(name: 'coverage-worker', size: 'l', ramDisk: false, bootstrapped: false) { catchError { kibanaCoverage.runTests() - kibanaTeamAssign.load('team_assignment', "### Upload Team Assignment JSON") handleIngestion(TIME_STAMP) } handleFail() @@ -30,7 +29,7 @@ def handleIngestion(timestamp) { kibanaCoverage.collectVcsInfo("### Collect VCS Info") kibanaCoverage.generateReports("### Merge coverage reports") kibanaCoverage.uploadCombinedReports() - kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, previousSha, '### Ingest && Upload') + kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, previousSha, teamAssignmentsPath(), '### Ingest && Upload') kibanaCoverage.uploadCoverageStaticSite(timestamp) } @@ -42,7 +41,7 @@ def handlePreviousSha() { def handleFail() { def buildStatus = buildUtils.getBuildStatus() - if(params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED' && buildStatus != 'UNSTABLE') { + if (params.NOTIFY_ON_FAILURE && buildStatus != 'SUCCESS' && buildStatus != 'ABORTED' && buildStatus != 'UNSTABLE') { slackNotifications.sendFailedBuild( channel: '#kibana-qa', username: 'Kibana QA' @@ -50,3 +49,7 @@ def handleFail() { } } +def teamAssignmentsPath() { + return 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt' +} + diff --git a/scripts/load_team_assignment.js b/scripts/generate_team_assignments.js similarity index 96% rename from scripts/load_team_assignment.js rename to scripts/generate_team_assignments.js index b8f5edc833634..07e29569532fc 100644 --- a/scripts/load_team_assignment.js +++ b/scripts/generate_team_assignments.js @@ -18,4 +18,4 @@ */ require('../src/setup_node_env'); -require('../src/dev/code_coverage/ingest_coverage/team_assignment').uploadTeamAssignmentJson(); +require('../src/dev/code_coverage/ingest_coverage/team_assignment/').generateTeamAssignments(); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js index 3a493539f6743..0ae55508e8434 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/either.test.js @@ -53,7 +53,7 @@ describe(`either datatype functions`, () => { expect(sut.inspect()).to.be('Right(undefined)'); }); }); - describe(`'fromNullable`, () => { + describe(`fromNullable`, () => { it(`should continue processing if a truthy is calculated`, () => { attempt({ detail: 'x' }).fold( () => {}, @@ -64,4 +64,18 @@ describe(`either datatype functions`, () => { attempt(false).fold(expectNull, () => {}); }); }); + describe(`predicate fns`, () => { + it(`right.isRight() is true`, () => { + expect(Either.right('a').isRight()).to.be(true); + }); + it(`right.isLeft() is false`, () => { + expect(Either.right('a').isLeft()).to.be(false); + }); + it(`left.isLeft() is true`, () => { + expect(Either.left().isLeft()).to.be(true); + }); + it(`left.isRight() is true`, () => { + expect(Either.left().isRight()).to.be(false); + }); + }); }); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js new file mode 100644 index 0000000000000..3ad43d9c2f673 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/enumerate_patterns.test.js @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { enumeratePatterns } from '../team_assignment/enumerate_patterns'; +import { resolve } from 'path'; +import { ToolingLog } from '@kbn/dev-utils'; + +const ROOT = resolve(__dirname, '../../../../..'); +const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, +}); + +describe(`enumeratePatterns`, () => { + it(`should not throw an unhandled error on a file path that is a glob, that expands to nothing`, () => { + const absoluteRoot = '/Users/tre/development/projects/kibana'; + expect( + enumeratePatterns(absoluteRoot)(log)( + new Map([['src/legacy/core_plugins/kibana/public/home/*.ts', ['kibana-core-ui']]]) + ) + ).to.eql(''); + }); + it(`should resolve x-pack/plugins/reporting/server/browsers/extract/unzip.js to kibana-reporting`, () => { + const actual = enumeratePatterns(ROOT)(log)( + new Map([['x-pack/plugins/reporting', ['kibana-reporting']]]) + ); + + expect( + actual[0].includes( + 'x-pack/plugins/reporting/server/browsers/extract/unzip.js kibana-reporting' + ) + ).to.be(true); + }); +}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js new file mode 100644 index 0000000000000..f480135b45ac6 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/enumeration_helpers.test.js @@ -0,0 +1,50 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import expect from '@kbn/expect'; +import { tryPath } from '../team_assignment/enumeration_helpers'; + +describe(`enumeration helper fns`, () => { + describe(`tryPath`, () => { + describe(`w/o glob file paths`, () => { + it(`should return a right on an existing path`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/ingest.js'; + const actual = tryPath(aPath); + expect(actual.isRight()).to.be(true); + }); + it(`should return a left on a non existing path`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/does_not_exist.js'; + const actual = tryPath(aPath); + expect(actual.isLeft()).to.be(true); + }); + }); + describe(`with glob file paths`, () => { + it(`should not error when the glob expands to nothing, but instead return a Left`, () => { + const aPath = 'src/legacy/core_plugins/kibana/public/home/*.ts'; + const actual = tryPath(aPath); + expect(actual.isLeft()).to.be(true); + }); + it(`should return a right on a glob that does indeed expand`, () => { + const aPath = 'src/dev/code_coverage/ingest_coverage/*.js'; + const actual = tryPath(aPath); + expect(actual.isRight()).to.be(true); + }); + }); + }); +}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js index 7ca7279e0d64c..f668c1f86f5b0 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/ingest_helpers.test.js @@ -18,13 +18,8 @@ */ import expect from '@kbn/expect'; -import { maybeTeamAssign, whichIndex } from '../ingest_helpers'; -import { - TOTALS_INDEX, - RESEARCH_TOTALS_INDEX, - RESEARCH_COVERAGE_INDEX, - // COVERAGE_INDEX, -} from '../constants'; +import { whichIndex } from '../ingest_helpers'; +import { TOTALS_INDEX, RESEARCH_TOTALS_INDEX, RESEARCH_COVERAGE_INDEX } from '../constants'; describe(`Ingest Helper fns`, () => { describe(`whichIndex`, () => { @@ -56,20 +51,4 @@ describe(`Ingest Helper fns`, () => { }); }); }); - describe(`maybeTeamAssign`, () => { - describe(`against a coverage index`, () => { - it(`should have the pipeline prop`, () => { - const actual = maybeTeamAssign(true, { a: 'blah' }); - expect(actual).to.have.property('pipeline'); - }); - }); - describe(`against a totals index`, () => { - describe(`for "prod"`, () => { - it(`should not have the pipeline prop`, () => { - const actual = maybeTeamAssign(false, { b: 'blah' }); - expect(actual).not.to.have.property('pipeline'); - }); - }); - }); - }); }); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json deleted file mode 100644 index 355c484a84fa3..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "abc": "123" -} diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt new file mode 100644 index 0000000000000..d8924bd563f30 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt @@ -0,0 +1,194 @@ +x-pack/plugins/dashboard_enhanced/public/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/mocks.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/plugin.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/drilldown_shared.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/flyout_create_drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_create_drilldown/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/flyout_edit_drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/index.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/flyout_edit_drilldown/menu_item.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/actions/test_helpers.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_drilldowns_services.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/collect_config_container.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.story.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/dashboard_drilldown_config.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/dashboard_drilldown_config/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/components/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/constants.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.test.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/drilldown.tsx kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/i18n.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/dashboard_to_dashboard_drilldown/types.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/drilldowns/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/public/services/index.ts kibana-app +x-pack/plugins/dashboard_enhanced/scripts/storybook.js kibana-app +x-pack/plugins/discover_enhanced/common/config.ts kibana-app +x-pack/plugins/discover_enhanced/common/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/abstract_explore_data_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.test.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/kibana_url.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/explore_data/shared.ts kibana-app +x-pack/plugins/discover_enhanced/public/actions/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/index.ts kibana-app +x-pack/plugins/discover_enhanced/public/plugin.ts kibana-app +x-pack/plugins/discover_enhanced/server/config.ts kibana-app +x-pack/plugins/discover_enhanced/server/index.ts kibana-app +x-pack/plugins/discover_enhanced/server/plugin.ts kibana-app +x-pack/plugins/lens/common/api.ts kibana-app +x-pack/plugins/lens/common/constants.ts kibana-app +x-pack/plugins/lens/common/index.ts kibana-app +x-pack/plugins/lens/common/types.ts kibana-app +x-pack/plugins/lens/config.ts kibana-app +x-pack/plugins/lens/public/app_plugin/app.test.tsx kibana-app +x-pack/plugins/lens/public/app_plugin/app.tsx kibana-app +x-pack/plugins/lens/public/app_plugin/index.ts kibana-app +x-pack/plugins/lens/public/app_plugin/mounter.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/expression.test.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/expression.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/index.ts kibana-app +x-pack/plugins/lens/public/datatable_visualization/visualization.test.tsx kibana-app +x-pack/plugins/lens/public/datatable_visualization/visualization.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/debounced_component.test.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/debounced_component.tsx kibana-app +x-pack/plugins/lens/public/debounced_component/index.ts kibana-app +x-pack/plugins/lens/public/drag_drop/drag_drop.test.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/drag_drop.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/index.ts kibana-app +x-pack/plugins/lens/public/drag_drop/providers.test.tsx kibana-app +x-pack/plugins/lens/public/drag_drop/providers.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/expression_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/__mocks__/suggestion_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/config_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/dimension_popover.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_actions.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/types.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/expression_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/frame_layout.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/save.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/state_management.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_helpers.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/suggestion_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/chart_switch.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/embeddable_factory.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/embeddable/expression_wrapper.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/format_column.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/index.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/merge_tables.test.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/merge_tables.ts kibana-app +x-pack/plugins/lens/public/editor_frame_service/mocks.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/service.test.tsx kibana-app +x-pack/plugins/lens/public/editor_frame_service/service.tsx kibana-app +x-pack/plugins/lens/public/help_menu_util.tsx kibana-app +x-pack/plugins/lens/public/id_generator/id_generator.test.ts kibana-app +x-pack/plugins/lens/public/id_generator/id_generator.ts kibana-app +x-pack/plugins/lens/public/id_generator/index.ts kibana-app +x-pack/plugins/lens/public/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/loader.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/__mocks__/state_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/change_indexpattern.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/bucket_nesting_editor.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/dimension_panel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/field_select.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/format_selector.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/dimension_panel/popover_editor.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/document_field.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/field_item.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/fields_accordion.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/indexpattern_suggestions.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.test.tsx kibana-app +x-pack/plugins/reporting/server/browsers/download/clean.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/download.test.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/download.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/ensure_downloaded.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/index.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/download/util.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/extract.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/extract_error.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/index.js kibana-reporting +x-pack/plugins/reporting/server/browsers/extract/unzip.js kibana-reporting +x-pack/plugins/reporting/server/browsers/index.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/install.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/network_policy.test.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/network_policy.ts kibana-reporting +x-pack/plugins/reporting/server/browsers/safe_child_process.ts kibana-reporting +x-pack/plugins/reporting/server/config/config.ts kibana-reporting +x-pack/plugins/reporting/server/config/create_config.test.ts kibana-reporting +x-pack/plugins/reporting/server/config/create_config.ts kibana-reporting +x-pack/plugins/reporting/server/config/default_chromium_sandbox_disabled.test.ts kibana-reporting +x-pack/plugins/lens/public/indexpattern_datasource/layerpanel.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/lens_field_icon.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/loader.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/loader.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/mocks.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/no_fields_callout.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/__mocks__/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/cardinality.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/column_types.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/count.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/date_histogram.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/metrics.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.test.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/terms.tsx kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/index.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/operations/operations.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/pure_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/rename_columns.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.test.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/state_helpers.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/types.ts kibana-app +x-pack/plugins/lens/public/indexpattern_datasource/utils.ts kibana-app +x-pack/plugins/lens/public/lens_ui_telemetry/factory.test.ts kibana-app diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js deleted file mode 100644 index e597ffb5d2f4b..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/__tests__/team_assignment.test.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import expect from '@kbn/expect'; -import { fetch } from '../team_assignment/get_data'; -import { noop } from '../utils'; - -describe(`Team Assignment`, () => { - const mockPath = 'src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.json'; - describe(`fetch fn`, () => { - it(`should be a fn`, () => { - expect(typeof fetch).to.be('function'); - }); - describe(`applied to a path that exists`, () => { - it(`should return the contents of the path`, () => { - const sut = fetch(mockPath); - expect(sut.chain(JSON.parse)).to.have.property('abc'); - }); - }); - describe(`applied to an non-existing path`, () => { - it(`should return a Left with the error message within`, () => { - const expectLeft = (err) => - expect(err.message).to.contain('ENOENT: no such file or directory'); - - fetch('fake_path.json').fold(expectLeft, noop); - }); - }); - }); -}); diff --git a/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js b/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js index 746bccc3d718a..79a53cc8f2541 100644 --- a/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js +++ b/src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js @@ -18,7 +18,8 @@ */ import expect from '@kbn/expect'; -import { ciRunUrl, coveredFilePath, itemizeVcs, prokPrevious } from '../transforms'; +import { ciRunUrl, coveredFilePath, itemizeVcs, prokPrevious, teamAssignment } from '../transforms'; +import { ToolingLog } from '@kbn/dev-utils'; describe(`Transform fn`, () => { describe(`ciRunUrl`, () => { @@ -83,4 +84,23 @@ describe(`Transform fn`, () => { ); }); }); + describe(`teamAssignment`, () => { + const teamAssignmentsPathMOCK = + 'src/dev/code_coverage/ingest_coverage/__tests__/mocks/team_assign_mock.txt'; + const coveredFilePath = 'x-pack/plugins/reporting/server/browsers/extract/unzip.js'; + const obj = { coveredFilePath }; + const log = new ToolingLog({ + level: 'info', + writeTo: process.stdout, + }); + + describe(`with a coveredFilePath of ${coveredFilePath}`, () => { + const expected = 'kibana-reporting'; + it(`should resolve to ${expected}`, async () => { + const actual = await teamAssignment(teamAssignmentsPathMOCK)(log)(obj); + const { team } = actual; + expect(team).to.eql(expected); + }); + }); + }); }); diff --git a/src/dev/code_coverage/ingest_coverage/constants.js b/src/dev/code_coverage/ingest_coverage/constants.js index f2f467e461ae5..8f850ac2f1f12 100644 --- a/src/dev/code_coverage/ingest_coverage/constants.js +++ b/src/dev/code_coverage/ingest_coverage/constants.js @@ -27,8 +27,6 @@ export const RESEARCH_COVERAGE_INDEX = export const RESEARCH_TOTALS_INDEX = process.env.RESEARCH_TOTALS_INDEX || `qa_research_total_code_coverage`; -export const TEAM_ASSIGNMENT_PIPELINE_NAME = process.env.PIPELINE_NAME || 'team_assignment'; - export const CODE_COVERAGE_CI_JOB_NAME = 'elastic+kibana+code-coverage'; export const RESEARCH_CI_JOB_NAME = 'elastic+kibana+qa-research'; export const CI_JOB_NAME = process.env.COVERAGE_JOB_NAME || RESEARCH_CI_JOB_NAME; diff --git a/src/dev/code_coverage/ingest_coverage/either.js b/src/dev/code_coverage/ingest_coverage/either.js index eeb48893f18d8..326f238074e30 100644 --- a/src/dev/code_coverage/ingest_coverage/either.js +++ b/src/dev/code_coverage/ingest_coverage/either.js @@ -20,11 +20,15 @@ /* eslint new-cap: 0 */ /* eslint no-unused-vars: 0 */ +import { always } from './utils'; + export const Right = (x) => ({ chain: (f) => f(x), map: (f) => Right(f(x)), fold: (leftFn, rightFn) => rightFn(x), inspect: () => `Right(${x})`, + isLeft: always(false), + isRight: always(true), }); Right.of = function of(x) { @@ -40,6 +44,8 @@ export const Left = (x) => ({ map: (f) => Left(x), fold: (leftFn, rightFn) => leftFn(x), inspect: () => `Left(${x})`, + isLeft: always(true), + isRight: always(false), }); Left.of = function of(x) { diff --git a/src/dev/code_coverage/ingest_coverage/index.js b/src/dev/code_coverage/ingest_coverage/index.js index 4047ee78ee6ec..3bb9ce2f38bc5 100644 --- a/src/dev/code_coverage/ingest_coverage/index.js +++ b/src/dev/code_coverage/ingest_coverage/index.js @@ -23,10 +23,11 @@ import { run, createFlagError } from '@kbn/dev-utils'; const ROOT = resolve(__dirname, '../../../..'); const flags = { - string: ['path', 'verbose', 'vcsInfoPath'], + string: ['path', 'verbose', 'vcsInfoPath', 'teamAssignmentsPath'], help: ` --path Required, path to the file to extract coverage data --vcsInfoPath Required, path to the git info file (branch, sha, author, & commit msg) +--teamAssignmentsPath Required, path to the team assignments data file `, }; @@ -36,12 +37,16 @@ export function runCoverageIngestionCli() { if (flags.path === '') throw createFlagError('please provide a single --path flag'); if (flags.vcsInfoPath === '') throw createFlagError('please provide a single --vcsInfoPath flag'); + if (flags.teamAssignmentsPath === '') + throw createFlagError('please provide a single --teamAssignments flag'); if (flags.verbose) log.verbose(`Verbose logging enabled`); const resolveRoot = resolve.bind(null, ROOT); const jsonSummaryPath = resolveRoot(flags.path); const vcsInfoFilePath = resolveRoot(flags.vcsInfoPath); - prok({ jsonSummaryPath, vcsInfoFilePath }, log); + const { teamAssignmentsPath } = flags; + + prok({ jsonSummaryPath, vcsInfoFilePath, teamAssignmentsPath }, log); }, { description: ` diff --git a/src/dev/code_coverage/ingest_coverage/ingest.js b/src/dev/code_coverage/ingest_coverage/ingest.js index 31a94d161a3cc..24da7a9338a46 100644 --- a/src/dev/code_coverage/ingest_coverage/ingest.js +++ b/src/dev/code_coverage/ingest_coverage/ingest.js @@ -19,7 +19,7 @@ const { Client } = require('@elastic/elasticsearch'); import { createFailError } from '@kbn/dev-utils'; -import { RESEARCH_CI_JOB_NAME, TEAM_ASSIGNMENT_PIPELINE_NAME } from './constants'; +import { RESEARCH_CI_JOB_NAME } from './constants'; import { errMsg, redact, whichIndex } from './ingest_helpers'; import { pretty, green } from './utils'; import { right, left } from './either'; @@ -34,14 +34,10 @@ const isResearchJob = process.env.COVERAGE_JOB_NAME === RESEARCH_CI_JOB_NAME ? t export const ingest = (log) => async (body) => { const isTotal = !!body.isTotal; const index = whichIndex(isResearchJob)(isTotal); - const isACoverageIndex = isTotal ? false : true; const stringified = pretty(body); - const pipeline = TEAM_ASSIGNMENT_PIPELINE_NAME; - const finalPayload = isACoverageIndex - ? { index, body: stringified, pipeline } - : { index, body: stringified }; + const finalPayload = { index, body: stringified }; const justLog = dontSendButLog(log); const doSendToIndex = doSend(index); @@ -77,11 +73,11 @@ async function send(logF, idx, redactedEsHostUrl, client, requestBody) { const sendMsg = (actuallySent, redactedEsHostUrl, payload) => { const { index, body } = payload; return `### ${actuallySent ? 'Sent' : 'Fake Sent'}: -${payload.pipeline ? `\t### Team Assignment Pipeline: ${green(payload.pipeline)}` : ''} ${redactedEsHostUrl ? `\t### ES Host: ${redactedEsHostUrl}` : ''} + \t### Index: ${green(index)} + \t### payload.body: ${body} -${process.env.NODE_ENV === 'integration_test' ? `ingest-pipe=>${payload.pipeline}` : ''} `; }; diff --git a/src/dev/code_coverage/ingest_coverage/ingest_helpers.js b/src/dev/code_coverage/ingest_coverage/ingest_helpers.js index 86bcf03977082..a7822a671887b 100644 --- a/src/dev/code_coverage/ingest_coverage/ingest_helpers.js +++ b/src/dev/code_coverage/ingest_coverage/ingest_helpers.js @@ -24,7 +24,6 @@ import { COVERAGE_INDEX, RESEARCH_COVERAGE_INDEX, RESEARCH_TOTALS_INDEX, - TEAM_ASSIGNMENT_PIPELINE_NAME, TOTALS_INDEX, } from './constants'; @@ -70,12 +69,6 @@ function color(whichColor) { }; } -export function maybeTeamAssign(isACoverageIndex, body) { - const doAddTeam = isACoverageIndex ? true : false; - const payload = doAddTeam ? { ...body, pipeline: TEAM_ASSIGNMENT_PIPELINE_NAME } : body; - return payload; -} - export function whichIndex(isResearchJob) { return (isTotal) => isTotal ? whichTotalsIndex(isResearchJob) : whichCoverageIndex(isResearchJob); diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js index ba73922ec508a..a4d07215efec1 100644 --- a/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/ingest_coverage.test.js @@ -20,6 +20,7 @@ import { resolve } from 'path'; import execa from 'execa'; import expect from '@kbn/expect'; +import shell from 'shelljs'; const ROOT_DIR = resolve(__dirname, '../../../../..'); const MOCKS_DIR = resolve(__dirname, './mocks'); @@ -35,9 +36,14 @@ const env = { }; describe('Ingesting coverage', () => { + const teamAssignmentsPath = + 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'; + const verboseArgs = [ 'scripts/ingest_coverage.js', '--verbose', + '--teamAssignmentsPath', + teamAssignmentsPath, '--vcsInfoPath', 'src/dev/code_coverage/ingest_coverage/integration_tests/mocks/VCS_INFO.txt', '--path', @@ -46,6 +52,21 @@ describe('Ingesting coverage', () => { const summaryPath = 'jest-combined/coverage-summary-manual-mix.json'; const resolved = resolve(MOCKS_DIR, summaryPath); + beforeAll(async () => { + const params = [ + 'scripts/generate_team_assignments.js', + '--src', + '.github/CODEOWNERS', + '--dest', + teamAssignmentsPath, + ]; + await execa(process.execPath, params, { cwd: ROOT_DIR, env }); + }); + + afterAll(() => { + shell.rm(teamAssignmentsPath); + }); + describe(`staticSiteUrl`, () => { let actualUrl = ''; const siteUrlRegex = /"staticSiteUrl":\s*(.+,)/; diff --git a/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json new file mode 100644 index 0000000000000..6e4d8ea954c2c --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/integration_tests/mocks/jest-combined/coverage-summary-qa-research-job.json @@ -0,0 +1,28 @@ +{ + "/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js": { + "lines": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "functions": { + "total": 1, + "covered": 1, + "skipped": 0, + "pct": 100 + }, + "statements": { + "total": 4, + "covered": 4, + "skipped": 0, + "pct": 100 + }, + "branches": { + "total": 0, + "covered": 0, + "skipped": 0, + "pct": 100 + } + } +} diff --git a/src/dev/code_coverage/ingest_coverage/process.js b/src/dev/code_coverage/ingest_coverage/process.js index 85a42cfffa6e2..28a7c9ccd41b0 100644 --- a/src/dev/code_coverage/ingest_coverage/process.js +++ b/src/dev/code_coverage/ingest_coverage/process.js @@ -18,7 +18,7 @@ */ import { fromEventPattern, of, fromEvent } from 'rxjs'; -import { concatMap, delay, map, takeUntil } from 'rxjs/operators'; +import { concatMap, delay, map, mergeMap, takeUntil } from 'rxjs/operators'; import jsonStream from './json_stream'; import { pipe, noop, green, always } from './utils'; import { ingest } from './ingest'; @@ -32,6 +32,7 @@ import { coveredFilePath, ciRunUrl, itemizeVcs, + teamAssignment, } from './transforms'; import { resolve } from 'path'; import { createReadStream } from 'fs'; @@ -50,9 +51,10 @@ const addPrePopulatedTimeStamp = addTimeStamp(process.env.TIME_STAMP || formatte const preamble = pipe(statsAndstaticSiteUrl, rootDirAndOrigPath, buildId, addPrePopulatedTimeStamp); const addTestRunnerAndStaticSiteUrl = pipe(testRunner, staticSite(staticSiteUrlBase)); -const transform = (jsonSummaryPath) => (log) => (vcsInfo) => { +const transform = (jsonSummaryPath) => (log) => (vcsInfo) => (teamAssignmentsPath) => { const objStream = jsonStream(jsonSummaryPath).on('done', noop); const itemizeVcsInfo = itemizeVcs(vcsInfo); + const assignTeams = teamAssignment(teamAssignmentsPath)(log); const jsonSummary$ = (_) => objStream.on('node', '!.*', _); @@ -64,6 +66,7 @@ const transform = (jsonSummaryPath) => (log) => (vcsInfo) => { map(ciRunUrl), map(addJsonSummaryPath(jsonSummaryPath)), map(addTestRunnerAndStaticSiteUrl), + mergeMap(assignTeams), concatMap((x) => of(x).pipe(delay(ms))) ) .subscribe(ingest(log)); @@ -83,7 +86,7 @@ const vcsInfoLines$ = (vcsInfoFilePath) => { return fromEvent(rl, 'line').pipe(takeUntil(fromEvent(rl, 'close'))); }; -export const prok = ({ jsonSummaryPath, vcsInfoFilePath }, log) => { +export const prok = ({ jsonSummaryPath, vcsInfoFilePath, teamAssignmentsPath }, log) => { validateRoot(COVERAGE_INGESTION_KIBANA_ROOT, log); logAll(jsonSummaryPath, log); @@ -93,7 +96,7 @@ export const prok = ({ jsonSummaryPath, vcsInfoFilePath }, log) => { vcsInfoLines$(vcsInfoFilePath).subscribe( mutateVcsInfo(vcsInfo), (err) => log.error(err), - always(xformWithPath(vcsInfo)) + always(xformWithPath(vcsInfo)(teamAssignmentsPath)) ); }; diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js b/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js new file mode 100644 index 0000000000000..8615e4a7cf014 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/enumerate_patterns.js @@ -0,0 +1,79 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { readdirSync, statSync } from 'fs'; +import { join } from 'path'; +import { + push, + prokGlob, + trim, + isBlackListedDir, + isWhiteListedFile, + isDir, + tryPath, + dropEmpty, + notFound, +} from './enumeration_helpers'; +import { stripLeading } from '../transforms'; + +export const enumeratePatterns = (rootPath) => (log) => (patterns) => { + const res = []; + const resPush = push(res); + const logNotFound = notFound(log); + + for (const entry of patterns) { + const [pathPattern, teams] = entry; + const cleaned = stripLeading(pathPattern); + const owner = teams[0]; + const existsWithOwner = pathExists(owner); + + const collect = (x) => existsWithOwner(x).forEach(resPush); + tryPath(cleaned).fold(logNotFound, collect); + } + + return res; + + function pathExists(owner) { + const creeper = (x) => creepFsSync(x, [], rootPath, owner); + return function creepAllAsGlobs(pathPattern) { + return prokGlob(pathPattern).map(creeper).filter(dropEmpty); + }; + } +}; + +function creepFsSync(aPath, xs, rootPath, owner) { + xs = xs || []; + + const joinRoot = join.bind(null, rootPath); + const trimRoot = trim(rootPath); + const joined = joinRoot(aPath); + const isADir = isDir(joined); + + (isADir ? readdirSync(joined) : [aPath]).forEach(maybeRecurse); + + return xs; + + function maybeRecurse(entry) { + const full = isADir ? join(aPath, entry) : entry; + const fullIsDir = statSync(full).isDirectory(); + + if (fullIsDir && !isBlackListedDir(full)) xs = creepFsSync(full, xs, rootPath, owner); + else if (isWhiteListedFile(full)) xs.push(`${trimRoot(full)} ${owner}`); + } +} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js b/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js new file mode 100644 index 0000000000000..44f50ce95e787 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/enumeration_helpers.js @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { statSync } from 'fs'; +import isGlob from 'is-glob'; +import glob from 'glob'; +import { left, right, tryCatch } from '../either'; + +export const push = (xs) => (x) => xs.push(x); +export const pathExists = (x) => tryCatch(() => statSync(x)).fold(left, right); +export const isDir = (x) => statSync(x).isDirectory(); +export const prokGlob = (x) => glob.sync(x, { nonull: true }); +export const trim = (ROOT) => (x) => x.replace(`${ROOT}/`, ''); +export const isWhiteListedFile = (x) => { + const isJsOrTsOrTsxOrJsx = /.(j|t)(s|sx)$/gm; + return isJsOrTsOrTsxOrJsx.test(x); +}; +export const isBlackListedDir = (x) => + /node_modules|__tests__|__fixture__|__fixtures__|build/gm.test(x); +const isGlobFound = (x) => (xs) => (x === xs[0] ? false : true); +export const globExpands = (x) => isGlobFound(x)(prokGlob(x)); +export const tryPath = (x) => { + const isAGlob = isGlob(x); + + if (isAGlob) return globExpands(x) ? right(x) : left(x); + + if (!isAGlob) return pathExists(x).isRight() ? right(x) : left(x); +}; +export const dropEmpty = (x) => x.length > 0; +export const notFound = (log) => (err) => log.error(`\n!!! Not Found: \n${err}`); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js b/src/dev/code_coverage/ingest_coverage/team_assignment/flush.js similarity index 51% rename from src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js rename to src/dev/code_coverage/ingest_coverage/team_assignment/flush.js index 22a9d0a461ebf..5150ac2e655f2 100644 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/update_ingest_pipeline.js +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/flush.js @@ -17,21 +17,28 @@ * under the License. */ -import { createFailError } from '@kbn/dev-utils'; -import { ES_HOST } from '../constants'; -import { pretty, green } from '../utils'; +import { writeFileSync } from 'fs'; +import shell from 'shelljs'; +import { tryCatch } from '../either'; +import { id } from '../utils'; -const { Client } = require('@elastic/elasticsearch'); +const encoding = 'utf8'; +const appendUtf8 = { flag: 'a', encoding }; -const node = ES_HOST; -const client = new Client({ node }); +export const flush = (dest) => (log) => (assignments) => { + log.verbose(`\n### Flushing assignments to: \n\t${dest}`); -export const update = (id) => (log) => async (body) => { - try { - await client.ingest.putPipeline({ id, body }); - log.verbose(`### Ingestion Pipeline ID: ${green(id)}`); - log.verbose(`### Payload Partial: \n${body.slice(0, 600)}...`); - } catch (e) { - throw createFailError(`${pretty(e.meta)}`); - } + const writeToFile = writeFileSync.bind(null, dest); + + writeToFile('', { encoding }); + + for (const xs of assignments) xs.forEach((x) => writeToFile(`${x}\n`, appendUtf8)); + + tryCatch(() => maybeShowSize(dest)).fold(id, (x) => { + log.verbose(`\n### Flushed [${x}] lines`); + }); }; +function maybeShowSize(x) { + const { output } = shell.exec(`wc -l ${x}`, { silent: true }); + return output.match(/\s*\d*\s*/)[0].trim(); +} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/index.js b/src/dev/code_coverage/ingest_coverage/team_assignment/index.js index 11f9748708283..3225198e1fd20 100644 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/index.js +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/index.js @@ -17,42 +17,41 @@ * under the License. */ -import { run } from '@kbn/dev-utils'; -import { TEAM_ASSIGNMENT_PIPELINE_NAME } from '../constants'; -import { fetch } from './get_data'; -import { update } from './update_ingest_pipeline'; +import { run, createFlagError } from '@kbn/dev-utils'; +import { parse } from './parse_owners'; +import { flush } from './flush'; +import { enumeratePatterns } from './enumerate_patterns'; +import { resolve } from 'path'; -const updatePipeline = update(TEAM_ASSIGNMENT_PIPELINE_NAME); - -const execute = ({ flags, log }) => { - if (flags.verbose) log.verbose(`### Verbose logging enabled`); - - const logLeft = handleErr(log); - const updateAndLog = updatePipeline(log); - - const { path } = flags; - - fetch(path).fold(logLeft, updateAndLog); -}; - -function handleErr(log) { - return (msg) => log.error(msg); -} - -const description = ` - -Upload the latest team assignment pipeline def from src, -to the cluster. - - `; +const ROOT = resolve(__dirname, '../../../../..'); const flags = { - string: ['path', 'verbose'], + string: ['src', 'dest'], help: ` ---path Required, path to painless definition for team assignment. +--src Required, path to CODEOWNERS file. +--dest Required, destination path of the assignments. `, }; -const usage = 'node scripts/load_team_assignment.js --verbose --path PATH_TO_PAINLESS_SCRIPT.json'; - -export const uploadTeamAssignmentJson = () => run(execute, { description, flags, usage }); +export const generateTeamAssignments = () => { + run( + ({ flags, log }) => { + if (flags.src === '') throw createFlagError('please provide a single --src flag'); + if (flags.dest === '') throw createFlagError('please provide a single --dest flag'); + const parseCodeOwners = parse(flags.src); + // TODO: Change the flow such that "Find Definition" easily finds these symbols. + // Currently, I'm just passing closures, point free. + parseCodeOwners(log)(enumeratePatterns(ROOT))(flush(flags.dest)); + }, + { + description: ` + +Create a file defining the team assignments, + parsed from the source of truth in + kbn-dev-utils. + + `, + flags, + } + ); +}; diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json b/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json deleted file mode 100644 index 30e78635ec2e9..0000000000000 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json +++ /dev/null @@ -1 +0,0 @@ -{"description":"Kibana code coverage team assignments","processors":[{"script":{"lang":"painless","source":"\n String path = ctx.coveredFilePath; \n if (path.indexOf('src/legacy/core_plugins/kibana/') == 0) {\n\n if (path.indexOf('src/legacy/core_plugins/kibana/common/utils') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/migrations') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/dashboard/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/dev_tools/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/discover/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/home') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/home/np_ready/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/local_application_service/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/kibana/public/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/lib') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/lib/management/saved_objects') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/import/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/kibana/server/routes/api/export/') == 0) ctx.team = 'kibana-platform';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/core_plugins/') == 0) {\n\n if (path.indexOf('src/legacy/core_plugins/apm_oss/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/legacy/core_plugins/console_legacy') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/elasticsearch') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/core_plugins/embeddable_api/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/input_control_vis') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/interpreter/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/kibana_react/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/newsfeed') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/legacy/core_plugins/region_map') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/legacy/core_plugins/status_page/public') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/core_plugins/testbed') == 0) ctx.team = 'kibana-platform';\n // else if (path.indexOf('src/legacy/core_plugins/tests_bundle/') == 0) ctx.team = 'kibana-platform';\n \n else if (path.indexOf('src/legacy/core_plugins/tile_map') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/legacy/core_plugins/timelion') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/ui_metric/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_tagcloud') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_vega') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/vis_type_vislib/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/core_plugins/visualizations/') == 0) ctx.team = 'kibana-app-arch';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/server/') == 0) {\n\n if (path.indexOf('src/legacy/server/config/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/http/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/legacy/server/index_patterns/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/server/keystore/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/logging/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/pid/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/sample_data/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/server/sass/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/saved_objects/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/status/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/server/url_shortening/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/server/utils/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/legacy/server/warnings/') == 0) ctx.team = 'kibana-operations';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('src/legacy/ui') == 0) {\n\n if (path.indexOf('src/legacy/ui/public/field_editor') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/timefilter') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/management') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/legacy/ui/public/state_management') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/legacy/ui/public/new_platform') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/plugin_discovery') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/chrome') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/notify') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/documentation_links') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/autoload') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/legacy/ui/public/capabilities') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('src/legacy/ui/public/apm') == 0) ctx.team = 'apm-ui';\n\n } else if (path.indexOf('src/plugins/') == 0) {\n\n if (path.indexOf('src/plugins/advanced_settings/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/apm_oss/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/plugins/bfetch/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/charts/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/charts/public/static/color_maps') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/console/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/dashboard/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/data/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/dev_tools/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/discover/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/embeddable/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/es_ui_shared/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('src/plugins/expressions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/home/public') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/home/server/tutorials') == 0) ctx.team = 'observability';\n else if (path.indexOf('src/plugins/home/server/services/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/home/') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/index_pattern_management/public/service') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/index_pattern_management/public') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/input_control_vis/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/inspector/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_legacy/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/kibana_react/public/code_editor') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('src/plugins/kibana_react/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_utils/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/management/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/kibana_usage_collection/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/legacy_export/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/maps_legacy/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/region_map/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/tile_map/') == 0) ctx.team = 'maps';\n else if (path.indexOf('src/plugins/timelion') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/navigation/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/newsfeed') == 0) ctx.team = 'kibana-core-ui';\n else if (path.indexOf('src/plugins/saved_objects_management/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/saved_objects/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/share/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/status_page/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/telemetry') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/testbed/server/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/plugins/ui_actions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/usage_collection/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('src/plugins/vis_default_editor') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/vis_type') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('src/plugins/visualizations/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('src/plugins/visualize/') == 0) ctx.team = 'kibana-app';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('x-pack/legacy/') == 0) {\n\n if (path.indexOf('x-pack/legacy/plugins/actions/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/alerting/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/apm/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/legacy/plugins/beats_management/') == 0) ctx.team = 'beats';\n else if (path.indexOf('x-pack/legacy/plugins/canvas/') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('x-pack/legacy/plugins/cross_cluster_replication/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/dashboard_mode/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/legacy/plugins/encrypted_saved_objects/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/legacy/plugins/index_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/infra/') == 0) ctx.team = 'logs-metrics-ui';\n else if (path.indexOf('x-pack/legacy/plugins/ingest_manager/') == 0) ctx.team = 'ingest-management';\n else if (path.indexOf('x-pack/legacy/plugins/license_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/maps/') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/legacy/plugins/ml/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/legacy/plugins/monitoring/') == 0) ctx.team = 'stack-monitoring-ui';\n else if (path.indexOf('x-pack/legacy/plugins/reporting') == 0) ctx.team = 'kibana-reporting';\n else if (path.indexOf('x-pack/legacy/plugins/rollup/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/security/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/legacy/plugins/siem/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/legacy/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules') == 0) ctx.team = 'security-intelligence-analytics';\n else if (path.indexOf('x-pack/legacy/plugins/snapshot_restore/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/spaces/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/legacy/plugins/task_manager') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/triggers_actions_ui/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/legacy/plugins/upgrade_assistant/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/plugins/uptime') == 0) ctx.team = 'uptime';\n else if (path.indexOf('x-pack/legacy/plugins/xpack_main/server/') == 0) ctx.team = 'kibana-platform';\n\n else if (path.indexOf('x-pack/legacy/server/lib/create_router/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/legacy/server/lib/check_license/') == 0) ctx.team = 'es-ui'; \n else if (path.indexOf('x-pack/legacy/server/lib/') == 0) ctx.team = 'kibana-platform'; \n else ctx.team = 'unknown';\n\n } else if (path.indexOf('x-pack/plugins/') == 0) {\n\n if (path.indexOf('x-pack/plugins/actions/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/advanced_ui_actions/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/alerts') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/alerting_builtins') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/apm/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/plugins/beats_management/') == 0) ctx.team = 'beats';\n else if (path.indexOf('x-pack/plugins/canvas/') == 0) ctx.team = 'kibana-canvas';\n else if (path.indexOf('x-pack/plugins/case') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/cloud/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/code/') == 0) ctx.team = 'code';\n else if (path.indexOf('x-pack/plugins/console_extensions/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/cross_cluster_replication/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/dashboard_enhanced') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/dashboard_mode') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/discover_enhanced') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/embeddable_enhanced') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/data_enhanced/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/drilldowns/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/encrypted_saved_objects/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/endpoint/') == 0) ctx.team = 'endpoint-app-team';\n else if (path.indexOf('x-pack/plugins/es_ui_shared/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/event_log/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/features/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/file_upload') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/plugins/global_search') == 0) ctx.team = 'kibana-platform';\n \n else if (path.indexOf('x-pack/plugins/graph/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/grokdebugger/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/index_lifecycle_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/index_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/infra/') == 0) ctx.team = 'logs-metrics-ui';\n else if (path.indexOf('x-pack/plugins/ingest_manager/') == 0) ctx.team = 'ingest-management';\n else if (path.indexOf('x-pack/plugins/ingest_pipelines/') == 0) ctx.team = 'es-ui';\n \n else if (path.indexOf('x-pack/plugins/lens/') == 0) ctx.team = 'kibana-app';\n else if (path.indexOf('x-pack/plugins/license_management/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/licensing/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('x-pack/plugins/lists/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/logstash') == 0) ctx.team = 'logstash';\n else if (path.indexOf('x-pack/plugins/maps/') == 0) ctx.team = 'kibana-gis';\n else if (path.indexOf('x-pack/plugins/maps_legacy_licensing') == 0) ctx.team = 'maps';\n else if (path.indexOf('x-pack/plugins/ml/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/plugins/monitoring') == 0) ctx.team = 'stack-monitoring-ui';\n else if (path.indexOf('x-pack/plugins/observability/') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('x-pack/plugins/oss_telemetry/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('x-pack/plugins/painless_lab/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/remote_clusters/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/reporting') == 0) ctx.team = 'kibana-reporting';\n else if (path.indexOf('x-pack/plugins/rollup/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/searchprofiler/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/security/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/security_solution/') == 0) ctx.team = 'siem';\n \n else if (path.indexOf('x-pack/plugins/siem/server/lib/detection_engine/rules/prepackaged_rules') == 0) ctx.team = 'security-intelligence-analytics';\n else if (path.indexOf('x-pack/plugins/siem/') == 0) ctx.team = 'siem';\n else if (path.indexOf('x-pack/plugins/snapshot_restore/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/spaces/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('x-pack/plugins/task_manager/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/telemetry_collection_xpack/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('x-pack/plugins/transform/') == 0) ctx.team = 'ml-ui';\n else if (path.indexOf('x-pack/plugins/translations/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('x-pack/plugins/triggers_actions_ui/') == 0) ctx.team = 'kibana-alerting-services';\n else if (path.indexOf('x-pack/plugins/upgrade_assistant/') == 0) ctx.team = 'es-ui';\n else if (path.indexOf('x-pack/plugins/ui_actions_enhanced') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('x-pack/plugins/uptime') == 0) ctx.team = 'uptime';\n \n else if (path.indexOf('x-pack/plugins/watcher/') == 0) ctx.team = 'es-ui';\n else ctx.team = 'unknown';\n\n } else if (path.indexOf('packages') == 0) {\n\n if (path.indexOf('packages/kbn-analytics/') == 0) ctx.team = 'pulse';\n else if (path.indexOf('packages/kbn-babel') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-config-schema/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('packages/elastic-datemath') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('packages/kbn-dev-utils') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-es/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-eslint') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-expect') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('packages/kbn-interpreter/') == 0) ctx.team = 'kibana-app-arch';\n else if (path.indexOf('packages/kbn-optimizer/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-pm/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-test/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-test-subj-selector/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('packages/kbn-ui-framework/') == 0) ctx.team = 'kibana-design';\n else if (path.indexOf('packages/kbn-ui-shared-deps/') == 0) ctx.team = 'kibana-operations';\n else ctx.team = 'unknown';\n\n } else {\n\n if (path.indexOf('config/kibana.yml') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/apm.js') == 0) ctx.team = 'apm-ui';\n else if (path.indexOf('src/core/') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('src/core/public/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/core/server/csp/') == 0) ctx.team = 'kibana-security';\n else if (path.indexOf('src/dev/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/dev/i18n/') == 0) ctx.team = 'kibana-localization';\n else if (path.indexOf('src/dev/run_check_published_api_changes.ts') == 0) ctx.team = 'kibana-platform';\n else if (path.indexOf('packages/kbn-es-archiver/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/optimize/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/setup_node_env/') == 0) ctx.team = 'kibana-operations';\n else if (path.indexOf('src/test_utils/') == 0) ctx.team = 'kibana-operations'; \n else ctx.team = 'unknown';\n }"}}]} diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js new file mode 100644 index 0000000000000..5c286bf747b80 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners.js @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { fromEvent } from 'rxjs'; +import { map, filter, takeUntil } from 'rxjs/operators'; +import { lineRead, pathAndTeams, empties, comments, dropCCDelim } from './parse_owners_helpers'; +import { pipe } from '../utils'; + +const mutate = (xs) => (x) => xs.push(x); +export const parse = (codeOwnersPath) => (log) => (enumerationF) => (flushF) => { + const cleanAndParse = pipe(dropCCDelim, pathAndTeams); + const allLines$ = (lineReader) => + fromEvent(lineReader, 'line').pipe( + filter(empties), + filter(comments), + map(cleanAndParse), + takeUntil(fromEvent(lineReader, 'close')) + ); + + const rl = lineRead(codeOwnersPath); + const data = []; + const mutateData = mutate(data); + allLines$(rl).subscribe( + mutateData, + (e) => log.error(e), + () => { + log.verbose(`\n### Parsing [${codeOwnersPath}] Complete`); + // TODO: Maybe change this pipe such that the log object is not passed twice. + pipe(enumerationF(log), flushF(log))(new Map(data)); + } + ); +}; diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js new file mode 100644 index 0000000000000..454accb00a7b6 --- /dev/null +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parse_owners_helpers.js @@ -0,0 +1,48 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { always, id, pipe } from '../utils'; +import * as Either from '../either'; +import readline from 'readline'; +import { createReadStream } from 'fs'; +import { pluckIndex } from '../transforms'; + +const coverageDelimRe = /^#CC#\s/; + +export const empties = (x) => x !== ''; +export const comments = (x) => !/^#\s{1,3}/.test(x); +const dropDelim = (x) => () => x.replace(coverageDelimRe, ''); + +export const dropCCDelim = (x) => + Either.fromNullable(coverageDelimRe.test(x)).fold(always(x), id(dropDelim(x))); + +const splitFilter = (splitter) => (x) => x.split(splitter).filter(empties); +const spaceSplit = splitFilter(' '); +const esSplit = splitFilter('@elastic/'); +const getFirst = pluckIndex(0); +const trimEsGrabFirst = pipe(esSplit, getFirst); + +export const pathAndTeams = (x) => { + const [path, ...teamEntries] = spaceSplit(x); + const teams = teamEntries.map(trimEsGrabFirst); + + return [path, teams]; +}; + +export const lineRead = (x) => readline.createInterface({ input: createReadStream(x) }); diff --git a/src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js b/src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js similarity index 64% rename from src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js rename to src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js index 34526a2f79302..50dd6f719f34e 100644 --- a/src/dev/code_coverage/ingest_coverage/team_assignment/get_data.js +++ b/src/dev/code_coverage/ingest_coverage/team_assignment/parsing_helpers.js @@ -17,17 +17,14 @@ * under the License. */ -import { readFileSync } from 'fs'; -import { resolve } from 'path'; -import { tryCatch as tc } from '../either'; +import { always } from '../utils'; +import * as Either from '../either'; -const ROOT = resolve(__dirname, '../../../../..'); +const coverageDelimRe = /^#CC#\s/; -const resolveFromRoot = resolve.bind(null, ROOT); +export const empties = (x) => x !== ''; +export const comments = (x) => !/^#\s{1,3}/.test(x); +const dropDelim = (x) => x.replace(coverageDelimRe, ''); -const resolved = (path) => () => resolveFromRoot(path); - -const getContents = (path) => tc(() => readFileSync(path, 'utf8')); - -// fetch :: String -> Left | Right -export const fetch = (path) => tc(resolved(path)).chain(getContents); +export const dropCCDelim = (x) => + Either.fromNullable(coverageDelimRe.test(x)).fold(always(x), always(dropDelim(x))); diff --git a/src/dev/code_coverage/ingest_coverage/transforms.js b/src/dev/code_coverage/ingest_coverage/transforms.js index b8c9acd6fc49d..d88ab08222f49 100644 --- a/src/dev/code_coverage/ingest_coverage/transforms.js +++ b/src/dev/code_coverage/ingest_coverage/transforms.js @@ -18,8 +18,12 @@ */ import * as Either from './either'; -import { fromNullable } from './maybe'; -import { always, id, noop } from './utils'; +import * as Maybe from './maybe'; +import { always, id, noop, pink } from './utils'; +import execa from 'execa'; +import { resolve } from 'path'; + +const ROOT_DIR = resolve(__dirname, '../../../..'); const maybeTotal = (x) => (x === 'total' ? Either.left(x) : Either.right(x)); @@ -83,20 +87,53 @@ export const staticSite = (urlBase) => (obj) => { return { ...obj, staticSiteUrl: prokForBoth() }; }; +const leadingSlashRe = /^\//; +export const maybeDropLeadingSlash = (x) => + leadingSlashRe.test(x) ? Either.right(x) : Either.left(x); +export const dropLeadingSlash = (x) => x.replace(leadingSlashRe, ''); +export const stripLeading = (x) => maybeDropLeadingSlash(x).fold(id, dropLeadingSlash); + export const coveredFilePath = (obj) => { const { staticSiteUrl, COVERAGE_INGESTION_KIBANA_ROOT } = obj; const withoutCoveredFilePath = always(obj); - const leadingSlashRe = /^\//; - const maybeDropLeadingSlash = (x) => (leadingSlashRe.test(x) ? Either.right(x) : Either.left(x)); - const dropLeadingSlash = (x) => x.replace(leadingSlashRe, ''); - const dropRoot = (root) => (x) => - maybeDropLeadingSlash(x.replace(root, '')).fold(id, dropLeadingSlash); + const dropRoot = (root) => (x) => stripLeading(x.replace(root, '')); return maybeTotal(staticSiteUrl) .map(dropRoot(COVERAGE_INGESTION_KIBANA_ROOT)) .fold(withoutCoveredFilePath, (coveredFilePath) => ({ ...obj, coveredFilePath })); }; +const findTeam = (x) => x.match(/.+\s{1,3}(.+)$/, 'gm'); +export const pluckIndex = (idx) => (xs) => xs[idx]; +const pluckTeam = pluckIndex(1); + +export const teamAssignment = (teamAssignmentsPath) => (log) => async (obj) => { + const { coveredFilePath } = obj; + const isTotal = Either.fromNullable(obj.isTotal); + + return isTotal.isRight() ? obj : await assignTeam(teamAssignmentsPath, coveredFilePath, log, obj); +}; +async function assignTeam(teamAssignmentsPath, coveredFilePath, log, obj) { + const params = [coveredFilePath, teamAssignmentsPath]; + + let grepResponse; + + try { + const { stdout } = await execa('grep', params, { cwd: ROOT_DIR }); + grepResponse = stdout; + } catch (e) { + log.error(`\n!!! Unknown Team for path: \n\t\t${pink(coveredFilePath)}\n`); + } + + return Either.fromNullable(grepResponse) + .map(findTeam) + .map(pluckTeam) + .fold( + () => ({ team: 'unknown', ...obj }), + (team) => ({ team, ...obj }) + ); +} + export const ciRunUrl = (obj) => Either.fromNullable(process.env.CI_RUN_URL).fold(always(obj), (ciRunUrl) => ({ ...obj, @@ -126,13 +163,12 @@ export const itemizeVcs = (vcsInfo) => (obj) => { }; const mutateVcs = (x) => (vcs.commitMsg = truncateMsg(x)); - fromNullable(commitMsg).map(mutateVcs); + Maybe.fromNullable(commitMsg).map(mutateVcs); const vcsCompareUrl = process.env.FETCHED_PREVIOUS ? `${comparePrefix()}/${process.env.FETCHED_PREVIOUS}...${sha}` : 'PREVIOUS SHA NOT PROVIDED'; - // const withoutPreviousL = always({ ...obj, vcs }); const withPreviousR = () => ({ ...obj, vcs: { diff --git a/src/dev/code_coverage/ingest_coverage/utils.js b/src/dev/code_coverage/ingest_coverage/utils.js index 7d817bdf7a6f3..274786b82da5c 100644 --- a/src/dev/code_coverage/ingest_coverage/utils.js +++ b/src/dev/code_coverage/ingest_coverage/utils.js @@ -22,6 +22,9 @@ import chalk from 'chalk'; export const pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args))); export const noop = () => {}; export const green = (x) => chalk.greenBright.bold(x); +export const pink = (x) => chalk.bgMagenta.bold.cyan.bold(x); export const id = (x) => x; -export const always = (x) => () => x; +export const always = (x) => () => x; // Wraps a value in a fn. Eager evaluation if passed a fn. export const pretty = (x) => JSON.stringify(x, null, 2); +export const pluck = (x) => (obj) => obj[x]; +export const flip2 = (f) => (a) => (b) => f(b)(a); diff --git a/src/dev/code_coverage/shell_scripts/assign_teams.sh b/src/dev/code_coverage/shell_scripts/assign_teams.sh deleted file mode 100644 index aaa14655a9a26..0000000000000 --- a/src/dev/code_coverage/shell_scripts/assign_teams.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -echo "### Code Coverage Team Assignment" -echo "" - -PIPELINE_NAME=$1 -export PIPELINE_NAME - -ES_HOST="https://${USER_FROM_VAULT}:${PASS_FROM_VAULT}@${HOST_FROM_VAULT}" -export ES_HOST - -node scripts/load_team_assignment.js --verbose --path src/dev/code_coverage/ingest_coverage/team_assignment/ingestion_pipeline_painless.json - -echo "### Code Coverage Team Assignment - Complete" -echo "" diff --git a/src/dev/code_coverage/shell_scripts/ingest_coverage.sh b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh similarity index 78% rename from src/dev/code_coverage/shell_scripts/ingest_coverage.sh rename to src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh index 0b67dac307473..62b81929ae79b 100644 --- a/src/dev/code_coverage/shell_scripts/ingest_coverage.sh +++ b/src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh @@ -27,19 +27,24 @@ export STATIC_SITE_URL_BASE DELAY=100 export DELAY +TEAM_ASSIGN_PATH=$5 + +# Build team assignments dat file +node scripts/generate_team_assignments.js --verbose --src .github/CODEOWNERS --dest $TEAM_ASSIGN_PATH + for x in jest functional; do echo "### Ingesting coverage for ${x}" COVERAGE_SUMMARY_FILE=target/kibana-coverage/${x}-combined/coverage-summary.json - node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt + node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH done # Need to override COVERAGE_INGESTION_KIBANA_ROOT since mocha json file has original intake worker path COVERAGE_SUMMARY_FILE=target/kibana-coverage/mocha-combined/coverage-summary.json export COVERAGE_INGESTION_KIBANA_ROOT=/dev/shm/workspace/kibana -node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt +node scripts/ingest_coverage.js --verbose --path ${COVERAGE_SUMMARY_FILE} --vcsInfoPath ./VCS_INFO.txt --teamAssignmentsPath $TEAM_ASSIGN_PATH echo "### Ingesting Code Coverage - Complete" echo "" diff --git a/vars/kibanaCoverage.groovy b/vars/kibanaCoverage.groovy index 66ebe3478fbec..e75ed8fef9875 100644 --- a/vars/kibanaCoverage.groovy +++ b/vars/kibanaCoverage.groovy @@ -169,31 +169,31 @@ def uploadCombinedReports() { ) } -def ingestData(jobName, buildNum, buildUrl, previousSha, title) { +def ingestData(jobName, buildNum, buildUrl, previousSha, teamAssignmentsPath, title) { kibanaPipeline.bash(""" source src/dev/ci_setup/setup_env.sh yarn kbn bootstrap --prefer-offline # Using existing target/kibana-coverage folder - . src/dev/code_coverage/shell_scripts/ingest_coverage.sh '${jobName}' ${buildNum} '${buildUrl}' ${previousSha} + . src/dev/code_coverage/shell_scripts/generate_team_assignments_and_ingest_coverage.sh '${jobName}' ${buildNum} '${buildUrl}' '${previousSha}' '${teamAssignmentsPath}' """, title) } -def ingestWithVault(jobName, buildNum, buildUrl, previousSha, title) { +def ingestWithVault(jobName, buildNum, buildUrl, previousSha, teamAssignmentsPath, title) { def vaultSecret = 'secret/kibana-issues/prod/coverage/elasticsearch' withVaultSecret(secret: vaultSecret, secret_field: 'host', variable_name: 'HOST_FROM_VAULT') { withVaultSecret(secret: vaultSecret, secret_field: 'username', variable_name: 'USER_FROM_VAULT') { withVaultSecret(secret: vaultSecret, secret_field: 'password', variable_name: 'PASS_FROM_VAULT') { - ingestData(jobName, buildNum, buildUrl, previousSha, title) + ingestData(jobName, buildNum, buildUrl, previousSha, teamAssignmentsPath, title) } } } } -def ingest(jobName, buildNumber, buildUrl, timestamp, previousSha, title) { +def ingest(jobName, buildNumber, buildUrl, timestamp, previousSha, teamAssignmentsPath, title) { withEnv([ "TIME_STAMP=${timestamp}", ]) { - ingestWithVault(jobName, buildNumber, buildUrl, previousSha, title) + ingestWithVault(jobName, buildNumber, buildUrl, previousSha, teamAssignmentsPath, title) } } diff --git a/vars/kibanaTeamAssign.groovy b/vars/kibanaTeamAssign.groovy index a3d9c16ef506e..fb93ed8ee0942 100644 --- a/vars/kibanaTeamAssign.groovy +++ b/vars/kibanaTeamAssign.groovy @@ -1,25 +1,23 @@ -def loadIngestionPipeline(ingestionPipelineName, title) { +def generateCodeOwners(destination, title) { kibanaPipeline.bash(""" source src/dev/ci_setup/setup_env.sh true yarn kbn bootstrap --prefer-offline - . src/dev/code_coverage/shell_scripts/assign_teams.sh '${ingestionPipelineName}' + . packages/kbn-dev-utils/src/code_ownership/shell_scripts/generate_code_owners.sh '${destination}' + cat '${destination}' """, title) } -def loadWithVault(ingestionPipelineName, title) { - def vaultSecret = 'secret/kibana-issues/prod/coverage/elasticsearch' - withVaultSecret(secret: vaultSecret, secret_field: 'host', variable_name: 'HOST_FROM_VAULT') { - withVaultSecret(secret: vaultSecret, secret_field: 'username', variable_name: 'USER_FROM_VAULT') { - withVaultSecret(secret: vaultSecret, secret_field: 'password', variable_name: 'PASS_FROM_VAULT') { - loadIngestionPipeline(ingestionPipelineName, title) - } - } - } -} +def generateTeamAssignments(teamAssignmentsPath, title) { + kibanaPipeline.bash(""" + source src/dev/ci_setup/setup_env.sh + yarn kbn bootstrap --prefer-offline -def load(ingestionPipelineName, title) { - loadWithVault(ingestionPipelineName, title) + # Build team assignments dat file + node scripts/generate_team_assignments.js --verbose --dest '${teamAssignmentsPath}' + + cat '${teamAssignmentsPath}' + """, title) } return this