[QA][Code Coverage] Coverage teams lookup w/o Additional Config (#77111)

* [QA][Code Coverage] Coverage teams lookup

* Fix test per cr.

* Drop unused fn's.

* Add integration test to prove that the sys does indeed
strip the CC prefix and still walks the fs.

* Cleanup "todo" list.

* Use import, like Dima's previous suggestion.

* Add coverage teams only definitions to CODEOWNERS per Lee.

* Add coverage teams for logstash, reporting and security.

* Update description.

* Update names per Lee.

* Drop mutation.

* Fix dupes.

* Add the file check, per Dima

* Add more teams

* Update regex to only match on "build/" and add test.

* More teams

* More teams

* Add print statement of the canonical timestamp,
so we can lookup stuff in gcp during errors.

* CR fixups
This commit is contained in:
Tre 2020-09-28 15:27:02 -06:00 committed by GitHub
parent 085cac13f2
commit 3a73e0b2ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 1054 additions and 211 deletions

View file

@ -12,8 +12,12 @@ kibanaPipeline(timeoutMinutes: 240) {
]) {
workers.base(name: 'coverage-worker', size: 'l', ramDisk: false, bootstrapped: false) {
catchError {
kibanaPipeline.bash("""
echo '${TIME_STAMP}'
""", "### Print Canonical Time Stamp")
kibanaCoverage.runTests()
kibanaTeamAssign.load('team_assignment', "### Upload Team Assignment JSON")
handleIngestion(TIME_STAMP)
}
handleFail()
@ -30,7 +34,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(), '### Generate Team Assignments && Ingest')
kibanaCoverage.uploadCoverageStaticSite(timestamp)
}
@ -42,7 +46,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 +54,7 @@ def handleFail() {
}
}
def teamAssignmentsPath() {
return 'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt'
}

129
.github/CODEOWNERS vendored
View file

@ -2,6 +2,9 @@
# Identify which groups will be pinged by changes to different parts of the codebase.
# For more info, see https://help.github.com/articles/about-codeowners/
# The #CC# prefix delineates Code Coverage,
# used for the 'team' designator within Kibana Stats
# App
/x-pack/plugins/dashboard_enhanced/ @elastic/kibana-app
/x-pack/plugins/discover_enhanced/ @elastic/kibana-app
@ -26,6 +29,33 @@
/src/plugins/vis_type_xy/ @elastic/kibana-app
/src/plugins/visualize/ @elastic/kibana-app
/src/plugins/visualizations/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public/local_application_service/ @elastic/kibana-app
#CC# /src/plugins/vis_type @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/common/utils @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/migrations @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public/dashboard/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public/dev_tools/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public/discover/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/kibana/public/local_application_service/ @elastic/kibana-app
#CC# /src/legacy/core_plugins/console_legacy @elastic/kibana-app
#CC# /src/legacy/core_plugins/input_control_vis @elastic/kibana-app
#CC# /src/legacy/core_plugins/timelion @elastic/kibana-app
#CC# /src/legacy/core_plugins/vis_type_tagcloud @elastic/kibana-app
#CC# /src/legacy/core_plugins/vis_type_vega @elastic/kibana-app
#CC# /src/legacy/core_plugins/vis_type_vislib/ @elastic/kibana-app
#CC# /src/legacy/server/sample_data/ @elastic/kibana-app
#CC# /src/legacy/server/url_shortening/ @elastic/kibana-app
#CC# /src/legacy/ui/public/state_management @elastic/kibana-app
#CC# /src/plugins/charts/public/static/color_maps @elastic/kibana-app
#CC# /src/plugins/index_pattern_management/public @elastic/kibana-app
#CC# /src/plugins/input_control_vis/ @elastic/kibana-app
#CC# /src/plugins/kibana_legacy/ @elastic/kibana-app
#CC# /src/plugins/timelion @elastic/kibana-app
#CC# /x-pack/legacy/plugins/dashboard_mode/ @elastic/kibana-app
#CC# /x-pack/plugins/dashboard_mode @elastic/kibana-app
#CC# /x-pack/plugins/lens/ @elastic/kibana-app
# App Architecture
/examples/bfetch_explorer/ @elastic/kibana-app-arch
@ -56,12 +86,37 @@
/x-pack/plugins/data_enhanced/ @elastic/kibana-app-arch
/x-pack/plugins/embeddable_enhanced/ @elastic/kibana-app-arch
/x-pack/plugins/ui_actions_enhanced/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/kibana/public/management/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/kibana/server/routes/api/management/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/embeddable_api/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/interpreter/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/kibana_react/ @elastic/kibana-app-arch
#CC# /src/legacy/core_plugins/status_page/public @elastic/kibana-app-arch
#CC# /src/legacy/server/index_patterns/ @elastic/kibana-app-arch
#CC# /src/legacy/ui/public/field_editor @elastic/kibana-app-arch
#CC# /src/legacy/ui/public/management @elastic/kibana-app-arch
#CC# /src/plugins/advanced_settings/ @elastic/kibana-app-arch
#CC# /src/plugins/bfetch/ @elastic/kibana-app-arch
#CC# /src/plugins/charts/ @elastic/kibana-app-arch
#CC# /src/plugins/index_pattern_management/public/service @elastic/kibana-app-arch
#CC# /src/plugins/inspector/ @elastic/kibana-app-arch
#CC# /src/plugins/saved_objects/ @elastic/kibana-app-arch
#CC# /src/plugins/share/ @elastic/kibana-app-arch
#CC# /src/plugins/vis_default_editor @elastic/kibana-app-arch
#CC# /x-pack/plugins/advanced_ui_actions/ @elastic/kibana-app-arch
#CC# /x-pack/plugins/drilldowns/ @elastic/kibana-app-arch
#CC# /packages/kbn-interpreter/ @elastic/kibana-app-arch
# APM
/x-pack/plugins/apm/ @elastic/apm-ui
/x-pack/test/functional/apps/apm/ @elastic/apm-ui
/src/plugins/apm_oss/ @elastic/apm-ui
/src/apm.js @watson @vigneshshanmugam
#CC# /src/plugins/apm_oss/ @elastic/apm-ui
#CC# /src/legacy/core_plugins/apm_oss/ @elastic/apm-ui
#CC# /src/legacy/ui/public/apm @elastic/apm-ui
#CC# /x-pack/legacy/plugins/apm/ @elastic/apm-ui
#CC# /x-pack/plugins/observability/ @elastic/apm-ui
# Client Side Monitoring (lives in APM directories but owned by Uptime)
/x-pack/plugins/apm/e2e/cypress/support/step_definitions/csm @elastic/uptime
@ -71,13 +126,19 @@
/x-pack/plugins/apm/server/lib/rum_client @elastic/uptime
/x-pack/plugins/apm/server/routes/rum_client.ts @elastic/uptime
/x-pack/plugins/apm/server/projections/rum_page_load_transactions.ts @elastic/uptime
/x-pack/plugins/apm/server/projections/rum_overview.ts @elastic/uptime
#CC# /x-pack/legacy/plugins/uptime @elastic/uptime
# Beats
/x-pack/plugins/beats_management/ @elastic/beats
/x-pack/legacy/plugins/beats_management/ @elastic/beats
#CC# /x-pack/plugins/beats_management/ @elastic/beats
# Canvas
/x-pack/plugins/canvas/ @elastic/kibana-canvas
/x-pack/test/functional/apps/canvas/ @elastic/kibana-canvas
#CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-canvas
#CC# /x-pack/legacy/plugins/canvas/ @elastic/kibana-canvas
# Core UI
# Exclude tutorials folder for now because they are not owned by Kibana app and most will move out soon
@ -85,6 +146,12 @@
/src/plugins/home/server/*.ts @elastic/kibana-core-ui
/src/plugins/home/server/services/ @elastic/kibana-core-ui
/x-pack/plugins/global_search_bar/ @elastic/kibana-core-ui
#CC# /src/legacy/core_plugins/newsfeed @elastic/kibana-core-ui
#CC# /src/plugins/newsfeed @elastic/kibana-core-ui
#CC# /src/plugins/home/public @elastic/kibana-core-ui
#CC# /src/plugins/home/server/services/ @elastic/kibana-core-ui
#CC# /src/plugins/home/ @elastic/kibana-core-ui
#CC# /x-pack/plugins/global_search_providers/ @elastic/kibana-core-ui
# Observability UIs
/x-pack/plugins/infra/ @elastic/logs-metrics-ui
@ -110,6 +177,14 @@
/x-pack/test/functional/apps/maps/ @elastic/kibana-gis
/x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis
/x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis
#CC# /src/legacy/core_plugins/region_map @elastic/kibana-gis
#CC# /src/legacy/core_plugins/tile_map @elastic/kibana-gis
#CC# /src/plugins/maps_legacy/ @elastic/kibana-gis
#CC# /x-pack/plugins/file_upload @elastic/kibana-gis
#CC# /x-pack/plugins/maps_legacy_licensing @elastic/kibana-gis
#CC# /src/plugins/home/server/tutorials @elastic/kibana-gis
#CC# /src/plugins/tile_map/ @elastic/kibana-gis
#CC# /src/plugins/region_map/ @elastic/kibana-gis
# Operations
/src/dev/ @elastic/kibana-operations
@ -132,6 +207,7 @@
/src/legacy/server/warnings/ @elastic/kibana-operations
/.ci/es-snapshots/ @elastic/kibana-operations
/vars/ @elastic/kibana-operations
#CC# /packages/kbn-expect/ @elastic/kibana-operations
# Quality Assurance
/src/dev/code_coverage @elastic/kibana-qa
@ -158,6 +234,31 @@
/src/plugins/status_page/ @elastic/kibana-platform
/src/plugins/saved_objects_management/ @elastic/kibana-platform
/src/dev/run_check_published_api_changes.ts @elastic/kibana-platform
#CC# /src/core/server/csp/ @elastic/kibana-platform
#CC# /src/legacy/core_plugins/kibana/server/lib @elastic/kibana-platform
#CC# /src/legacy/core_plugins/kibana/server/lib/management/saved_objects @elastic/kibana-platform
#CC# /src/legacy/core_plugins/kibana/server/routes/api/import/ @elastic/kibana-platform
#CC# /src/legacy/core_plugins/kibana/server/routes/api/export/ @elastic/kibana-platform
#CC# /src/legacy/core_plugins/elasticsearch @elastic/kibana-platform
#CC# /src/legacy/core_plugins/testbed @elastic/kibana-platform
#CC# /src/legacy/server/config/ @elastic/kibana-platform
#CC# /src/legacy/server/http/ @elastic/kibana-platform
#CC# /src/legacy/server/status/ @elastic/kibana-platform
#CC# /src/legacy/ui/public/new_platform @elastic/kibana-platform
#CC# /src/legacy/ui/public/plugin_discovery @elastic/kibana-platform
#CC# /src/legacy/ui/public/chrome @elastic/kibana-platform
#CC# /src/legacy/ui/public/notify @elastic/kibana-platform
#CC# /src/legacy/ui/public/documentation_links @elastic/kibana-platform
#CC# /src/legacy/ui/public/autoload @elastic/kibana-platform
#CC# /src/plugins/legacy_export/ @elastic/kibana-platform
#CC# /src/plugins/status_page/ @elastic/kibana-platform
#CC# /src/plugins/testbed/server/ @elastic/kibana-platform
#CC# /x-pack/legacy/plugins/xpack_main/server/ @elastic/kibana-platform
#CC# /x-pack/legacy/server/lib/ @elastic/kibana-platform
#CC# /x-pack/plugins/cloud/ @elastic/kibana-platform
#CC# /x-pack/plugins/features/ @elastic/kibana-platform
#CC# /x-pack/plugins/global_search/ @elastic/kibana-platform
#CC# /src/legacy/plugin_discovery/ @elastic/kibana-platform
# Security
/src/core/server/csp/ @elastic/kibana-security @elastic/kibana-platform
@ -177,12 +278,19 @@
/x-pack/test/security_functional/ @elastic/kibana-security
/x-pack/test/spaces_api_integration/ @elastic/kibana-security
/x-pack/test/token_api_integration/ @elastic/kibana-security
#CC# /src/legacy/ui/public/capabilities @elastic/kibana-security
#CC# /x-pack/legacy/plugins/encrypted_saved_objects/ @elastic/kibana-security
#CC# /x-pack/plugins/security_solution/ @elastic/kibana-security
#CC# /x-pack/plugins/security/ @elastic/kibana-security
#CC# /x-pack/plugins/audit_trail/ @elastic/kibana-security
# Kibana Localization
/src/dev/i18n/ @elastic/kibana-localization
/src/legacy/server/i18n/ @elastic/kibana-localization
/src/core/public/i18n/ @elastic/kibana-localization
/packages/kbn-i18n/ @elastic/kibana-localization
#CC# /src/legacy/server/i18n/ @elastic/kibana-localization
#CC# /x-pack/plugins/translations/ @elastic/kibana-localization
# Kibana Telemetry
/packages/kbn-analytics/ @elastic/kibana-telemetry
@ -211,6 +319,11 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
/x-pack/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services
/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/ @elastic/kibana-alerting-services
/x-pack/test/functional_with_es_ssl/fixtures/plugins/alerts/ @elastic/kibana-alerting-services
#CC# /x-pack/legacy/plugins/actions/ @elastic/kibana-alerting-services
#CC# /x-pack/legacy/plugins/alerting/ @elastic/kibana-alerting-services
#CC# /x-pack/legacy/plugins/task_manager @elastic/kibana-alerting-services
#CC# /x-pack/legacy/plugins/triggers_actions_ui/ @elastic/kibana-alerting-services
#CC# /x-pack/plugins/alerting_builtins @elastic/kibana-alerting-services
# Enterprise Search
# Shared
@ -248,6 +361,12 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
/x-pack/plugins/ingest_pipelines/ @elastic/es-ui
/packages/kbn-ace/ @elastic/es-ui
/packages/kbn-monaco/ @elastic/es-ui
#CC# /x-pack/legacy/plugins/rollup/ @elastic/es-ui
#CC# /x-pack/legacy/server/lib/create_router/ @elastic/es-ui
#CC# /x-pack/legacy/server/lib/check_license/ @elastic/es-ui
#CC# /x-pack/plugins/console_extensions/ @elastic/es-ui
#CC# /x-pack/plugins/cross_cluster_replication/ @elastic/es-ui
#CC# /x-pack/plugins/es_ui_shared/ @elastic/es-u
# Endpoint
/x-pack/plugins/endpoint/ @elastic/endpoint-app-team @elastic/siem
@ -257,6 +376,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team @elastic/siem
/x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team @elastic/siem
/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team @elastic/siem
#CC# /x-pack/legacy/plugins/siem/ @elastic/siem
#CC# /x-pack/plugins/siem/ @elastic/siem
#CC# /x-pack/plugins/security_solution/ @elastic/siem
# Security Solution
/x-pack/plugins/security_solution/ @elastic/siem @elastic/endpoint-app-team
@ -271,6 +393,7 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
# Design (at the bottom for specificity of SASS files)
**/*.scss @elastic/kibana-design
#CC# /packages/kbn-ui-framework/ @elastic/kibana-design
# Core design
/src/plugins/dashboard/**/*.scss @elastic/kibana-core-ui-designers
@ -292,3 +415,9 @@ x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @elastic/kib
/x-pack/plugins/endpoint/**/*.scss @elastic/security-design
/x-pack/plugins/security_solution/**/*.scss @elastic/security-design
# Logstash
#CC# /x-pack/plugins/logstash/ @elastic/logstash
# Reporting
#CC# /x-pack/plugins/reporting/ @elastic/kibana-reporting-services

View file

@ -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();

View file

@ -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);
});
});
});

View file

@ -0,0 +1,60 @@
/*
* 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 { ToolingLog, REPO_ROOT } from '@kbn/dev-utils';
const log = new ToolingLog({
level: 'info',
writeTo: process.stdout,
});
describe(`enumeratePatterns`, () => {
it(`should resolve x-pack/plugins/reporting/server/browsers/extract/unzip.js to kibana-reporting`, () => {
const actual = enumeratePatterns(REPO_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);
});
it(`should resolve src/plugins/charts/public/static/color_maps/color_maps.ts to kibana-app`, () => {
const actual = enumeratePatterns(REPO_ROOT)(log)(
new Map([['src/plugins/charts/public/static/color_maps', ['kibana-app']]])
);
expect(actual[0][0]).to.be(
'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app'
);
});
it(`should resolve x-pack/plugins/security_solution/public/common/components/exceptions/builder/translations.ts to kibana-security`, () => {
const short = 'x-pack/plugins/security_solution';
const actual = enumeratePatterns(REPO_ROOT)(log)(new Map([[short, ['kibana-security']]]));
expect(
actual[0].includes(
`${short}/public/common/components/exceptions/builder/translations.ts kibana-security`
)
).to.be(true);
});
});

View file

@ -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);
});
});
});
});

View file

@ -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');
});
});
});
});
});

View file

@ -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

View file

@ -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);
});
});
});
});

View file

@ -18,9 +18,17 @@
*/
import expect from '@kbn/expect';
import { ciRunUrl, coveredFilePath, itemizeVcs, prokPrevious } from '../transforms';
import {
ciRunUrl,
coveredFilePath,
itemizeVcs,
prokPrevious,
teamAssignment,
last,
} from '../transforms';
import { ToolingLog } from '@kbn/dev-utils';
describe(`Transform fn`, () => {
describe(`Transform fns`, () => {
describe(`ciRunUrl`, () => {
it(`should add the url when present in the environment`, () => {
process.env.CI_RUN_URL = 'blah';
@ -83,4 +91,59 @@ 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);
});
});
describe(`with a coveredFilePath of src/plugins/charts/public/static/color_maps/color_maps.ts`, () => {
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);
});
});
describe(`last fn`, () => {
describe(`applied to n results`, () => {
it(`should pick the last one`, () => {
const nteams = `src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app
src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch`;
const actual = last(nteams);
expect(actual).to.be(
'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch'
);
});
});
describe(`applied to 1 result`, () => {
it(`should pick that 1 result`, () => {
const nteams =
'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch';
const actual = last(nteams);
expect(actual).to.be(
'src/plugins/charts/public/static/color_maps/color_maps.ts kibana-app-arch'
);
});
});
});
});
});

View file

@ -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;

View file

@ -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) {

View file

@ -20,13 +20,16 @@
import { resolve } from 'path';
import { prok } from './process';
import { run, createFlagError } from '@kbn/dev-utils';
import { pathExists } from './team_assignment/enumeration_helpers';
import { id, reThrow } from './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 +39,18 @@ 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;
pathExists(teamAssignmentsPath).fold(reThrow, id);
prok({ jsonSummaryPath, vcsInfoFilePath, teamAssignmentsPath }, log);
},
{
description: `

View file

@ -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}` : ''}
`;
};

View file

@ -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);

View file

@ -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*(.+,)/;

View file

@ -0,0 +1,6 @@
# GitHub CODEOWNERS definition
# Identify which groups will be pinged by changes to different parts of the codebase.
# For more info, see https://help.github.com/articles/about-codeowners/
# App
/x-pack/plugins/code/ @elastic/kibana-tre

View file

@ -0,0 +1,28 @@
{
"/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/src/plugins/charts/public/static/color_maps/color_maps.ts": {
"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
}
}
}

View file

@ -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
}
}
}

View file

@ -0,0 +1,58 @@
/*
* 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 { 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');
describe('Team Assignment', () => {
const teamAssignmentsPath =
'src/dev/code_coverage/ingest_coverage/team_assignment/team_assignments.txt';
const mockCodeOwners = 'CODEOWNERS';
const resolved = resolve(MOCKS_DIR, mockCodeOwners);
beforeAll(async () => {
const params = [
'scripts/generate_team_assignments.js',
'--src',
resolved,
'--dest',
teamAssignmentsPath,
];
await execa(process.execPath, params, { cwd: ROOT_DIR });
});
afterAll(() => {
shell.rm(teamAssignmentsPath);
});
describe(`when the codeowners file contains #CC#`, () => {
it(`should strip the prefix and still drill down through the fs`, async () => {
const { stdout } = await execa('grep', ['tre', teamAssignmentsPath], { cwd: ROOT_DIR });
expect(stdout).to.be(`x-pack/plugins/code/server/config.ts kibana-tre
x-pack/plugins/code/server/index.ts kibana-tre
x-pack/plugins/code/server/plugin.test.ts kibana-tre
x-pack/plugins/code/server/plugin.ts kibana-tre`);
});
});
});

View file

@ -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))
);
};

View file

@ -0,0 +1,78 @@
/*
* 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,
isRejectedDir,
isFileAllowed,
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, team] = entry;
const cleaned = stripLeading(pathPattern);
const existsWithOwner = pathExists(team);
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 && !isRejectedDir(full)) xs = creepFsSync(full, xs, rootPath, owner);
else if (isFileAllowed(full)) xs.push(`${trimRoot(full)} ${owner}`);
}
}

View file

@ -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 isFileAllowed = (x) => {
const isJsOrTsOrTsxOrJsx = /.(j|t)(s|sx)$/gm;
return isJsOrTsOrTsxOrJsx.test(x);
};
export const isRejectedDir = (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}`);

View file

@ -0,0 +1,44 @@
/*
* 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 { writeFileSync } from 'fs';
import shell from 'shelljs';
import { tryCatch } from '../either';
import { id } from '../utils';
const encoding = 'utf8';
const appendUtf8 = { flag: 'a', encoding };
export const flush = (dest) => (log) => (assignments) => {
log.verbose(`\n### Flushing assignments to: \n\t${dest}`);
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();
}

View file

@ -17,42 +17,55 @@
* 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';
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.
`;
import { run, createFlagError, REPO_ROOT } from '@kbn/dev-utils';
import { parse } from './parse_owners';
import { flush } from './flush';
import { enumeratePatterns } from './enumerate_patterns';
import { pipe } from '../utils';
import { reduce } from 'rxjs/operators';
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 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');
export const uploadTeamAssignmentJson = () => run(execute, { description, flags, usage });
const logCreepAndFlush = pipe(
logSuccess(flags.src, log),
enumeratePatterns(REPO_ROOT)(log),
flush(flags.dest)(log)
);
parse(flags.src).pipe(reduce(toMap, new Map())).subscribe(logCreepAndFlush);
},
{
description: `
Create a file defining the team assignments,
parsed from .github/CODEOWNERS
`,
flags,
}
);
};
function toMap(acc, x) {
acc.set(x[0], x[1][0]);
return acc;
}
function logSuccess(src, log) {
return (dataObj) => {
log.verbose(`\n### Parsing [${src}] Complete`);
return dataObj;
};
}

File diff suppressed because one or more lines are too long

View file

@ -17,21 +17,19 @@
* under the License.
*/
import { createFailError } from '@kbn/dev-utils';
import { ES_HOST } from '../constants';
import { pretty, green } from '../utils';
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 { Client } = require('@elastic/elasticsearch');
const cleanAndParse = pipe(dropCCDelim, pathAndTeams);
const node = ES_HOST;
const client = new Client({ node });
const allLines$ = (lineReader) =>
fromEvent(lineReader, 'line').pipe(
filter(empties),
filter(comments),
map(cleanAndParse),
takeUntil(fromEvent(lineReader, 'close'))
);
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)}`);
}
};
export const parse = (codeOwnersPath) => allLines$(lineRead(codeOwnersPath));

View file

@ -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) });

View file

@ -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)));

View file

@ -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,60 @@ 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);
};
export const last = (x) => {
const xs = x.split('\n');
const len = xs.length;
return len === 1 ? xs[0] : xs[len - 1];
};
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(last)
.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 +170,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: {

View file

@ -22,6 +22,10 @@ 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 reThrow = (e) => {
throw e;
};

View file

@ -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 ""

View file

@ -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 ""

View file

@ -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)
}
}

View file

@ -1,25 +1,13 @@
def loadIngestionPipeline(ingestionPipelineName, title) {
def generateTeamAssignments(teamAssignmentsPath, title) {
kibanaPipeline.bash("""
source src/dev/ci_setup/setup_env.sh true
source src/dev/ci_setup/setup_env.sh
yarn kbn bootstrap --prefer-offline
. src/dev/code_coverage/shell_scripts/assign_teams.sh '${ingestionPipelineName}'
# Build team assignments dat file
node scripts/generate_team_assignments.js --verbose --dest '${teamAssignmentsPath}'
cat '${teamAssignmentsPath}'
""", 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 load(ingestionPipelineName, title) {
loadWithVault(ingestionPipelineName, title)
}
return this