Commit d9fb45d6 authored by Brandon Labuschagne's avatar Brandon Labuschagne Committed by Phil Hughes

Add everage to CI/CD deployment chart

This commit adds an average line to the
CI/CD deployment freguency chart

Changelog: added
EE: true
parent 138725b9
...@@ -2,12 +2,14 @@ ...@@ -2,12 +2,14 @@
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import * as DoraApi from 'ee/api/dora_api'; import * as DoraApi from 'ee/api/dora_api';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { s__ } from '~/locale'; import { s__, sprintf } from '~/locale';
import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue'; import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue';
import DoraChartHeader from './dora_chart_header.vue'; import DoraChartHeader from './dora_chart_header.vue';
import { import {
allChartDefinitions, allChartDefinitions,
areaChartOptions, areaChartOptions,
averageSeriesOptions,
averageSeriesName,
chartDescriptionText, chartDescriptionText,
chartDocumentationHref, chartDocumentationHref,
LAST_WEEK, LAST_WEEK,
...@@ -15,7 +17,7 @@ import { ...@@ -15,7 +17,7 @@ import {
LAST_90_DAYS, LAST_90_DAYS,
CHART_TITLE, CHART_TITLE,
} from './static_data/deployment_frequency'; } from './static_data/deployment_frequency';
import { apiDataToChartSeries } from './util'; import { apiDataToChartSeries, seriesToAverageSeries } from './util';
export default { export default {
name: 'DeploymentFrequencyCharts', name: 'DeploymentFrequencyCharts',
...@@ -33,6 +35,11 @@ export default { ...@@ -33,6 +35,11 @@ export default {
default: '', default: '',
}, },
}, },
chartInDays: {
[LAST_WEEK]: 7,
[LAST_MONTH]: 30,
[LAST_90_DAYS]: 90,
},
data() { data() {
return { return {
chartData: { chartData: {
...@@ -76,7 +83,19 @@ export default { ...@@ -76,7 +83,19 @@ export default {
throw new Error('Either projectPath or groupPath must be provided'); throw new Error('Either projectPath or groupPath must be provided');
} }
this.chartData[id] = apiDataToChartSeries(apiData, startDate, endDate, CHART_TITLE); const seriesData = apiDataToChartSeries(apiData, startDate, endDate, CHART_TITLE);
const { data } = seriesData[0];
this.chartData[id] = [
...seriesData,
{
...averageSeriesOptions,
...seriesToAverageSeries(
data,
sprintf(averageSeriesName, { days: this.$options.chartInDays[id] }),
),
},
];
}), }),
); );
......
...@@ -3,6 +3,8 @@ import { s__ } from '~/locale'; ...@@ -3,6 +3,8 @@ import { s__ } from '~/locale';
export * from './shared'; export * from './shared';
export const averageSeriesName = s__('DORA4Metrics|Average (last %{days}d)');
export const CHART_TITLE = s__('DORA4Metrics|Deployment frequency'); export const CHART_TITLE = s__('DORA4Metrics|Deployment frequency');
export const areaChartOptions = { export const areaChartOptions = {
......
...@@ -36,6 +36,12 @@ const sharedRequestParams = { ...@@ -36,6 +36,12 @@ const sharedRequestParams = {
per_page: 100, per_page: 100,
}; };
export const averageSeriesOptions = {
areaStyle: {
opacity: 0,
},
};
export const allChartDefinitions = [ export const allChartDefinitions = [
{ {
id: LAST_WEEK, id: LAST_WEEK,
......
...@@ -147,3 +147,24 @@ export const buildNullSeriesForLeadTimeChart = (seriesData) => { ...@@ -147,3 +147,24 @@ export const buildNullSeriesForLeadTimeChart = (seriesData) => {
return [nullSeries, nonNullSeries]; return [nullSeries, nonNullSeries];
}; };
/**
* Converts a data series into a formatted average series
*
* @param {Array} chartSeriesData Correctly formatted chart series data
*
* @returns {Object} An object containing the series name and an array of original data keys with the average of the dataset as each value.
*/
export const seriesToAverageSeries = (chartSeriesData, seriesName) => {
if (!chartSeriesData) return {};
const average =
Math.round(
(chartSeriesData.reduce((acc, day) => acc + day[1], 0) / chartSeriesData.length) * 10,
) / 10;
return {
name: seriesName,
data: chartSeriesData.map((day) => [day[0], average]),
};
};
import lastWeekData from 'test_fixtures/api/dora/metrics/daily_lead_time_for_changes_for_last_week.json'; import lastWeekData from 'test_fixtures/api/dora/metrics/daily_lead_time_for_changes_for_last_week.json';
import { apiDataToChartSeries, buildNullSeriesForLeadTimeChart } from 'ee/dora/components/util'; import {
apiDataToChartSeries,
buildNullSeriesForLeadTimeChart,
seriesToAverageSeries,
} from 'ee/dora/components/util';
describe('ee/dora/components/util.js', () => { describe('ee/dora/components/util.js', () => {
describe('apiDataToChartSeries', () => { describe('apiDataToChartSeries', () => {
...@@ -209,4 +213,40 @@ describe('ee/dora/components/util.js', () => { ...@@ -209,4 +213,40 @@ describe('ee/dora/components/util.js', () => {
expect(chartData).toMatchSnapshot(); expect(chartData).toMatchSnapshot();
}); });
}); });
describe('seriesToAverageSeries', () => {
const seriesName = 'Average';
it('returns an empty object if chart data is undefined', () => {
const data = seriesToAverageSeries(undefined, seriesName);
expect(data).toStrictEqual({});
});
it('returns an empty object if chart data is blank', () => {
const data = seriesToAverageSeries(null, seriesName);
expect(data).toStrictEqual({});
});
it('returns the correct average values', () => {
const data = seriesToAverageSeries(
[
['Jul 1', 2],
['Jul 2', 3],
['Jul 3', 4],
],
seriesName,
);
expect(data).toStrictEqual({
name: seriesName,
data: [
['Jul 1', 3],
['Jul 2', 3],
['Jul 3', 3],
],
});
});
});
}); });
...@@ -10796,6 +10796,9 @@ msgstr "" ...@@ -10796,6 +10796,9 @@ msgstr ""
msgid "DORA4Metrics|%{startDate} - %{endDate}" msgid "DORA4Metrics|%{startDate} - %{endDate}"
msgstr "" msgstr ""
msgid "DORA4Metrics|Average (last %{days}d)"
msgstr ""
msgid "DORA4Metrics|Date" msgid "DORA4Metrics|Date"
msgstr "" msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment