Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-06-16 15:09:00 +00:00
parent b019dc959e
commit a6533d71f5
34 changed files with 298 additions and 101 deletions

View File

@ -130,16 +130,19 @@ export default {
<span data-testid="legend-text">{{ legendText }}</span>
</template>
</gl-infinite-scroll>
<div v-if="showNoResultsMessage" class="text-muted ml-2 js-no-results-message">
<div v-if="showNoResultsMessage" class="gl-text-gray-600 gl-ml-3 js-no-results-message">
{{ __('Sorry, no projects matched your search') }}
</div>
<div
v-if="showMinimumSearchQueryMessage"
class="text-muted ml-2 js-minimum-search-query-message"
class="gl-text-gray-600 gl-ml-3 js-minimum-search-query-message"
>
{{ __('Enter at least three characters to search') }}
</div>
<div v-if="showSearchErrorMessage" class="text-danger ml-2 js-search-error-message">
<div
v-if="showSearchErrorMessage"
class="gl-text-red-500 gl-font-weight-bold gl-ml-3 js-search-error-message"
>
{{ __('Something went wrong, unable to search projects') }}
</div>
</div>

View File

@ -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: [

View File

@ -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,

View File

@ -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|

View File

@ -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)

View File

@ -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?

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
8ba7386e21ebb3ac082e322059b41d423cede484e60748222de6a0673c3ca41f

View File

@ -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))
);

View File

@ -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).

View File

@ -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

View File

@ -133,7 +133,7 @@ module Gitlab
end
def protocol_allowed?
Gitlab::ProtocolAccess.allowed?(protocol)
Gitlab::ProtocolAccess.allowed?(protocol, project: project)
end
private

View File

@ -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

View File

@ -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

View File

@ -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 ""

View File

@ -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

View File

@ -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'

View File

@ -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|

View File

@ -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

View File

@ -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

View File

@ -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(/<(?<url>.*)>; rel="(?<rel>\w+)"/)
break nil unless match
{ url: match[:url], rel: match[:rel] }
end.compact
end
end
end
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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