Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-05-26 12:08:30 +00:00
parent 628f2eef70
commit d94409aaaf
43 changed files with 355 additions and 249 deletions

View File

@ -24,6 +24,7 @@ const PERSISTENT_USER_CALLOUTS = [
'.js-geo-migrate-hashed-storage-callout',
'.js-unlimited-members-during-trial-alert',
'.js-branch-rules-info-callout',
'.js-new-navigation-callout',
];
const initCallouts = () => {

View File

@ -180,7 +180,7 @@ export default {
this.isEditing = true;
updateDraft(this.autosaveKey, this.note.body);
},
async updateNote(newText) {
async updateNote({ commentText }) {
try {
this.isEditing = false;
await this.$apollo.mutate({
@ -188,7 +188,7 @@ export default {
variables: {
input: {
id: this.note.id,
body: newText,
body: commentText,
},
},
optimisticResponse: {
@ -196,14 +196,14 @@ export default {
errors: [],
note: {
...this.note,
bodyHtml: renderMarkdown(newText),
bodyHtml: renderMarkdown(commentText),
},
},
},
});
clearDraft(this.autosaveKey);
} catch (error) {
updateDraft(this.autosaveKey, newText);
updateDraft(this.autosaveKey, commentText);
this.isEditing = true;
this.$emit('error', __('Something went wrong when updating a comment. Please try again'));
Sentry.captureException(error);

View File

@ -16,6 +16,7 @@ module Users
WEB_HOOK_DISABLED = 'web_hook_disabled'
ULTIMATE_FEATURE_REMOVAL_BANNER = 'ultimate_feature_removal_banner'
BRANCH_RULES_INFO_CALLOUT = 'branch_rules_info_callout'
NEW_NAVIGATION_CALLOUT = 'new_navigation_callout'
def show_gke_cluster_integration_callout?(project)
active_nav_link?(controller: sidebar_operations_paths) &&
@ -79,6 +80,10 @@ module Users
!user_dismissed?(BRANCH_RULES_INFO_CALLOUT)
end
def show_new_navigation_callout?
show_super_sidebar? && !user_dismissed?(NEW_NAVIGATION_CALLOUT)
end
def ultimate_feature_removal_banner_dismissed?(project)
return false unless project

View File

@ -11,7 +11,8 @@ module Namespaces
alias_attribute :namespace_id, :parent_id
has_one :project, foreign_key: :project_namespace_id, inverse_of: :project_namespace
delegate :execute_hooks, :execute_integrations, to: :project, allow_nil: true
delegate :execute_hooks, :execute_integrations, :group, to: :project, allow_nil: true
delegate :external_references_supported?, :default_issues_tracker?, to: :project
def self.sti_name
'Project'

View File

@ -13,8 +13,7 @@ module Organizations
validates :name,
presence: true,
length: { maximum: 255 },
uniqueness: { case_sensitive: false }
length: { maximum: 255 }
def default?
id == DEFAULT_ORGANIZATION_ID

View File

@ -2908,7 +2908,13 @@ class Project < ApplicationRecord
def default_branch_protected?
branch_protection = Gitlab::Access::BranchProtection.new(self.namespace.default_branch_protection)
branch_protection.fully_protected? || branch_protection.developer_can_merge?
branch_protection.fully_protected? || branch_protection.developer_can_merge? || branch_protection.developer_can_initial_push?
end
def initial_push_to_default_branch_allowed_for_developer?
branch_protection = Gitlab::Access::BranchProtection.new(self.namespace.default_branch_protection)
!branch_protection.any? || branch_protection.developer_can_push? || branch_protection.developer_can_initial_push?
end
def environments_for_scope(scope)

View File

@ -26,10 +26,16 @@ class ProtectedBranch < ApplicationRecord
end
def self.protected_ref_accessible_to?(ref, user, project:, action:, protected_refs: nil)
# Maintainers, owners and admins are allowed to create the default branch
if project.empty_repo?
member_access = project.team.max_member_access(user.id)
if project.empty_repo? && project.default_branch_protected?
# Admins are always allowed to create the default branch
return true if user.admin? || user.can?(:admin_project, project)
# Developers can push if it is allowed by default branch protection settings
if member_access == Gitlab::Access::DEVELOPER && project.initial_push_to_default_branch_allowed_for_developer?
return true
end
end
super

View File

@ -69,7 +69,8 @@ module Users
repository_storage_limit_banner_info_threshold: 67, # EE-only
repository_storage_limit_banner_warning_threshold: 68, # EE-only
repository_storage_limit_banner_alert_threshold: 69, # EE-only
repository_storage_limit_banner_error_threshold: 70 # EE-only
repository_storage_limit_banner_error_threshold: 70, # EE-only
new_navigation_callout: 71
}
validates :feature_name,

View File

@ -20,6 +20,7 @@
.mobile-overlay
= dispensable_render_if_exists 'layouts/header/verification_reminder'
.alert-wrapper.gl-force-block-formatting-context
= dispensable_render 'shared/new_nav_announcement'
= dispensable_render 'shared/outdated_browser'
= dispensable_render_if_exists "layouts/header/licensed_user_count_threshold"
= dispensable_render_if_exists "layouts/header/token_expiry_notification"

View File

@ -0,0 +1,33 @@
- return unless show_new_navigation_callout?
- changes_url = 'https://gitlab.com/groups/gitlab-org/-/epics/9044#whats-different'
- vision_url = 'https://about.gitlab.com/blog/2023/05/01/gitlab-product-navigation/'
- design_url = 'https://about.gitlab.com/blog/2023/05/15/overhauling-the-navigation-is-like-building-a-dream-home/'
- feedback_url = 'https://gitlab.com/gitlab-org/gitlab/-/issues/409005'
- docs_url = help_page_path('tutorials/left_sidebar/index')
- changes_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: changes_url }
- vision_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: vision_url }
- design_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: design_url }
- link_end = '</a>'.html_safe
- welcome_text = _('For the next few releases, you can go to your avatar at any time to turn the new navigation on and off.')
- cta_text = _('Read more about the %{changes_link_start}changes%{link_end}, the %{vision_link_start}vision%{link_end}, and the %{design_link_start}design%{link_end}.' % { changes_link_start: changes_link_start,
vision_link_start: vision_link_start,
design_link_start: design_link_start,
link_end: link_end}).html_safe # rubocop:disable Gettext/StaticIdentifier
= render Pajamas::AlertComponent.new(dismissible: true, title: _('Welcome to a new navigation experience'),
alert_options: { class: 'js-new-navigation-callout', data: { feature_id: "new_navigation_callout", dismiss_endpoint: callouts_path }}) do |c|
- c.with_body do
%p
= welcome_text
= cta_text
- c.with_actions do
= render Pajamas::ButtonComponent.new(variant: :confirm,
href: docs_url,
button_options: { class: 'gl-alert-action', data: { track_action: 'click_button', track_label: 'banner_nav_learn_more' } }) do |c|
= _('Learn more')
= render Pajamas::ButtonComponent.new(href: feedback_url,
button_options: { data: { track_action: 'click_button', track_label: 'banner_nav_provide_feedback' } }) do |c|
= _('Provide feedback')

View File

@ -1263,33 +1263,6 @@
:weight: 1
:idempotent: false
:tags: []
- :name: github_importer:github_import_import_pull_request_merged_by
:worker_name: Gitlab::GithubImport::ImportPullRequestMergedByWorker
:feature_category: :importers
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :cpu
:weight: 1
:idempotent: false
:tags: []
- :name: github_importer:github_import_import_pull_request_review
:worker_name: Gitlab::GithubImport::ImportPullRequestReviewWorker
:feature_category: :importers
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :cpu
:weight: 1
:idempotent: false
:tags: []
- :name: github_importer:github_import_import_release_attachments
:worker_name: Gitlab::GithubImport::ImportReleaseAttachmentsWorker
:feature_category: :importers
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: false
:tags: []
- :name: github_importer:github_import_pull_requests_import_merged_by
:worker_name: Gitlab::GithubImport::PullRequests::ImportMergedByWorker
:feature_category: :importers

View File

@ -1,25 +0,0 @@
# frozen_string_literal: true
# TODO: remove in 16.1 milestone
# https://gitlab.com/gitlab-org/gitlab/-/issues/409706
module Gitlab
module GithubImport
class ImportPullRequestMergedByWorker # rubocop:disable Scalability/IdempotentWorker
include ObjectImporter
worker_resource_boundary :cpu
def representation_class
Gitlab::GithubImport::Representation::PullRequest
end
def importer_class
Importer::PullRequests::MergedByImporter
end
def object_type
:pull_request_merged_by
end
end
end
end

View File

@ -1,25 +0,0 @@
# frozen_string_literal: true
# TODO: remove in 16.1 milestone
# https://gitlab.com/gitlab-org/gitlab/-/issues/409706
module Gitlab
module GithubImport
class ImportPullRequestReviewWorker # rubocop:disable Scalability/IdempotentWorker
include ObjectImporter
worker_resource_boundary :cpu
def representation_class
Gitlab::GithubImport::Representation::PullRequestReview
end
def importer_class
Importer::PullRequests::ReviewImporter
end
def object_type
:pull_request_review
end
end
end
end

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
# TODO: remove in 16.1 milestone
# https://gitlab.com/gitlab-org/gitlab/-/issues/409706
module Gitlab
module GithubImport
class ImportReleaseAttachmentsWorker # rubocop:disable Scalability/IdempotentWorker
include ObjectImporter
def representation_class
Representation::NoteText
end
def importer_class
Importer::NoteAttachmentsImporter
end
def object_type
:release_attachment
end
end
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class RemoveGitHubImportDeprecatedWorkers < Gitlab::Database::Migration[2.1]
DEPRECATED_JOB_CLASSES = %w[
Gitlab::GithubImport::ImportPullRequestMergedByWorker
Gitlab::GithubImport::ImportPullRequestReviewWorker
Gitlab::GithubImport::ImportReleaseAttachmentsWorker
]
disable_ddl_transaction!
def up
sidekiq_remove_jobs(job_klasses: DEPRECATED_JOB_CLASSES)
end
def down
# This migration removes any instances of deprecated workers and cannot be undone.
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class RemoveIndexOnNameOnOrganization < Gitlab::Database::Migration[2.1]
disable_ddl_transaction!
INDEX_NAME = 'unique_organizations_on_name_lower'
def up
remove_concurrent_index_by_name :organizations, INDEX_NAME
end
def down
add_concurrent_index :organizations, 'lower(name)', name: INDEX_NAME
end
end

View File

@ -0,0 +1 @@
b5c1ad2fe2f4d38b39ac9c621b36f62c0a06b74846f5afdad4d88804bb1d7acf

View File

@ -0,0 +1 @@
1cafb842d106d59f63dc12d4cdb215af023f8a6d19d80cbd69af3de51f5d4bac

View File

@ -33227,8 +33227,6 @@ CREATE UNIQUE INDEX unique_index_on_system_note_metadata_id ON resource_link_eve
CREATE UNIQUE INDEX unique_merge_request_metrics_by_merge_request_id ON merge_request_metrics USING btree (merge_request_id);
CREATE UNIQUE INDEX unique_organizations_on_name_lower ON organizations USING btree (lower(name));
CREATE UNIQUE INDEX unique_packages_project_id_and_name_and_version_when_debian ON packages_packages USING btree (project_id, name, version) WHERE ((package_type = 9) AND (status <> 4));
CREATE UNIQUE INDEX unique_postgres_async_fk_validations_name_and_table_name ON postgres_async_foreign_key_validations USING btree (name, table_name);

View File

@ -25992,6 +25992,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_info_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_INFO_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_info_threshold. |
| <a id="usercalloutfeaturenameenumnamespace_storage_limit_banner_warning_threshold"></a>`NAMESPACE_STORAGE_LIMIT_BANNER_WARNING_THRESHOLD` | Callout feature name for namespace_storage_limit_banner_warning_threshold. |
| <a id="usercalloutfeaturenameenumnamespace_storage_pre_enforcement_banner"></a>`NAMESPACE_STORAGE_PRE_ENFORCEMENT_BANNER` | Callout feature name for namespace_storage_pre_enforcement_banner. |
| <a id="usercalloutfeaturenameenumnew_navigation_callout"></a>`NEW_NAVIGATION_CALLOUT` | Callout feature name for new_navigation_callout. |
| <a id="usercalloutfeaturenameenumnew_top_level_group_alert"></a>`NEW_TOP_LEVEL_GROUP_ALERT` | Callout feature name for new_top_level_group_alert. |
| <a id="usercalloutfeaturenameenumnew_user_signups_cap_reached"></a>`NEW_USER_SIGNUPS_CAP_REACHED` | Callout feature name for new_user_signups_cap_reached. |
| <a id="usercalloutfeaturenameenumpersonal_access_token_expiry"></a>`PERSONAL_ACCESS_TOKEN_EXPIRY` | Callout feature name for personal_access_token_expiry. |

View File

@ -834,6 +834,7 @@ The `default_branch_protection` attribute determines whether users with the Deve
| `1` | Partial protection. Users with the Developer or Maintainer role can: <br>- Push new commits |
| `2` | Full protection. Only users with the Maintainer role can: <br>- Push new commits |
| `3` | Protected against pushes. Users with the Maintainer role can: <br>- Push new commits<br>- Force push changes<br>- Accept merge requests<br>Users with the Developer role can:<br>- Accept merge requests|
| `4` | Protected against pushes except initial push. User with the Developer rope can: <br>- Push commit to empty repository.<br> Users with the Maintainer role can: <br>- Push new commits<br>- Force push changes<br>- Accept merge requests<br>Users with the Developer role can:<br>- Accept merge requests|
## New Subgroup

View File

@ -149,10 +149,10 @@ comments.
This worker imports note attachments that are linked inside Markdown.
For each entity with Markdown text in the project, we schedule a job of:
- `Gitlab::GithubImport::ImportReleaseAttachmentsWorker` for every release.
- `Gitlab::GithubImport::ImportNoteAttachmentsWorker` for every note.
- `Gitlab::GithubImport::ImportIssueAttachmentsWorker` for every issue.
- `Gitlab::GithubImport::ImportMergeRequestAttachmentsWorker` for every merge request.
- `Gitlab::GithubImport::Importer::Attachments::ReleasesImporter` for every release.
- `Gitlab::GithubImport::Importer::Attachments::NotesImporter` for every note.
- `Gitlab::GithubImport::Importer::Attachments::IssuesImporter` for every issue.
- `Gitlab::GithubImport::Importer::Attachments::MergeRequestsImporter` for every merge request.
Each job:

View File

@ -95,6 +95,8 @@ unless a subgroup configuration overrides it.
## Protect initial default branches **(FREE SELF)**
> Full protection after initial push [added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/118729) in GitLab 16.0.
GitLab administrators and group owners can define [branch protections](../../../project/protected_branches.md)
to apply to every repository's [default branch](#default-branch)
at the [instance level](#instance-level-default-branch-protection) and
@ -108,6 +110,8 @@ at the [instance level](#instance-level-default-branch-protection) and
but cannot force push.
- **Fully protected** - Developers cannot push new commits, but maintainers can.
No one can force push.
- **Fully protected after initial push** - Developers can push the initial commit
to a repository, but none afterward. Maintainers can always push. No one can force push.
### Instance-level default branch protection **(FREE SELF)**

View File

@ -326,7 +326,11 @@ module Feature
end
def l2_cache_backend
::Gitlab::Redis::FeatureFlag.cache_store
if !Gitlab::Utils.to_boolean(ENV['GITLAB_USE_FEATURE_FLAG_REDIS'])
Rails.cache
else
::Gitlab::Redis::FeatureFlag.cache_store
end
end
def log(key:, action:, **extra)

View File

@ -23,6 +23,7 @@ module Gitlab
PROTECTION_DEV_CAN_PUSH = 1
PROTECTION_FULL = 2
PROTECTION_DEV_CAN_MERGE = 3
PROTECTION_DEV_CAN_INITIAL_PUSH = 4
# Default project creation level
NO_ONE_PROJECT_ACCESS = 0
@ -95,6 +96,11 @@ module Gitlab
label: s_('DefaultBranchProtection|Fully protected'),
help_text: s_('DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push.'),
value: PROTECTION_FULL
},
{
label: s_('DefaultBranchProtection|Fully protected after initial push'),
help_text: s_('DefaultBranchProtection|Developers can push the initial commit to a repository, but none afterward. Maintainers can always push. No one can force push.'),
value: PROTECTION_DEV_CAN_INITIAL_PUSH
}
]
end

View File

@ -34,6 +34,10 @@ module Gitlab
level == PROTECTION_DEV_CAN_PUSH
end
def developer_can_initial_push?
level == PROTECTION_DEV_CAN_INITIAL_PUSH
end
def developer_can_merge?
level == PROTECTION_DEV_CAN_MERGE
end

View File

@ -67,13 +67,6 @@ module Gitlab
# All `pg_` tables are marked as `internal`
return :gitlab_internal if table_name.start_with?('pg_')
# Sometimes the name of an index can be interpreted as a table's name.
# For eg, if we execute "ALTER INDEX my_index..", my_index is interpreted as a table name.
# In such cases, we should return the schema of the database table actually
# holding that index.
index_name = table_name
derive_schema_from_index(index_name)
end
# rubocop:enable Metrics/CyclomaticComplexity
@ -131,15 +124,6 @@ module Gitlab
@schema_names ||= self.views_and_tables_to_schema.values.to_set
end
private_class_method def self.derive_schema_from_index(index_name)
index = Gitlab::Database::PostgresIndex.find_by(name: index_name,
schema: ApplicationRecord.connection.current_schema)
return unless index
table_schema(index.tablename)
end
private_class_method def self.build_dictionary(path_globs)
Dir.glob(path_globs).each_with_object({}) do |file_path, dic|
data = YAML.load_file(file_path)

View File

@ -14476,6 +14476,9 @@ msgstr ""
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
msgstr ""
msgid "DefaultBranchProtection|Developers can push the initial commit to a repository, but none afterward. Maintainers can always push. No one can force push."
msgstr ""
msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
msgstr ""
@ -14485,6 +14488,9 @@ msgstr ""
msgid "DefaultBranchProtection|Fully protected"
msgstr ""
msgid "DefaultBranchProtection|Fully protected after initial push"
msgstr ""
msgid "DefaultBranchProtection|Not protected"
msgstr ""
@ -19223,6 +19229,9 @@ msgstr ""
msgid "For more information, see the File Hooks documentation."
msgstr ""
msgid "For the next few releases, you can go to your avatar at any time to turn the new navigation on and off."
msgstr ""
msgid "Forbidden"
msgstr ""
@ -22417,6 +22426,9 @@ msgstr ""
msgid "I accept the %{terms_link}"
msgstr ""
msgid "I am sorry, I am unable to find the issue you are looking for."
msgstr ""
msgid "I do not know."
msgstr ""
@ -37316,6 +37328,9 @@ msgstr ""
msgid "Read more about GitLab at %{link_to_promo}."
msgstr ""
msgid "Read more about the %{changes_link_start}changes%{link_end}, the %{vision_link_start}vision%{link_end}, and the %{design_link_start}design%{link_end}."
msgstr ""
msgid "Read their documentation."
msgstr ""
@ -50828,6 +50843,9 @@ msgstr ""
msgid "Welcome to GitLab,%{br_tag}%{name}!"
msgstr ""
msgid "Welcome to a new navigation experience"
msgstr ""
msgid "Welcome, %{name}!"
msgstr ""

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'new navigation callout', :js, feature_category: :navigation do
let_it_be(:callout_title) { _('Welcome to a new navigation experience') }
before do
sign_in(user)
visit root_path
end
context 'with new navigation toggled on' do
let_it_be(:user) { create(:user, use_new_navigation: true) }
it 'shows a callout about the new navigation' do
expect(page).to have_content callout_title
end
context 'when user dismisses callout' do
it 'hides callout' do
expect(page).to have_content callout_title
page.within(find('[data-feature-id="new_navigation_callout"]')) do
find('[data-testid="close-icon"]').click
end
wait_for_requests
visit root_path
expect(page).not_to have_content callout_title
end
end
end
context 'with new navigation toggled off' do
let_it_be(:user) { create(:user, use_new_navigation: false) }
it 'does not show the callout' do
expect(page).not_to have_content callout_title
end
end
end

View File

@ -133,7 +133,7 @@ describe('Work Item Note', () => {
findNoteActions().vm.$emit('startEditing');
await nextTick();
findCommentForm().vm.$emit('submitForm', updatedNoteText);
findCommentForm().vm.$emit('submitForm', { commentText: updatedNoteText });
expect(successHandler).toHaveBeenCalledWith({
input: {
@ -148,7 +148,7 @@ describe('Work Item Note', () => {
findNoteActions().vm.$emit('startEditing');
await nextTick();
findCommentForm().vm.$emit('submitForm', updatedNoteText);
findCommentForm().vm.$emit('submitForm', { commentText: updatedNoteText });
await waitForPromises();
expect(findCommentForm().exists()).toBe(false);
@ -161,7 +161,7 @@ describe('Work Item Note', () => {
findNoteActions().vm.$emit('startEditing');
await nextTick();
findCommentForm().vm.$emit('submitForm', updatedNoteText);
findCommentForm().vm.$emit('submitForm', { commentText: updatedNoteText });
await waitForPromises();
});

View File

@ -212,7 +212,15 @@ RSpec.describe Feature, :clean_gitlab_redis_feature_flag, stub_feature_flags: fa
end
it { expect(described_class.send(:l1_cache_backend)).to eq(Gitlab::ProcessMemoryCache.cache_backend) }
it { expect(described_class.send(:l2_cache_backend)).to eq(Gitlab::Redis::FeatureFlag.cache_store) }
it { expect(described_class.send(:l2_cache_backend)).to eq(Rails.cache) }
context 'when GITLAB_USE_FEATURE_FLAG_REDIS is set to true' do
before do
stub_env('GITLAB_USE_FEATURE_FLAG_REDIS', 'true')
end
it { expect(described_class.send(:l2_cache_backend)).to eq(Gitlab::Redis::FeatureFlag.cache_store) }
end
it 'caches the status in L1 and L2 caches',
:request_store, :use_clean_rails_memory_store_caching do

View File

@ -7,10 +7,11 @@ RSpec.describe Gitlab::Access::BranchProtection do
describe '#any?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | true
end
with_them do
@ -20,10 +21,11 @@ RSpec.describe Gitlab::Access::BranchProtection do
describe '#developer_can_push?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | false
end
with_them do
@ -35,10 +37,11 @@ RSpec.describe Gitlab::Access::BranchProtection do
describe '#developer_can_merge?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | false
end
with_them do
@ -50,10 +53,11 @@ RSpec.describe Gitlab::Access::BranchProtection do
describe '#fully_protected?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | false
end
with_them do
@ -62,4 +66,20 @@ RSpec.describe Gitlab::Access::BranchProtection do
end
end
end
describe '#developer_can_initial_push?' do
where(:level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | true
end
with_them do
it do
expect(described_class.new(level).developer_can_initial_push?).to eq(result)
end
end
end
end

View File

@ -20,12 +20,6 @@ RSpec.describe Gitlab::Database::GitlabSchema, feature_category: :database do
shared_examples 'maps table name to table schema' do
using RSpec::Parameterized::TableSyntax
before do
ApplicationRecord.connection.execute(<<~SQL)
CREATE INDEX index_name_on_table_belonging_to_gitlab_main ON public.projects (name);
SQL
end
where(:name, :classification) do
'ci_builds' | :gitlab_ci
'my_schema.ci_builds' | :gitlab_ci
@ -37,7 +31,6 @@ RSpec.describe Gitlab::Database::GitlabSchema, feature_category: :database do
'_test_gitlab_ci_table' | :gitlab_ci
'_test_my_table' | :gitlab_shared
'pg_attribute' | :gitlab_internal
'index_name_on_table_belonging_to_gitlab_main' | :gitlab_main
end
with_them do
@ -155,6 +148,18 @@ RSpec.describe Gitlab::Database::GitlabSchema, feature_category: :database do
it { is_expected.to be_nil }
end
context 'when an index name is used as the table name' do
before do
ApplicationRecord.connection.execute(<<~SQL)
CREATE INDEX index_on_projects ON public.projects USING gin (name gin_trgm_ops)
SQL
end
let(:name) { 'index_on_projects' }
it { is_expected.to be_nil }
end
end
describe '.table_schema!' do

View File

@ -7,6 +7,9 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_ana
before do
allow(Gitlab::Database::QueryAnalyzer.instance).to receive(:all_analyzers).and_return([analyzer])
ApplicationRecord.connection.execute(<<~SQL)
CREATE INDEX index_on_projects ON public.projects USING gin (name gin_trgm_ops)
SQL
end
it 'does not increment metrics if feature flag is disabled' do
@ -59,6 +62,11 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_ana
sql: "SELECT 1 FROM projects LEFT JOIN not_in_schema ON not_in_schema.project_id=projects.id",
expect_error:
/Could not find gitlab schema for table not_in_schema/
},
"for query altering an INDEX" => {
model: ApplicationRecord,
sql: "ALTER INDEX index_on_projects SET ( fastupdate = false )",
no_op: true
}
}
end
@ -74,6 +82,10 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_ana
if expect_error
expect { process_sql(model, sql) }.to raise_error(expect_error)
elsif no_op
expect(described_class.schemas_metrics).not_to receive(:increment)
process_sql(model, sql)
else
expect(described_class.schemas_metrics).to receive(:increment)
.with(expectations).and_call_original

View File

@ -15,7 +15,6 @@ RSpec.describe Organizations::Organization, type: :model, feature_category: :cel
subject { create(:organization) }
it { is_expected.to validate_presence_of(:name) }
it { is_expected.to validate_uniqueness_of(:name).case_insensitive }
it { is_expected.to validate_length_of(:name).is_at_most(255) }
end

View File

@ -2707,10 +2707,34 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr
subject { project.default_branch_protected? }
where(:default_branch_protection_level, :result) do
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_NONE | false
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | false
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | true
Gitlab::Access::PROTECTION_FULL | true
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | true
end
with_them do
before do
expect(project.namespace).to receive(:default_branch_protection).and_return(default_branch_protection_level)
end
it { is_expected.to eq(result) }
end
end
describe 'initial_push_to_default_branch_allowed_for_developer?' do
let_it_be(:namespace) { create(:namespace) }
let_it_be(:project) { create(:project, namespace: namespace) }
subject { project.initial_push_to_default_branch_allowed_for_developer? }
where(:default_branch_protection_level, :result) do
Gitlab::Access::PROTECTION_NONE | true
Gitlab::Access::PROTECTION_DEV_CAN_PUSH | true
Gitlab::Access::PROTECTION_DEV_CAN_MERGE | false
Gitlab::Access::PROTECTION_FULL | false
Gitlab::Access::PROTECTION_DEV_CAN_INITIAL_PUSH | true
end
with_them do

View File

@ -507,6 +507,44 @@ RSpec.describe ProtectedBranch, feature_category: :source_code_management do
it { is_expected.to eq(true) }
end
context 'when project is an empty repository' do
before do
allow(project).to receive(:empty_repo?).and_return(true)
end
context 'when user is an admin' do
let(:current_user) { admin }
it { is_expected.to eq(true) }
end
context 'when user is maintainer' do
let(:current_user) { maintainer }
it { is_expected.to eq(true) }
end
context 'when user is developer and initial push is allowed' do
let(:current_user) { developer }
before do
allow(project).to receive(:initial_push_to_default_branch_allowed_for_developer?).and_return(true)
end
it { is_expected.to eq(true) }
end
context 'when user is developer and initial push is not allowed' do
let(:current_user) { developer }
before do
allow(project).to receive(:initial_push_to_default_branch_allowed_for_developer?).and_return(false)
end
it { is_expected.to eq(false) }
end
end
end
describe '.by_name' do

View File

@ -32,6 +32,7 @@ end
RSpec.shared_examples 'work items comments' do |type|
let(:form_selector) { '[data-testid="work-item-add-comment"]' }
let(:edit_button) { '[data-testid="edit-work-item-note"]' }
let(:textarea_selector) { '[data-testid="work-item-add-comment"] #work-item-add-or-edit-comment' }
let(:is_mac) { page.evaluate_script('navigator.platform').include?('Mac') }
let(:modifier_key) { is_mac ? :command : :control }
@ -53,6 +54,22 @@ RSpec.shared_examples 'work items comments' do |type|
end
end
it 'successfully updates existing comments' do
set_comment
click_button "Comment"
wait_for_all_requests
find(edit_button).click
send_keys(" updated")
click_button "Save comment"
wait_for_all_requests
page.within(".main-notes-list") do
expect(page).to have_content "Test comment updated"
end
end
context 'for work item note actions signed in user with developer role' do
it 'shows work item note actions' do
set_comment

View File

@ -48,6 +48,20 @@ RSpec.describe Database::PreventCrossJoins, :suppress_gitlab_schemas_validate_co
expect { ApplicationRecord.connection.execute('SELECT SELECT FROM SELECT') }.to raise_error(ActiveRecord::StatementInvalid)
end
end
context 'when an ALTER INDEX query is used' do
before do
ApplicationRecord.connection.execute(<<~SQL)
CREATE INDEX index_on_projects ON public.projects USING gin (name gin_trgm_ops)
SQL
end
it 'does not raise exception' do
expect do
ApplicationRecord.connection.execute('ALTER INDEX index_on_projects SET ( fastupdate = false )')
end.not_to raise_error
end
end
end
end

View File

@ -268,7 +268,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Gitlab::BitbucketServerImport::Stage::ImportPullRequestsWorker' => 3,
'Gitlab::BitbucketServerImport::Stage::ImportRepositoryWorker' => 3,
'Gitlab::GithubImport::AdvanceStageWorker' => 3,
'Gitlab::GithubImport::ImportReleaseAttachmentsWorker' => 5,
'Gitlab::GithubImport::Attachments::ImportReleaseWorker' => 5,
'Gitlab::GithubImport::Attachments::ImportNoteWorker' => 5,
'Gitlab::GithubImport::Attachments::ImportIssueWorker' => 5,
@ -280,8 +279,6 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
'Gitlab::GithubImport::ImportNoteWorker' => 5,
'Gitlab::GithubImport::ImportProtectedBranchWorker' => 5,
'Gitlab::GithubImport::ImportCollaboratorWorker' => 5,
'Gitlab::GithubImport::ImportPullRequestMergedByWorker' => 5,
'Gitlab::GithubImport::ImportPullRequestReviewWorker' => 5,
'Gitlab::GithubImport::PullRequests::ImportReviewRequestWorker' => 5,
'Gitlab::GithubImport::PullRequests::ImportReviewWorker' => 5,
'Gitlab::GithubImport::PullRequests::ImportMergedByWorker' => 5,

View File

@ -1,15 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::ImportPullRequestMergedByWorker, feature_category: :importers do
it { is_expected.to include_module(Gitlab::GithubImport::ObjectImporter) }
describe '#representation_class' do
it { expect(subject.representation_class).to eq(Gitlab::GithubImport::Representation::PullRequest) }
end
describe '#importer_class' do
it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::PullRequests::MergedByImporter) }
end
end

View File

@ -1,15 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::ImportPullRequestReviewWorker, feature_category: :importers do
it { is_expected.to include_module(Gitlab::GithubImport::ObjectImporter) }
describe '#representation_class' do
it { expect(subject.representation_class).to eq(Gitlab::GithubImport::Representation::PullRequestReview) }
end
describe '#importer_class' do
it { expect(subject.importer_class).to eq(Gitlab::GithubImport::Importer::PullRequests::ReviewImporter) }
end
end

View File

@ -1,50 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::ImportReleaseAttachmentsWorker, feature_category: :importers do
subject(:worker) { described_class.new }
describe '#import' do
let(:import_state) { create(:import_state, :started) }
let(:project) do
instance_double('Project', full_path: 'foo/bar', id: 1, import_state: import_state)
end
let(:client) { instance_double('Gitlab::GithubImport::Client') }
let(:importer) { instance_double('Gitlab::GithubImport::Importer::NoteAttachmentsImporter') }
let(:release_hash) do
{
'record_db_id' => rand(100),
'record_type' => 'Release',
'tag' => 'v1.0',
'text' => <<-TEXT
Some text...
![special-image](https://user-images.githubusercontent.com...)
TEXT
}
end
it 'imports an issue event' do
expect(Gitlab::GithubImport::Importer::NoteAttachmentsImporter)
.to receive(:new)
.with(
an_instance_of(Gitlab::GithubImport::Representation::NoteText),
project,
client
)
.and_return(importer)
expect(importer).to receive(:execute)
expect(Gitlab::GithubImport::ObjectCounter)
.to receive(:increment)
.and_call_original
worker.import(project, client, release_hash)
end
end
end