Skip to content

Commit 175bdb5

Browse files
[QA] [Code Coverage] Integrate with Team Assignment Pipeline and Add Research and Development Indexes and Cluster (#69348)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent 0047eed commit 175bdb5

File tree

13 files changed

+244
-106
lines changed

13 files changed

+244
-106
lines changed

.ci/Jenkinsfile_coverage

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def handleIngestion(timestamp) {
2828
kibanaCoverage.collectVcsInfo("### Collect VCS Info")
2929
kibanaCoverage.generateReports("### Merge coverage reports")
3030
kibanaCoverage.uploadCombinedReports()
31-
kibanaCoverage.ingest(timestamp, '### Injest && Upload')
31+
kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, '### Ingest && Upload')
3232
kibanaCoverage.uploadCoverageStaticSite(timestamp)
3333
}
3434

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132

133133
# Quality Assurance
134134
/src/dev/code_coverage @elastic/kibana-qa
135+
/vars/*Coverage.groovy @elastic/kibana-qa
135136
/test/functional/services/common @elastic/kibana-qa
136137
/test/functional/services/lib @elastic/kibana-qa
137138
/test/functional/services/remote @elastic/kibana-qa

src/dev/code_coverage/ingest_coverage/__tests__/ingest.test.js

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Licensed to Elasticsearch B.V. under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch B.V. licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import expect from '@kbn/expect';
21+
import { maybeTeamAssign, whichIndex } from '../ingest_helpers';
22+
import {
23+
TOTALS_INDEX,
24+
RESEARCH_TOTALS_INDEX,
25+
RESEARCH_COVERAGE_INDEX,
26+
// COVERAGE_INDEX,
27+
} from '../constants';
28+
29+
describe(`Ingest Helper fns`, () => {
30+
describe(`whichIndex`, () => {
31+
describe(`against the research job`, () => {
32+
const whichIndexAgainstResearchJob = whichIndex(true);
33+
describe(`against the totals index`, () => {
34+
const isTotal = true;
35+
it(`should return the Research Totals Index`, () => {
36+
const actual = whichIndexAgainstResearchJob(isTotal);
37+
expect(actual).to.be(RESEARCH_TOTALS_INDEX);
38+
});
39+
});
40+
describe(`against the coverage index`, () => {
41+
it(`should return the Research Totals Index`, () => {
42+
const isTotal = false;
43+
const actual = whichIndexAgainstResearchJob(isTotal);
44+
expect(actual).to.be(RESEARCH_COVERAGE_INDEX);
45+
});
46+
});
47+
});
48+
describe(`against the "prod" job`, () => {
49+
const whichIndexAgainstProdJob = whichIndex(false);
50+
describe(`against the totals index`, () => {
51+
const isTotal = true;
52+
it(`should return the "Prod" Totals Index`, () => {
53+
const actual = whichIndexAgainstProdJob(isTotal);
54+
expect(actual).to.be(TOTALS_INDEX);
55+
});
56+
});
57+
});
58+
});
59+
describe(`maybeTeamAssign`, () => {
60+
describe(`against a coverage index`, () => {
61+
it(`should have the pipeline prop`, () => {
62+
const actual = maybeTeamAssign(true, { a: 'blah' });
63+
expect(actual).to.have.property('pipeline');
64+
});
65+
});
66+
describe(`against a totals index`, () => {
67+
describe(`for "prod"`, () => {
68+
it(`should not have the pipeline prop`, () => {
69+
const actual = maybeTeamAssign(false, { b: 'blah' });
70+
expect(actual).not.to.have.property('pipeline');
71+
});
72+
});
73+
});
74+
});
75+
});

src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,33 @@ describe(`Transform fn`, () => {
3232
});
3333
});
3434
describe(`coveredFilePath`, () => {
35-
it(`should remove the jenkins workspace path`, () => {
36-
const obj = {
37-
staticSiteUrl:
38-
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
39-
COVERAGE_INGESTION_KIBANA_ROOT:
40-
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana',
41-
};
42-
expect(coveredFilePath(obj)).to.have.property(
43-
'coveredFilePath',
44-
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
45-
);
35+
describe(`in the code-coverage job`, () => {
36+
it(`should remove the jenkins workspace path`, () => {
37+
const obj = {
38+
staticSiteUrl:
39+
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
40+
COVERAGE_INGESTION_KIBANA_ROOT:
41+
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana',
42+
};
43+
expect(coveredFilePath(obj)).to.have.property(
44+
'coveredFilePath',
45+
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
46+
);
47+
});
48+
});
49+
describe(`in the qa research job`, () => {
50+
it(`should remove the jenkins workspace path`, () => {
51+
const obj = {
52+
staticSiteUrl:
53+
'/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
54+
COVERAGE_INGESTION_KIBANA_ROOT:
55+
'/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana',
56+
};
57+
expect(coveredFilePath(obj)).to.have.property(
58+
'coveredFilePath',
59+
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
60+
);
61+
});
4662
});
4763
});
4864
describe(`itemizeVcs`, () => {

src/dev/code_coverage/ingest_coverage/constants.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,17 @@
1818
*/
1919

2020
export const COVERAGE_INDEX = process.env.COVERAGE_INDEX || 'kibana_code_coverage';
21+
2122
export const TOTALS_INDEX = process.env.TOTALS_INDEX || `kibana_total_code_coverage`;
23+
24+
export const RESEARCH_COVERAGE_INDEX =
25+
process.env.RESEARCH_COVERAGE_INDEX || 'qa_research_code_coverage';
26+
27+
export const RESEARCH_TOTALS_INDEX =
28+
process.env.RESEARCH_TOTALS_INDEX || `qa_research_total_code_coverage`;
29+
30+
export const TEAM_ASSIGNMENT_PIPELINE_NAME = process.env.PIPELINE_NAME || 'team_assignment';
31+
32+
export const CODE_COVERAGE_CI_JOB_NAME = 'elastic+kibana+code-coverage';
33+
export const RESEARCH_CI_JOB_NAME = 'elastic+kibana+qa-research';
34+
export const CI_JOB_NAME = process.env.COVERAGE_JOB_NAME || RESEARCH_CI_JOB_NAME;

src/dev/code_coverage/ingest_coverage/ingest.js

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,40 +19,77 @@
1919

2020
const { Client } = require('@elastic/elasticsearch');
2121
import { createFailError } from '@kbn/dev-utils';
22-
import { COVERAGE_INDEX, TOTALS_INDEX } from './constants';
23-
import { errMsg, redact } from './ingest_helpers';
24-
import { noop } from './utils';
22+
import { RESEARCH_CI_JOB_NAME, TEAM_ASSIGNMENT_PIPELINE_NAME } from './constants';
23+
import { errMsg, redact, whichIndex } from './ingest_helpers';
24+
import { pretty, green } from './utils';
2525
import { right, left } from './either';
2626

2727
const node = process.env.ES_HOST || 'http://localhost:9200';
28+
2829
const client = new Client({ node });
29-
const pipeline = process.env.PIPELINE_NAME || 'team_assignment';
30-
const redacted = redact(node);
30+
const redactedEsHostUrl = redact(node);
31+
const parse = JSON.parse.bind(null);
32+
const isResearchJob = process.env.COVERAGE_JOB_NAME === RESEARCH_CI_JOB_NAME ? true : false;
3133

3234
export const ingest = (log) => async (body) => {
33-
const index = body.isTotal ? TOTALS_INDEX : COVERAGE_INDEX;
34-
const maybeWithPipeline = maybeTeamAssign(index, body);
35-
const withIndex = { index, body: maybeWithPipeline };
36-
const dontSend = noop;
37-
38-
log.verbose(withIndex);
39-
40-
process.env.NODE_ENV === 'integration_test'
41-
? left(null)
42-
: right(withIndex).fold(dontSend, async function doSend(finalPayload) {
43-
await send(index, redacted, finalPayload);
44-
});
35+
const isTotal = !!body.isTotal;
36+
const index = whichIndex(isResearchJob)(isTotal);
37+
const isACoverageIndex = isTotal ? false : true;
38+
39+
const stringified = pretty(body);
40+
const pipeline = TEAM_ASSIGNMENT_PIPELINE_NAME;
41+
42+
const finalPayload = isACoverageIndex
43+
? { index, body: stringified, pipeline }
44+
: { index, body: stringified };
45+
46+
const justLog = dontSendButLog(log);
47+
const doSendToIndex = doSend(index);
48+
const doSendRedacted = doSendToIndex(redactedEsHostUrl)(log)(client);
49+
50+
eitherSendOrNot(finalPayload).fold(justLog, doSendRedacted);
4551
};
4652

47-
async function send(idx, redacted, requestBody) {
53+
function doSend(index) {
54+
return (redactedEsHostUrl) => (log) => (client) => async (payload) => {
55+
const logF = logSend(true)(redactedEsHostUrl)(log);
56+
await send(logF, index, redactedEsHostUrl, client, payload);
57+
};
58+
}
59+
60+
function dontSendButLog(log) {
61+
return (payload) => {
62+
logSend(false)(null)(log)(payload);
63+
};
64+
}
65+
66+
async function send(logF, idx, redactedEsHostUrl, client, requestBody) {
4867
try {
4968
await client.index(requestBody);
69+
logF(requestBody);
5070
} catch (e) {
51-
throw createFailError(errMsg(idx, redacted, requestBody, e));
71+
const { body } = requestBody;
72+
const parsed = parse(body);
73+
throw createFailError(errMsg(idx, redactedEsHostUrl, parsed, e));
5274
}
5375
}
5476

55-
export function maybeTeamAssign(index, body) {
56-
const payload = index === TOTALS_INDEX ? body : { ...body, pipeline };
57-
return payload;
77+
const sendMsg = (actuallySent, redactedEsHostUrl, payload) => {
78+
const { index, body } = payload;
79+
return `### ${actuallySent ? 'Sent' : 'Fake Sent'}:
80+
${redactedEsHostUrl ? `\t### ES Host: ${redactedEsHostUrl}` : ''}
81+
\t### Index: ${green(index)}
82+
\t### payload.body: ${body}
83+
${process.env.NODE_ENV === 'integration_test' ? `ingest-pipe=>${payload.pipeline}` : ''}
84+
`;
85+
};
86+
87+
function logSend(actuallySent) {
88+
return (redactedEsHostUrl) => (log) => (payload) => {
89+
log.verbose(sendMsg(actuallySent, redactedEsHostUrl, payload));
90+
};
91+
}
92+
93+
function eitherSendOrNot(payload) {
94+
return process.env.NODE_ENV === 'integration_test' ? left(payload) : right(payload);
5895
}

src/dev/code_coverage/ingest_coverage/ingest_helpers.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
import { always, pretty } from './utils';
2121
import chalk from 'chalk';
2222
import { fromNullable } from './either';
23+
import {
24+
COVERAGE_INDEX,
25+
RESEARCH_COVERAGE_INDEX,
26+
RESEARCH_TOTALS_INDEX,
27+
TEAM_ASSIGNMENT_PIPELINE_NAME,
28+
TOTALS_INDEX,
29+
} from './constants';
2330

2431
export function errMsg(index, redacted, body, e) {
2532
const orig = fromNullable(e.body).fold(
@@ -38,6 +45,9 @@ ${orig}
3845
3946
### Troubleshooting Hint:
4047
${red('Perhaps the coverage data was not merged properly?\n')}
48+
49+
### Error.meta (stringified):
50+
${pretty(e.meta)}
4151
`;
4252
}
4353

@@ -59,3 +69,21 @@ function color(whichColor) {
5969
return chalk[whichColor].bgWhiteBright(x);
6070
};
6171
}
72+
73+
export function maybeTeamAssign(isACoverageIndex, body) {
74+
const doAddTeam = isACoverageIndex ? true : false;
75+
const payload = doAddTeam ? { ...body, pipeline: TEAM_ASSIGNMENT_PIPELINE_NAME } : body;
76+
return payload;
77+
}
78+
79+
export function whichIndex(isResearchJob) {
80+
return (isTotal) =>
81+
isTotal ? whichTotalsIndex(isResearchJob) : whichCoverageIndex(isResearchJob);
82+
}
83+
function whichTotalsIndex(isResearchJob) {
84+
return isResearchJob ? RESEARCH_TOTALS_INDEX : TOTALS_INDEX;
85+
}
86+
87+
function whichCoverageIndex(isResearchJob) {
88+
return isResearchJob ? RESEARCH_COVERAGE_INDEX : COVERAGE_INDEX;
89+
}

0 commit comments

Comments
 (0)