Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-14 03:10:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-14 03:10:28 +0300
commit968e01a6dd8f4765223f4d1ffb096483f5cce3eb (patch)
treecca2d6ae4a68559da95528f848ff3f1530350698
parent3825437c53474e3d6f3a7d82ef4f26583212531e (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/lib/utils/keys.js1
-rw-r--r--app/assets/javascripts/releases/components/app_edit_new.vue15
-rw-r--r--app/assets/javascripts/releases/components/asset_links_form.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js3
-rw-r--r--app/controllers/projects/merge_requests_controller.rb2
-rw-r--r--app/graphql/resolvers/ci_configuration/sast_resolver.rb17
-rw-r--r--app/graphql/types/project_type.rb4
-rw-r--r--app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json76
-rw-r--r--changelogs/unreleased/jdb-mlc-enable-default.yml5
-rw-r--r--changelogs/unreleased/nfriend-prevent-submission-of-invalid-form-on-new-release-page.yml5
-rw-r--r--doc/.vale/gitlab/ContractionsDiscard.yml (renamed from doc/.vale/gitlab/Contractions.yml)16
-rw-r--r--doc/.vale/gitlab/ContractionsKeep.yml25
-rw-r--r--doc/user/group/saml_sso/index.md1
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md15
-rw-r--r--spec/features/global_search_spec.rb2
-rw-r--r--spec/frontend/releases/components/app_edit_new_spec.js18
-rw-r--r--spec/frontend/releases/components/asset_links_form_spec.js143
-rw-r--r--spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb28
-rw-r--r--spec/graphql/types/project_type_spec.rb90
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci_for_sast.yml13
-rw-r--r--spec/support/shared_contexts/read_ci_configuration_shared_context.rb9
21 files changed, 395 insertions, 107 deletions
diff --git a/app/assets/javascripts/lib/utils/keys.js b/app/assets/javascripts/lib/utils/keys.js
index 8e5420e87ea..b7ba6d3a071 100644
--- a/app/assets/javascripts/lib/utils/keys.js
+++ b/app/assets/javascripts/lib/utils/keys.js
@@ -2,3 +2,4 @@
export const ESC_KEY = 'Escape';
export const ESC_KEY_IE11 = 'Esc'; // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
+export const ENTER_KEY = 'Enter';
diff --git a/app/assets/javascripts/releases/components/app_edit_new.vue b/app/assets/javascripts/releases/components/app_edit_new.vue
index 1710abe72ef..7b7c80a6269 100644
--- a/app/assets/javascripts/releases/components/app_edit_new.vue
+++ b/app/assets/javascripts/releases/components/app_edit_new.vue
@@ -85,7 +85,7 @@ export default {
saveButtonLabel() {
return this.isExistingRelease ? __('Save changes') : __('Create release');
},
- isSaveChangesDisabled() {
+ isFormSubmissionDisabled() {
return this.isUpdatingRelease || !this.isValid;
},
milestoneComboboxExtraLinks() {
@@ -116,13 +116,18 @@ export default {
'updateReleaseNotes',
'updateReleaseMilestones',
]),
+ submitForm() {
+ if (!this.isFormSubmissionDisabled) {
+ this.saveRelease();
+ }
+ },
},
};
</script>
<template>
<div class="d-flex flex-column">
<p class="pt-3 js-subtitle-text" v-html="subtitleText"></p>
- <form v-if="showForm" @submit.prevent="saveRelease()">
+ <form v-if="showForm" class="js-quick-submit" @submit.prevent="submitForm">
<tag-field />
<gl-form-group>
<label for="release-title">{{ __('Release title') }}</label>
@@ -134,7 +139,7 @@ export default {
class="form-control"
/>
</gl-form-group>
- <gl-form-group class="w-50">
+ <gl-form-group class="w-50" @keydown.enter.prevent.capture>
<label>{{ __('Milestones') }}</label>
<div class="d-flex flex-column col-md-6 col-sm-10 pl-0">
<milestone-combobox
@@ -163,8 +168,6 @@ export default {
data-supports-quick-actions="false"
:aria-label="__('Release notes')"
:placeholder="__('Write your release notes or drag your files hereā€¦')"
- @keydown.meta.enter="saveRelease()"
- @keydown.ctrl.enter="saveRelease()"
></textarea>
</template>
</markdown-field>
@@ -179,7 +182,7 @@ export default {
category="primary"
variant="success"
type="submit"
- :disabled="isSaveChangesDisabled"
+ :disabled="isFormSubmissionDisabled"
data-testid="submit-button"
>
{{ saveButtonLabel }}
diff --git a/app/assets/javascripts/releases/components/asset_links_form.vue b/app/assets/javascripts/releases/components/asset_links_form.vue
index d0d1485d8e7..07fab840067 100644
--- a/app/assets/javascripts/releases/components/asset_links_form.vue
+++ b/app/assets/javascripts/releases/components/asset_links_form.vue
@@ -49,6 +49,12 @@ export default {
this.removeAssetLink(linkId);
this.ensureAtLeastOneLink();
},
+ updateUrl(link, newUrl) {
+ this.updateAssetLinkUrl({ linkIdToUpdate: link.id, newUrl });
+ },
+ updateName(link, newName) {
+ this.updateAssetLinkName({ linkIdToUpdate: link.id, newName });
+ },
hasDuplicateUrl(link) {
return Boolean(this.getLinkErrors(link).isDuplicate);
},
@@ -138,7 +144,9 @@ export default {
type="text"
class="form-control"
:state="isUrlValid(link)"
- @change="updateAssetLinkUrl({ linkIdToUpdate: link.id, newUrl: $event })"
+ @change="updateUrl(link, $event)"
+ @keydown.ctrl.enter="updateUrl(link, $event.target.value)"
+ @keydown.meta.enter="updateUrl(link, $event.target.value)"
/>
<template #invalid-feedback>
<span v-if="hasEmptyUrl(link)" class="invalid-feedback d-inline">
@@ -175,7 +183,9 @@ export default {
type="text"
class="form-control"
:state="isNameValid(link)"
- @change="updateAssetLinkName({ linkIdToUpdate: link.id, newName: $event })"
+ @change="updateName(link, $event)"
+ @keydown.ctrl.enter="updateName(link, $event.target.value)"
+ @keydown.meta.enter="updateName(link, $event.target.value)"
/>
<template #invalid-feedback>
<span v-if="hasEmptyName(link)" class="invalid-feedback d-inline">
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index 319b6c333f4..dc8a6b56d58 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -32,5 +32,8 @@ export default {
isMergeImmediatelyDangerous() {
return false;
},
+ shouldRenderMergeTrainHelperText() {
+ return false;
+ },
},
};
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index f3a47b03e2e..9b246979860 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -33,7 +33,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:widget_visibility_polling, @project, default_enabled: true)
push_frontend_feature_flag(:merge_ref_head_comments, @project, default_enabled: true)
push_frontend_feature_flag(:mr_commit_neighbor_nav, @project, default_enabled: true)
- push_frontend_feature_flag(:multiline_comments, @project)
+ push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:auto_expand_collapsed_diffs, @project, default_enabled: true)
diff --git a/app/graphql/resolvers/ci_configuration/sast_resolver.rb b/app/graphql/resolvers/ci_configuration/sast_resolver.rb
new file mode 100644
index 00000000000..e8c42076ea2
--- /dev/null
+++ b/app/graphql/resolvers/ci_configuration/sast_resolver.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require "json"
+
+module Resolvers
+ module CiConfiguration
+ class SastResolver < BaseResolver
+ SAST_UI_SCHEMA_PATH = 'app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json'
+
+ type ::Types::CiConfiguration::Sast::Type, null: true
+
+ def resolve(**args)
+ Gitlab::Json.parse(File.read(Rails.root.join(SAST_UI_SCHEMA_PATH)))
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index 5562db69de6..523e019b955 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -175,6 +175,10 @@ module Types
description: 'A single environment of the project',
resolver: Resolvers::EnvironmentsResolver.single
+ field :sast_ci_configuration, ::Types::CiConfiguration::Sast::Type, null: true,
+ description: 'SAST CI configuration for the project',
+ resolver: ::Resolvers::CiConfiguration::SastResolver
+
field :issue,
Types::IssueType,
null: true,
diff --git a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
index aa4dd60a9fb..cce2b28529f 100644
--- a/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
+++ b/app/validators/json_schemas/security_ci_configuration_schemas/sast_ui_schema.json
@@ -4,43 +4,83 @@
"field" : "SECURE_ANALYZERS_PREFIX",
"label" : "Image prefix",
"type": "string",
- "default_value": "",
- "value": "",
- "description": "Analyzer image's registry prefix (or Name of the registry providing the analyzers' image)"
+ "default_value": "registry.gitlab.com/gitlab-org/security-products/analyzers",
+ "value": ""
},
{
"field" : "SAST_EXCLUDED_PATHS",
"label" : "Excluded Paths",
"type": "string",
- "default_value": "",
- "value": "",
- "description": "Comma-separated list of paths to be excluded from analyzer output. Patterns can be globs, file paths, or folder paths."
+ "default_value": "spec, test, tests, tmp",
+ "value": ""
},
{
"field" : "SAST_ANALYZER_IMAGE_TAG",
"label" : "Image tag",
"type": "string",
- "default_value": "",
- "value": "",
- "description": "Analyzer image's tag"
+ "options": [],
+ "default_value": "2",
+ "value": ""
+ },
+ {
+ "field" : "SAST_DISABLED",
+ "label" : "Disable SAST",
+ "type": "options",
+ "options": [
+ {
+ "value" :"true",
+ "label" : "true (disables SAST)"
+ },
+ {
+ "value":"false",
+ "label":"false (enables SAST)"
+ }
+ ],
+ "default_value": "false",
+ "value": ""
}
],
"pipeline": [
{
"field" : "stage",
"label" : "Stage",
- "type": "string",
- "default_value": "",
- "value": "",
- "description": "Pipeline stage in which the scan jobs run"
+ "type": "dropdown",
+ "options": [
+ {
+ "value" :"test",
+ "label" : "test"
+ },
+ {
+ "value":"build",
+ "label":"build"
+ }
+ ],
+ "default_value": "test",
+ "value": ""
},
{
- "field" : "SEARCH_MAX_DEPTH",
- "label" : "Search maximum depth",
- "type": "string",
+ "field" : "allow_failure",
+ "label" : "Allow Failure",
+ "type": "options",
+ "options": [
+ {
+ "value" :"true",
+ "label" : "Allows pipeline failure"
+ },
+ {
+ "value": "false",
+ "label": "Does not allow pipeline failure"
+ }
+ ],
+ "default_value": "true",
+ "value": ""
+ },
+ {
+ "field" : "rules",
+ "label" : "Rules",
+ "type": "multiline",
"default_value": "",
- "value": "",
- "description": "Maximum depth of language and framework detection"
+ "value": ""
}
],
"analyzers": [
diff --git a/changelogs/unreleased/jdb-mlc-enable-default.yml b/changelogs/unreleased/jdb-mlc-enable-default.yml
new file mode 100644
index 00000000000..5a9972bfa79
--- /dev/null
+++ b/changelogs/unreleased/jdb-mlc-enable-default.yml
@@ -0,0 +1,5 @@
+---
+title: Enable Multiline Comments by default
+merge_request: 39370
+author:
+type: changed
diff --git a/changelogs/unreleased/nfriend-prevent-submission-of-invalid-form-on-new-release-page.yml b/changelogs/unreleased/nfriend-prevent-submission-of-invalid-form-on-new-release-page.yml
new file mode 100644
index 00000000000..8a7b08b46be
--- /dev/null
+++ b/changelogs/unreleased/nfriend-prevent-submission-of-invalid-form-on-new-release-page.yml
@@ -0,0 +1,5 @@
+---
+title: Improve submission behavior of the New/Edit Release page
+merge_request: 39145
+author:
+type: added
diff --git a/doc/.vale/gitlab/Contractions.yml b/doc/.vale/gitlab/ContractionsDiscard.yml
index c6b970ab6e9..698fda86b5b 100644
--- a/doc/.vale/gitlab/Contractions.yml
+++ b/doc/.vale/gitlab/ContractionsDiscard.yml
@@ -1,7 +1,7 @@
---
-# Suggestion: gitlab.Contractions
+# Suggestion: gitlab.ContractionsDiscard
#
-# Checks for use of common and uncommon contractions.
+# Suggests a list of agreed-upon contractions to discard.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
@@ -12,18 +12,6 @@ nonword: false
ignorecase: true
swap:
- # Common contractions are ok
- it is: it's
- can not: can't
- cannot: can't
- do not: don't
- have not: haven't
- that is: that's
- we are: we're
- would not: wouldn't
- you are: you're
- you have: you've
-
# Uncommon contractions are not ok
aren't: are not
couldn't: could not
diff --git a/doc/.vale/gitlab/ContractionsKeep.yml b/doc/.vale/gitlab/ContractionsKeep.yml
new file mode 100644
index 00000000000..eeaf65e0829
--- /dev/null
+++ b/doc/.vale/gitlab/ContractionsKeep.yml
@@ -0,0 +1,25 @@
+---
+# Suggestion: gitlab.ContractionsKeep
+#
+# Suggests a list of agreed-upon contractions to keep.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: substitution
+message: 'Use "%s" instead of "%s", for a friendly, informal tone.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#language
+level: suggestion
+nonword: false
+ignorecase: true
+swap:
+
+ # Common contractions are ok
+ it is: it's
+ can not: can't
+ cannot: can't
+ do not: don't
+ have not: haven't
+ that is: that's
+ we are: we're
+ would not: wouldn't
+ you are: you're
+ you have: you've
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 3040c31de7f..13878e72162 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -80,6 +80,7 @@ Please note that the certificate [fingerprint algorithm](#additional-providers-a
With this option enabled, users must go through your group's GitLab single sign-on URL. They may also be added via SCIM, if configured. Users cannot be added manually, and may only access project/group resources via the UI by signing in through the SSO URL.
However, users will not be prompted to sign in through SSO on each visit. GitLab will check whether a user has authenticated through SSO, and will only prompt the user to sign in via SSO if the session has expired.
+You can see more information about how long a session is valid in our [user profile documentation](../../profile/#why-do-i-keep-getting-signed-out).
We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152).
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index 496525c147c..4e821145339 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -151,11 +151,12 @@ in a Merge Request. To do so, click the **{comment}** **comment** icon in the gu
### Commenting on multiple lines
> - [Introduced](https://gitlab.com/gitlab-org/ux-research/-/issues/870) in GitLab 13.2.
-> - It's deployed behind a feature flag, disabled by default.
+> - It's deployed behind a feature flag, enabled by default.
+> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221268) on GitLab 13.3.
> - It's enabled on GitLab.com.
-> - It can be enabled or disabled per-project.
+> - It can be disabled or enabled per-project.
> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [enable it](#enable-or-disable-multiline-comments-core-only). **(CORE ONLY)**
+> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments-core-only). **(CORE ONLY)**
GitLab provides a way to select which lines of code a comment refers to. After starting a comment
a dropdown selector is shown to select the first line that this comment refers to.
@@ -178,16 +179,16 @@ It is deployed behind a feature flag that is **disabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
can opt to enable it for your instance.
-To enable it:
+To disable it:
```ruby
-Feature.enable(:multiline_comments)
+Feature.disable(:multiline_comments)
```
-To disable it:
+To enable it:
```ruby
-Feature.disable(:multiline_comments)
+Feature.enable(:multiline_comments)
```
## Pipeline status in merge requests widgets
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
index c878ee7329f..0ca626381d4 100644
--- a/spec/features/global_search_spec.rb
+++ b/spec/features/global_search_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe 'Global search' do
end
end
- it 'closes the dropdown on blur', :js do
+ it 'closes the dropdown on blur', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/201841' do
fill_in 'search', with: "a"
dropdown = find('.js-dashboard-search-options')
diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js
index 4e0fa9d265c..b789040a27c 100644
--- a/spec/frontend/releases/components/app_edit_new_spec.js
+++ b/spec/frontend/releases/components/app_edit_new_spec.js
@@ -83,11 +83,10 @@ describe('Release edit/new component', () => {
});
const findSubmitButton = () => wrapper.find('button[type=submit]');
+ const findForm = () => wrapper.find('form');
describe(`basic functionality tests: all tests unrelated to the "${BACK_URL_PARAM}" parameter`, () => {
- beforeEach(() => {
- factory();
- });
+ beforeEach(factory);
it('calls initializeRelease when the component is created', () => {
expect(actions.initializeRelease).toHaveBeenCalledTimes(1);
@@ -122,15 +121,14 @@ describe('Release edit/new component', () => {
});
it('calls saveRelease when the form is submitted', () => {
- wrapper.find('form').trigger('submit');
+ findForm().trigger('submit');
+
expect(actions.saveRelease).toHaveBeenCalledTimes(1);
});
});
describe(`when the URL does not contain a "${BACK_URL_PARAM}" parameter`, () => {
- beforeEach(() => {
- factory();
- });
+ beforeEach(factory);
it(`renders a "Cancel" button with an href pointing to "${BACK_URL_PARAM}"`, () => {
const cancelButton = wrapper.find('.js-cancel-button');
@@ -246,6 +244,12 @@ describe('Release edit/new component', () => {
it('renders the submit button as disabled', () => {
expect(findSubmitButton().attributes('disabled')).toBe('disabled');
});
+
+ it('does not allow the form to be submitted', () => {
+ findForm().trigger('submit');
+
+ expect(actions.saveRelease).not.toHaveBeenCalled();
+ });
});
});
});
diff --git a/spec/frontend/releases/components/asset_links_form_spec.js b/spec/frontend/releases/components/asset_links_form_spec.js
index e1f8592270e..727d593d851 100644
--- a/spec/frontend/releases/components/asset_links_form_spec.js
+++ b/spec/frontend/releases/components/asset_links_form_spec.js
@@ -3,6 +3,7 @@ import { mount, createLocalVue } from '@vue/test-utils';
import AssetLinksForm from '~/releases/components/asset_links_form.vue';
import { release as originalRelease } from '../mock_data';
import * as commonUtils from '~/lib/utils/common_utils';
+import { ENTER_KEY } from '~/lib/utils/keys';
import { ASSET_LINK_TYPE, DEFAULT_ASSET_LINK_TYPE } from '~/releases/constants';
const localVue = createLocalVue();
@@ -91,42 +92,128 @@ describe('Release edit component', () => {
expect(actions.removeAssetLink).toHaveBeenCalledTimes(1);
});
- it('calls the "updateAssetLinkUrl" store method when text is entered into the "URL" input field', () => {
- const linkIdToUpdate = release.assets.links[0].id;
- const newUrl = 'updated url';
+ describe('URL input field', () => {
+ let input;
+ let linkIdToUpdate;
+ let newUrl;
- expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled();
+ beforeEach(() => {
+ input = wrapper.find({ ref: 'urlInput' }).element;
+ linkIdToUpdate = release.assets.links[0].id;
+ newUrl = 'updated url';
+ });
- wrapper.find({ ref: 'urlInput' }).vm.$emit('change', newUrl);
+ const expectStoreMethodNotToBeCalled = () => {
+ expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled();
+ };
- expect(actions.updateAssetLinkUrl).toHaveBeenCalledTimes(1);
- expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith(
- expect.anything(),
- {
- linkIdToUpdate,
- newUrl,
- },
- undefined,
- );
+ const dispatchKeydowEvent = eventParams => {
+ const event = new KeyboardEvent('keydown', eventParams);
+
+ input.dispatchEvent(event);
+ };
+
+ const expectStoreMethodToBeCalled = () => {
+ expect(actions.updateAssetLinkUrl).toHaveBeenCalledTimes(1);
+ expect(actions.updateAssetLinkUrl).toHaveBeenCalledWith(
+ expect.anything(),
+ {
+ linkIdToUpdate,
+ newUrl,
+ },
+ undefined,
+ );
+ };
+
+ it('calls the "updateAssetLinkUrl" store method when text is entered into the "URL" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ wrapper.find({ ref: 'urlInput' }).vm.$emit('change', newUrl);
+
+ expectStoreMethodToBeCalled();
+ });
+
+ it('calls the "updateAssetLinkUrl" store method when Ctrl+Enter is pressed inside the "URL" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ input.value = newUrl;
+
+ dispatchKeydowEvent({ key: ENTER_KEY, ctrlKey: true });
+
+ expectStoreMethodToBeCalled();
+ });
+
+ it('calls the "updateAssetLinkUrl" store method when Cmd+Enter is pressed inside the "URL" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ input.value = newUrl;
+
+ dispatchKeydowEvent({ key: ENTER_KEY, metaKey: true });
+
+ expectStoreMethodToBeCalled();
+ });
});
- it('calls the "updateAssetLinkName" store method when text is entered into the "Link title" input field', () => {
- const linkIdToUpdate = release.assets.links[0].id;
- const newName = 'updated name';
+ describe('Link title field', () => {
+ let input;
+ let linkIdToUpdate;
+ let newName;
- expect(actions.updateAssetLinkName).not.toHaveBeenCalled();
+ beforeEach(() => {
+ input = wrapper.find({ ref: 'nameInput' }).element;
+ linkIdToUpdate = release.assets.links[0].id;
+ newName = 'updated name';
+ });
- wrapper.find({ ref: 'nameInput' }).vm.$emit('change', newName);
+ const expectStoreMethodNotToBeCalled = () => {
+ expect(actions.updateAssetLinkUrl).not.toHaveBeenCalled();
+ };
- expect(actions.updateAssetLinkName).toHaveBeenCalledTimes(1);
- expect(actions.updateAssetLinkName).toHaveBeenCalledWith(
- expect.anything(),
- {
- linkIdToUpdate,
- newName,
- },
- undefined,
- );
+ const dispatchKeydowEvent = eventParams => {
+ const event = new KeyboardEvent('keydown', eventParams);
+
+ input.dispatchEvent(event);
+ };
+
+ const expectStoreMethodToBeCalled = () => {
+ expect(actions.updateAssetLinkName).toHaveBeenCalledTimes(1);
+ expect(actions.updateAssetLinkName).toHaveBeenCalledWith(
+ expect.anything(),
+ {
+ linkIdToUpdate,
+ newName,
+ },
+ undefined,
+ );
+ };
+
+ it('calls the "updateAssetLinkName" store method when text is entered into the "Link title" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ wrapper.find({ ref: 'nameInput' }).vm.$emit('change', newName);
+
+ expectStoreMethodToBeCalled();
+ });
+
+ it('calls the "updateAssetLinkName" store method when Ctrl+Enter is pressed inside the "Link title" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ input.value = newName;
+
+ dispatchKeydowEvent({ key: ENTER_KEY, ctrlKey: true });
+
+ expectStoreMethodToBeCalled();
+ });
+
+ it('calls the "updateAssetLinkName" store method when Cmd+Enter is pressed inside the "Link title" input field', () => {
+ expectStoreMethodNotToBeCalled();
+
+ input.value = newName;
+
+ dispatchKeydowEvent({ key: ENTER_KEY, metaKey: true });
+
+ expectStoreMethodToBeCalled();
+ });
});
it('calls the "updateAssetLinkType" store method when an option is selected from the "Type" dropdown', () => {
diff --git a/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb b/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
new file mode 100644
index 00000000000..de69ad5d450
--- /dev/null
+++ b/spec/graphql/resolvers/ci_configuration/sast_resolver_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::CiConfiguration::SastResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project) }
+
+ describe '#resolve' do
+ subject(:sast_config) { resolve(described_class, ctx: { current_user: user }, obj: project) }
+
+ it 'returns global variable informations related to SAST' do
+ expect(sast_config['global'].first['field']).to eql("SECURE_ANALYZERS_PREFIX")
+ expect(sast_config['global'].first['label']).to eql("Image prefix")
+ expect(sast_config['global'].first['type']).to eql("string")
+
+ expect(sast_config['pipeline'].first['field']).to eql("stage")
+ expect(sast_config['pipeline'].first['label']).to eql("Stage")
+ expect(sast_config['pipeline'].first['type']).to eql("dropdown")
+
+ expect(sast_config['analyzers'].first['name']).to eql("brakeman")
+ expect(sast_config['analyzers'].first['label']).to eql("Brakeman")
+ expect(sast_config['analyzers'].first['enabled']).to be true
+ end
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 8a5d0cdf12d..a0b6858fc99 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -26,7 +26,7 @@ RSpec.describe GitlabSchema.types['Project'] do
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
alert_management_alerts alert_management_alert alert_management_alert_status_counts
- container_expiration_policy service_desk_enabled service_desk_address
+ container_expiration_policy sast_ci_configuration service_desk_enabled service_desk_address
issue_status_counts
]
@@ -150,5 +150,93 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::ContainerExpirationPolicyType) }
end
+ describe 'sast_ci_configuration' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:query) do
+ %(
+ query {
+ project(fullPath: "#{project.full_path}") {
+ sastCiConfiguration {
+ global {
+ nodes {
+ type
+ options {
+ nodes {
+ label
+ value
+ }
+ }
+ field
+ label
+ defaultValue
+ value
+ }
+ }
+ pipeline {
+ nodes {
+ type
+ options {
+ nodes {
+ label
+ value
+ }
+ }
+ field
+ label
+ defaultValue
+ value
+ }
+ }
+ analyzers {
+ nodes {
+ name
+ label
+ enabled
+ }
+ }
+ }
+ }
+ }
+ )
+ end
+
+ subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
+
+ before do
+ project.add_developer(user)
+ end
+
+ it "returns the project's sast configuration for global variables" do
+ query_result = subject.dig('data', 'project', 'sastCiConfiguration', 'global', 'nodes')
+ first_config = query_result.first
+ fourth_config = query_result[3]
+ expect(first_config['type']).to eq('string')
+ expect(first_config['field']).to eq('SECURE_ANALYZERS_PREFIX')
+ expect(first_config['label']).to eq('Image prefix')
+ expect(first_config['defaultValue']).to eq('registry.gitlab.com/gitlab-org/security-products/analyzers')
+ expect(first_config['value']).to eq('')
+ expect(first_config['options']).to be_nil
+ expect(fourth_config['options']['nodes']).to match([{ "value" => "true", "label" => "true (disables SAST)" },
+ { "value" => "false", "label" => "false (enables SAST)" }])
+ end
+
+ it "returns the project's sast configuration for pipeline variables" do
+ configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'pipeline', 'nodes').first
+ expect(configuration['type']).to eq('dropdown')
+ expect(configuration['field']).to eq('stage')
+ expect(configuration['label']).to eq('Stage')
+ expect(configuration['defaultValue']).to eq('test')
+ expect(configuration['value']).to eq('')
+ end
+
+ it "returns the project's sast configuration for analyzer variables" do
+ configuration = subject.dig('data', 'project', 'sastCiConfiguration', 'analyzers', 'nodes').first
+ expect(configuration['name']).to eq('brakeman')
+ expect(configuration['label']).to eq('Brakeman')
+ expect(configuration['enabled']).to eq(true)
+ end
+ end
+
it_behaves_like 'a GraphQL type with labels'
end
diff --git a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml b/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
deleted file mode 100644
index 4134660e4b9..00000000000
--- a/spec/support/gitlab_stubs/gitlab_ci_for_sast.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-include:
- - template: SAST.gitlab-ci.yml
-
-variables:
- SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers2"
- SAST_EXCLUDED_PATHS: "spec, executables"
-
-stages:
- - our_custom_security_stage
-sast:
- stage: our_custom_security_stage
- variables:
- SEARCH_MAX_DEPTH: 8
diff --git a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb b/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
deleted file mode 100644
index f8f33e2a745..00000000000
--- a/spec/support/shared_contexts/read_ci_configuration_shared_context.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'read ci configuration for sast enabled project' do
- let_it_be(:gitlab_ci_yml_content) do
- File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci_for_sast.yml'))
- end
-
- let_it_be(:project) { create(:project, :repository) }
-end