diff --git a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
index f21092af501..67ad7769c7c 100644
--- a/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
+++ b/app/assets/javascripts/vue_shared/components/project_selector/project_selector.vue
@@ -130,16 +130,19 @@ export default {
{{ legendText }}
-
+
{{ __('Sorry, no projects matched your search') }}
{{ __('Enter at least three characters to search') }}
-
+
{{ __('Something went wrong, unable to search projects') }}
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 4d163824ef6..2ae0442c005 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -108,6 +108,7 @@ class Admin::GroupsController < Admin::ApplicationController
:visibility_level,
:require_two_factor_authentication,
:two_factor_grace_period,
+ :enabled_git_access_protocol,
:project_creation_level,
:subgroup_creation_level,
admin_note_attributes: [
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index fd3bcc67b12..327b4832f31 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -285,6 +285,7 @@ class GroupsController < Groups::ApplicationController
:chat_team_name,
:require_two_factor_authentication,
:two_factor_grace_period,
+ :enabled_git_access_protocol,
:project_creation_level,
:subgroup_creation_level,
:default_branch_protection,
diff --git a/app/controllers/jwks_controller.rb b/app/controllers/jwks_controller.rb
index 3b0e6ca2eb1..d3a8d3dafea 100644
--- a/app/controllers/jwks_controller.rb
+++ b/app/controllers/jwks_controller.rb
@@ -13,10 +13,6 @@ class JwksController < Doorkeeper::OpenidConnect::DiscoveryController
def payload
[
- # We keep openid_connect_signing_key so that we can seamlessly
- # replace it with ci_jwt_signing_key and remove it on the next release.
- # TODO: Remove openid_connect_signing_key in 13.7
- # https://gitlab.com/gitlab-org/gitlab/-/issues/221031
Rails.application.secrets.openid_connect_signing_key,
Gitlab::CurrentSettings.ci_jwt_signing_key
].compact.map do |key_data|
diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb
index 348a5af699d..9ea9509bc28 100644
--- a/app/helpers/groups_helper.rb
+++ b/app/helpers/groups_helper.rb
@@ -167,6 +167,17 @@ module GroupsHelper
}
end
+ def enabled_git_access_protocol_options_for_group
+ case ::Gitlab::CurrentSettings.enabled_git_access_protocol
+ when nil, ""
+ [[_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]]
+ when "ssh"
+ [[_("Only SSH"), "ssh"]]
+ when "http"
+ [[_("Only HTTP(S)"), "http"]]
+ end
+ end
+
private
def group_title_link(group, hidable: false, show_avatar: false, for_dropdown: false)
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index e7bf1ff42a5..5bb06cdbb4a 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -557,6 +557,14 @@ class Namespace < ApplicationRecord
cluster_enabled_granted? || certificate_based_clusters_enabled_ff?
end
+ def enabled_git_access_protocol
+ # If the instance-level setting is enabled, we defer to that
+ return ::Gitlab::CurrentSettings.enabled_git_access_protocol unless ::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
+
+ # Otherwise we use the stored setting on the group
+ namespace_settings&.enabled_git_access_protocol
+ end
+
private
def cluster_enabled_granted?
diff --git a/app/models/namespace_setting.rb b/app/models/namespace_setting.rb
index ef917c8a22e..504daf2662e 100644
--- a/app/models/namespace_setting.rb
+++ b/app/models/namespace_setting.rb
@@ -9,14 +9,17 @@ class NamespaceSetting < ApplicationRecord
belongs_to :namespace, inverse_of: :namespace_settings
+ enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true
+ enum enabled_git_access_protocol: { all: 0, ssh: 1, http: 2 }, _suffix: true
+
+ validates :enabled_git_access_protocol, inclusion: { in: enabled_git_access_protocols.keys }
+
validate :default_branch_name_content
validate :allow_mfa_for_group
validate :allow_resource_access_token_creation_for_group
before_validation :normalize_default_branch_name
- enum jobs_to_be_done: { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5 }, _suffix: true
-
chronic_duration_attr :runner_token_expiration_interval_human_readable, :runner_token_expiration_interval
chronic_duration_attr :subgroup_runner_token_expiration_interval_human_readable, :subgroup_runner_token_expiration_interval
chronic_duration_attr :project_runner_token_expiration_interval_human_readable, :project_runner_token_expiration_interval
@@ -24,7 +27,7 @@ class NamespaceSetting < ApplicationRecord
NAMESPACE_SETTINGS_PARAMS = [:default_branch_name, :delayed_project_removal,
:lock_delayed_project_removal, :resource_access_token_creation_allowed,
:prevent_sharing_groups_outside_hierarchy, :new_user_signups_cap,
- :setup_for_company, :jobs_to_be_done, :runner_token_expiration_interval,
+ :setup_for_company, :jobs_to_be_done, :runner_token_expiration_interval, :enabled_git_access_protocol,
:subgroup_runner_token_expiration_interval, :project_runner_token_expiration_interval].freeze
self.primary_key = :namespace_id
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index b5fa08aed79..5dc2d322bb3 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -1,5 +1,5 @@
= gitlab_ui_form_for @application_setting, url: repository_admin_application_settings_path(anchor: 'js-repository-storage-settings'), html: { class: 'fieldset-form' } do |f|
- = form_errors(@application_setting)
+ = form_errors(@application_setting, pajamas_alert: true)
%fieldset
.sub-section
diff --git a/app/views/groups/settings/_git_access_protocols.html.haml b/app/views/groups/settings/_git_access_protocols.html.haml
new file mode 100644
index 00000000000..df798db79ad
--- /dev/null
+++ b/app/views/groups/settings/_git_access_protocols.html.haml
@@ -0,0 +1,7 @@
+- if group.root? && Feature.enabled?(:group_level_git_protocol_control, group)
+ .form-group
+ = f.label s_('Enabled Git access protocols'), class: 'label-bold'
+ = f.select :enabled_git_access_protocol, options_for_select(enabled_git_access_protocol_options_for_group, group.enabled_git_access_protocol), {}, class: 'form-control', data: { qa_selector: 'enabled_git_access_protocol_dropdown' }, disabled: !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
+ - if !::Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
+ .form-text.text-muted
+ = _("This setting has been configured at the instance level and cannot be overridden per group")
diff --git a/app/views/groups/settings/_permissions.html.haml b/app/views/groups/settings/_permissions.html.haml
index ecb31b37fd3..a30770b292d 100644
--- a/app/views/groups/settings/_permissions.html.haml
+++ b/app/views/groups/settings/_permissions.html.haml
@@ -37,6 +37,7 @@
- if @group.licensed_feature_available?(:group_wikis)
= render_if_exists 'groups/settings/wiki', f: f, group: @group
= render 'groups/settings/lfs', f: f
+ = render 'groups/settings/git_access_protocols', f: f, group: @group
= render 'groups/settings/project_creation_level', f: f, group: @group
= render 'groups/settings/subgroup_creation_level', f: f, group: @group
= render_if_exists 'groups/settings/prevent_forking', f: f, group: @group
diff --git a/app/views/projects/graphs/show.html.haml b/app/views/projects/graphs/show.html.haml
index 1973b23a062..c7639eec75d 100644
--- a/app/views/projects/graphs/show.html.haml
+++ b/app/views/projects/graphs/show.html.haml
@@ -1,7 +1,7 @@
- page_title _('Contributors')
-.sub-header-block.bg-gray-light.gl-p-5
- .tree-ref-holder.inline.vertical-align-middle
+.sub-header-block.gl-bg-gray-10.gl-p-5
+ .tree-ref-holder.gl-display-inline-block.gl-vertical-align-middle.gl-mr-3>
= render 'shared/ref_switcher', destination: 'graphs'
= link_to s_('Commits|History'), project_commits_path(@project, current_ref), class: 'btn gl-button btn-default'
diff --git a/config/feature_flags/development/ci_jwt_signing_key.yml b/config/feature_flags/development/group_level_git_protocol_control.yml
similarity index 53%
rename from config/feature_flags/development/ci_jwt_signing_key.yml
rename to config/feature_flags/development/group_level_git_protocol_control.yml
index 7d96264e25f..ad9ba309d69 100644
--- a/config/feature_flags/development/ci_jwt_signing_key.yml
+++ b/config/feature_flags/development/group_level_git_protocol_control.yml
@@ -1,8 +1,8 @@
---
-name: ci_jwt_signing_key
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34249
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546
-milestone: '13.6'
+name: group_level_git_protocol_control
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89817
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/365357
+milestone: '15.1'
type: development
-group: group::configure
-default_enabled: true
+group: group::source code
+default_enabled: false
diff --git a/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml b/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml
new file mode 100644
index 00000000000..658db1a27af
--- /dev/null
+++ b/config/metrics/counts_28d/20220525231314_unique_monthly_active_users.yml
@@ -0,0 +1,23 @@
+---
+key_path: counts_monthly.unique_active_users
+name:
+description: Users that have a last_activity_on date within the past 28 days
+product_category:
+product_section: dev
+product_stage: manage
+product_group: group::manage
+value_type: number
+status: active
+milestone: "15.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88631
+time_frame: 28d
+data_source: database
+data_category: optional
+instrumentation_class: UniqueActiveUsersMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb b/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb
new file mode 100644
index 00000000000..2f16467acd1
--- /dev/null
+++ b/db/migrate/20220610125248_add_enabled_git_access_protocol_to_namespace_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddEnabledGitAccessProtocolToNamespaceSettings < Gitlab::Database::Migration[2.0]
+ def change
+ add_column :namespace_settings, :enabled_git_access_protocol, :integer, default: 0, null: false, limit: 2
+ end
+end
diff --git a/db/schema_migrations/20220610125248 b/db/schema_migrations/20220610125248
new file mode 100644
index 00000000000..25e863f8c14
--- /dev/null
+++ b/db/schema_migrations/20220610125248
@@ -0,0 +1 @@
+8ba7386e21ebb3ac082e322059b41d423cede484e60748222de6a0673c3ca41f
\ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a3f5ece22b9..cc1f70bc8a8 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -17500,6 +17500,7 @@ CREATE TABLE namespace_settings (
subgroup_runner_token_expiration_interval integer,
project_runner_token_expiration_interval integer,
exclude_from_free_user_cap boolean DEFAULT false NOT NULL,
+ enabled_git_access_protocol smallint DEFAULT 0 NOT NULL,
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255))
);
diff --git a/doc/user/project/repository/mirror/pull.md b/doc/user/project/repository/mirror/pull.md
index 73103a9af3d..3599faf4de6 100644
--- a/doc/user/project/repository/mirror/pull.md
+++ b/doc/user/project/repository/mirror/pull.md
@@ -96,9 +96,9 @@ assigned when you set up pull mirroring.
> Moved to GitLab Premium in 13.9.
Pull mirroring uses polling to detect new branches and commits added upstream,
-often minutes afterwards. If you notify GitLab by
-[API](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project),
-updates are pulled immediately.
+often minutes afterwards. You can notify GitLab using an
+[API call](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project),
+but the [minimum interval for pull mirroring limits](index.md#force-an-update) is still enforced.
For more information, read
[Start the pull mirroring process for a project](../../../../api/projects.md#start-the-pull-mirroring-process-for-a-project).
diff --git a/lib/gitlab/ci/jwt.rb b/lib/gitlab/ci/jwt.rb
index 97774bc5e13..19678def666 100644
--- a/lib/gitlab/ci/jwt.rb
+++ b/lib/gitlab/ci/jwt.rb
@@ -73,11 +73,7 @@ module Gitlab
def key
@key ||= begin
- key_data = if Feature.enabled?(:ci_jwt_signing_key, build.project)
- Gitlab::CurrentSettings.ci_jwt_signing_key
- else
- Rails.application.secrets.openid_connect_signing_key
- end
+ key_data = Gitlab::CurrentSettings.ci_jwt_signing_key
raise NoSigningKeyError unless key_data
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index c96c8afd22d..66fd7aaedea 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -133,7 +133,7 @@ module Gitlab
end
def protocol_allowed?
- Gitlab::ProtocolAccess.allowed?(protocol)
+ Gitlab::ProtocolAccess.allowed?(protocol, project: project)
end
private
diff --git a/lib/gitlab/protocol_access.rb b/lib/gitlab/protocol_access.rb
index efeb1e07d49..5bcbf7b5cca 100644
--- a/lib/gitlab/protocol_access.rb
+++ b/lib/gitlab/protocol_access.rb
@@ -2,14 +2,42 @@
module Gitlab
module ProtocolAccess
- def self.allowed?(protocol)
- if protocol == 'web'
+ class << self
+ def allowed?(protocol, project: nil)
+ # Web is always allowed
+ return true if protocol == "web"
+
+ # System settings
+ return false unless instance_allowed?(protocol)
+
+ # Group-level settings
+ return false unless namespace_allowed?(protocol, namespace: project&.root_namespace)
+
+ # Default to allowing all protocols
true
- elsif Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
- true
- else
+ end
+
+ private
+
+ def instance_allowed?(protocol)
+ # If admin hasn't configured this setting, default to true
+ return true if Gitlab::CurrentSettings.enabled_git_access_protocol.blank?
+
protocol == Gitlab::CurrentSettings.enabled_git_access_protocol
end
+
+ def namespace_allowed?(protocol, namespace: nil)
+ # If the namespace parameter was nil, we default to true here
+ return true if namespace.nil?
+
+ # Return immediately if all protocols are allowed
+ return true if namespace.enabled_git_access_protocol == "all"
+
+ # If the setting is somehow nil, such as in an unsaved state, we default to allow
+ return true if namespace.enabled_git_access_protocol.blank?
+
+ protocol == namespace.enabled_git_access_protocol
+ end
end
end
end
diff --git a/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb
new file mode 100644
index 00000000000..9da30db05dd
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class UniqueActiveUsersMetric < DatabaseMetric
+ operation :count
+ relation { ::User.active }
+
+ metric_options do
+ {
+ batch_size: 10_000
+ }
+ end
+
+ def time_constraints
+ case time_frame
+ when '28d'
+ monthly_time_range_db_params(column: :last_activity_on)
+ else
+ super
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d82e155eeaa..4c5129d0b1a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -6481,6 +6481,9 @@ msgstr ""
msgid "Bold text"
msgstr ""
+msgid "Both SSH and HTTP(S)"
+msgstr ""
+
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -26700,6 +26703,9 @@ msgstr ""
msgid "Only 1 appearances row can exist"
msgstr ""
+msgid "Only HTTP(S)"
+msgstr ""
+
msgid "Only Issue ID or merge request ID is required"
msgstr ""
@@ -26709,6 +26715,9 @@ msgstr ""
msgid "Only Project Members"
msgstr ""
+msgid "Only SSH"
+msgstr ""
+
msgid "Only Task can be assigned as a child in hierarchy."
msgstr ""
@@ -39387,6 +39396,9 @@ msgstr ""
msgid "This setting can be overridden in each project."
msgstr ""
+msgid "This setting has been configured at the instance level and cannot be overridden per group"
+msgstr ""
+
msgid "This setting is allowed for forked projects only"
msgstr ""
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
index edb7838e81d..89150c73069 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb
@@ -73,7 +73,7 @@ module QA
let(:source_commits) { source_project.commits(auto_paginate: true).map { |c| c[:id] } }
let(:source_labels) { source_project.labels(auto_paginate: true).map { |l| l.except(:id) } }
let(:source_milestones) { source_project.milestones(auto_paginate: true).map { |ms| ms.except(:id, :web_url, :project_id) } }
- let(:source_pipelines) { source_project.pipelines.map { |pp| pp.except(:id, :web_url, :project_id) } }
+ let(:source_pipelines) { source_project.pipelines(auto_paginate: true).map { |pp| pp.except(:id, :web_url, :project_id) } }
let(:source_mrs) { fetch_mrs(source_project, source_api_client) }
let(:source_issues) { fetch_issues(source_project, source_api_client) }
@@ -259,7 +259,7 @@ module QA
missing_comments = verify_comments(type, actual, expected)
{
- "#{type}s": (expected.keys - actual.keys).map { |it| actual[it].slice(:title, :url) },
+ "#{type}s": (expected.keys - actual.keys).map { |it| actual[it]&.slice(:title, :url) }.compact,
"#{type}_comments": missing_comments
}
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
index 19aa3d12568..63ae90aed9c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb
@@ -2,16 +2,9 @@
module QA
RSpec.describe 'Manage' do
- describe 'Project access tokens', :reliable, feature_flag: {
- name: 'bootstrap_confirmation_modals',
- scope: :global
- } do
+ describe 'Project access tokens', :reliable do
let(:project_access_token) { QA::Resource::ProjectAccessToken.fabricate_via_browser_ui! }
- before do
- Runtime::Feature.enable(:bootstrap_confirmation_modals)
- end
-
it(
'can be created and revoked via the UI',
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347688'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index 2300e384ab5..0bd470fcb77 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', feature_flag: {
- name: 'bootstrap_confirmation_modals',
- scope: :global
- } do
+ RSpec.describe 'Create' do
describe 'Create, list, and delete branches via web', :requires_admin do
master_branch = nil
second_branch = 'second-branch'
@@ -19,8 +16,6 @@ module QA
commit_message_of_third_branch = "Add #{file_third_branch}"
before do
- Runtime::Feature.enable(:bootstrap_confirmation_modals)
-
Flow::Login.sign_in
project = Resource::Project.fabricate_via_api! do |proj|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
index 171567b7ed9..1a7c64a363f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/add_comment_to_snippet_spec.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', feature_flag: {
- name: 'bootstrap_confirmation_modals',
- scope: :global
- } do
+ RSpec.describe 'Create' do
describe 'Adding comments on snippets' do
let(:comment_author) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
let(:comment_content) { 'Comment 123' }
@@ -23,7 +20,6 @@ module QA
end
before do
- Runtime::Feature.enable(:bootstrap_confirmation_modals)
Flow::Login.sign_in
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
index ed421ac7279..e4204776c46 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/copy_snippet_file_contents_spec.rb
@@ -1,10 +1,7 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create', :reliable, feature_flag: {
- name: 'bootstrap_confirmation_modals',
- scope: :global
- } do
+ RSpec.describe 'Create', :reliable do
describe 'Multiple file snippet' do
let(:first_file_content) { 'First file content' }
let(:second_file_content) { 'Second file content' }
@@ -38,23 +35,22 @@ module QA
let(:files) do
[
- {
- number: 1,
- content: first_file_content
- },
- {
- number: 2,
- content: second_file_content
- },
- {
- number: 3,
- content: third_file_content
- }
+ {
+ number: 1,
+ content: first_file_content
+ },
+ {
+ number: 2,
+ content: second_file_content
+ },
+ {
+ number: 3,
+ content: third_file_content
+ }
]
end
before do
- Runtime::Feature.enable(:bootstrap_confirmation_modals)
Flow::Login.sign_in
end
diff --git a/qa/qa/support/api.rb b/qa/qa/support/api.rb
index 0c0a1a90ff2..a1bbe9f378a 100644
--- a/qa/qa/support/api.rb
+++ b/qa/qa/support/api.rb
@@ -141,31 +141,18 @@ module QA
get(url).tap { |resp| not_ok_error.call(resp) if resp.code != HTTP_STATUS_OK }
end
- page, pages = response.headers.values_at(:x_page, :x_total_pages)
+ page, pages, next_page = response.headers.values_at(:x_page, :x_total_pages, :x_next_page)
api_endpoint = url.match(%r{v4/(\S+)\?})[1]
QA::Runtime::Logger.debug("Fetching page (#{page}/#{pages}) for '#{api_endpoint}' ...") unless pages.to_i <= 1
yield parse_body(response)
- next_link = pagination_links(response).find { |link| link[:rel] == 'next' }
- break unless next_link
+ break if next_page.empty?
- url = next_link[:url]
+ url = url.match?(/&page=\d+/) ? url.gsub(/&page=\d+/, "&page=#{next_page}") : "#{url}&page=#{next_page}"
end
end
-
- def pagination_links(response)
- link = response.headers[:link]
- return unless link
-
- link.split(',').map do |link|
- match = link.match(/<(?
.*)>; rel="(?\w+)"/)
- break nil unless match
-
- { url: match[:url], rel: match[:rel] }
- end.compact
- end
end
end
end
diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb
index 3ea5701c134..bcbe571db5e 100644
--- a/spec/helpers/groups_helper_spec.rb
+++ b/spec/helpers/groups_helper_spec.rb
@@ -472,4 +472,36 @@ RSpec.describe GroupsHelper do
})
end
end
+
+ describe "#enabled_git_access_protocol_options_for_group" do
+ subject { helper.enabled_git_access_protocol_options_for_group }
+
+ before do
+ expect(::Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(instance_setting)
+ end
+
+ context "instance setting is nil" do
+ let(:instance_setting) { nil }
+
+ it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
+ end
+
+ context "instance setting is blank" do
+ let(:instance_setting) { nil }
+
+ it { is_expected.to contain_exactly([_("Both SSH and HTTP(S)"), "all"], [_("Only SSH"), "ssh"], [_("Only HTTP(S)"), "http"]) }
+ end
+
+ context "instance setting is ssh" do
+ let(:instance_setting) { "ssh" }
+
+ it { is_expected.to contain_exactly([_("Only SSH"), "ssh"]) }
+ end
+
+ context "instance setting is http" do
+ let(:instance_setting) { "http" }
+
+ it { is_expected.to contain_exactly([_("Only HTTP(S)"), "http"]) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/jwt_spec.rb b/spec/lib/gitlab/ci/jwt_spec.rb
index b0d6f5adfb1..179e2efc0c7 100644
--- a/spec/lib/gitlab/ci/jwt_spec.rb
+++ b/spec/lib/gitlab/ci/jwt_spec.rb
@@ -160,20 +160,8 @@ RSpec.describe Gitlab::Ci::Jwt do
subject(:jwt) { described_class.for_build(build) }
- context 'when ci_jwt_signing_key feature flag is disabled' do
+ context 'when ci_jwt_signing_key is present' do
before do
- stub_feature_flags(ci_jwt_signing_key: false)
-
- allow(Rails.application.secrets).to receive(:openid_connect_signing_key).and_return(rsa_key_data)
- end
-
- it_behaves_like 'generating JWT for build'
- end
-
- context 'when ci_jwt_signing_key feature flag is enabled' do
- before do
- stub_feature_flags(ci_jwt_signing_key: true)
-
stub_application_setting(ci_jwt_signing_key: rsa_key_data)
end
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index e628a06a542..5ee9cf05b3e 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe Gitlab::GitAccess do
describe '#check with single protocols allowed' do
def disable_protocol(protocol)
- allow(Gitlab::ProtocolAccess).to receive(:allowed?).with(protocol).and_return(false)
+ allow(Gitlab::ProtocolAccess).to receive(:allowed?).with(protocol, project: project).and_return(false)
end
context 'ssh disabled' do
diff --git a/spec/lib/gitlab/protocol_access_spec.rb b/spec/lib/gitlab/protocol_access_spec.rb
new file mode 100644
index 00000000000..4722ea99608
--- /dev/null
+++ b/spec/lib/gitlab/protocol_access_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Gitlab::ProtocolAccess do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:p1) { create(:project, :repository, namespace: group) }
+
+ describe ".allowed?" do
+ where(:protocol, :project, :admin_setting, :namespace_setting, :expected_result) do
+ "web" | nil | nil | nil | true
+ "ssh" | nil | nil | nil | true
+ "http" | nil | nil | nil | true
+ "ssh" | nil | "" | nil | true
+ "http" | nil | "" | nil | true
+ "ssh" | nil | "ssh" | nil | true
+ "http" | nil | "http" | nil | true
+ "ssh" | nil | "http" | nil | false
+ "http" | nil | "ssh" | nil | false
+ "ssh" | ref(:p1) | nil | "all" | true
+ "http" | ref(:p1) | nil | "all" | true
+ "ssh" | ref(:p1) | nil | "ssh" | true
+ "http" | ref(:p1) | nil | "http" | true
+ "ssh" | ref(:p1) | nil | "http" | false
+ "http" | ref(:p1) | nil | "ssh" | false
+ "ssh" | ref(:p1) | "" | "all" | true
+ "http" | ref(:p1) | "" | "all" | true
+ "ssh" | ref(:p1) | "ssh" | "ssh" | true
+ "http" | ref(:p1) | "http" | "http" | true
+ end
+
+ with_them do
+ subject { described_class.allowed?(protocol, project: project) }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:enabled_git_access_protocol).and_return(admin_setting)
+
+ if project.present?
+ project.root_namespace.namespace_settings.update!(enabled_git_access_protocol: namespace_setting)
+ end
+ end
+
+ it do
+ is_expected.to be(expected_result)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb
new file mode 100644
index 00000000000..8a0ce61de74
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/unique_active_users_metric_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::UniqueActiveUsersMetric do
+ let_it_be(:user1) { create(:user, last_activity_on: 1.day.ago) }
+ let_it_be(:user2) { create(:user, last_activity_on: 5.days.ago) }
+ let_it_be(:user3) { create(:user, last_activity_on: 50.days.ago) }
+ let_it_be(:user4) { create(:user) }
+ let_it_be(:user5) { create(:user, user_type: 1, last_activity_on: 5.days.ago ) } # support bot
+ let_it_be(:user6) { create(:user, state: 'blocked') }
+
+ context '28d' do
+ let(:start) { 30.days.ago.to_date.to_s }
+ let(:finish) { 2.days.ago.to_date.to_s }
+ let(:expected_value) { 1 }
+ let(:expected_query) do
+ "SELECT COUNT(\"users\".\"id\") FROM \"users\" WHERE (\"users\".\"state\" IN ('active')) AND " \
+ "(\"users\".\"user_type\" IS NULL OR \"users\".\"user_type\" IN (6, 4)) AND \"users\".\"last_activity_on\" " \
+ "BETWEEN '#{start}' AND '#{finish}'"
+ end
+
+ it_behaves_like 'a correct instrumented metric value and query', { time_frame: '28d' }
+ end
+
+ context 'all' do
+ let(:expected_value) { 4 }
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'all' }
+ end
+end
diff --git a/spec/models/namespace_setting_spec.rb b/spec/models/namespace_setting_spec.rb
index c9f8a1bcdc2..25234db5734 100644
--- a/spec/models/namespace_setting_spec.rb
+++ b/spec/models/namespace_setting_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe NamespaceSetting, type: :model do
end
it { is_expected.to define_enum_for(:jobs_to_be_done).with_values([:basics, :move_repository, :code_storage, :exploring, :ci, :other]).with_suffix }
+ it { is_expected.to define_enum_for(:enabled_git_access_protocol).with_values([:all, :ssh, :http]).with_suffix }
describe "validations" do
describe "#default_branch_name_content" do