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>2022-03-11 18:07:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-03-11 18:07:48 +0300
commite46506bcc32de1af076ec8a5d51d405f827dd986 (patch)
treebb08cb3d53132eef0e8d17e1f6bab9d672454ddd
parente105f6b881d9341331558c8c42f90391bab2fd19 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/admin/applications/components/delete_application.vue84
-rw-r--r--app/assets/javascripts/admin/applications/index.js15
-rw-r--r--app/assets/javascripts/pages/admin/applications/index.js3
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js14
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/attention_requested_toggle.vue23
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue2
-rw-r--r--app/models/repository.rb4
-rw-r--r--app/models/snippet.rb2
-rw-r--r--app/views/admin/applications/_delete_form.html.haml9
-rw-r--r--app/views/admin/applications/index.html.haml2
-rw-r--r--doc/api/graphql/reference/index.md4
-rw-r--r--doc/development/database/database_reviewer_guidelines.md8
-rw-r--r--doc/development/experiment_guide/index.md12
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md8
-rw-r--r--lib/gitlab/git/repository.rb4
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb4
-rw-r--r--locale/gitlab.pot12
-rw-r--r--package.json2
-rw-r--r--spec/frontend/admin/applications/components/__snapshots__/delete_application_spec.js.snap20
-rw-r--r--spec/frontend/admin/applications/components/delete_application_spec.js69
-rw-r--r--spec/frontend/sidebar/components/attention_requested_toggle_spec.js62
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb12
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb20
-rw-r--r--spec/models/repository_spec.rb8
-rw-r--r--spec/models/snippet_spec.rb27
-rw-r--r--spec/presenters/projects/security/configuration_presenter_spec.rb2
-rw-r--r--spec/support/shared_examples/features/manage_applications_shared_examples.rb2
-rw-r--r--yarn.lock18
31 files changed, 372 insertions, 88 deletions
diff --git a/Gemfile b/Gemfile
index 64e5ea8bcce..5e7b3738185 100644
--- a/Gemfile
+++ b/Gemfile
@@ -479,7 +479,7 @@ gem 'ssh_data', '~> 1.2'
gem 'spamcheck', '~> 0.1.0'
# Gitaly GRPC protocol definitions
-gem 'gitaly', '~> 14.9.0.pre.rc2'
+gem 'gitaly', '~> 14.9.0.pre.rc3'
# KAS GRPC protocol definitions
gem 'kas-grpc', '~> 0.0.2'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6fe4cdc9726..d2e2d1e6438 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -455,7 +455,7 @@ GEM
rails (>= 3.2.0)
git (1.7.0)
rchardet (~> 1.8)
- gitaly (14.9.0.pre.rc2)
+ gitaly (14.9.0.pre.rc3)
grpc (~> 1.0)
github-markup (1.7.0)
gitlab (4.16.1)
@@ -1486,7 +1486,7 @@ DEPENDENCIES
gettext (~> 3.3)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.3)
- gitaly (~> 14.9.0.pre.rc2)
+ gitaly (~> 14.9.0.pre.rc3)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
gitlab-dangerfiles (~> 2.10.2)
diff --git a/app/assets/javascripts/admin/applications/components/delete_application.vue b/app/assets/javascripts/admin/applications/components/delete_application.vue
new file mode 100644
index 00000000000..77694296b0a
--- /dev/null
+++ b/app/assets/javascripts/admin/applications/components/delete_application.vue
@@ -0,0 +1,84 @@
+<script>
+import { GlModal, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import csrf from '~/lib/utils/csrf';
+
+export default {
+ components: {
+ GlModal,
+ GlSprintf,
+ },
+ data() {
+ return {
+ name: '',
+ path: '',
+ buttons: [],
+ };
+ },
+ mounted() {
+ this.buttons = document.querySelectorAll('.js-application-delete-button');
+
+ this.buttons.forEach((button) => button.addEventListener('click', this.buttonEvent));
+ },
+ destroy() {
+ this.buttons.forEach((button) => button.removeEventListener('click', this.buttonEvent));
+ },
+ methods: {
+ buttonEvent(e) {
+ e.preventDefault();
+ this.show(e.target.dataset);
+ },
+ show(dataset) {
+ const { name, path } = dataset;
+
+ this.name = name;
+ this.path = path;
+
+ this.$refs.deleteModal.show();
+ },
+ deleteApplication() {
+ this.$refs.deleteForm.submit();
+ },
+ },
+ i18n: {
+ destroy: __('Destroy'),
+ title: __('Confirm destroy application'),
+ body: __('Are you sure that you want to destroy %{application}'),
+ },
+ modal: {
+ actionPrimary: {
+ text: __('Destroy'),
+ attributes: {
+ variant: 'danger',
+ },
+ },
+ actionSecondary: {
+ text: __('Cancel'),
+ attributes: {
+ variant: 'default',
+ },
+ },
+ },
+ csrf,
+};
+</script>
+<template>
+ <gl-modal
+ ref="deleteModal"
+ :title="$options.i18n.title"
+ :action-primary="$options.modal.actionPrimary"
+ :action-secondary="$options.modal.actionSecondary"
+ modal-id="delete-application-modal"
+ size="sm"
+ @primary="deleteApplication"
+ ><gl-sprintf :message="$options.i18n.body">
+ <template #application>
+ <strong>{{ name }}</strong>
+ </template></gl-sprintf
+ >
+ <form ref="deleteForm" method="post" :action="path">
+ <input type="hidden" name="_method" value="delete" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ </form>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/admin/applications/index.js b/app/assets/javascripts/admin/applications/index.js
new file mode 100644
index 00000000000..5875fd18729
--- /dev/null
+++ b/app/assets/javascripts/admin/applications/index.js
@@ -0,0 +1,15 @@
+import Vue from 'vue';
+import DeleteApplication from './components/delete_application.vue';
+
+export default () => {
+ const el = document.querySelector('.js-application-delete-modal');
+
+ if (!el) return false;
+
+ return new Vue({
+ el,
+ render(h) {
+ return h(DeleteApplication);
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/admin/applications/index.js b/app/assets/javascripts/pages/admin/applications/index.js
new file mode 100644
index 00000000000..3397b02aeba
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/applications/index.js
@@ -0,0 +1,3 @@
+import initApplicationDeleteButtons from '~/admin/applications';
+
+initApplicationDeleteButtons();
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 11e092d8eb4..3def5e9d6b7 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -222,14 +222,12 @@ export const securityFeatures = [
helpPath: COVERAGE_FUZZING_HELP_PATH,
configurationHelpPath: COVERAGE_FUZZING_CONFIG_HELP_PATH,
type: REPORT_TYPE_COVERAGE_FUZZING,
- secondary: gon?.features?.corpusManagementUi
- ? {
- type: REPORT_TYPE_CORPUS_MANAGEMENT,
- name: CORPUS_MANAGEMENT_NAME,
- description: CORPUS_MANAGEMENT_DESCRIPTION,
- configurationText: CORPUS_MANAGEMENT_CONFIG_TEXT,
- }
- : {},
+ secondary: {
+ type: REPORT_TYPE_CORPUS_MANAGEMENT,
+ name: CORPUS_MANAGEMENT_NAME,
+ description: CORPUS_MANAGEMENT_DESCRIPTION,
+ configurationText: CORPUS_MANAGEMENT_CONFIG_TEXT,
+ },
},
];
diff --git a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
index a27dbee31ec..558fe8ca2aa 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -114,7 +114,7 @@ export default {
class="gl-display-inline-block"
>
<attention-requested-toggle
- v-if="showVerticalList && user.can_update_merge_request"
+ v-if="showVerticalList"
:user="user"
type="assignee"
@toggle-attention-requested="toggleAttentionRequested"
diff --git a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
index 42e56906e2c..d11bed4f058 100644
--- a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
+++ b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
@@ -8,6 +8,8 @@ export default {
attentionRequestedReviewer: __('Request attention to review'),
attentionRequestedAssignee: __('Request attention'),
removeAttentionRequested: __('Remove attention request'),
+ attentionRequestedNoPermission: __('Attention requested'),
+ noAttentionRequestedNoPermission: __('No attention request'),
},
components: {
GlButton,
@@ -33,17 +35,25 @@ export default {
computed: {
tooltipTitle() {
if (this.user.attention_requested) {
- return this.$options.i18n.removeAttentionRequested;
+ if (this.user.can_update_merge_request) {
+ return this.$options.i18n.removeAttentionRequested;
+ }
+
+ return this.$options.i18n.attentionRequestedNoPermission;
+ }
+
+ if (this.user.can_update_merge_request) {
+ return this.type === 'reviewer'
+ ? this.$options.i18n.attentionRequestedReviewer
+ : this.$options.i18n.attentionRequestedAssignee;
}
- return this.type === 'reviewer'
- ? this.$options.i18n.attentionRequestedReviewer
- : this.$options.i18n.attentionRequestedAssignee;
+ return this.$options.i18n.noAttentionRequestedNoPermission;
},
},
methods: {
toggleAttentionRequired() {
- if (this.loading) return;
+ if (this.loading || !this.user.can_update_merge_request) return;
this.$root.$emit(BV_HIDE_TOOLTIP);
this.loading = true;
@@ -60,12 +70,13 @@ export default {
</script>
<template>
- <span v-gl-tooltip.left.viewport="tooltipTitle">
+ <span v-gl-tooltip.left.viewport="tooltipTitle" class="gl-display-inline-block">
<gl-button
:loading="loading"
:variant="user.attention_requested ? 'warning' : 'default'"
:icon="user.attention_requested ? 'attention-solid' : 'attention'"
:aria-label="tooltipTitle"
+ :class="{ 'gl-pointer-events-none': !user.can_update_merge_request }"
size="small"
category="tertiary"
@click="toggleAttentionRequired"
diff --git a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
index adaf1b65f3f..9485802d3da 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/uncollapsed_reviewer_list.vue
@@ -98,7 +98,7 @@ export default {
data-testid="reviewer"
>
<attention-requested-toggle
- v-if="glFeatures.mrAttentionRequests && user.can_update_merge_request"
+ v-if="glFeatures.mrAttentionRequests"
:user="user"
type="reviewer"
@toggle-attention-requested="toggleAttentionRequested"
diff --git a/app/models/repository.rb b/app/models/repository.rb
index e0b1901d188..346478b6689 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1085,10 +1085,10 @@ class Repository
blob.data
end
- def create_if_not_exists
+ def create_if_not_exists(default_branch = nil)
return if exists?
- raw.create_repository
+ raw.create_repository(default_branch)
after_create
true
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index b04fca64c87..ac87da4f3c8 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -367,7 +367,7 @@ class Snippet < ApplicationRecord
def create_repository
return if repository_exists? && snippet_repository
- repository.create_if_not_exists
+ repository.create_if_not_exists(default_branch)
track_snippet_repository(repository.storage)
end
diff --git a/app/views/admin/applications/_delete_form.html.haml b/app/views/admin/applications/_delete_form.html.haml
index d348ad507c2..16ec8014c5e 100644
--- a/app/views/admin/applications/_delete_form.html.haml
+++ b/app/views/admin/applications/_delete_form.html.haml
@@ -1,4 +1,5 @@
-- submit_btn_css ||= 'gl-button btn btn-danger btn-sm'
-= form_tag admin_application_path(application) do
- %input{ :name => "_method", :type => "hidden", :value => "delete" }/
- = submit_tag 'Destroy', class: submit_btn_css, data: { confirm: _('Are you sure?') }
+
+- submit_btn_css ||= 'gl-button btn btn-danger btn-sm js-application-delete-button'
+%button{ class: submit_btn_css, data: { path: admin_application_path(application), name: application.name } }
+ = _('Destroy')
+
diff --git a/app/views/admin/applications/index.html.haml b/app/views/admin/applications/index.html.haml
index 28a7bd1820a..86a4ab00ba3 100644
--- a/app/views/admin/applications/index.html.haml
+++ b/app/views/admin/applications/index.html.haml
@@ -33,3 +33,5 @@
%td= render 'delete_form', application: application
= paginate @applications, theme: 'gitlab'
+
+.js-application-delete-modal
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 169d5dee615..16d4a8a85be 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -1161,8 +1161,6 @@ Input type: `ConfigureSecretDetectionInput`
### `Mutation.corpusCreate`
-Available only when feature flag `corpus_management` is enabled. This flag is enabled by default.
-
Input type: `CorpusCreateInput`
#### Arguments
@@ -13789,7 +13787,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectcontainerexpirationpolicy"></a>`containerExpirationPolicy` | [`ContainerExpirationPolicy`](#containerexpirationpolicy) | Container expiration policy of the project. |
| <a id="projectcontainerregistryenabled"></a>`containerRegistryEnabled` | [`Boolean`](#boolean) | Indicates if Container Registry is enabled for the current user. |
| <a id="projectcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the project. |
-| <a id="projectcorpuses"></a>`corpuses` | [`CoverageFuzzingCorpusConnection`](#coveragefuzzingcorpusconnection) | Find corpuses of the project. Available only when feature flag `corpus_management` is enabled. This flag is enabled by default. (see [Connections](#connections)) |
+| <a id="projectcorpuses"></a>`corpuses` | [`CoverageFuzzingCorpusConnection`](#coveragefuzzingcorpusconnection) | Find corpuses of the project. (see [Connections](#connections)) |
| <a id="projectcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of the project creation. |
| <a id="projectdastscannerprofiles"></a>`dastScannerProfiles` | [`DastScannerProfileConnection`](#dastscannerprofileconnection) | DAST scanner profiles associated with the project. (see [Connections](#connections)) |
| <a id="projectdastsiteprofiles"></a>`dastSiteProfiles` | [`DastSiteProfileConnection`](#dastsiteprofileconnection) | DAST Site Profiles associated with the project. (see [Connections](#connections)) |
diff --git a/doc/development/database/database_reviewer_guidelines.md b/doc/development/database/database_reviewer_guidelines.md
index bc18e606f21..8c216d8247f 100644
--- a/doc/development/database/database_reviewer_guidelines.md
+++ b/doc/development/database/database_reviewer_guidelines.md
@@ -26,18 +26,12 @@ For more information on the database review process, check the [database review
## How to apply for becoming a database reviewer
-Team members are encouraged to self-identify as database domain experts and add it to their [team profile](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/team.yml)
+Team members are encouraged to self-identify as database domain experts, and add it to their profile YAML file:
```yaml
projects:
gitlab:
- reviewer database
-```
-
-Assign the MR which adds your expertise to the `team.yml` file to a database maintainer
-or the [Database Team's Engineering Manager](https://about.gitlab.com/handbook/engineering/development/enablement/database/).
-
-Once the `team.yml` update is merged, the [Reviewer roulette](../code_review.md#reviewer-roulette)
may recommend you as a database reviewer.
## Resources for database reviewers
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 254c136ef79..c34e5eb36dc 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -64,3 +64,15 @@ We recommend the following workflow:
1. **If the experiment is a success**, designers add the new icon or illustration to the Pajamas UI kit as part of the cleanup process.
Engineers can then add it to the [SVG library](https://gitlab-org.gitlab.io/gitlab-svgs/) and modify the implementation based on the
[Frontend Development Guidelines](../fe_guide/icons.md#usage-in-hamlrails-2).
+
+## Turn off all experiments
+
+When there is a case on GitLab.com (SaaS) that necessitates turning off all experiments, we have this control.
+
+You can toggle experiments on SaaS on and off using the `gitlab_experiment` [feature flag](../feature_flags).
+
+This can be done via chatops:
+
+- [disable](../feature_flags/controls.md#disabling-feature-flags): `/chatops run feature set gitlab_experiment false`
+- [enable](../feature_flags/controls.md#process): `/chatops run feature delete gitlab_experiment`
+ - This allows the `default_enabled` [value of true in the yml](https://gitlab.com/gitlab-org/gitlab/-/blob/016430f6751b0c34abb24f74608c80a1a8268f20/config/feature_flags/ops/gitlab_experiment.yml#L8) to be honored.
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 290d4a06dcc..a893106f52a 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -144,12 +144,8 @@ You can download the JSON report file from the CI/CD pipelines page. For more in
## Corpus registry
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an
-administrator to [disable the feature flags](../../../administration/feature_flags.md) named
-`corpus_management` and `corpus_management_ui`. On GitLab.com, this feature is available.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/347187) in GitLab 14.9. [Feature flags `corpus_management` and `corpus_management_ui`](https://gitlab.com/gitlab-org/gitlab/-/issues/328418) removed.
The corpus registry is a library of corpuses. Corpuses in a project's registry are available to
all jobs in that project. A project-wide registry is a more efficient way to manage corpuses than
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index c3ee5b97379..1492ea1ce76 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -99,9 +99,9 @@ module Gitlab
gitaly_repository_client.exists?
end
- def create_repository
+ def create_repository(default_branch = nil)
wrapped_gitaly_errors do
- gitaly_repository_client.create_repository
+ gitaly_repository_client.create_repository(default_branch)
rescue GRPC::AlreadyExists => e
raise RepositoryExists, e.message
end
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 51d0730bb1d..5c447dfd417 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -107,8 +107,8 @@ module Gitlab
end
# rubocop: enable Metrics/ParameterLists
- def create_repository
- request = Gitaly::CreateRepositoryRequest.new(repository: @gitaly_repo)
+ def create_repository(default_branch = nil)
+ request = Gitaly::CreateRepositoryRequest.new(repository: @gitaly_repo, default_branch: default_branch)
GitalyClient.call(@storage, :repository_service, :create_repository, request, timeout: GitalyClient.fast_timeout)
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 9697ca955db..c78a131974b 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4696,6 +4696,9 @@ msgstr ""
msgid "Are you sure that you want to archive this project?"
msgstr ""
+msgid "Are you sure that you want to destroy %{application}"
+msgstr ""
+
msgid "Are you sure that you want to unarchive this project?"
msgstr ""
@@ -5032,6 +5035,9 @@ msgstr ""
msgid "Attention"
msgstr ""
+msgid "Attention requested"
+msgstr ""
+
msgid "Audit Events"
msgstr ""
@@ -9281,6 +9287,9 @@ msgstr ""
msgid "Confirm approval"
msgstr ""
+msgid "Confirm destroy application"
+msgstr ""
+
msgid "Confirm new password"
msgstr ""
@@ -24672,6 +24681,9 @@ msgstr ""
msgid "No assignee"
msgstr ""
+msgid "No attention request"
+msgstr ""
+
msgid "No authentication methods configured."
msgstr ""
diff --git a/package.json b/package.json
index 4a5dfced431..8fbf2cf3d8d 100644
--- a/package.json
+++ b/package.json
@@ -155,6 +155,7 @@
"pikaday": "^1.8.0",
"popper.js": "^1.16.1",
"portal-vue": "^2.1.7",
+ "postcss": "8.4.5",
"prismjs": "^1.21.0",
"prosemirror-markdown": "1.7.1",
"prosemirror-model": "^1.16.1",
@@ -239,7 +240,6 @@
"miragejs": "^0.1.40",
"mock-apollo-client": "1.2.0",
"nodemon": "^2.0.4",
- "postcss": "^8.4.5",
"prettier": "2.2.1",
"prosemirror-schema-basic": "^1.1.2",
"prosemirror-schema-list": "^1.1.6",
diff --git a/spec/frontend/admin/applications/components/__snapshots__/delete_application_spec.js.snap b/spec/frontend/admin/applications/components/__snapshots__/delete_application_spec.js.snap
new file mode 100644
index 00000000000..459a113b6d1
--- /dev/null
+++ b/spec/frontend/admin/applications/components/__snapshots__/delete_application_spec.js.snap
@@ -0,0 +1,20 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`DeleteApplication the modal component form matches the snapshot 1`] = `
+<form
+ action="application/path/1"
+ method="post"
+>
+ <input
+ name="_method"
+ type="hidden"
+ value="delete"
+ />
+
+ <input
+ name="authenticity_token"
+ type="hidden"
+ value="mock-csrf-token"
+ />
+</form>
+`;
diff --git a/spec/frontend/admin/applications/components/delete_application_spec.js b/spec/frontend/admin/applications/components/delete_application_spec.js
new file mode 100644
index 00000000000..20119b64952
--- /dev/null
+++ b/spec/frontend/admin/applications/components/delete_application_spec.js
@@ -0,0 +1,69 @@
+import { GlModal, GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import DeleteApplication from '~/admin/applications/components/delete_application.vue';
+
+const path = 'application/path/1';
+const name = 'Application name';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+describe('DeleteApplication', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(DeleteApplication, {
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findForm = () => wrapper.find('form');
+
+ beforeEach(() => {
+ setFixtures(`
+ <button class="js-application-delete-button" data-path="${path}" data-name="${name}">Destroy</button>
+ `);
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('the modal component', () => {
+ beforeEach(() => {
+ wrapper.vm.$refs.deleteModal.show = jest.fn();
+ document.querySelector('.js-application-delete-button').click();
+ });
+
+ it('displays the modal component', () => {
+ const modal = findModal();
+
+ expect(modal.exists()).toBe(true);
+ expect(modal.props('title')).toBe('Confirm destroy application');
+ expect(modal.text()).toBe(`Are you sure that you want to destroy ${name}`);
+ });
+
+ describe('form', () => {
+ it('matches the snapshot', () => {
+ expect(findForm().element).toMatchSnapshot();
+ });
+
+ describe('form submission', () => {
+ let formSubmitSpy;
+
+ beforeEach(() => {
+ formSubmitSpy = jest.spyOn(wrapper.vm.$refs.deleteForm, 'submit');
+ findModal().vm.$emit('primary');
+ });
+
+ it('submits the form on the modal primary action', () => {
+ expect(formSubmitSpy).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/attention_requested_toggle_spec.js b/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
index 0939297a754..a9ae23c1624 100644
--- a/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
+++ b/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
@@ -16,7 +16,10 @@ describe('Attention require toggle', () => {
});
it('renders button', () => {
- factory({ type: 'reviewer', user: { attention_requested: false } });
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: false, can_update_merge_request: true },
+ });
expect(findToggle().exists()).toBe(true);
});
@@ -28,7 +31,10 @@ describe('Attention require toggle', () => {
`(
'renders $icon icon when attention_requested is $attentionRequested',
({ attentionRequested, icon }) => {
- factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: attentionRequested, can_update_merge_request: true },
+ });
expect(findToggle().props('icon')).toBe(icon);
},
@@ -41,27 +47,47 @@ describe('Attention require toggle', () => {
`(
'renders button with variant $variant when attention_requested is $attentionRequested',
({ attentionRequested, variant }) => {
- factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: attentionRequested, can_update_merge_request: true },
+ });
expect(findToggle().props('variant')).toBe(variant);
},
);
it('emits toggle-attention-requested on click', async () => {
- factory({ type: 'reviewer', user: { attention_requested: true } });
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: true, can_update_merge_request: true },
+ });
await findToggle().trigger('click');
expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual([
{
- user: { attention_requested: true },
+ user: { attention_requested: true, can_update_merge_request: true },
callback: expect.anything(),
},
]);
});
+ it('does not emit toggle-attention-requested on click if can_update_merge_request is false', async () => {
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: true, can_update_merge_request: false },
+ });
+
+ await findToggle().trigger('click');
+
+ expect(wrapper.emitted('toggle-attention-requested')).toBe(undefined);
+ });
+
it('sets loading on click', async () => {
- factory({ type: 'reviewer', user: { attention_requested: true } });
+ factory({
+ type: 'reviewer',
+ user: { attention_requested: true, can_update_merge_request: true },
+ });
await findToggle().trigger('click');
@@ -69,14 +95,24 @@ describe('Attention require toggle', () => {
});
it.each`
- type | attentionRequested | tooltip
- ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequested}
- ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedReviewer}
- ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedAssignee}
+ type | attentionRequested | tooltip | canUpdateMergeRequest
+ ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequested} | ${true}
+ ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedReviewer} | ${true}
+ ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedAssignee} | ${true}
+ ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.attentionRequestedNoPermission} | ${false}
+ ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.noAttentionRequestedNoPermission} | ${false}
+ ${'assignee'} | ${true} | ${AttentionRequestedToggle.i18n.attentionRequestedNoPermission} | ${false}
+ ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.noAttentionRequestedNoPermission} | ${false}
`(
- 'sets tooltip as $tooltip when attention_requested is $attentionRequested and type is $type',
- ({ type, attentionRequested, tooltip }) => {
- factory({ type, user: { attention_requested: attentionRequested } });
+ 'sets tooltip as $tooltip when attention_requested is $attentionRequested, type is $type and, can_update_merge_request is $canUpdateMergeRequest',
+ ({ type, attentionRequested, tooltip, canUpdateMergeRequest }) => {
+ factory({
+ type,
+ user: {
+ attention_requested: attentionRequested,
+ can_update_merge_request: canUpdateMergeRequest,
+ },
+ });
expect(findToggle().attributes('aria-label')).toBe(tooltip);
},
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index d22aa86dbe0..cfa03db52fe 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -78,6 +78,10 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat
end
shared_examples 'migration_bot user commits files' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('main')
+ end
+
it do
subject
@@ -89,6 +93,10 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat
end
shared_examples 'commits the file to the repository' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('main')
+ end
+
context 'when author can update snippet and use git' do
it 'creates the repository and commit the file' do
subject
@@ -269,6 +277,10 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migrat
let!(:snippet) { snippets.create!(id: 5, type: 'PersonalSnippet', author_id: other_user.id, file_name: file_name, content: content) }
let(:ids) { [4, 5] }
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('main')
+ end
+
after do
raw_repository(snippet).remove
raw_repository(invalid_snippet).remove
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 229ab70a65d..39de9a65390 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -218,6 +218,26 @@ RSpec.describe Gitlab::GitalyClient::RepositoryService do
end
end
+ describe '#create_repository' do
+ it 'sends a create_repository message without arguments' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:create_repository)
+ .with(gitaly_request_with_path(storage_name, relative_path).and(gitaly_request_with_params(default_branch: '')), kind_of(Hash))
+ .and_return(double)
+
+ client.create_repository
+ end
+
+ it 'sends a create_repository message with default branch' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:create_repository)
+ .with(gitaly_request_with_path(storage_name, relative_path).and(gitaly_request_with_params(default_branch: 'default-branch-name')), kind_of(Hash))
+ .and_return(double)
+
+ client.create_repository('default-branch-name')
+ end
+ end
+
describe '#create_from_snapshot' do
it 'sends a create_repository_from_snapshot message' do
expect_any_instance_of(Gitaly::RepositoryService::Stub)
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index e592a4964f5..215f83adf5d 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -3062,6 +3062,14 @@ RSpec.describe Repository do
repository.create_if_not_exists
end
+ it 'creates a repository with a default branch name' do
+ default_branch_name = 'branch-a'
+ repository.create_if_not_exists(default_branch_name)
+ repository.create_file(user, 'file', 'content', message: 'initial commit', branch_name: default_branch_name)
+
+ expect(repository.root_ref).to eq(default_branch_name)
+ end
+
context 'it does nothing if the repository already existed' do
let(:project) { create(:project, :repository) }
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 92e4bc7d1a9..e80814cef5c 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -667,6 +667,16 @@ RSpec.describe Snippet do
expect(snippet.repository.exists?).to be_truthy
end
+ it 'sets the default branch' do
+ expect(snippet).to receive(:default_branch).and_return('default-branch-1')
+ expect(subject).to be_truthy
+
+ snippet.repository.create_file(snippet.author, 'file', 'content', message: 'initial commit', branch_name: 'default-branch-1')
+
+ expect(snippet.repository.exists?).to be_truthy
+ expect(snippet.repository.root_ref).to eq('default-branch-1')
+ end
+
it 'tracks snippet repository' do
expect do
subject
@@ -677,6 +687,7 @@ RSpec.describe Snippet do
expect(snippet).to receive(:repository_storage).and_return('picked')
expect(snippet).to receive(:repository_exists?).and_return(false)
expect(snippet.repository).to receive(:create_if_not_exists)
+ allow(snippet).to receive(:default_branch).and_return('picked')
subject
@@ -899,22 +910,6 @@ RSpec.describe Snippet do
end
end
- context 'when repository is empty' do
- let(:snippet) { create(:snippet, :empty_repo) }
-
- before do
- allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return(default_branch)
- end
-
- context 'when default branch in settings is different from "master"' do
- let(:default_branch) { 'custom-branch' }
-
- it 'changes the HEAD reference to the default branch' do
- expect { subject }.to change { File.read(head_path).squish }.to("ref: refs/heads/#{default_branch}")
- end
- end
- end
-
context 'when repository is not empty' do
let(:snippet) { create(:snippet, :empty_repo) }
diff --git a/spec/presenters/projects/security/configuration_presenter_spec.rb b/spec/presenters/projects/security/configuration_presenter_spec.rb
index 5f874ab5a3f..47ef0cf1192 100644
--- a/spec/presenters/projects/security/configuration_presenter_spec.rb
+++ b/spec/presenters/projects/security/configuration_presenter_spec.rb
@@ -13,8 +13,6 @@ RSpec.describe Projects::Security::ConfigurationPresenter do
before do
stub_licensed_features(licensed_scan_types.to_h { |type| [type, true] })
-
- stub_feature_flags(corpus_management_ui: false)
end
describe '#to_html_data_attribute' do
diff --git a/spec/support/shared_examples/features/manage_applications_shared_examples.rb b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
index 27d50c67f24..3a8267b21da 100644
--- a/spec/support/shared_examples/features/manage_applications_shared_examples.rb
+++ b/spec/support/shared_examples/features/manage_applications_shared_examples.rb
@@ -5,7 +5,7 @@ RSpec.shared_examples 'manage applications' do
let_it_be(:application_name_changed) { "#{application_name} changed" }
let_it_be(:application_redirect_uri) { 'https://foo.bar' }
- it 'allows user to manage applications' do
+ it 'allows user to manage applications', :js do
visit new_application_path
expect(page).to have_content 'Add new application'
diff --git a/yarn.lock b/yarn.lock
index bf202d8a113..a03a9ea80d8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -9447,15 +9447,7 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
-postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6:
- version "7.0.39"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
- integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
- dependencies:
- picocolors "^0.2.1"
- source-map "^0.6.1"
-
-postcss@^8.2.1, postcss@^8.4.5:
+postcss@8.4.5, postcss@^8.2.1, postcss@^8.4.5:
version "8.4.5"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
@@ -9464,6 +9456,14 @@ postcss@^8.2.1, postcss@^8.4.5:
picocolors "^1.0.0"
source-map-js "^1.0.1"
+postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6:
+ version "7.0.39"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+ integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+ dependencies:
+ picocolors "^0.2.1"
+ source-map "^0.6.1"
+
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"