Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-05-18 21:10:16 +00:00
parent 042cd704b8
commit 039b920db3
43 changed files with 495 additions and 73 deletions

View file

@ -72,8 +72,6 @@ Rails/SaveBang:
- 'ee/spec/models/visible_approvable_spec.rb'
- 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
- 'ee/spec/services/ee/boards/lists/list_service_spec.rb'

View file

@ -22,6 +22,7 @@ class SessionsController < Devise::SessionsController
prepend_before_action :check_captcha, only: [:create]
prepend_before_action :store_redirect_uri, only: [:new]
prepend_before_action :require_no_authentication_without_flash, only: [:new, :create]
prepend_before_action :check_forbidden_password_based_login, if: -> { action_name == 'create' && password_based_login? }
prepend_before_action :ensure_password_authentication_enabled!, if: -> { action_name == 'create' && password_based_login? }
before_action :auto_sign_in_with_provider, only: [:new]
@ -313,6 +314,13 @@ class SessionsController < Devise::SessionsController
def set_invite_params
@invite_email = ActionController::Base.helpers.sanitize(params[:invite_email])
end
def check_forbidden_password_based_login
if find_user&.password_based_login_forbidden?
flash[:alert] = _('You are not allowed to log in using password')
redirect_to new_user_session_path
end
end
end
SessionsController.prepend_mod_with('SessionsController')

View file

@ -19,5 +19,9 @@ module Types
field :branch_names, [GraphQL::STRING_TYPE], null: true, calls_gitaly: true,
complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
resolver: Resolvers::RepositoryBranchNamesResolver
field :disk_path, GraphQL::STRING_TYPE,
description: 'Shows a disk path of the repository.',
null: true,
authorize: :read_storage_disk_path
end
end

View file

@ -161,7 +161,7 @@ module CommitsHelper
ref,
{
merge_request: merge_request,
pipeline_status: hashed_pipeline_status(commit, ref),
pipeline_status: commit.status_for(ref),
xhr: request.xhr?,
controller: controller.controller_path,
path: @path # referred to in #link_to_browse_code
@ -242,14 +242,4 @@ module CommitsHelper
project_commit_path(project, commit)
end
end
private
def hashed_pipeline_status(commit, ref)
status = commit.status_for(ref)
return if status.nil?
Digest::SHA1.hexdigest(status.to_s)
end
end

View file

@ -14,6 +14,7 @@ module Ci
belongs_to :project
scope :by_project_and_keys, -> (project, keys) { where(project_id: project.id, key_hash: keys) }
scope :deletable, -> { where('NOT EXISTS (?)', Ci::UnitTestFailure.select(1).where("#{Ci::UnitTestFailure.table_name}.unit_test_id = #{table_name}.id")) }
class << self
def find_or_create_by_batch(project, unit_test_attrs)

View file

@ -11,6 +11,8 @@ module Ci
belongs_to :unit_test, class_name: "Ci::UnitTest", foreign_key: :unit_test_id
belongs_to :build, class_name: "Ci::Build", foreign_key: :build_id
scope :deletable, -> { where('failed_at < ?', REPORT_WINDOW.ago) }
def self.recent_failures_count(project:, unit_test_keys:, date_range: REPORT_WINDOW.ago..Time.current)
joins(:unit_test)
.where(

View file

@ -649,7 +649,7 @@ class Group < Namespace
end
def access_request_approvers_to_be_notified
members.owners.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
members.owners.connected_to_user.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end
def supports_events?

View file

@ -92,11 +92,13 @@ class Member < ApplicationRecord
.reorder(nil)
end
scope :connected_to_user, -> { where.not(user_id: nil) }
# This scope is exclusively used to get the members
# that can possibly have project_authorization records
# to projects/groups.
scope :authorizable, -> do
where.not(user_id: nil)
connected_to_user
.non_request
.non_minimal_access
end

View file

@ -2454,7 +2454,7 @@ class Project < ApplicationRecord
end
def access_request_approvers_to_be_notified
members.maintainers.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
members.maintainers.connected_to_user.order_recent_sign_in.limit(ACCESS_REQUEST_APPROVERS_TO_BE_NOTIFIED_LIMIT)
end
def pages_lookup_path(trim_prefix: nil, domain: nil)

View file

@ -1121,6 +1121,11 @@ class User < ApplicationRecord
Gitlab::CurrentSettings.password_authentication_enabled_for_git? && !password_based_omniauth_user?
end
# method overriden in EE
def password_based_login_forbidden?
false
end
def can_change_username?
gitlab_config.username_changing_enabled
end

View file

@ -171,6 +171,7 @@ class ProjectPolicy < BasePolicy
rule { guest | admin }.enable :read_project_for_iids
rule { admin }.enable :update_max_artifacts_size
rule { admin }.enable :read_storage_disk_path
rule { can?(:read_all_resources) }.enable :read_confidential_issues
rule { guest }.enable :guest_access

View file

@ -31,11 +31,11 @@ module Projects
def group_members
return [] unless current_user.can?(:admin_group, project.group)
# We need `.where.not(user_id: nil)` here otherwise when a group has an
# We need `.connected_to_user` here otherwise when a group has an
# invitee, it would make the following query return 0 rows since a NULL
# user_id would be present in the subquery
# See http://stackoverflow.com/questions/129077/not-in-clause-and-null-values
non_null_user_ids = project.project_members.where.not(user_id: nil).select(:user_id)
non_null_user_ids = project.project_members.connected_to_user.select(:user_id)
GroupMembersFinder.new(project.group).execute.where.not(user_id: non_null_user_ids)
end
# rubocop: enable CodeReuse/ActiveRecord

View file

@ -0,0 +1,37 @@
# frozen_string_literal: true
module Ci
class DeleteUnitTestsService
include EachBatch
BATCH_SIZE = 100
def execute
purge_data!(Ci::UnitTestFailure)
purge_data!(Ci::UnitTest)
end
private
def purge_data!(klass)
loop do
break unless delete_batch!(klass)
end
end
# rubocop: disable CodeReuse/ActiveRecord
def delete_batch!(klass)
deleted = 0
ActiveRecord::Base.transaction do
ids = klass.deletable.lock('FOR UPDATE SKIP LOCKED').limit(BATCH_SIZE).pluck(:id)
break if ids.empty?
deleted = klass.where(id: ids).delete_all
end
deleted > 0
end
# rubocop: enable CodeReuse/ActiveRecord
end
end

View file

@ -182,6 +182,15 @@
:weight: 1
:idempotent:
:tags: []
- :name: cronjob:ci_delete_unit_tests
:worker_name: Ci::DeleteUnitTestsWorker
:feature_category: :continuous_integration
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: cronjob:ci_pipeline_artifacts_expire_artifacts
:worker_name: Ci::PipelineArtifacts::ExpireArtifactsWorker
:feature_category: :continuous_integration

View file

@ -0,0 +1,18 @@
# frozen_string_literal: true
module Ci
class DeleteUnitTestsWorker
include ApplicationWorker
# rubocop:disable Scalability/CronWorkerContext
# This worker does not perform work scoped to a context
include CronjobQueue
# rubocop:enable Scalability/CronWorkerContext
feature_category :continuous_integration
idempotent!
def perform
Ci::DeleteUnitTestsService.new.execute
end
end
end

View file

@ -0,0 +1,5 @@
---
title: Add repository diskPath parameter to GraphQL API
merge_request: 61725
author:
type: added

View file

@ -0,0 +1,5 @@
---
title: Filter out unconnected-to-user members from receiving on access request emails
merge_request: 61819
author:
type: fixed

View file

@ -1,5 +0,0 @@
---
title: Add duplicated gin trigram index on notes table (note) to replace existing
merge_request: 61430
author:
type: performance

View file

@ -0,0 +1,5 @@
---
title: Add cron worker for cleaning up unit test tables
merge_request: 61463
author:
type: added

View file

@ -572,6 +572,9 @@ Settings.cron_jobs['ssh_keys_expiring_soon_notification_worker']['job_class'] =
Settings.cron_jobs['users_deactivate_dormant_users_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['users_deactivate_dormant_users_worker']['cron'] ||= '21,42 0-4 * * *'
Settings.cron_jobs['users_deactivate_dormant_users_worker']['job_class'] = 'Users::DeactivateDormantUsersWorker'
Settings.cron_jobs['ci_delete_unit_tests_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ci_delete_unit_tests_worker']['cron'] ||= '0 0 * * *'
Settings.cron_jobs['ci_delete_unit_tests_worker']['job_class'] = 'Ci::DeleteUnitTestsWorker'
Gitlab.com do
Settings.cron_jobs['batched_background_migrations_worker'] ||= Settingslogic.new({})

View file

@ -1,26 +0,0 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class CreateIndexOnNotesNote < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DUPLICATE_INDEX_NAME = 'index_notes_on_note_gin_trigram'
CURRENT_INDEX_NAME = 'index_notes_on_note_trigram'
disable_ddl_transaction!
# https://gitlab.com/gitlab-org/gitlab/-/issues/218410#note_565624409
# We are having troubles with the index, and some inserts are taking a long time
# so in this migration we are recreating the index
def up
add_concurrent_index :notes, :note, name: DUPLICATE_INDEX_NAME, using: :gin, opclass: :gin_trgm_ops
remove_concurrent_index_by_name :notes, CURRENT_INDEX_NAME
end
def down
add_concurrent_index :notes, :note, name: CURRENT_INDEX_NAME, using: :gin, opclass: :gin_trgm_ops
remove_concurrent_index_by_name :notes, DUPLICATE_INDEX_NAME
end
end

View file

@ -1 +0,0 @@
2d11da499f49964f37cc0a2c541cf58182416ae7b6b0e762a135b327099de1a4

View file

@ -23674,7 +23674,7 @@ CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
CREATE INDEX index_notes_on_note_gin_trigram ON notes USING gin (note gin_trgm_ops);
CREATE INDEX index_notes_on_note_trigram ON notes USING gin (note gin_trgm_ops);
CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);

View file

@ -11926,6 +11926,7 @@ Represents the source code attached to a release in a particular format.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="repositorydiskpath"></a>`diskPath` | [`String`](#string) | Shows a disk path of the repository. |
| <a id="repositoryempty"></a>`empty` | [`Boolean!`](#boolean) | Indicates repository has no visible content. |
| <a id="repositoryexists"></a>`exists` | [`Boolean!`](#boolean) | Indicates a corresponding Git repository exists on disk. |
| <a id="repositoryrootref"></a>`rootRef` | [`String`](#string) | Default branch of the repository. |

View file

@ -59,6 +59,13 @@ If you have other target branches, include them in your regex. (See [Enabling pu
The default branch also defaults to being a [protected branch](../user/project/protected_branches.md),
which already limits users from pushing directly.
Some example regular expressions you can use in push rules:
- `^JIRA-` Branches must start with `JIRA-`.
- `-JIRA$` Branches must end with `-JIRA`.
- `^[a-z0-9\\-]{4,15}$` Branches must be between `4` and `15` characters long,
accepting only lowercase letters, numbers and dashes.
#### Default restricted branch names
> Introduced in GitLab 12.10.

View file

@ -1160,6 +1160,56 @@ The API Fuzzing engine outputs an error message when it cannot establish a conne
- Remove the `FUZZAPI_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the API Fuzzing CI/CD template. We recommend this method instead of manually setting a value.
- If removing the variable is not possible, check to see if this value has changed in the latest version of the [API Fuzzing CI/CD template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/API-Fuzzing.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
### Application cannot determine the base URL for the target API
The API Fuzzing analyzer outputs an error message when it cannot determine the target API after inspecting the OpenAPI document. This error message is shown when the target API has not been set in the `.gitlab-ci.yml`file, it is not available in the `environment_url.txt` file, and it could not be computed using the OpenAPI document.
There is an order of precedence in which the API Fuzzing analyzer tries to get the target API when checking the different sources. First, it will try to use the `FUZZAPI_TARGET_URL`. If the environment variable has not been set, then the API Fuzzing analyzer will attempt to use the `environment_url.txt` file. If there is no file `environment_url.txt`, the API Fuzzing analyzer will then use the OpenAPI document contents and the URL provided in `FUZZAPI_OPENAPI` (if a URL is provided) to try to compute the target API.
The best-suited solution will depend on whether or not your target API changes for each deployment. In static environments, the target API is the same for each deployment, in this case please refer to the [static environment solution](#static-environment-solution). If the target API changes for each deployment a [dynamic environment solution](#dynamic-environment-solutions) should be applied.
#### Static environment solution
This solution is for pipelines in which the target API URL doesn't change (is static).
**Add environmental variable**
For environments where the target API remains the same, we recommend you specify the target URL by using the `FUZZAPI_TARGET_URL` environment variable. In your `.gitlab-ci.yml` file, add a variable `FUZZAPI_TARGET_URL`. The variable must be set to the base URL of API testing target. For example:
```yaml
include:
- template: API-Fuzzing.gitlab-ci.yml
variables:
FUZZAPI_TARGET_URL: http://test-deployment/
FUZZAPI_OPENAPI: test-api-specification.json
```
#### Dynamic environment solutions
In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend to use the `environment_url.txt` file when dealing with dynamic environments.
**Use environment_url.txt**
To support dynamic environments in which the target API URL changes during each pipeline, API Fuzzing supports the use of an `environment_url.txt` file that contains the URL to use. This file is not checked into the repository, instead it's created during the pipeline by the job that deploys the test target and collected as an artifact that can be used by later jobs in the pipeline. The job that creates the `environment_url.txt` file must run before the API Fuzzing job.
1. Modify the test target deployment job adding the base URL in an `environment_url.txt` file at the root of your project.
1. Modify the test target deployment job collecting the `environment_url.txt` as an artifact.
Example:
```yaml
deploy-test-target:
script:
# Perform deployment steps
# Create environment_url.txt (example)
- echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.example.org > environment_url.txt
artifacts:
paths:
- environment_url.txt
```
<!--
### Target Container

View file

@ -1076,6 +1076,56 @@ The DAST API engine outputs an error message when it cannot establish a connecti
- Remove the `DAST_API_API` variable from the `.gitlab-ci.yml` file. The value will be inherited from the DAST API CI/CD template. We recommend this method instead of manually setting a value.
- If removing the variable is not possible, check to see if this value has changed in the latest version of the [DAST API CI/CD template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/DAST-API.gitlab-ci.yml). If so, update the value in the `.gitlab-ci.yml` file.
### Application cannot determine the base URL for the target API
The DAST API engine outputs an error message when it cannot determine the target API after inspecting the OpenAPI document. This error message is shown when the target API has not been set in the `.gitlab-ci.yml` file, it is not available in the `environment_url.txt` file, and it could not be computed using the OpenAPI document.
There is a order of precedence in which the DAST API engine tries to get the target API when checking the different sources. First, it will try to use the `DAST_API_TARGET_URL`. If the environment variable has not been set, then the DAST API engine will attempt to use the `environment_url.txt` file. If there is no file `environment_url.txt`, then the DAST API engine will use the OpenAPI document contents and the URL provided in `DAST_API_OPENAPI` (if a URL is provided) to try to compute the target API.
The best-suited solution will depend on whether or not your target API changes for each deployment. In static environments, the target API is the same for each deployment, in this case please refer to the [static environment solution](#static-environment-solution). If the target API changes for each deployment a [dynamic environment solution](#dynamic-environment-solutions) should be applied.
#### Static environment solution
This solution is for pipelines in which the target API URL doesn't change (is static).
**Add environmental variable**
For environments where the target API remains the same, we recommend you specify the target URL by using the `DAST_API_TARGET_URL` environment variable. In your `.gitlab-ci.yml`, add a variable `DAST_API_TARGET_URL`. The variable must be set to the base URL of API testing target. For example:
```yaml
include:
- template: DAST-API.gitlab-ci.yml
variables:
DAST_API_TARGET_URL: http://test-deployment/
DAST_API_OPENAPI: test-api-specification.json
```
#### Dynamic environment solutions
In a dynamic environment your target API changes for each different deployment. In this case, there is more than one possible solution, we recommend you use the `environment_url.txt` file when dealing with dynamic environments.
**Use environment_url.txt**
To support dynamic environments in which the target API URL changes during each pipeline, DAST API engine supports the use of an `environment_url.txt` file that contains the URL to use. This file is not checked into the repository, instead it's created during the pipeline by the job that deploys the test target and collected as an artifact that can be used by later jobs in the pipeline. The job that creates the `environment_url.txt` file must run before the DAST API engine job.
1. Modify the test target deployment job adding the base URL in an `environment_url.txt` file at the root of your project.
1. Modify the test target deployment job collecting the `environment_url.txt` as an artifact.
Example:
```yaml
deploy-test-target:
script:
# Perform deployment steps
# Create environment_url.txt (example)
- echo http://${CI_PROJECT_ID}-${CI_ENVIRONMENT_SLUG}.example.org > environment_url.txt
artifacts:
paths:
- environment_url.txt
```
## Glossary
- Assert: Assertions are detection modules used by checks to trigger a vulnerability. Many assertions have

View file

@ -68,8 +68,8 @@ time as pushing changes:
| `merge_request.description="<description>"` | Set the description of the merge request. Ex: `git push -o merge_request.description="The description I want"`. | [12.2](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/64320) |
| `merge_request.label="<label>"` | Add labels to the merge request. If the label does not exist, it is created. For example, for two labels: `git push -o merge_request.label="label1" -o merge_request.label="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
| `merge_request.unlabel="<label>"` | Remove labels from the merge request. For example, for two labels: `git push -o merge_request.unlabel="label1" -o merge_request.unlabel="label2"`. | [12.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31831) |
| `merge_request.assign="<user>"` | Assign users to the merge request. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [12.9](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/XXXXX) |
| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [12.9](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/XXXXX) |
| `merge_request.assign="<user>"` | Assign users to the merge request. For example, for two users: `git push -o merge_request.assign="user1" -o merge_request.assign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
| `merge_request.unassign="<user>"` | Remove assigned users from the merge request. For example, for two users: `git push -o merge_request.unassign="user1" -o merge_request.unassign="user2"`. | [13.10](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25904) |
If you use a push option that requires text with spaces in it, you need to enclose it
in quotes (`"`). You can omit the quotes if there are no spaces. Some examples:

View file

@ -18,7 +18,7 @@ module API
# rubocop: disable CodeReuse/ActiveRecord
def retrieve_members(source, params:, deep: false)
members = deep ? find_all_members(source) : source_members(source).where.not(user_id: nil)
members = deep ? find_all_members(source) : source_members(source).connected_to_user
members = members.includes(:user)
members = members.references(:user).merge(User.search(params[:query])) if params[:query].present?
members = members.where(user_id: params[:user_ids]) if params[:user_ids].present?

View file

@ -9,6 +9,7 @@ module Gitlab
class Authentication < Gitlab::Auth::OAuth::Authentication
def login(login, password)
return false unless Gitlab::CurrentSettings.password_authentication_enabled_for_git?
return false if user.password_based_login_forbidden?
return user if user&.valid_password?(password)
end

View file

@ -11,6 +11,8 @@ module Gitlab
attr_reader :subject, :user
delegate :cache_key, to: :subject
def initialize(subject, user)
@subject = subject
@user = user

View file

@ -0,0 +1,52 @@
# Read more about the feature here: https://docs.gitlab.com/ee/user/project/merge_requests/browser_performance_testing.html
stages:
- build
- test
- deploy
- performance
browser_performance:
stage: performance
image: docker:git
variables:
URL: ''
SITESPEED_IMAGE: sitespeedio/sitespeed.io
SITESPEED_VERSION: 14.1.0
SITESPEED_OPTIONS: ''
services:
- docker:stable-dind
script:
- mkdir gitlab-exporter
# Busybox wget does not support proxied HTTPS, get the real thing.
# See https://gitlab.com/gitlab-org/gitlab/-/issues/287611.
- (env | grep -i _proxy= 2>&1 >/dev/null) && apk --no-cache add wget
- wget -O ./gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/1.1.0/index.js
- mkdir sitespeed-results
- |
function propagate_env_vars() {
CURRENT_ENV=$(printenv)
for VAR_NAME; do
echo $CURRENT_ENV | grep "${VAR_NAME}=" > /dev/null && echo "--env $VAR_NAME "
done
}
- |
docker run \
$(propagate_env_vars \
auto_proxy \
https_proxy \
http_proxy \
no_proxy \
AUTO_PROXY \
HTTPS_PROXY \
HTTP_PROXY \
NO_PROXY \
) \
--shm-size=1g --rm -v "$(pwd)":/sitespeed.io $SITESPEED_IMAGE:$SITESPEED_VERSION --plugins.add ./gitlab-exporter --cpu --outputFolder sitespeed-results $URL $SITESPEED_OPTIONS
- mv sitespeed-results/data/performance.json browser-performance.json
artifacts:
paths:
- sitespeed-results/
reports:
browser_performance: browser-performance.json

View file

@ -36988,6 +36988,9 @@ msgstr ""
msgid "You are not allowed to approve a user"
msgstr ""
msgid "You are not allowed to log in using password"
msgstr ""
msgid "You are not allowed to push into this branch. Create another branch or open a merge request."
msgstr ""

View file

@ -16,4 +16,6 @@ RSpec.describe GitlabSchema.types['Repository'] do
specify { expect(described_class).to have_graphql_field(:blobs) }
specify { expect(described_class).to have_graphql_field(:branch_names, calls_gitaly?: true, complexity: 170) }
specify { expect(described_class).to have_graphql_field(:disk_path) }
end

View file

@ -291,10 +291,11 @@ RSpec.describe CommitsHelper do
end
describe "#commit_partial_cache_key" do
subject { helper.commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
subject(:cache_key) { helper.commit_partial_cache_key(commit, ref: ref, merge_request: merge_request, request: request) }
let(:commit) { create(:commit).present(current_user: user) }
let(:commit_status) { create(:commit_status) }
let(:commit_status) { Gitlab::Ci::Status::Running.new(pipeline, user) }
let(:pipeline) { create(:ci_pipeline, :running) }
let(:user) { create(:user) }
let(:ref) { "master" }
let(:merge_request) { nil }
@ -315,12 +316,19 @@ RSpec.describe CommitsHelper do
is_expected.to include(
{
merge_request: merge_request,
pipeline_status: Digest::SHA1.hexdigest(commit_status.to_s),
pipeline_status: commit_status,
xhr: true,
controller: "commits",
path: current_path
}
)
end
describe "final cache key output" do
subject { ActiveSupport::Cache.expand_cache_key(cache_key) }
it { is_expected.to include(commit.cache_key) }
it { is_expected.to include(pipeline.cache_key) }
end
end
end

View file

@ -0,0 +1,17 @@
# frozen_string_literal: true
require "spec_helper"
RSpec.describe Gitlab::Ci::Status::Core do
let(:subj) { double("subject", cache_key: "foo") }
subject(:status) do
described_class.new(subj, double("user"))
end
describe "#cache_key" do
it "uses the subject's cache key" do
expect(status.cache_key).to eq(subj.cache_key)
end
end
end

View file

@ -2245,22 +2245,31 @@ RSpec.describe Group do
end
describe '#access_request_approvers_to_be_notified' do
it 'returns a maximum of ten, active, non_requested owners of the group in recent_sign_in descending order' do
group = create(:group, :public)
let_it_be(:group) { create(:group, :public) }
it 'returns a maximum of ten owners of the group in recent_sign_in descending order' do
users = create_list(:user, 12, :with_sign_ins)
active_owners = users.map do |user|
create(:group_member, :owner, group: group, user: user)
end
create(:group_member, :owner, :blocked, group: group)
create(:group_member, :maintainer, group: group)
create(:group_member, :access_request, :owner, group: group)
active_owners_in_recent_sign_in_desc_order = group.members_and_requesters.where(id: active_owners).order_recent_sign_in.limit(10)
active_owners_in_recent_sign_in_desc_order = group.members_and_requesters
.id_in(active_owners)
.order_recent_sign_in.limit(10)
expect(group.access_request_approvers_to_be_notified).to eq(active_owners_in_recent_sign_in_desc_order)
end
it 'returns active, non_invited, non_requested owners of the group' do
owner = create(:group_member, :owner, source: group)
create(:group_member, :maintainer, group: group)
create(:group_member, :owner, :invited, group: group)
create(:group_member, :owner, :access_request, group: group)
create(:group_member, :owner, :blocked, group: group)
expect(group.access_request_approvers_to_be_notified.to_a).to eq([owner])
end
end
describe '.groups_including_descendants_by' do

View file

@ -408,6 +408,20 @@ RSpec.describe Member do
it { is_expected.not_to include @member_with_minimal_access }
end
describe '.connected_to_user' do
subject { described_class.connected_to_user.to_a }
it { is_expected.to include @owner }
it { is_expected.to include @maintainer }
it { is_expected.to include @accepted_invite_member }
it { is_expected.to include @accepted_request_member }
it { is_expected.to include @blocked_maintainer }
it { is_expected.to include @blocked_developer }
it { is_expected.to include @requested_member }
it { is_expected.to include @member_with_minimal_access }
it { is_expected.not_to include @invited_member }
end
describe '.authorizable' do
subject { described_class.authorizable.to_a }

View file

@ -6304,23 +6304,31 @@ RSpec.describe Project, factory_default: :keep do
end
describe '#access_request_approvers_to_be_notified' do
it 'returns a maximum of ten, active, non_requested maintainers of the project in recent_sign_in descending order' do
group = create(:group, :public)
project = create(:project, group: group)
let_it_be(:project) { create(:project, group: create(:group, :public)) }
it 'returns a maximum of ten maintainers of the project in recent_sign_in descending order' do
users = create_list(:user, 12, :with_sign_ins)
active_maintainers = users.map do |user|
create(:project_member, :maintainer, user: user)
create(:project_member, :maintainer, user: user, project: project)
end
create(:project_member, :maintainer, :blocked, project: project)
create(:project_member, :developer, project: project)
create(:project_member, :access_request, :maintainer, project: project)
active_maintainers_in_recent_sign_in_desc_order = project.members_and_requesters.where(id: active_maintainers).order_recent_sign_in.limit(10)
active_maintainers_in_recent_sign_in_desc_order = project.members_and_requesters
.id_in(active_maintainers)
.order_recent_sign_in.limit(10)
expect(project.access_request_approvers_to_be_notified).to eq(active_maintainers_in_recent_sign_in_desc_order)
end
it 'returns active, non_invited, non_requested maintainers of the project' do
maintainer = create(:project_member, :maintainer, source: project)
create(:project_member, :developer, project: project)
create(:project_member, :maintainer, :invited, project: project)
create(:project_member, :maintainer, :access_request, project: project)
create(:project_member, :maintainer, :blocked, project: project)
expect(project.access_request_approvers_to_be_notified.to_a).to eq([maintainer])
end
end
describe '#pages_lookup_path' do

View file

@ -393,6 +393,34 @@ RSpec.describe ProjectPolicy do
end
end
describe 'read_storage_disk_path' do
context 'when no user' do
let(:current_user) { anonymous }
it { expect_disallowed(:read_storage_disk_path) }
end
context 'admin' do
let(:current_user) { admin }
context 'when admin mode is enabled', :enable_admin_mode do
it { expect_allowed(:read_storage_disk_path) }
end
context 'when admin mode is disabled' do
it { expect_disallowed(:read_storage_disk_path) }
end
end
%w(guest reporter developer maintainer owner).each do |role|
context role do
let(:current_user) { send(role) }
it { expect_disallowed(:read_storage_disk_path) }
end
end
end
context 'alert bot' do
let(:current_user) { User.alert_bot }

View file

@ -36,6 +36,30 @@ RSpec.describe 'getting a repository in a project' do
end
end
context 'as a non-admin' do
let(:current_user) { create(:user) }
before do
project.add_role(current_user, :developer)
end
it 'does not return diskPath' do
post_graphql(query, current_user: current_user)
expect(graphql_data['project']['repository']).not_to be_nil
expect(graphql_data['project']['repository']['diskPath']).to be_nil
end
end
context 'as an admin' do
it 'returns diskPath' do
post_graphql(query, current_user: create(:admin))
expect(graphql_data['project']['repository']).not_to be_nil
expect(graphql_data['project']['repository']['diskPath']).to eq project.disk_path
end
end
context 'when the repository is only accessible to members' do
let(:project) do
create(:project, :public, :repository, repository_access_level: ProjectFeature::PRIVATE)

View file

@ -0,0 +1,52 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::DeleteUnitTestsService do
describe '#execute' do
let!(:unit_test_1) { create(:ci_unit_test) }
let!(:unit_test_2) { create(:ci_unit_test) }
let!(:unit_test_3) { create(:ci_unit_test) }
let!(:unit_test_4) { create(:ci_unit_test) }
let!(:unit_test_1_recent_failure) { create(:ci_unit_test_failure, unit_test: unit_test_1) }
let!(:unit_test_1_old_failure) { create(:ci_unit_test_failure, unit_test: unit_test_1, failed_at: 15.days.ago) }
let!(:unit_test_2_old_failure) { create(:ci_unit_test_failure, unit_test: unit_test_2, failed_at: 15.days.ago) }
let!(:unit_test_3_old_failure) { create(:ci_unit_test_failure, unit_test: unit_test_3, failed_at: 15.days.ago) }
let!(:unit_test_4_old_failure) { create(:ci_unit_test_failure, unit_test: unit_test_4, failed_at: 15.days.ago) }
before do
stub_const("#{described_class.name}::BATCH_SIZE", 2)
described_class.new.execute
end
it 'does not delete unit test failures not older than 14 days' do
expect(unit_test_1_recent_failure.reload).to be_persisted
end
it 'deletes unit test failures older than 14 days' do
ids = [
unit_test_1_old_failure,
unit_test_2_old_failure,
unit_test_3_old_failure,
unit_test_4_old_failure
].map(&:id)
result = Ci::UnitTestFailure.where(id: ids)
expect(result).to be_empty
end
it 'deletes unit tests that have no more associated unit test failures' do
ids = [
unit_test_2,
unit_test_3,
unit_test_4
].map(&:id)
result = Ci::UnitTest.where(id: ids)
expect(result).to be_empty
end
end
end

View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::DeleteUnitTestsWorker do
let(:worker) { described_class.new }
describe '#perform' do
it 'executes a service' do
expect_next_instance_of(Ci::DeleteUnitTestsService) do |instance|
expect(instance).to receive(:execute)
end
worker.perform
end
end
it_behaves_like 'an idempotent worker' do
let!(:unit_test_1) { create(:ci_unit_test) }
let!(:unit_test_2) { create(:ci_unit_test) }
let!(:unit_test_1_recent_failure) { create(:ci_unit_test_failure, unit_test: unit_test_1) }
let!(:unit_test_2_old_failure) { create(:ci_unit_test_failure, unit_test: unit_test_2, failed_at: 15.days.ago) }
it 'only deletes old unit tests and their failures' do
subject
expect(unit_test_1.reload).to be_persisted
expect(unit_test_1_recent_failure.reload).to be_persisted
expect(Ci::UnitTest.find_by(id: unit_test_2.id)).to be_nil
expect(Ci::UnitTestFailure.find_by(id: unit_test_2_old_failure.id)).to be_nil
end
end
end