Add latest changes from gitlab-org/gitlab@14-1-stable-ee

This commit is contained in:
GitLab Bot 2021-07-27 22:40:43 +00:00
parent ad1c34c03d
commit bbe511b231
19 changed files with 501 additions and 14 deletions

View File

@ -58,7 +58,7 @@ body.gl-dark {
}
}
.md code {
.md :not(pre.code) > code {
background-color: $gray-200;
}
}

View File

@ -3,13 +3,12 @@
class ApplicationSetting
class Term < ApplicationRecord
include CacheMarkdownField
include NullifyIfBlank
has_many :term_agreements
cache_markdown_field :terms
nullify_if_blank :terms
validates :terms, presence: true
def self.latest
order(:id).last

View File

@ -67,8 +67,10 @@ module ApplicationSettings
end
def update_terms(terms)
return unless terms.present?
# Avoid creating a new terms record if the text is exactly the same.
terms = terms&.strip
terms = terms.strip
return if terms == @application_setting.terms
ApplicationSetting::Term.create(terms: terms)

View File

@ -9,6 +9,12 @@ def master_process?
end
warmup do |app|
# The following is necessary to ensure stale Prometheus metrics don't accumulate over time.
# It needs to be done as early as here to ensure metrics files aren't deleted.
# After we hit our app in `warmup`, first metrics and corresponding files already being created,
# for example in `lib/gitlab/metrics/requests_rack_middleware.rb`.
Prometheus::CleanupMultiprocDirService.new.execute if master_process?
client = Rack::MockRequest.new(app)
client.get('/')
end

View File

@ -40,9 +40,6 @@ if !Rails.env.test? && Gitlab::Metrics.prometheus_metrics_enabled?
# When running Puma in a Single mode, `on_master_start` and `on_worker_start` are the same.
# Thus, we order these events to run `reinitialize_on_pid_change` with `force: true` first.
Gitlab::Cluster::LifecycleEvents.on_master_start do
# Ensure that stale Prometheus metrics don't accumulate over time
::Prometheus::CleanupMultiprocDirService.new.execute
::Prometheus::Client.reinitialize_on_pid_change(force: true)
if Gitlab::Runtime.puma?

View File

@ -0,0 +1,139 @@
- title: Track progress on overall DevOps adoption
body: |
See the total number of key DevOps features adopted across your organization using the new progress bars in DevOps Adoption. Progress bars help you understand the value that teams are getting from GitLab and evaluate the state of your DevOps transformation.
stage: Manage
self-managed: true
gitlab-com: true
packages: [Ultimate]
url: https://docs.gitlab.com/ee/user/group/devops_adoption/
image_url: https://about.gitlab.com/images/14_1/progressbar.png
published_at: 2021-07-22
release: 14.1
- title: Track use of security scanning across multiple teams
body: |
Track which groups across your organization have enabled SAST and DAST scanning. This is helpful for verifying compliance with organizational requirements, responding to audit requests, and tracking progress on company initiatives to make applications more secure. To track adoption, go to the **Sec** tab in DevOps Adoption either at the group level or instance level.
To see groups that have enabled fuzz testing and dependency scanning, use [the DevOps API](https://docs.gitlab.com/ee/api/graphql/reference/index.html#devopsadoptionsnapshot). Fuzz testing and dependency scanning will be added to the DevOps Adoption UI in an upcoming release.
stage: Manage
self-managed: true
gitlab-com: true
packages: [Ultimate]
url: https://docs.gitlab.com/ee/user/group/devops_adoption
image_url: https://about.gitlab.com/images/14_1/scanadoption.png
published_at: 2021-07-22
release: 14.1
- title: Create and apply patches in VS Code
body: |
When reviewing a merge request (MR) it can be helpful to make suggestions to many of the changed files. This is often done by creating a patch file with the suggestions and sharing it with others. The problem is that this requires several manual steps like running Git commands and uploading the patch file somewhere others can download it.
With [GitLab Workflow](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow) [v3.26.0](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/CHANGELOG.md#3260-2021-07-13) for VS Code you can now create and apply patches directly in your editor. The new `GitLab: Create snippet patch` command creates a patch with the changes in your editor and uploads that patch as a [GitLab snippet](https://docs.gitlab.com/ee/user/snippets.html).
Anyone can search for patches in the project's snippets and apply them directly in VS Code with the `GitLab: Apply snippet patch` command. The applied changes can then be committed to the MR.
Sharing and collaborating around patches is a great way to propose more complex suggestions and provide clear improvements. Patches created in VS Code can also be linked to others through snippets and downloaded and applied outside of VS Code for users with different editing tools.
stage: Create
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: 'https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md#create-and-apply-snippet-patch'
image_url: https://img.youtube.com/vi/QQxpLoKJULQ/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
- title: Code coverage merge request approval rule
body: |
To keep code test coverage high, you need to ensure that merge requests to your codebase never decrease test coverage. Previously, the only way to enforce this was to [require approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/#required-approvals) from users who would check for test coverage decreases as part of their reviews.
Now you can enforce this organizational policy with the new Coverage check approval rule. This is a simple way to ensure merge requests that would decrease test coverage cannot be merged.
stage: Verify
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: 'https://docs.gitlab.com/ee/ci/pipelines/settings.html#coverage-check-approval-rule'
image_url: https://about.gitlab.com/images/14_1/coverage-mr-approval-rule.png
published_at: 2021-07-22
release: 14.1
- title: Registration Features
body: |
[Registration Features](https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program) introduces the ability for free, self-managed users running GitLab EE to access paid features by registering with GitLab and sharing activity data via [Service Ping](https://docs.gitlab.com/ee/development/service_ping/index.html#what-is-service-ping). The first feature introduced is [email from GitLab](https://docs.gitlab.com/ee/tools/email.html), enabling instance administrators to email users within their instance.
stage: Growth
self-managed: true
gitlab-com: false
packages: [Free]
url: 'https://docs.gitlab.com/ee/development/service_ping/index.html#registration-features-program'
image_url: https://about.gitlab.com/images/14_1/registration-features.png
published_at: 2021-07-22
release: 14.1
- title: Build, publish, and share Helm charts
body: |
Helm defines a [chart](https://helm.sh/docs/intro/using_helm/#three-big-concepts) as a Helm package that contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. For organizations that create and manage their own Helm charts, it's important to have a central repository to collect and share them.
GitLab already supports a variety of other [package manager formats](https://docs.gitlab.com/ee/user/packages/). Why not also support Helm? That's what community member and [MVP from the 14.0 milestone](https://about.gitlab.com/releases/2021/06/22/gitlab-14-0-released/#mvp) [Mathieu Parent](https://gitlab.com/sathieu) asked several months ago before breaking ground on the new GitLab Helm chart registry. The collaboration between the community and GitLab is part of our [dual flywheel strategy](https://about.gitlab.com/company/strategy/#dual-flywheels) and one of the reasons we love working at GitLab. Chapeau Mathieu!
Now you can use your GitLab project to publish and share packaged Helm charts. Simply add your project as a remote, authenticating with a personal access, deploy, or CI/CD job token. Once that's done you can use the Helm client or GitLab CI/CD to manage your Helm charts. You can also download the charts using the [API](https://docs.gitlab.com/ee/api/packages.html#get-a-project-package) or the [user interface](https://docs.gitlab.com/ee/user/packages/package_registry/#download-a-package).
stage: Package
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/packages/helm_repository/
image_url: https://img.youtube.com/vi/B6K373-pAgw/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
- title: Escalation Policies
body: |
Being on-call is a stressful, 24/7 job. It's possible to miss a notification despite your best efforts and intentions. Teams that maintain critical systems can't afford to miss alerts for outages or service disruptions. Escalation policies are a safety net for these situations. Escalation policies contain time-boxed steps that automatically page a responder in the next escalation step if the responder in the step before didn't respond. To protect your company from missed critical alerts, create an escalation policy in the GitLab project where you manage on-call schedules.
In GitLab 14.1, users can create, view, or delete escalation policies.
stage: Monitor
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/operations/incident_management/escalation_policies.html
image_url: https://img.youtube.com/vi/-1MuKzWJXKQ/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
- title: CI/CD Tunnel for Kubernetes clusters
body: |
Until now, connecting Kubernetes clusters to GitLab CI/CD required users to open up their clusters towards GitLab. Some organizations do not encourage opening up their firewall externally due to security concerns.
GitLab now ships with a CI/CD Tunnel that connects GitLab Runners with your Kubernetes cluster using the [GitLab Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/). This enables versatile GitOps workflows where the deployment logic can be coded in the pipeline.
You and your team can safely use your preferred tool to run the deployment itself using `kubectl`, `helm`, `kpt`, `tanka`, or anything else without security concerns.
To use the tunnel, define the `kubecontext` in your CI/CD pipeline to connect with your agent. To simplify this process, we plan to [automatically inject the `kubecontext`](https://gitlab.com/gitlab-org/gitlab/-/issues/324275) into the CI/CD environment in a future iteration.
The CI/CD tunnel is currently supported only from the project where the agent was configured but we are working on [adding group-level support](https://gitlab.com/groups/gitlab-org/-/epics/5784). You can safely start using the tunnel on GitLab SaaS and self-managed instances.
stage: Configure
self-managed: true
gitlab-com: true
packages: [Premium, Ultimate]
url: https://docs.gitlab.com/ee/user/clusters/agent/ci_cd_tunnel.html
image_url: https://img.youtube.com/vi/eXxM4ScqiJs/hqdefault.jpg
published_at: 2021-07-22
release: 14.1
- title: External status checks for merge requests
body: |
You can now contact an external API to perform a status check in a merge request. This is a great way to integrate GitLab with third-party systems that:
- Run in an external system and do not have specific pipeline jobs.
- Require manual approval in another system.
In the project, APIs for the status checks can be configured (using either the GitLab UI or the GitLab API) and then when a change is made to a merge request, that API is called with various details about the merge request. The external API can then respond with a return code to indicate if the check has passed. This result is then shown in the merge request.
This allows teams to easily stay in sync and makes it easy to see that merge requests have met external requirements before being merged, adding an extra method to ensure compliance requirements are met.
stage: Manage
self-managed: true
gitlab-com: true
packages: [Ultimate]
url: https://docs.gitlab.com/ee/user/project/merge_requests/status_checks.html
image_url: https://about.gitlab.com/images/14_1/status-checks-pending.png
published_at: 2021-07-22
release: 14.1
- title: Pronouns viewable in user profile snapshot
body: |
You can now see pronouns on the snapshot view of a user profile when you hover over someone's name on an issue or merge request. This helps users better respond to comments using the correct pronouns without needing to navigate to the user's profile.
stage: Manage
self-managed: true
gitlab-com: true
packages: [Free, Premium, Ultimate]
url: 'https://docs.gitlab.com/ee/user/profile/#add-your-gender-pronouns'
image_url: https://about.gitlab.com/images/14_1/pronouns.png
published_at: 2021-07-22
release: 14.1

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
class ChangeApplicationSettingTermsNotNull < ActiveRecord::Migration[6.1]
def up
execute("UPDATE application_setting_terms SET terms = '' WHERE terms IS NULL")
change_column_null :application_setting_terms, :terms, false
end
def down
change_column_null :application_setting_terms, :terms, true
end
end

View File

@ -7,7 +7,8 @@ class BackfillCiBuildTraceSectionsForBigintConversion < ActiveRecord::Migration[
COLUMN = :build_id
def up
backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100, primary_key: COLUMN
# No-op to disable the migration:
# backfill_conversion_of_integer_to_bigint TABLE, COLUMN, batch_size: 15000, sub_batch_size: 100, primary_key: COLUMN
end
def down

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class RevertBackfillCiBuildTraceSectionsForBigintConversion < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
TABLE = :ci_build_trace_sections
COLUMN = :build_id
def up
revert_backfill_conversion_of_integer_to_bigint TABLE, COLUMN, primary_key: COLUMN
end
def down
# no-op
end
end

View File

@ -0,0 +1 @@
6096780be4fae007485f150a019fc4555153e4b22b893d5fe29be36834d970a9

View File

@ -0,0 +1 @@
c9057cb28d2576551eafe78998023742018fa8351f2e550b7e35832a5509d21c

View File

@ -9216,7 +9216,7 @@ ALTER SEQUENCE appearances_id_seq OWNED BY appearances.id;
CREATE TABLE application_setting_terms (
id integer NOT NULL,
cached_markdown_version integer,
terms text,
terms text NOT NULL,
terms_html text
);

View File

@ -89,6 +89,32 @@ module Gitlab
job.user
end
def find_user_from_basic_auth_password
return unless has_basic_credentials?(current_request)
login, password = user_name_and_password(current_request)
return if ::Gitlab::Auth::CI_JOB_USER == login
Gitlab::Auth.find_with_user_password(login, password)
end
def find_user_from_lfs_token
return unless has_basic_credentials?(current_request)
login, token = user_name_and_password(current_request)
user = User.by_login(login)
user if user && Gitlab::LfsToken.new(user).token_valid?(token)
end
def find_user_from_personal_access_token
return unless access_token
validate_access_token!
access_token&.user || raise(UnauthorizedError)
end
# We allow Private Access Tokens with `api` scope to be used by web
# requests on RSS feeds or ICS files for backwards compatibility.
# It is also used by GraphQL/API requests.
@ -308,6 +334,10 @@ module Gitlab
current_request.path.starts_with?(Gitlab::Utils.append_path(Gitlab.config.gitlab.relative_url_root, '/api/'))
end
def git_request?
Gitlab::PathRegex.repository_git_route_regex.match?(current_request.path)
end
def archive_request?
current_request.path.include?('/-/archive/')
end

View File

@ -34,7 +34,10 @@ module Gitlab
find_user_from_feed_token(request_format) ||
find_user_from_static_object_token(request_format) ||
find_user_from_basic_auth_job ||
find_user_from_job_token
find_user_from_job_token ||
find_user_from_lfs_token ||
find_user_from_personal_access_token ||
find_user_from_basic_auth_password
rescue Gitlab::Auth::AuthenticationError
nil
end
@ -58,7 +61,7 @@ module Gitlab
def route_authentication_setting
@route_authentication_setting ||= {
job_token_allowed: api_request?,
basic_auth_personal_access_token: api_request?
basic_auth_personal_access_token: api_request? || git_request?
}
end
end

View File

@ -708,6 +708,122 @@ RSpec.describe Gitlab::Auth::AuthFinders do
end
end
describe '#find_user_from_basic_auth_password' do
subject { find_user_from_basic_auth_password }
context 'when the request does not have AUTHORIZATION header' do
it { is_expected.to be_nil }
end
it 'returns nil without user and password' do
set_basic_auth_header(nil, nil)
is_expected.to be_nil
end
it 'returns nil without password' do
set_basic_auth_header('some-user', nil)
is_expected.to be_nil
end
it 'returns nil without user' do
set_basic_auth_header(nil, 'password')
is_expected.to be_nil
end
it 'returns nil with CI username' do
set_basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'password')
is_expected.to be_nil
end
it 'returns nil with wrong password' do
set_basic_auth_header(user.username, 'wrong-password')
is_expected.to be_nil
end
it 'returns user with correct credentials' do
set_basic_auth_header(user.username, user.password)
is_expected.to eq(user)
end
end
describe '#find_user_from_lfs_token' do
subject { find_user_from_lfs_token }
context 'when the request does not have AUTHORIZATION header' do
it { is_expected.to be_nil }
end
it 'returns nil without user and token' do
set_basic_auth_header(nil, nil)
is_expected.to be_nil
end
it 'returns nil without token' do
set_basic_auth_header('some-user', nil)
is_expected.to be_nil
end
it 'returns nil without user' do
set_basic_auth_header(nil, 'token')
is_expected.to be_nil
end
it 'returns nil with wrong token' do
set_basic_auth_header(user.username, 'wrong-token')
is_expected.to be_nil
end
it 'returns user with correct user and correct token' do
lfs_token = Gitlab::LfsToken.new(user).token
set_basic_auth_header(user.username, lfs_token)
is_expected.to eq(user)
end
it 'returns nil with wrong user and correct token' do
lfs_token = Gitlab::LfsToken.new(user).token
other_user = create(:user)
set_basic_auth_header(other_user.username, lfs_token)
is_expected.to be_nil
end
end
describe '#find_user_from_personal_access_token' do
subject { find_user_from_personal_access_token }
it 'returns nil without access token' do
allow_any_instance_of(described_class).to receive(:access_token).and_return(nil)
is_expected.to be_nil
end
it 'returns user with correct access token' do
personal_access_token = create(:personal_access_token, user: user)
allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token)
is_expected.to eq(user)
end
it 'returns exception if access token has no user' do
personal_access_token = create(:personal_access_token, user: user)
allow_any_instance_of(described_class).to receive(:access_token).and_return(personal_access_token)
allow_any_instance_of(PersonalAccessToken).to receive(:user).and_return(nil)
expect { subject }.to raise_error(Gitlab::Auth::UnauthorizedError)
end
end
describe '#validate_access_token!' do
subject { validate_access_token! }

View File

@ -45,6 +45,9 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
let!(:feed_token_user) { build(:user) }
let!(:static_object_token_user) { build(:user) }
let!(:job_token_user) { build(:user) }
let!(:lfs_token_user) { build(:user) }
let!(:basic_auth_access_token_user) { build(:user) }
let!(:basic_auth_password_user) { build(:user) }
it 'returns access_token user first' do
allow_any_instance_of(described_class).to receive(:find_user_from_web_access_token)
@ -78,6 +81,30 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
expect(subject.find_sessionless_user(:api)).to eq job_token_user
end
it 'returns lfs_token user if no job_token user found' do
allow_any_instance_of(described_class)
.to receive(:find_user_from_lfs_token)
.and_return(lfs_token_user)
expect(subject.find_sessionless_user(:api)).to eq lfs_token_user
end
it 'returns basic_auth_access_token user if no lfs_token user found' do
allow_any_instance_of(described_class)
.to receive(:find_user_from_personal_access_token)
.and_return(basic_auth_access_token_user)
expect(subject.find_sessionless_user(:api)).to eq basic_auth_access_token_user
end
it 'returns basic_auth_access_password user if no basic_auth_access_token user found' do
allow_any_instance_of(described_class)
.to receive(:find_user_from_basic_auth_password)
.and_return(basic_auth_password_user)
expect(subject.find_sessionless_user(:api)).to eq basic_auth_password_user
end
it 'returns nil if no user found' do
expect(subject.find_sessionless_user(:api)).to be_blank
end
@ -194,4 +221,27 @@ RSpec.describe Gitlab::Auth::RequestAuthenticator do
expect(subject.runner).to be_blank
end
end
describe '#route_authentication_setting' do
using RSpec::Parameterized::TableSyntax
where(:script_name, :expected_job_token_allowed, :expected_basic_auth_personal_access_token) do
'/api/endpoint' | true | true
'/namespace/project.git' | false | true
'/web/endpoint' | false | false
end
with_them do
before do
env['SCRIPT_NAME'] = script_name
end
it 'returns correct settings' do
expect(subject.send(:route_authentication_setting)).to eql({
job_token_allowed: expected_job_token_allowed,
basic_auth_personal_access_token: expected_basic_auth_personal_access_token
})
end
end
end
end

View File

@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ApplicationSetting::Term do
it { is_expected.to nullify_if_blank(:terms) }
it { is_expected.to validate_presence_of(:terms) }
describe '.latest' do
it 'finds the latest terms' do

View File

@ -677,4 +677,118 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
it_behaves_like 'reject requests over the rate limit'
end
end
describe 'Gitlab::RackAttack::Request#unauthenticated?' do
let_it_be(:url) { "/api/v4/projects" }
let_it_be(:user) { create(:user) }
def expect_unauthenticated_request
expect_next_instance_of(Rack::Attack::Request) do |instance|
expect(instance.unauthenticated?).to be true
end
end
def expect_authenticated_request
expect_next_instance_of(Rack::Attack::Request) do |instance|
expect(instance.unauthenticated?).to be false
end
end
before do
settings_to_set[:throttle_unauthenticated_enabled] = true
stub_application_setting(settings_to_set)
end
context 'without authentication' do
it 'request is unauthenticated' do
expect_unauthenticated_request
get url
end
end
context 'authenticated by a runner token' do
let_it_be(:runner) { create(:ci_runner) }
it 'request is authenticated' do
expect_authenticated_request
get url, params: { token: runner.token }
end
end
context 'authenticated with personal access token' do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
it 'request is authenticated by token in query string' do
expect_authenticated_request
get url, params: { private_token: personal_access_token.token }
end
it 'request is authenticated by token in the headers' do
expect_authenticated_request
get url, headers: personal_access_token_headers(personal_access_token)
end
it 'request is authenticated by token in the OAuth headers' do
expect_authenticated_request
get url, headers: oauth_token_headers(personal_access_token)
end
it 'request is authenticated by token in basic auth' do
expect_authenticated_request
get url, headers: basic_auth_headers(user, personal_access_token)
end
end
context 'authenticated with OAuth token' do
let(:application) { Doorkeeper::Application.create!(name: "MyApp", redirect_uri: "https://app.com", owner: user) }
let(:oauth_token) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: "api") }
it 'request is authenticated by token in query string' do
expect_authenticated_request
get url, params: { access_token: oauth_token.token }
end
it 'request is authenticated by token in the headers' do
expect_authenticated_request
get url, headers: oauth_token_headers(oauth_token)
end
end
context 'authenticated with lfs token' do
it 'request is authenticated by token in basic auth' do
lfs_token = Gitlab::LfsToken.new(user)
encoded_login = ["#{user.username}:#{lfs_token.token}"].pack('m0')
expect_authenticated_request
get url, headers: { 'AUTHORIZATION' => "Basic #{encoded_login}" }
end
end
context 'authenticated with regular login' do
it 'request is authenticated after login' do
login_as(user)
expect_authenticated_request
get url
end
it 'request is authenticated by credentials in basic auth' do
encoded_login = ["#{user.username}:#{user.password}"].pack('m0')
expect_authenticated_request
get url, headers: { 'AUTHORIZATION' => "Basic #{encoded_login}" }
end
end
end
end

View File

@ -23,8 +23,8 @@ RSpec.describe ApplicationSettings::UpdateService do
context 'when the passed terms are blank' do
let(:params) { { terms: '' } }
it 'does create terms' do
expect { subject.execute }.to change { ApplicationSetting::Term.count }.by(1)
it 'does not create terms' do
expect { subject.execute }.not_to change { ApplicationSetting::Term.count }
end
end