Commit 423cda68 authored by Jannik Lehmann's avatar Jannik Lehmann Committed by Kushal Pandya

Add Autodevops alert to security Config Page

parent 946f3833
<script>
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
export default {
components: {
GlSprintf,
GlAlert,
GlLink,
},
inject: ['autoDevopsHelpPagePath', 'autoDevopsPath'],
i18n: {
primaryButtonText: s__('SecurityConfiguration|Enable Auto DevOps'),
body: s__(
'SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}',
),
},
methods: {
dismissMethod() {
this.$emit('dismiss');
},
},
};
</script>
<template>
<gl-alert
variant="info"
:primary-button-link="autoDevopsPath"
:primary-button-text="$options.i18n.primaryButtonText"
@dismiss="dismissMethod"
>
<gl-sprintf :message="$options.i18n.body">
<template #link="{ content }">
<gl-link :href="autoDevopsHelpPagePath">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</gl-alert>
</template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui'; import { GlTab, GlTabs, GlSprintf, GlLink } from '@gitlab/ui';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue'; import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
import FeatureCard from './feature_card.vue'; import FeatureCard from './feature_card.vue';
import SectionLayout from './section_layout.vue'; import SectionLayout from './section_layout.vue';
import UpgradeBanner from './upgrade_banner.vue'; import UpgradeBanner from './upgrade_banner.vue';
...@@ -31,6 +32,7 @@ export default { ...@@ -31,6 +32,7 @@ export default {
FeatureCard, FeatureCard,
SectionLayout, SectionLayout,
UpgradeBanner, UpgradeBanner,
AutoDevOpsAlert,
UserCalloutDismisser, UserCalloutDismisser,
}, },
props: { props: {
...@@ -47,6 +49,16 @@ export default { ...@@ -47,6 +49,16 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
autoDevopsEnabled: {
type: Boolean,
required: false,
default: false,
},
canEnableAutoDevops: {
type: Boolean,
required: false,
default: false,
},
gitlabCiHistoryPath: { gitlabCiHistoryPath: {
type: String, type: String,
required: false, required: false,
...@@ -67,16 +79,26 @@ export default { ...@@ -67,16 +79,26 @@ export default {
canViewCiHistory() { canViewCiHistory() {
return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath); return Boolean(this.gitlabCiPresent && this.gitlabCiHistoryPath);
}, },
shouldShowDevopsAlert() {
return !this.autoDevopsEnabled && !this.gitlabCiPresent && this.canEnableAutoDevops;
},
}, },
}; };
</script> </script>
<template> <template>
<article> <article>
<user-callout-dismisser
v-if="shouldShowDevopsAlert"
feature-name="security_configuration_devops_alert"
>
<template #default="{ dismiss, shouldShowCallout }">
<auto-dev-ops-alert v-if="shouldShowCallout" class="gl-mt-3" @dismiss="dismiss" />
</template>
</user-callout-dismisser>
<header> <header>
<h1 class="gl-font-size-h1">{{ $options.i18n.securityConfiguration }}</h1> <h1 class="gl-font-size-h1">{{ $options.i18n.securityConfiguration }}</h1>
</header> </header>
<user-callout-dismisser v-if="canUpgrade" feature-name="security_configuration_upgrade_banner"> <user-callout-dismisser v-if="canUpgrade" feature-name="security_configuration_upgrade_banner">
<template #default="{ dismiss, shouldShowCallout }"> <template #default="{ dismiss, shouldShowCallout }">
<upgrade-banner v-if="shouldShowCallout" @close="dismiss" /> <upgrade-banner v-if="shouldShowCallout" @close="dismiss" />
......
...@@ -20,6 +20,8 @@ export const initRedesignedSecurityConfiguration = (el) => { ...@@ -20,6 +20,8 @@ export const initRedesignedSecurityConfiguration = (el) => {
features, features,
latestPipelinePath, latestPipelinePath,
gitlabCiHistoryPath, gitlabCiHistoryPath,
autoDevopsHelpPagePath,
autoDevopsPath,
} = el.dataset; } = el.dataset;
const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures( const { augmentedSecurityFeatures, augmentedComplianceFeatures } = augmentFeatures(
...@@ -34,6 +36,8 @@ export const initRedesignedSecurityConfiguration = (el) => { ...@@ -34,6 +36,8 @@ export const initRedesignedSecurityConfiguration = (el) => {
provide: { provide: {
projectPath, projectPath,
upgradePath, upgradePath,
autoDevopsHelpPagePath,
autoDevopsPath,
}, },
render(createElement) { render(createElement) {
return createElement(RedesignedSecurityConfigurationApp, { return createElement(RedesignedSecurityConfigurationApp, {
...@@ -42,7 +46,11 @@ export const initRedesignedSecurityConfiguration = (el) => { ...@@ -42,7 +46,11 @@ export const initRedesignedSecurityConfiguration = (el) => {
augmentedSecurityFeatures, augmentedSecurityFeatures,
latestPipelinePath, latestPipelinePath,
gitlabCiHistoryPath, gitlabCiHistoryPath,
...parseBooleanDataAttributes(el, ['gitlabCiPresent']), ...parseBooleanDataAttributes(el, [
'gitlabCiPresent',
'autoDevopsEnabled',
'canEnableAutoDevops',
]),
}, },
}); });
}, },
......
...@@ -34,7 +34,8 @@ class UserCallout < ApplicationRecord ...@@ -34,7 +34,8 @@ class UserCallout < ApplicationRecord
security_configuration_upgrade_banner: 32, security_configuration_upgrade_banner: 32,
cloud_licensing_subscription_activation_banner: 33, # EE-only cloud_licensing_subscription_activation_banner: 33, # EE-only
trial_status_reminder_d14: 34, # EE-only trial_status_reminder_d14: 34, # EE-only
trial_status_reminder_d3: 35 # EE-only trial_status_reminder_d3: 35, # EE-only
security_configuration_devops_alert: 36 # EE-only
} }
validates :user, presence: true validates :user, presence: true
......
...@@ -15290,6 +15290,7 @@ Name of the feature that the callout is for. ...@@ -15290,6 +15290,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumpipeline_needs_banner"></a>`PIPELINE_NEEDS_BANNER` | Callout feature name for pipeline_needs_banner. | | <a id="usercalloutfeaturenameenumpipeline_needs_banner"></a>`PIPELINE_NEEDS_BANNER` | Callout feature name for pipeline_needs_banner. |
| <a id="usercalloutfeaturenameenumpipeline_needs_hover_tip"></a>`PIPELINE_NEEDS_HOVER_TIP` | Callout feature name for pipeline_needs_hover_tip. | | <a id="usercalloutfeaturenameenumpipeline_needs_hover_tip"></a>`PIPELINE_NEEDS_HOVER_TIP` | Callout feature name for pipeline_needs_hover_tip. |
| <a id="usercalloutfeaturenameenumregistration_enabled_callout"></a>`REGISTRATION_ENABLED_CALLOUT` | Callout feature name for registration_enabled_callout. | | <a id="usercalloutfeaturenameenumregistration_enabled_callout"></a>`REGISTRATION_ENABLED_CALLOUT` | Callout feature name for registration_enabled_callout. |
| <a id="usercalloutfeaturenameenumsecurity_configuration_devops_alert"></a>`SECURITY_CONFIGURATION_DEVOPS_ALERT` | Callout feature name for security_configuration_devops_alert. |
| <a id="usercalloutfeaturenameenumsecurity_configuration_upgrade_banner"></a>`SECURITY_CONFIGURATION_UPGRADE_BANNER` | Callout feature name for security_configuration_upgrade_banner. | | <a id="usercalloutfeaturenameenumsecurity_configuration_upgrade_banner"></a>`SECURITY_CONFIGURATION_UPGRADE_BANNER` | Callout feature name for security_configuration_upgrade_banner. |
| <a id="usercalloutfeaturenameenumservice_templates_deprecated_callout"></a>`SERVICE_TEMPLATES_DEPRECATED_CALLOUT` | Callout feature name for service_templates_deprecated_callout. | | <a id="usercalloutfeaturenameenumservice_templates_deprecated_callout"></a>`SERVICE_TEMPLATES_DEPRECATED_CALLOUT` | Callout feature name for service_templates_deprecated_callout. |
| <a id="usercalloutfeaturenameenumsuggest_pipeline"></a>`SUGGEST_PIPELINE` | Callout feature name for suggest_pipeline. | | <a id="usercalloutfeaturenameenumsuggest_pipeline"></a>`SUGGEST_PIPELINE` | Callout feature name for suggest_pipeline. |
......
...@@ -29045,6 +29045,9 @@ msgstr "" ...@@ -29045,6 +29045,9 @@ msgstr ""
msgid "SecurityConfiguration|Enable %{feature}" msgid "SecurityConfiguration|Enable %{feature}"
msgstr "" msgstr ""
msgid "SecurityConfiguration|Enable Auto DevOps"
msgstr ""
msgid "SecurityConfiguration|Enabled" msgid "SecurityConfiguration|Enabled"
msgstr "" msgstr ""
...@@ -29078,6 +29081,9 @@ msgstr "" ...@@ -29078,6 +29081,9 @@ msgstr ""
msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan." msgid "SecurityConfiguration|Once you've enabled a scan for the default branch, any subsequent feature branch you create will include the scan."
msgstr "" msgstr ""
msgid "SecurityConfiguration|Quickly enable all continuous testing and compliance tools by enabling %{linkStart}Auto DevOps%{linkEnd}"
msgstr ""
msgid "SecurityConfiguration|Runtime security metrics for application environments." msgid "SecurityConfiguration|Runtime security metrics for application environments."
msgstr "" msgstr ""
......
import { GlAlert } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import AutoDevopsAlert from '~/security_configuration/components/auto_dev_ops_alert.vue';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
const autoDevopsPath = '/enableAutoDevopsPath';
describe('AutoDevopsAlert component', () => {
let wrapper;
const createComponent = () => {
wrapper = mount(AutoDevopsAlert, {
provide: {
autoDevopsHelpPagePath,
autoDevopsPath,
},
});
};
const findAlert = () => wrapper.findComponent(GlAlert);
beforeEach(() => {
createComponent();
});
afterEach(() => {
wrapper.destroy();
});
it('contains correct body text', () => {
expect(wrapper.text()).toContain('Quickly enable all');
});
it('renders the link correctly', () => {
const link = wrapper.find('a');
expect(link.attributes('href')).toBe(autoDevopsHelpPagePath);
expect(link.text()).toBe('Auto DevOps');
});
it('bubbles up dismiss events from the GlAlert', () => {
expect(wrapper.emitted('dismiss')).toBe(undefined);
findAlert().vm.$emit('dismiss');
expect(wrapper.emitted('dismiss')).toEqual([[]]);
});
it('has a button pointing to autoDevopsPath', () => {
expect(findAlert().props()).toMatchObject({
primaryButtonText: 'Enable Auto DevOps',
primaryButtonLink: autoDevopsPath,
});
});
});
...@@ -2,6 +2,7 @@ import { GlTab } from '@gitlab/ui'; ...@@ -2,6 +2,7 @@ import { GlTab } from '@gitlab/ui';
import { mount } from '@vue/test-utils'; import { mount } from '@vue/test-utils';
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser'; import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import AutoDevopsAlert from '~/security_configuration/components/auto_dev_ops_alert.vue';
import { import {
SAST_NAME, SAST_NAME,
SAST_SHORT_NAME, SAST_SHORT_NAME,
...@@ -13,6 +14,7 @@ import { ...@@ -13,6 +14,7 @@ import {
LICENSE_COMPLIANCE_HELP_PATH, LICENSE_COMPLIANCE_HELP_PATH,
} from '~/security_configuration/components/constants'; } from '~/security_configuration/components/constants';
import FeatureCard from '~/security_configuration/components/feature_card.vue'; import FeatureCard from '~/security_configuration/components/feature_card.vue';
import RedesignedSecurityConfigurationApp, { import RedesignedSecurityConfigurationApp, {
i18n, i18n,
} from '~/security_configuration/components/redesigned_app.vue'; } from '~/security_configuration/components/redesigned_app.vue';
...@@ -23,6 +25,8 @@ import { ...@@ -23,6 +25,8 @@ import {
} from '~/vue_shared/security_reports/constants'; } from '~/vue_shared/security_reports/constants';
const upgradePath = '/upgrade'; const upgradePath = '/upgrade';
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
const autoDevopsPath = '/autoDevopsPath';
const gitlabCiHistoryPath = 'test/historyPath'; const gitlabCiHistoryPath = 'test/historyPath';
describe('redesigned App component', () => { describe('redesigned App component', () => {
...@@ -37,6 +41,8 @@ describe('redesigned App component', () => { ...@@ -37,6 +41,8 @@ describe('redesigned App component', () => {
propsData, propsData,
provide: { provide: {
upgradePath, upgradePath,
autoDevopsHelpPagePath,
autoDevopsPath,
}, },
stubs: { stubs: {
UserCalloutDismisser: makeMockUserCalloutDismisser({ UserCalloutDismisser: makeMockUserCalloutDismisser({
...@@ -76,6 +82,7 @@ describe('redesigned App component', () => { ...@@ -76,6 +82,7 @@ describe('redesigned App component', () => {
container: findByTestId('compliance-testing-tab'), container: findByTestId('compliance-testing-tab'),
}); });
const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner); const findUpgradeBanner = () => wrapper.findComponent(UpgradeBanner);
const findAutoDevopsAlert = () => wrapper.findComponent(AutoDevopsAlert);
const securityFeaturesMock = [ const securityFeaturesMock = [
{ {
...@@ -154,6 +161,44 @@ describe('redesigned App component', () => { ...@@ -154,6 +161,44 @@ describe('redesigned App component', () => {
}); });
}); });
describe('autoDevOpsAlert', () => {
describe('given the right props', () => {
beforeEach(() => {
createComponent({
augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock,
autoDevopsEnabled: false,
gitlabCiPresent: false,
canEnableAutoDevops: true,
});
});
it('should show AutoDevopsAlert', () => {
expect(findAutoDevopsAlert().exists()).toBe(true);
});
it('calls the dismiss callback when closing the AutoDevopsAlert', () => {
expect(userCalloutDismissSpy).not.toHaveBeenCalled();
findAutoDevopsAlert().vm.$emit('dismiss');
expect(userCalloutDismissSpy).toHaveBeenCalledTimes(1);
});
});
describe('given the wrong props', () => {
beforeEach(() => {
createComponent({
augmentedSecurityFeatures: securityFeaturesMock,
augmentedComplianceFeatures: complianceFeaturesMock,
});
});
it('should not show AutoDevopsAlert', () => {
expect(findAutoDevopsAlert().exists()).toBe(false);
});
});
});
describe('upgrade banner', () => { describe('upgrade banner', () => {
const makeAvailable = (available) => (feature) => ({ ...feature, available }); const makeAvailable = (available) => (feature) => ({ ...feature, available });
......
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