Commit 7db12ed1 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch '220578-history-button-for-sast-ui-config-page' into 'master'

Link to CI file history in Security Configuration

See merge request gitlab-org/gitlab!41673
parents 8afdc95f 4297f002
...@@ -15,18 +15,22 @@ The Security Configuration page displays the configuration state of each securit ...@@ -15,18 +15,22 @@ The Security Configuration page displays the configuration state of each securit
current project. current project.
To view a project's security configuration, go to the project's home page, To view a project's security configuration, go to the project's home page,
then in the left sidebar, go to **Security & Compliance** > **Configuration**. then in the left sidebar go to **Security & Compliance > Configuration**.
## Status For each security control the page displays:
- **Status** - Status of the security control: enabled, not enabled, or available.
- **Manage** - A management option or a link to the documentation.
For each security control, the page displays the status and either a management option or a ## Status
documentation link.
The status of each security control is determined by the project's latest default branch The status of each security control is determined by the project's latest default branch
[CI pipeline](../../../ci/pipelines/index.md). [CI pipeline](../../../ci/pipelines/index.md).
If a job with the expected security report artifact exists in the pipeline, the feature's status is If a job with the expected security report artifact exists in the pipeline, the feature's status is
_enabled_. _enabled_.
For SAST, click **View history** to see the `.gitlab-ci.yml` file’s history.
NOTE: **Note:** NOTE: **Note:**
If the latest pipeline used [Auto DevOps](../../../topics/autodevops/index.md), If the latest pipeline used [Auto DevOps](../../../topics/autodevops/index.md),
all security features are configured by default. all security features are configured by default.
......
...@@ -5,6 +5,7 @@ import { s__, __ } from '~/locale'; ...@@ -5,6 +5,7 @@ import { s__, __ } from '~/locale';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue'; import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import AutoFixSettings from './auto_fix_settings.vue'; import AutoFixSettings from './auto_fix_settings.vue';
import FeatureStatus from './feature_status.vue';
import ManageFeature from './manage_feature.vue'; import ManageFeature from './manage_feature.vue';
export default { export default {
...@@ -15,6 +16,7 @@ export default { ...@@ -15,6 +16,7 @@ export default {
GlTable, GlTable,
AutoFixSettings, AutoFixSettings,
LocalStorageSync, LocalStorageSync,
FeatureStatus,
ManageFeature, ManageFeature,
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
...@@ -50,6 +52,11 @@ export default { ...@@ -50,6 +52,11 @@ export default {
required: false, required: false,
default: false, default: false,
}, },
gitlabCiHistoryPath: {
type: String,
required: false,
default: '',
},
autoDevopsPath: { autoDevopsPath: {
type: String, type: String,
required: false, required: false,
...@@ -167,6 +174,14 @@ export default { ...@@ -167,6 +174,14 @@ export default {
</div> </div>
</template> </template>
<template #cell(status)="{ item }">
<feature-status
:feature="item"
:gitlab-ci-present="gitlabCiPresent"
:gitlab-ci-history-path="gitlabCiHistoryPath"
/>
</template>
<template #cell(manage)="{ item }"> <template #cell(manage)="{ item }">
<manage-feature <manage-feature
:feature="item" :feature="item"
......
<script>
import { GlLink } from '@gitlab/ui';
export default {
components: {
GlLink,
},
props: {
feature: {
type: Object,
required: true,
},
gitlabCiPresent: {
type: Boolean,
required: false,
default: false,
},
gitlabCiHistoryPath: {
type: String,
required: false,
default: '',
},
},
computed: {
canViewCiHistory() {
const { type, configured } = this.feature;
return type === 'sast' && configured && this.gitlabCiPresent;
},
},
};
</script>
<template>
<div>
{{ feature.status }}
<template v-if="canViewCiHistory">
<br />
<gl-link :href="gitlabCiHistoryPath">{{ s__('SecurityConfiguration|View history') }}</gl-link>
</template>
</div>
</template>
...@@ -17,6 +17,7 @@ export default function init() { ...@@ -17,6 +17,7 @@ export default function init() {
dependencyScanningHelpPath, dependencyScanningHelpPath,
toggleAutofixSettingEndpoint, toggleAutofixSettingEndpoint,
createSastMergeRequestPath, createSastMergeRequestPath,
gitlabCiHistoryPath,
} = el.dataset; } = el.dataset;
return new Vue({ return new Vue({
...@@ -38,6 +39,7 @@ export default function init() { ...@@ -38,6 +39,7 @@ export default function init() {
'canEnableAutoDevops', 'canEnableAutoDevops',
'gitlabCiPresent', 'gitlabCiPresent',
]), ]),
gitlabCiHistoryPath,
autoFixSettingsProps: { autoFixSettingsProps: {
autoFixEnabled: JSON.parse(autoFixEnabled), autoFixEnabled: JSON.parse(autoFixEnabled),
autoFixHelpPath, autoFixHelpPath,
......
...@@ -62,6 +62,7 @@ module Projects ...@@ -62,6 +62,7 @@ module Projects
auto_fix_enabled: autofix_enabled, auto_fix_enabled: autofix_enabled,
can_toggle_auto_fix_settings: auto_fix_permission, can_toggle_auto_fix_settings: auto_fix_permission,
gitlab_ci_present: gitlab_ci_present?, gitlab_ci_present: gitlab_ci_present?,
gitlab_ci_history_path: gitlab_ci_history_path,
auto_fix_user_path: '/' # TODO: real link will be updated with https://gitlab.com/gitlab-org/gitlab/-/issues/215669 auto_fix_user_path: '/' # TODO: real link will be updated with https://gitlab.com/gitlab-org/gitlab/-/issues/215669
} }
end end
...@@ -93,6 +94,11 @@ module Projects ...@@ -93,6 +94,11 @@ module Projects
latest_pipeline.try(:config_path) == Gitlab::FileDetector::PATTERNS[:gitlab_ci] latest_pipeline.try(:config_path) == Gitlab::FileDetector::PATTERNS[:gitlab_ci]
end end
def gitlab_ci_history_path
gitlab_ci = Gitlab::FileDetector::PATTERNS[:gitlab_ci]
Gitlab::Routing.url_helpers.project_blame_path(project, File.join(project.default_branch, gitlab_ci))
end
def features def features
scans = scan_types.map do |scan_type| scans = scan_types.map do |scan_type|
if scanner_enabled?(scan_type) if scanner_enabled?(scan_type)
......
---
title: Add link to GitLab CI history in Security Configuration
merge_request: 41673
author:
type: added
...@@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils'; ...@@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils';
import { merge } from 'lodash'; import { merge } from 'lodash';
import { GlAlert, GlLink } from '@gitlab/ui'; import { GlAlert, GlLink } from '@gitlab/ui';
import SecurityConfigurationApp from 'ee/security_configuration/components/app.vue'; import SecurityConfigurationApp from 'ee/security_configuration/components/app.vue';
import FeatureStatus from 'ee/security_configuration/components/feature_status.vue';
import ManageFeature from 'ee/security_configuration/components/manage_feature.vue'; import ManageFeature from 'ee/security_configuration/components/manage_feature.vue';
import stubChildren from 'helpers/stub_children'; import stubChildren from 'helpers/stub_children';
import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { useLocalStorageSpy } from 'helpers/local_storage_helper';
...@@ -16,6 +17,7 @@ const propsData = { ...@@ -16,6 +17,7 @@ const propsData = {
autoDevopsPath: 'http://autoDevopsPath', autoDevopsPath: 'http://autoDevopsPath',
helpPagePath: 'http://helpPagePath', helpPagePath: 'http://helpPagePath',
gitlabCiPresent: false, gitlabCiPresent: false,
gitlabCiHistoryPath: '/ci/history',
autoFixSettingsProps: {}, autoFixSettingsProps: {},
createSastMergeRequestPath: 'http://createSastMergeRequestPath', createSastMergeRequestPath: 'http://createSastMergeRequestPath',
}; };
...@@ -173,27 +175,17 @@ describe('Security Configuration App', () => { ...@@ -173,27 +175,17 @@ describe('Security Configuration App', () => {
const { feature, status, manage } = getRowCells(rows.at(i)); const { feature, status, manage } = getRowCells(rows.at(i));
expect(feature.text()).toMatch(features[i].name); expect(feature.text()).toMatch(features[i].name);
expect(feature.text()).toMatch(features[i].description); expect(feature.text()).toMatch(features[i].description);
expect(status.text()).toMatch(features[i].configured ? 'Enabled' : 'Not enabled'); expect(status.find(FeatureStatus).props()).toEqual({
expect(manage.find(ManageFeature).props()).toMatchObject({ feature: features[i],
gitlabCiPresent: propsData.gitlabCiPresent,
gitlabCiHistoryPath: propsData.gitlabCiHistoryPath,
});
expect(manage.find(ManageFeature).props()).toEqual({
feature: features[i], feature: features[i],
autoDevopsEnabled: propsData.autoDevopsEnabled, autoDevopsEnabled: propsData.autoDevopsEnabled,
createSastMergeRequestPath: propsData.createSastMergeRequestPath, createSastMergeRequestPath: propsData.createSastMergeRequestPath,
}); });
} }
}); });
describe('given a feature enabled by Auto DevOps', () => {
it('displays the expected status text', () => {
const features = generateFeatures(1, {
configured: true,
status: 'Enabled with Auto DevOps',
});
createComponent({ propsData: { features, autoDevopsEnabled: true } });
const { status } = getRowCells(getFeaturesRows().at(0));
expect(status.text()).toMatch('Enabled with Auto DevOps');
});
});
}); });
}); });
import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import FeatureStatus from 'ee/security_configuration/components/feature_status.vue';
import { generateFeatures } from './helpers';
const gitlabCiHistoryPath = '/ci/history';
describe('FeatureStatus component', () => {
let wrapper;
let feature;
const createComponent = options => {
wrapper = shallowMount(FeatureStatus, options);
};
afterEach(() => {
wrapper.destroy();
feature = undefined;
});
const findHistoryLink = () => wrapper.find(GlLink);
describe.each`
context | type | configured | gitlabCiPresent | shouldShowHistory
${'no CI with sast disabled'} | ${'sast'} | ${false} | ${false} | ${false}
${'CI with sast disabled'} | ${'sast'} | ${false} | ${true} | ${false}
${'no CI with sast enabled'} | ${'sast'} | ${true} | ${false} | ${false}
${'CI with foo enabled'} | ${'foo'} | ${true} | ${true} | ${false}
${'CI with sast enabled'} | ${'sast'} | ${true} | ${true} | ${true}
`('given $context', ({ type, configured, gitlabCiPresent, shouldShowHistory }) => {
beforeEach(() => {
[feature] = generateFeatures(1, { type, configured });
createComponent({
propsData: { feature, gitlabCiPresent, gitlabCiHistoryPath },
});
});
it('shows feature status text', () => {
expect(wrapper.text()).toContain(feature.status);
});
it(`${shouldShowHistory ? 'shows' : 'does not show'} the history link`, () => {
expect(findHistoryLink().exists()).toBe(shouldShowHistory);
});
if (shouldShowHistory) {
it("sets the link's href correctly", () => {
expect(findHistoryLink().attributes('href')).toBe(gitlabCiHistoryPath);
});
}
});
});
...@@ -37,6 +37,10 @@ RSpec.describe Projects::Security::ConfigurationPresenter do ...@@ -37,6 +37,10 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
expect(subject[:create_sast_merge_request_path]).to eq(project_security_configuration_sast_path(project)) expect(subject[:create_sast_merge_request_path]).to eq(project_security_configuration_sast_path(project))
end end
it 'includes the path to gitlab_ci history' do
expect(subject[:gitlab_ci_history_path]).to eq(project_blame_path(project, 'master/.gitlab-ci.yml'))
end
context "when the latest default branch pipeline's source is auto devops" do context "when the latest default branch pipeline's source is auto devops" do
before do before do
pipeline = create( pipeline = create(
......
...@@ -22124,6 +22124,9 @@ msgstr "" ...@@ -22124,6 +22124,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}" msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr "" msgstr ""
msgid "SecurityConfiguration|View history"
msgstr ""
msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}." msgid "SecurityConfiguration|You can quickly enable all security scanning tools by enabling %{linkStart}Auto DevOps%{linkEnd}."
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