Skip to content

Commit

Permalink
[QA] [Code Coverage] Integrate with Team Assignment Pipeline and Add …
Browse files Browse the repository at this point in the history
…Research and Development Indexes and Cluster (#69348)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
wayneseymour and elasticmachine committed Jun 30, 2020
1 parent 0047eed commit 175bdb5
Show file tree
Hide file tree
Showing 13 changed files with 244 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .ci/Jenkinsfile_coverage
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def handleIngestion(timestamp) {
kibanaCoverage.collectVcsInfo("### Collect VCS Info")
kibanaCoverage.generateReports("### Merge coverage reports")
kibanaCoverage.uploadCombinedReports()
kibanaCoverage.ingest(timestamp, '### Injest && Upload')
kibanaCoverage.ingest(env.JOB_NAME, BUILD_NUMBER, BUILD_URL, timestamp, '### Ingest && Upload')
kibanaCoverage.uploadCoverageStaticSite(timestamp)
}

Expand Down
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@

# Quality Assurance
/src/dev/code_coverage @elastic/kibana-qa
/vars/*Coverage.groovy @elastic/kibana-qa
/test/functional/services/common @elastic/kibana-qa
/test/functional/services/lib @elastic/kibana-qa
/test/functional/services/remote @elastic/kibana-qa
Expand Down
37 changes: 0 additions & 37 deletions src/dev/code_coverage/ingest_coverage/__tests__/ingest.test.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* 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 { maybeTeamAssign, whichIndex } from '../ingest_helpers';
import {
TOTALS_INDEX,
RESEARCH_TOTALS_INDEX,
RESEARCH_COVERAGE_INDEX,
// COVERAGE_INDEX,
} from '../constants';

describe(`Ingest Helper fns`, () => {
describe(`whichIndex`, () => {
describe(`against the research job`, () => {
const whichIndexAgainstResearchJob = whichIndex(true);
describe(`against the totals index`, () => {
const isTotal = true;
it(`should return the Research Totals Index`, () => {
const actual = whichIndexAgainstResearchJob(isTotal);
expect(actual).to.be(RESEARCH_TOTALS_INDEX);
});
});
describe(`against the coverage index`, () => {
it(`should return the Research Totals Index`, () => {
const isTotal = false;
const actual = whichIndexAgainstResearchJob(isTotal);
expect(actual).to.be(RESEARCH_COVERAGE_INDEX);
});
});
});
describe(`against the "prod" job`, () => {
const whichIndexAgainstProdJob = whichIndex(false);
describe(`against the totals index`, () => {
const isTotal = true;
it(`should return the "Prod" Totals Index`, () => {
const actual = whichIndexAgainstProdJob(isTotal);
expect(actual).to.be(TOTALS_INDEX);
});
});
});
});
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');
});
});
});
});
});
38 changes: 27 additions & 11 deletions src/dev/code_coverage/ingest_coverage/__tests__/transforms.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,33 @@ describe(`Transform fn`, () => {
});
});
describe(`coveredFilePath`, () => {
it(`should remove the jenkins workspace path`, () => {
const obj = {
staticSiteUrl:
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
COVERAGE_INGESTION_KIBANA_ROOT:
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana',
};
expect(coveredFilePath(obj)).to.have.property(
'coveredFilePath',
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
);
describe(`in the code-coverage job`, () => {
it(`should remove the jenkins workspace path`, () => {
const obj = {
staticSiteUrl:
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
COVERAGE_INGESTION_KIBANA_ROOT:
'/var/lib/jenkins/workspace/elastic+kibana+code-coverage/kibana',
};
expect(coveredFilePath(obj)).to.have.property(
'coveredFilePath',
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
);
});
});
describe(`in the qa research job`, () => {
it(`should remove the jenkins workspace path`, () => {
const obj = {
staticSiteUrl:
'/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana/x-pack/plugins/reporting/server/browsers/extract/unzip.js',
COVERAGE_INGESTION_KIBANA_ROOT:
'/var/lib/jenkins/workspace/elastic+kibana+qa-research/kibana',
};
expect(coveredFilePath(obj)).to.have.property(
'coveredFilePath',
'x-pack/plugins/reporting/server/browsers/extract/unzip.js'
);
});
});
});
describe(`itemizeVcs`, () => {
Expand Down
13 changes: 13 additions & 0 deletions src/dev/code_coverage/ingest_coverage/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,17 @@
*/

export const COVERAGE_INDEX = process.env.COVERAGE_INDEX || 'kibana_code_coverage';

export const TOTALS_INDEX = process.env.TOTALS_INDEX || `kibana_total_code_coverage`;

export const RESEARCH_COVERAGE_INDEX =
process.env.RESEARCH_COVERAGE_INDEX || 'qa_research_code_coverage';

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;
81 changes: 59 additions & 22 deletions src/dev/code_coverage/ingest_coverage/ingest.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,40 +19,77 @@

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

const node = process.env.ES_HOST || 'http://localhost:9200';

const client = new Client({ node });
const pipeline = process.env.PIPELINE_NAME || 'team_assignment';
const redacted = redact(node);
const redactedEsHostUrl = redact(node);
const parse = JSON.parse.bind(null);
const isResearchJob = process.env.COVERAGE_JOB_NAME === RESEARCH_CI_JOB_NAME ? true : false;

export const ingest = (log) => async (body) => {
const index = body.isTotal ? TOTALS_INDEX : COVERAGE_INDEX;
const maybeWithPipeline = maybeTeamAssign(index, body);
const withIndex = { index, body: maybeWithPipeline };
const dontSend = noop;

log.verbose(withIndex);

process.env.NODE_ENV === 'integration_test'
? left(null)
: right(withIndex).fold(dontSend, async function doSend(finalPayload) {
await send(index, redacted, finalPayload);
});
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 justLog = dontSendButLog(log);
const doSendToIndex = doSend(index);
const doSendRedacted = doSendToIndex(redactedEsHostUrl)(log)(client);

eitherSendOrNot(finalPayload).fold(justLog, doSendRedacted);
};

async function send(idx, redacted, requestBody) {
function doSend(index) {
return (redactedEsHostUrl) => (log) => (client) => async (payload) => {
const logF = logSend(true)(redactedEsHostUrl)(log);
await send(logF, index, redactedEsHostUrl, client, payload);
};
}

function dontSendButLog(log) {
return (payload) => {
logSend(false)(null)(log)(payload);
};
}

async function send(logF, idx, redactedEsHostUrl, client, requestBody) {
try {
await client.index(requestBody);
logF(requestBody);
} catch (e) {
throw createFailError(errMsg(idx, redacted, requestBody, e));
const { body } = requestBody;
const parsed = parse(body);
throw createFailError(errMsg(idx, redactedEsHostUrl, parsed, e));
}
}

export function maybeTeamAssign(index, body) {
const payload = index === TOTALS_INDEX ? body : { ...body, pipeline };
return payload;
const sendMsg = (actuallySent, redactedEsHostUrl, payload) => {
const { index, body } = payload;
return `### ${actuallySent ? 'Sent' : 'Fake Sent'}:
${redactedEsHostUrl ? `\t### ES Host: ${redactedEsHostUrl}` : ''}
\t### Index: ${green(index)}
\t### payload.body: ${body}
${process.env.NODE_ENV === 'integration_test' ? `ingest-pipe=>${payload.pipeline}` : ''}
`;
};

function logSend(actuallySent) {
return (redactedEsHostUrl) => (log) => (payload) => {
log.verbose(sendMsg(actuallySent, redactedEsHostUrl, payload));
};
}

function eitherSendOrNot(payload) {
return process.env.NODE_ENV === 'integration_test' ? left(payload) : right(payload);
}
28 changes: 28 additions & 0 deletions src/dev/code_coverage/ingest_coverage/ingest_helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
import { always, pretty } from './utils';
import chalk from 'chalk';
import { fromNullable } from './either';
import {
COVERAGE_INDEX,
RESEARCH_COVERAGE_INDEX,
RESEARCH_TOTALS_INDEX,
TEAM_ASSIGNMENT_PIPELINE_NAME,
TOTALS_INDEX,
} from './constants';

export function errMsg(index, redacted, body, e) {
const orig = fromNullable(e.body).fold(
Expand All @@ -38,6 +45,9 @@ ${orig}
### Troubleshooting Hint:
${red('Perhaps the coverage data was not merged properly?\n')}
### Error.meta (stringified):
${pretty(e.meta)}
`;
}

Expand All @@ -59,3 +69,21 @@ function color(whichColor) {
return chalk[whichColor].bgWhiteBright(x);
};
}

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);
}
function whichTotalsIndex(isResearchJob) {
return isResearchJob ? RESEARCH_TOTALS_INDEX : TOTALS_INDEX;
}

function whichCoverageIndex(isResearchJob) {
return isResearchJob ? RESEARCH_COVERAGE_INDEX : COVERAGE_INDEX;
}
Loading

0 comments on commit 175bdb5

Please sign in to comment.