Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
875662ef7b
commit
dd5d37c7f6
18 changed files with 236 additions and 135 deletions
2
Gemfile
2
Gemfile
|
@ -121,7 +121,7 @@ gem 'carrierwave', '~> 1.3'
|
|||
gem 'mini_magick', '~> 4.10.1'
|
||||
|
||||
# for backups
|
||||
gem 'fog-aws', '~> 3.12'
|
||||
gem 'fog-aws', '~> 3.14'
|
||||
# Locked until fog-google resolves https://github.com/fog/fog-google/issues/421.
|
||||
# Also see config/initializers/fog_core_patch.rb.
|
||||
gem 'fog-core', '= 2.1.0'
|
||||
|
|
|
@ -409,7 +409,7 @@ GEM
|
|||
fog-json
|
||||
ipaddress (~> 0.8)
|
||||
xml-simple (~> 1.1)
|
||||
fog-aws (3.12.0)
|
||||
fog-aws (3.14.0)
|
||||
fog-core (~> 2.1)
|
||||
fog-json (~> 1.1)
|
||||
fog-xml (~> 0.1)
|
||||
|
@ -1488,7 +1488,7 @@ DEPENDENCIES
|
|||
flipper-active_support_cache_store (~> 0.21.0)
|
||||
flowdock (~> 0.7)
|
||||
fog-aliyun (~> 0.3)
|
||||
fog-aws (~> 3.12)
|
||||
fog-aws (~> 3.14)
|
||||
fog-core (= 2.1.0)
|
||||
fog-google (~> 1.15)
|
||||
fog-local (~> 0.6)
|
||||
|
|
|
@ -97,14 +97,17 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="discussion-header note-wrapper">
|
||||
<div v-once class="timeline-icon gl-align-self-start gl-flex-shrink-0 gl-flex-shrink gl-mr-4">
|
||||
<div class="discussion-header gl-display-flex gl-align-items-center gl-p-5">
|
||||
<div
|
||||
v-once
|
||||
class="timeline-icon gl-align-self-start gl-flex-shrink-0 gl-flex-shrink gl-ml-3 gl-mr-4"
|
||||
>
|
||||
<user-avatar-link
|
||||
v-if="author"
|
||||
:link-href="author.path"
|
||||
:img-src="author.avatar_url"
|
||||
:img-alt="author.name"
|
||||
:img-size="32"
|
||||
:img-size="24"
|
||||
:img-css-classes="'gl-mr-0!' /* NOTE: this is needed only while we migrate user-avatar-image to GlAvatar (https://gitlab.com/groups/gitlab-org/-/epics/7731) */"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -565,7 +565,6 @@ $system-note-svg-size: 16px;
|
|||
}
|
||||
|
||||
.discussion-header {
|
||||
min-height: $line-height-base * 2em;
|
||||
box-sizing: content-box;
|
||||
|
||||
.note-header-info {
|
||||
|
@ -580,6 +579,7 @@ $system-note-svg-size: 16px;
|
|||
&.note-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-right: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@ module Resolvers
|
|||
def cutoff(id, sha)
|
||||
if sha.present? || id.present?
|
||||
specific_version(id, sha)
|
||||
elsif at_version = context[:at_version_argument]
|
||||
by_id(at_version) # See: DesignsResolver
|
||||
else
|
||||
:unconstrained
|
||||
end
|
||||
|
|
|
@ -249,7 +249,7 @@ module Integrations
|
|||
|
||||
ref = data[:ref] || data.dig(:object_attributes, :ref)
|
||||
return true if ref.blank? # No need to check protected branches when there is no ref
|
||||
return true if Gitlab::Git.tag_ref?(ref) # Skip protected branch check because it doesn't support tags
|
||||
return true if Gitlab::Git.tag_ref?(project.repository.expand_ref(ref) || ref) # Skip protected branch check because it doesn't support tags
|
||||
|
||||
notify_for_branch?(data)
|
||||
end
|
||||
|
|
|
@ -117,6 +117,8 @@ module MergeRequests
|
|||
if delete_source_branch?
|
||||
MergeRequests::DeleteSourceBranchWorker.perform_async(@merge_request.id, @merge_request.source_branch_sha, branch_deletion_user.id)
|
||||
end
|
||||
|
||||
merge_request_merge_param
|
||||
end
|
||||
|
||||
def clean_merge_jid
|
||||
|
@ -135,6 +137,12 @@ module MergeRequests
|
|||
@merge_request.can_remove_source_branch?(branch_deletion_user)
|
||||
end
|
||||
|
||||
def merge_request_merge_param
|
||||
if @merge_request.can_remove_source_branch?(branch_deletion_user) && !params.fetch('should_remove_source_branch', nil).nil?
|
||||
@merge_request.update(merge_params: @merge_request.merge_params.merge('should_remove_source_branch' => params['should_remove_source_branch']))
|
||||
end
|
||||
end
|
||||
|
||||
def handle_merge_error(log_message:, save_message_on_model: false)
|
||||
Gitlab::AppLogger.error("MergeService ERROR: #{merge_request_info} - #{log_message}")
|
||||
@merge_request.update(merge_error: log_message) if save_message_on_model
|
||||
|
|
|
@ -34,6 +34,6 @@
|
|||
.gl-new-dropdown-item-text-wrapper
|
||||
= _('Email patches')
|
||||
%li.gl-new-dropdown-item
|
||||
= link_to merge_request_path(@merge_request, format: :diff), class: 'dropdown-item', data: { qa_selector: 'download_plain_diff_menu_item' } do
|
||||
= link_to merge_request_path(@merge_request, format: :diff), class: 'dropdown-item', download: '', data: { qa_selector: 'download_plain_diff_menu_item' } do
|
||||
.gl-new-dropdown-item-text-wrapper
|
||||
= _('Plain diff')
|
||||
|
|
|
@ -239,18 +239,19 @@ in the `connection` setting.
|
|||
|
||||
The connection settings match those provided by [fog-aws](https://github.com/fog/fog-aws):
|
||||
|
||||
| Setting | Description | Default |
|
||||
|---------------------------------|------------------------------------|---------|
|
||||
| `provider` | Always `AWS` for compatible hosts. | `AWS` |
|
||||
| `aws_access_key_id` | AWS credentials, or compatible. | |
|
||||
| `aws_secret_access_key` | AWS credentials, or compatible. | |
|
||||
| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
|
||||
| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
|
||||
| `region` | AWS region. | |
|
||||
| `host` | S3 compatible host for when not using AWS. For example, `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
|
||||
| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
|
||||
| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false`. |
|
||||
| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys. | `false` |
|
||||
| Setting | Description | Default |
|
||||
|---------------------------------------------|------------------------------------|---------|
|
||||
| `provider` | Always `AWS` for compatible hosts. | `AWS` |
|
||||
| `aws_access_key_id` | AWS credentials, or compatible. | |
|
||||
| `aws_secret_access_key` | AWS credentials, or compatible. | |
|
||||
| `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` |
|
||||
| `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` |
|
||||
| `region` | AWS region. | |
|
||||
| `host` | S3 compatible host for when not using AWS. For example, `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` |
|
||||
| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) |
|
||||
| `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false`. |
|
||||
| `use_iam_profile` | Set to `true` to use IAM profile instead of access keys. | `false` |
|
||||
| `aws_credentials_refresh_threshold_seconds` | Sets the [automatic refresh threshold](https://github.com/fog/fog-aws#controlling-credential-refresh-time-with-iam-authentication) when using temporary credentials in IAM. | `15` |
|
||||
|
||||
#### Oracle Cloud S3 connection settings
|
||||
|
||||
|
|
|
@ -152,16 +152,14 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "path=a
|
|||
--form "file=@/path/to/file" "https://gitlab.example.com/api/v4/projects/import"
|
||||
```
|
||||
|
||||
cURL doesn't support posting a file from a remote server. Importing a project from a remote server can be accomplished through something like the following:
|
||||
cURL doesn't support posting a file from a remote server. This example imports a project
|
||||
using Python's `open` method:
|
||||
|
||||
```python
|
||||
import requests
|
||||
from io import BytesIO
|
||||
|
||||
s3_file = requests.get(presigned_url)
|
||||
|
||||
url = 'https://gitlab.example.com/api/v4/projects/import'
|
||||
files = {'file': ('file.tar.gz', BytesIO(s3_file.content))}
|
||||
files = { "file": open("project_export.tar.gz", "rb") }
|
||||
data = {
|
||||
"path": "example-project",
|
||||
"namespace": "example-group"
|
||||
|
@ -293,6 +291,27 @@ curl --request POST \
|
|||
}'
|
||||
```
|
||||
|
||||
This example imports from an Amazon S3 bucket, using a module that connects to Amazon S3:
|
||||
|
||||
```python
|
||||
import requests
|
||||
from io import BytesIO
|
||||
|
||||
s3_file = requests.get(presigned_url)
|
||||
|
||||
url = 'https://gitlab.example.com/api/v4/projects/import'
|
||||
files = {'file': ('file.tar.gz', BytesIO(s3_file.content))}
|
||||
data = {
|
||||
"path": "example-project",
|
||||
"namespace": "example-group"
|
||||
}
|
||||
headers = {
|
||||
'Private-Token': "<your_access_token>"
|
||||
}
|
||||
|
||||
requests.post(url, headers=headers, data=data, files=files)
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
|
|
|
@ -508,3 +508,13 @@ the `webservice` container has the following tags:
|
|||
- `master`
|
||||
- `master-ubi8`
|
||||
- `master-fips`
|
||||
|
||||
### Testing merge requests with a FIPS pipeline
|
||||
|
||||
Merge requests that can trigger Package and QA, can trigger a FIPS package and a
|
||||
Reference Architecture test pipeline. The base image used for the trigger is
|
||||
Ubuntu 20.04 FIPS:
|
||||
|
||||
1. Trigger `package-and-qa`, if not already triggered.
|
||||
1. On the `gitlab-omnibus-mirror` child pipeline, manually trigger `Trigger:package:fips`.
|
||||
1. When the package job is complete, manually trigger the `RAT:FIPS` job.
|
||||
|
|
|
@ -409,15 +409,11 @@ module API
|
|||
# error helpers
|
||||
|
||||
def forbidden!(reason = nil)
|
||||
message = ['403 Forbidden']
|
||||
message << "- #{reason}" if reason
|
||||
render_api_error!(message.join(' '), 403)
|
||||
render_api_error_with_reason!(403, '403 Forbidden', reason)
|
||||
end
|
||||
|
||||
def bad_request!(reason = nil)
|
||||
message = ['400 Bad request']
|
||||
message << "- #{reason}" if reason
|
||||
render_api_error!(message.join(' '), 400)
|
||||
render_api_error_with_reason!(400, '400 Bad request', reason)
|
||||
end
|
||||
|
||||
def bad_request_missing_attribute!(attribute)
|
||||
|
@ -437,8 +433,8 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
def unauthorized!
|
||||
render_api_error!('401 Unauthorized', 401)
|
||||
def unauthorized!(reason = nil)
|
||||
render_api_error_with_reason!(401, '401 Unauthorized', reason)
|
||||
end
|
||||
|
||||
def not_allowed!(message = nil)
|
||||
|
@ -491,6 +487,12 @@ module API
|
|||
model.errors.messages
|
||||
end
|
||||
|
||||
def render_api_error_with_reason!(status, message, reason)
|
||||
message = [message]
|
||||
message << "- #{reason}" if reason
|
||||
render_api_error!(message.join(' '), status)
|
||||
end
|
||||
|
||||
def render_api_error!(message, status)
|
||||
render_structured_api_error!({ 'message' => message }, status)
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ module API
|
|||
installation = JiraConnectInstallation.find_by_client_key(jwt.iss_claim)
|
||||
|
||||
if !installation || !jwt.valid?(installation.shared_secret) || !jwt.verify_context_qsh_claim
|
||||
unauthorized!
|
||||
unauthorized!('JWT authentication failed')
|
||||
end
|
||||
|
||||
jira_user = installation.client.user_info(jwt.sub_claim)
|
||||
|
|
|
@ -106,14 +106,6 @@ RSpec.describe Resolvers::DesignManagement::VersionsResolver do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'by at_version in parent' do
|
||||
before do
|
||||
query_context[:at_version_argument] = first_version.to_global_id
|
||||
end
|
||||
|
||||
it_behaves_like 'a query for all_versions up to the first_version'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
RSpec.describe API::Helpers do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
subject { Class.new.include(described_class).new }
|
||||
subject(:helper) { Class.new.include(described_class).new }
|
||||
|
||||
describe '#current_user' do
|
||||
include Rack::Test::Methods
|
||||
|
@ -69,17 +69,17 @@ RSpec.describe API::Helpers do
|
|||
shared_examples 'project finder' do
|
||||
context 'when project exists' do
|
||||
it 'returns requested project' do
|
||||
expect(subject.find_project(existing_id)).to eq(project)
|
||||
expect(helper.find_project(existing_id)).to eq(project)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(subject.find_project(non_existing_id)).to be_nil
|
||||
expect(helper.find_project(non_existing_id)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when project id is not provided' do
|
||||
it 'returns nil' do
|
||||
expect(subject.find_project(nil)).to be_nil
|
||||
expect(helper.find_project(nil)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -105,7 +105,7 @@ RSpec.describe API::Helpers do
|
|||
it 'does not hit the database' do
|
||||
expect(Project).not_to receive(:find_by_full_path)
|
||||
|
||||
subject.find_project(non_existing_id)
|
||||
helper.find_project(non_existing_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -116,7 +116,7 @@ RSpec.describe API::Helpers do
|
|||
it 'does not return the project pending delete' do
|
||||
expect(Project).not_to receive(:find_by_full_path)
|
||||
|
||||
expect(subject.find_project(project_pending_delete.id)).to be_nil
|
||||
expect(helper.find_project(project_pending_delete.id)).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -126,7 +126,7 @@ RSpec.describe API::Helpers do
|
|||
it 'does not return the hidden project' do
|
||||
expect(Project).not_to receive(:find_by_full_path)
|
||||
|
||||
expect(subject.find_project(hidden_project.id)).to be_nil
|
||||
expect(helper.find_project(hidden_project.id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -138,25 +138,25 @@ RSpec.describe API::Helpers do
|
|||
shared_examples 'private project without access' do
|
||||
before do
|
||||
project.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
|
||||
allow(subject).to receive(:authenticate_non_public?).and_return(false)
|
||||
allow(helper).to receive(:authenticate_non_public?).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns not found' do
|
||||
expect(subject).to receive(:not_found!)
|
||||
expect(helper).to receive(:not_found!)
|
||||
|
||||
subject.find_project!(project.id)
|
||||
helper.find_project!(project.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
allow(subject).to receive(:initial_current_user).and_return(user)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:initial_current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'public project' do
|
||||
it 'returns requested project' do
|
||||
expect(subject.find_project!(project.id)).to eq(project)
|
||||
expect(helper.find_project!(project.id)).to eq(project)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -167,13 +167,13 @@ RSpec.describe API::Helpers do
|
|||
|
||||
context 'when user is not authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(nil)
|
||||
allow(subject).to receive(:initial_current_user).and_return(nil)
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
allow(helper).to receive(:initial_current_user).and_return(nil)
|
||||
end
|
||||
|
||||
context 'public project' do
|
||||
it 'returns requested project' do
|
||||
expect(subject.find_project!(project.id)).to eq(project)
|
||||
expect(helper.find_project!(project.id)).to eq(project)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -188,21 +188,21 @@ RSpec.describe API::Helpers do
|
|||
let(:user) { project.first_owner}
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
allow(subject).to receive(:authorized_project_scope?).and_return(true)
|
||||
allow(subject).to receive(:job_token_authentication?).and_return(false)
|
||||
allow(subject).to receive(:authenticate_non_public?).and_return(false)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:authorized_project_scope?).and_return(true)
|
||||
allow(helper).to receive(:job_token_authentication?).and_return(false)
|
||||
allow(helper).to receive(:authenticate_non_public?).and_return(false)
|
||||
end
|
||||
|
||||
shared_examples 'project finder' do
|
||||
context 'when project exists' do
|
||||
it 'returns requested project' do
|
||||
expect(subject.find_project!(existing_id)).to eq(project)
|
||||
expect(helper.find_project!(existing_id)).to eq(project)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(subject).to receive(:render_api_error!).with('404 Project Not Found', 404)
|
||||
expect(subject.find_project!(non_existing_id)).to be_nil
|
||||
expect(helper).to receive(:render_api_error!).with('404 Project Not Found', 404)
|
||||
expect(helper.find_project!(non_existing_id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -227,9 +227,9 @@ RSpec.describe API::Helpers do
|
|||
|
||||
it 'does not hit the database' do
|
||||
expect(Project).not_to receive(:find_by_full_path)
|
||||
expect(subject).to receive(:render_api_error!).with('404 Project Not Found', 404)
|
||||
expect(helper).to receive(:render_api_error!).with('404 Project Not Found', 404)
|
||||
|
||||
subject.find_project!(non_existing_id)
|
||||
helper.find_project!(non_existing_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -243,25 +243,25 @@ RSpec.describe API::Helpers do
|
|||
shared_examples 'private group without access' do
|
||||
before do
|
||||
group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
|
||||
allow(subject).to receive(:authenticate_non_public?).and_return(false)
|
||||
allow(helper).to receive(:authenticate_non_public?).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns not found' do
|
||||
expect(subject).to receive(:not_found!)
|
||||
expect(helper).to receive(:not_found!)
|
||||
|
||||
subject.find_group!(group.id)
|
||||
helper.find_group!(group.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
allow(subject).to receive(:initial_current_user).and_return(user)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:initial_current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'public group' do
|
||||
it 'returns requested group' do
|
||||
expect(subject.find_group!(group.id)).to eq(group)
|
||||
expect(helper.find_group!(group.id)).to eq(group)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -272,13 +272,13 @@ RSpec.describe API::Helpers do
|
|||
|
||||
context 'when user is not authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(nil)
|
||||
allow(subject).to receive(:initial_current_user).and_return(nil)
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
allow(helper).to receive(:initial_current_user).and_return(nil)
|
||||
end
|
||||
|
||||
context 'public group' do
|
||||
it 'returns requested group' do
|
||||
expect(subject.find_group!(group.id)).to eq(group)
|
||||
expect(helper.find_group!(group.id)).to eq(group)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -293,21 +293,21 @@ RSpec.describe API::Helpers do
|
|||
let(:user) { group.first_owner }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
allow(subject).to receive(:authorized_project_scope?).and_return(true)
|
||||
allow(subject).to receive(:job_token_authentication?).and_return(false)
|
||||
allow(subject).to receive(:authenticate_non_public?).and_return(false)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:authorized_project_scope?).and_return(true)
|
||||
allow(helper).to receive(:job_token_authentication?).and_return(false)
|
||||
allow(helper).to receive(:authenticate_non_public?).and_return(false)
|
||||
end
|
||||
|
||||
shared_examples 'group finder' do
|
||||
context 'when group exists' do
|
||||
it 'returns requested group' do
|
||||
expect(subject.find_group!(existing_id)).to eq(group)
|
||||
expect(helper.find_group!(existing_id)).to eq(group)
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
expect(subject).to receive(:render_api_error!).with('404 Group Not Found', 404)
|
||||
expect(subject.find_group!(non_existing_id)).to be_nil
|
||||
expect(helper).to receive(:render_api_error!).with('404 Group Not Found', 404)
|
||||
expect(helper.find_group!(non_existing_id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -335,25 +335,25 @@ RSpec.describe API::Helpers do
|
|||
shared_examples 'private group without access' do
|
||||
before do
|
||||
group.update_column(:visibility_level, Gitlab::VisibilityLevel.level_value('private'))
|
||||
allow(subject).to receive(:authenticate_non_public?).and_return(false)
|
||||
allow(helper).to receive(:authenticate_non_public?).and_return(false)
|
||||
end
|
||||
|
||||
it 'returns not found' do
|
||||
expect(subject).to receive(:not_found!)
|
||||
expect(helper).to receive(:not_found!)
|
||||
|
||||
subject.find_group_by_full_path!(group.full_path)
|
||||
helper.find_group_by_full_path!(group.full_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user)
|
||||
allow(subject).to receive(:initial_current_user).and_return(user)
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
allow(helper).to receive(:initial_current_user).and_return(user)
|
||||
end
|
||||
|
||||
context 'public group' do
|
||||
it 'returns requested group' do
|
||||
expect(subject.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
expect(helper.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -367,7 +367,7 @@ RSpec.describe API::Helpers do
|
|||
end
|
||||
|
||||
it 'returns requested group with access' do
|
||||
expect(subject.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
expect(helper.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -375,13 +375,13 @@ RSpec.describe API::Helpers do
|
|||
|
||||
context 'when user is not authenticated' do
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(nil)
|
||||
allow(subject).to receive(:initial_current_user).and_return(nil)
|
||||
allow(helper).to receive(:current_user).and_return(nil)
|
||||
allow(helper).to receive(:initial_current_user).and_return(nil)
|
||||
end
|
||||
|
||||
context 'public group' do
|
||||
it 'returns requested group' do
|
||||
expect(subject.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
expect(helper.find_group_by_full_path!(group.full_path)).to eq(group)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -397,13 +397,13 @@ RSpec.describe API::Helpers do
|
|||
shared_examples 'namespace finder' do
|
||||
context 'when namespace exists' do
|
||||
it 'returns requested namespace' do
|
||||
expect(subject.find_namespace(existing_id)).to eq(namespace)
|
||||
expect(helper.find_namespace(existing_id)).to eq(namespace)
|
||||
end
|
||||
end
|
||||
|
||||
context "when namespace doesn't exists" do
|
||||
it 'returns nil' do
|
||||
expect(subject.find_namespace(non_existing_id)).to be_nil
|
||||
expect(helper.find_namespace(non_existing_id)).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -427,9 +427,9 @@ RSpec.describe API::Helpers do
|
|||
let(:user1) { create(:user) }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:current_user).and_return(user1)
|
||||
allow(subject).to receive(:header).and_return(nil)
|
||||
allow(subject).to receive(:not_found!).and_raise('404 Namespace not found')
|
||||
allow(helper).to receive(:current_user).and_return(user1)
|
||||
allow(helper).to receive(:header).and_return(nil)
|
||||
allow(helper).to receive(:not_found!).and_raise('404 Namespace not found')
|
||||
end
|
||||
|
||||
context 'when namespace is group' do
|
||||
|
@ -477,7 +477,7 @@ RSpec.describe API::Helpers do
|
|||
|
||||
describe '#find_namespace!' do
|
||||
let(:namespace_finder) do
|
||||
subject.find_namespace!(namespace.id)
|
||||
helper.find_namespace!(namespace.id)
|
||||
end
|
||||
|
||||
it_behaves_like 'user namespace finder'
|
||||
|
@ -488,7 +488,7 @@ RSpec.describe API::Helpers do
|
|||
let_it_be(:other_project) { create(:project) }
|
||||
let_it_be(:job) { create(:ci_build) }
|
||||
|
||||
let(:send_authorized_project_scope) { subject.authorized_project_scope?(project) }
|
||||
let(:send_authorized_project_scope) { helper.authorized_project_scope?(project) }
|
||||
|
||||
where(:job_token_authentication, :route_setting, :feature_flag, :same_job_project, :expected_result) do
|
||||
false | false | false | false | true
|
||||
|
@ -511,9 +511,9 @@ RSpec.describe API::Helpers do
|
|||
|
||||
with_them do
|
||||
before do
|
||||
allow(subject).to receive(:job_token_authentication?).and_return(job_token_authentication)
|
||||
allow(subject).to receive(:route_authentication_setting).and_return(job_token_scope: route_setting ? :project : nil)
|
||||
allow(subject).to receive(:current_authenticated_job).and_return(job)
|
||||
allow(helper).to receive(:job_token_authentication?).and_return(job_token_authentication)
|
||||
allow(helper).to receive(:route_authentication_setting).and_return(job_token_scope: route_setting ? :project : nil)
|
||||
allow(helper).to receive(:current_authenticated_job).and_return(job)
|
||||
allow(job).to receive(:project).and_return(same_job_project ? project : other_project)
|
||||
|
||||
stub_feature_flags(ci_job_token_scope: false)
|
||||
|
@ -531,15 +531,15 @@ RSpec.describe API::Helpers do
|
|||
let(:blob) { double(name: 'foobar') }
|
||||
|
||||
let(:send_git_blob) do
|
||||
subject.send(:send_git_blob, repository, blob)
|
||||
subject.header
|
||||
helper.send(:send_git_blob, repository, blob)
|
||||
helper.header
|
||||
end
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:env).and_return({})
|
||||
allow(subject).to receive(:content_type)
|
||||
allow(subject).to receive(:header).and_return({})
|
||||
allow(subject).to receive(:body).and_return('')
|
||||
allow(helper).to receive(:env).and_return({})
|
||||
allow(helper).to receive(:content_type)
|
||||
allow(helper).to receive(:header).and_return({})
|
||||
allow(helper).to receive(:body).and_return('')
|
||||
allow(Gitlab::Workhorse).to receive(:send_git_blob)
|
||||
end
|
||||
|
||||
|
@ -572,19 +572,19 @@ RSpec.describe API::Helpers do
|
|||
it 'tracks redis hll event' do
|
||||
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
|
||||
|
||||
subject.increment_unique_values(event_name, value)
|
||||
helper.increment_unique_values(event_name, value)
|
||||
end
|
||||
|
||||
it 'logs an exception for unknown event' do
|
||||
expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
|
||||
|
||||
subject.increment_unique_values(unknown_event, value)
|
||||
helper.increment_unique_values(unknown_event, value)
|
||||
end
|
||||
|
||||
it 'does not track event for nil values' do
|
||||
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
|
||||
|
||||
subject.increment_unique_values(unknown_event, nil)
|
||||
helper.increment_unique_values(unknown_event, nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -659,21 +659,21 @@ RSpec.describe API::Helpers do
|
|||
|
||||
context 'when unmodified check passes' do
|
||||
before do
|
||||
allow(subject).to receive(:check_unmodified_since!).with(project.updated_at).and_return(true)
|
||||
allow(helper).to receive(:check_unmodified_since!).with(project.updated_at).and_return(true)
|
||||
end
|
||||
|
||||
it 'destroys given project' do
|
||||
allow(subject).to receive(:status).with(204)
|
||||
allow(subject).to receive(:body).with(false)
|
||||
allow(helper).to receive(:status).with(204)
|
||||
allow(helper).to receive(:body).with(false)
|
||||
expect(project).to receive(:destroy).and_call_original
|
||||
|
||||
expect { subject.destroy_conditionally!(project) }.to change(Project, :count).by(-1)
|
||||
expect { helper.destroy_conditionally!(project) }.to change(Project, :count).by(-1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when unmodified check fails' do
|
||||
before do
|
||||
allow(subject).to receive(:check_unmodified_since!).with(project.updated_at).and_throw(:error)
|
||||
allow(helper).to receive(:check_unmodified_since!).with(project.updated_at).and_throw(:error)
|
||||
end
|
||||
|
||||
# #destroy_conditionally! uses Grape errors which Ruby-throws a symbol, shifting execution to somewhere else.
|
||||
|
@ -683,7 +683,7 @@ RSpec.describe API::Helpers do
|
|||
it 'does not destroy given project' do
|
||||
expect(project).not_to receive(:destroy)
|
||||
|
||||
expect { subject.destroy_conditionally!(project) }.to throw_symbol(:error).and change { Project.count }.by(0)
|
||||
expect { helper.destroy_conditionally!(project) }.to throw_symbol(:error).and change { Project.count }.by(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -692,30 +692,30 @@ RSpec.describe API::Helpers do
|
|||
let(:unmodified_since_header) { Time.now.change(usec: 0) }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:headers).and_return('If-Unmodified-Since' => unmodified_since_header.to_s)
|
||||
allow(helper).to receive(:headers).and_return('If-Unmodified-Since' => unmodified_since_header.to_s)
|
||||
end
|
||||
|
||||
context 'when last modified is later than header value' do
|
||||
it 'renders error' do
|
||||
expect(subject).to receive(:render_api_error!)
|
||||
expect(helper).to receive(:render_api_error!)
|
||||
|
||||
subject.check_unmodified_since!(unmodified_since_header + 1.hour)
|
||||
helper.check_unmodified_since!(unmodified_since_header + 1.hour)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when last modified is earlier than header value' do
|
||||
it 'does not render error' do
|
||||
expect(subject).not_to receive(:render_api_error!)
|
||||
expect(helper).not_to receive(:render_api_error!)
|
||||
|
||||
subject.check_unmodified_since!(unmodified_since_header - 1.hour)
|
||||
helper.check_unmodified_since!(unmodified_since_header - 1.hour)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when last modified is equal to header value' do
|
||||
it 'does not render error' do
|
||||
expect(subject).not_to receive(:render_api_error!)
|
||||
expect(helper).not_to receive(:render_api_error!)
|
||||
|
||||
subject.check_unmodified_since!(unmodified_since_header)
|
||||
helper.check_unmodified_since!(unmodified_since_header)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -723,9 +723,9 @@ RSpec.describe API::Helpers do
|
|||
let(:unmodified_since_header) { nil }
|
||||
|
||||
it 'does not render error' do
|
||||
expect(subject).not_to receive(:render_api_error!)
|
||||
expect(helper).not_to receive(:render_api_error!)
|
||||
|
||||
subject.check_unmodified_since!(Time.now)
|
||||
helper.check_unmodified_since!(Time.now)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -733,9 +733,9 @@ RSpec.describe API::Helpers do
|
|||
let(:unmodified_since_header) { "abcd" }
|
||||
|
||||
it 'does not render error' do
|
||||
expect(subject).not_to receive(:render_api_error!)
|
||||
expect(helper).not_to receive(:render_api_error!)
|
||||
|
||||
subject.check_unmodified_since!(Time.now)
|
||||
helper.check_unmodified_since!(Time.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -810,14 +810,71 @@ RSpec.describe API::Helpers do
|
|||
|
||||
before do
|
||||
u = current_user_set ? user : nil
|
||||
subject.instance_variable_set(:@current_user, u)
|
||||
helper.instance_variable_set(:@current_user, u)
|
||||
|
||||
allow(subject).to receive(:params).and_return(params)
|
||||
allow(helper).to receive(:params).and_return(params)
|
||||
end
|
||||
|
||||
it 'returns the expected result' do
|
||||
expect(subject.order_by_similarity?(allow_unauthorized: allow_unauthorized)).to eq(expected)
|
||||
expect(helper.order_by_similarity?(allow_unauthorized: allow_unauthorized)).to eq(expected)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#render_api_error_with_reason!' do
|
||||
before do
|
||||
allow(helper).to receive(:env).and_return({})
|
||||
allow(helper).to receive(:header).and_return({})
|
||||
allow(helper).to receive(:error!)
|
||||
end
|
||||
|
||||
it 'renders error with code' do
|
||||
expect(helper).to receive(:set_status_code_in_env).with(999)
|
||||
expect(helper).to receive(:error!).with({ 'message' => 'a message - good reason' }, 999, {})
|
||||
|
||||
helper.render_api_error_with_reason!(999, 'a message', 'good reason')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#unauthorized!' do
|
||||
it 'renders 401' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(401, '401 Unauthorized', nil)
|
||||
|
||||
helper.unauthorized!
|
||||
end
|
||||
|
||||
it 'renders 401 with a reason' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(401, '401 Unauthorized', 'custom reason')
|
||||
|
||||
helper.unauthorized!('custom reason')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#forbidden!' do
|
||||
it 'renders 401' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(403, '403 Forbidden', nil)
|
||||
|
||||
helper.forbidden!
|
||||
end
|
||||
|
||||
it 'renders 401 with a reason' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(403, '403 Forbidden', 'custom reason')
|
||||
|
||||
helper.forbidden!('custom reason')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#bad_request!' do
|
||||
it 'renders 400' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(400, '400 Bad request', nil)
|
||||
|
||||
helper.bad_request!
|
||||
end
|
||||
|
||||
it 'renders 401 with a reason' do
|
||||
expect(helper).to receive(:render_api_error_with_reason!).with(400, '400 Bad request', 'custom reason')
|
||||
|
||||
helper.bad_request!('custom reason')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -41,6 +41,7 @@ RSpec.describe API::Integrations::JiraConnect::Subscriptions do
|
|||
post_subscriptions
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
expect(json_response).to eq('message' => '401 Unauthorized - JWT authentication failed')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2645,6 +2645,7 @@ RSpec.describe API::MergeRequests do
|
|||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(source_repository.branch_exists?(source_branch)).to be false
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2663,6 +2664,7 @@ RSpec.describe API::MergeRequests do
|
|||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(source_repository.branch_exists?(source_branch)).to be false
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be nil
|
||||
end
|
||||
|
||||
it 'does not remove the source branch' do
|
||||
|
@ -2673,6 +2675,7 @@ RSpec.describe API::MergeRequests do
|
|||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(source_repository.branch_exists?(source_branch)).to be_truthy
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -263,10 +263,13 @@ RSpec.describe MergeRequests::MergeService do
|
|||
merge_request.update_attribute(:merge_params, { 'force_remove_source_branch' => '1' })
|
||||
end
|
||||
|
||||
# Not a real use case. When a merger merges a MR , merge param 'should_remove_source_branch' is defined
|
||||
it 'removes the source branch using the author user' do
|
||||
expect(::MergeRequests::DeleteSourceBranchWorker).to receive(:perform_async).with(merge_request.id, merge_request.source_branch_sha, merge_request.author.id)
|
||||
|
||||
service.execute(merge_request)
|
||||
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be nil
|
||||
end
|
||||
|
||||
context 'when the merger set the source branch not to be removed' do
|
||||
|
@ -276,6 +279,8 @@ RSpec.describe MergeRequests::MergeService do
|
|||
expect(::MergeRequests::DeleteSourceBranchWorker).not_to receive(:perform_async)
|
||||
|
||||
service.execute(merge_request)
|
||||
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -289,6 +294,8 @@ RSpec.describe MergeRequests::MergeService do
|
|||
expect(::MergeRequests::DeleteSourceBranchWorker).to receive(:perform_async).with(merge_request.id, merge_request.source_branch_sha, user.id)
|
||||
|
||||
service.execute(merge_request)
|
||||
|
||||
expect(merge_request.reload.should_remove_source_branch?).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue