Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
3682a3a317
commit
c311ce331f
|
@ -343,3 +343,9 @@
|
||||||
box-shadow: 0 0 0 1px inset;
|
box-shadow: 0 0 0 1px inset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fix scoped label padding in cases where old markdown uses the old label structure */
|
||||||
|
.gl-label-text + .gl-label-text {
|
||||||
|
@include gl-pl-2;
|
||||||
|
@include gl-pr-3;
|
||||||
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ class RegistrationsController < Devise::RegistrationsController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_registration
|
def update_registration
|
||||||
|
return redirect_to new_user_registration_path unless current_user
|
||||||
|
|
||||||
user_params = params.require(:user).permit(:role, :setup_for_company)
|
user_params = params.require(:user).permit(:role, :setup_for_company)
|
||||||
result = ::Users::SignupService.new(current_user, user_params).execute
|
result = ::Users::SignupService.new(current_user, user_params).execute
|
||||||
|
|
||||||
|
|
|
@ -898,7 +898,11 @@ module Ci
|
||||||
def collect_test_reports!(test_reports)
|
def collect_test_reports!(test_reports)
|
||||||
test_reports.get_suite(group_name).tap do |test_suite|
|
test_reports.get_suite(group_name).tap do |test_suite|
|
||||||
each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob|
|
each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob|
|
||||||
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, test_suite, job: self)
|
Gitlab::Ci::Parsers.fabricate!(file_type).parse!(
|
||||||
|
blob,
|
||||||
|
test_suite,
|
||||||
|
job: self
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -964,6 +968,12 @@ module Ci
|
||||||
status_commit_hooks.push(block)
|
status_commit_hooks.push(block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def max_test_cases_per_report
|
||||||
|
# NOTE: This is temporary and will be replaced later by a value
|
||||||
|
# that would come from an actual application limit.
|
||||||
|
::Gitlab.com? ? 500_000 : 0
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def run_status_commit_hooks!
|
def run_status_commit_hooks!
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
module Avatarable
|
module Avatarable
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
USER_AVATAR_SIZES = [16, 20, 23, 24, 26, 32, 36, 38, 40, 48, 60, 64, 96, 120, 160].freeze
|
USER_AVATAR_SIZES = [16, 20, 23, 24, 26, 32, 36, 38, 40, 48, 60, 64, 90, 96, 120, 160].freeze
|
||||||
PROJECT_AVATAR_SIZES = [15, 40, 48, 64, 88].freeze
|
PROJECT_AVATAR_SIZES = [15, 40, 48, 64, 88].freeze
|
||||||
GROUP_AVATAR_SIZES = [15, 37, 38, 39, 40, 64, 96].freeze
|
GROUP_AVATAR_SIZES = [15, 37, 38, 39, 40, 64, 96].freeze
|
||||||
|
|
||||||
|
|
|
@ -1599,6 +1599,12 @@ class MergeRequest < ApplicationRecord
|
||||||
.find_by(sha: diff_base_sha, ref: target_branch)
|
.find_by(sha: diff_base_sha, ref: target_branch)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def merge_base_pipeline
|
||||||
|
@merge_base_pipeline ||= project.ci_pipelines
|
||||||
|
.order(id: :desc)
|
||||||
|
.find_by(sha: actual_head_pipeline.target_sha, ref: target_branch)
|
||||||
|
end
|
||||||
|
|
||||||
def discussions_rendered_on_frontend?
|
def discussions_rendered_on_frontend?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -120,7 +120,11 @@ class MergeRequestWidgetEntity < Grape::Entity
|
||||||
end
|
end
|
||||||
|
|
||||||
expose :base_path do |merge_request|
|
expose :base_path do |merge_request|
|
||||||
base_pipeline_downloadable_path_for_report_type(:codequality)
|
if use_merge_base_with_merged_results?
|
||||||
|
merge_base_pipeline_downloadable_path_for_report_type(:codequality)
|
||||||
|
else
|
||||||
|
base_pipeline_downloadable_path_for_report_type(:codequality)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -156,6 +160,16 @@ class MergeRequestWidgetEntity < Grape::Entity
|
||||||
object.base_pipeline&.present(current_user: current_user)
|
object.base_pipeline&.present(current_user: current_user)
|
||||||
&.downloadable_path_for_report_type(file_type)
|
&.downloadable_path_for_report_type(file_type)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def use_merge_base_with_merged_results?
|
||||||
|
Feature.enabled?(:merge_base_pipelines, object.target_project) &&
|
||||||
|
object.actual_head_pipeline&.merge_request_event_type == :merged_result
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_base_pipeline_downloadable_path_for_report_type(file_type)
|
||||||
|
object.merge_base_pipeline&.present(current_user: current_user)
|
||||||
|
&.downloadable_path_for_report_type(file_type)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
MergeRequestWidgetEntity.prepend_if_ee('EE::MergeRequestWidgetEntity')
|
MergeRequestWidgetEntity.prepend_if_ee('EE::MergeRequestWidgetEntity')
|
||||||
|
|
|
@ -6,7 +6,7 @@ class GroupExportWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
|
|
||||||
feature_category :importers
|
feature_category :importers
|
||||||
loggable_arguments 2
|
loggable_arguments 2
|
||||||
sidekiq_options retry: false
|
sidekiq_options retry: false, dead: false
|
||||||
|
|
||||||
def perform(current_user_id, group_id, params = {})
|
def perform(current_user_id, group_id, params = {})
|
||||||
current_user = User.find(current_user_id)
|
current_user = User.find(current_user_id)
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
class GroupImportWorker # rubocop:disable Scalability/IdempotentWorker
|
class GroupImportWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
include ApplicationWorker
|
include ApplicationWorker
|
||||||
|
|
||||||
sidekiq_options retry: false
|
sidekiq_options retry: false, dead: false
|
||||||
feature_category :importers
|
feature_category :importers
|
||||||
|
|
||||||
def perform(user_id, group_id)
|
def perform(user_id, group_id)
|
||||||
|
|
|
@ -8,7 +8,7 @@ class ProjectExportWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
worker_resource_boundary :memory
|
worker_resource_boundary :memory
|
||||||
urgency :throttled
|
urgency :throttled
|
||||||
loggable_arguments 2, 3
|
loggable_arguments 2, 3
|
||||||
sidekiq_options retry: false
|
sidekiq_options retry: false, dead: false
|
||||||
sidekiq_options status_expiration: StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION
|
sidekiq_options status_expiration: StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION
|
||||||
|
|
||||||
def perform(current_user_id, project_id, after_export_strategy = {}, params = {})
|
def perform(current_user_id, project_id, after_export_strategy = {}, params = {})
|
||||||
|
|
|
@ -8,7 +8,7 @@ class RepositoryImportWorker # rubocop:disable Scalability/IdempotentWorker
|
||||||
feature_category :importers
|
feature_category :importers
|
||||||
worker_has_external_dependencies!
|
worker_has_external_dependencies!
|
||||||
# Do not retry on Import/Export until https://gitlab.com/gitlab-org/gitlab/-/issues/16812 is solved.
|
# Do not retry on Import/Export until https://gitlab.com/gitlab-org/gitlab/-/issues/16812 is solved.
|
||||||
sidekiq_options retry: false
|
sidekiq_options retry: false, dead: false
|
||||||
sidekiq_options status_expiration: Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION
|
sidekiq_options status_expiration: Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION
|
||||||
|
|
||||||
# technical debt: https://gitlab.com/gitlab-org/gitlab/issues/33991
|
# technical debt: https://gitlab.com/gitlab-org/gitlab/issues/33991
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Automatically expand diffs for merge requests with changes to a single file
|
||||||
|
merge_request: 44629
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Redirect when no user is signed in when updating registration
|
||||||
|
merge_request: 45276
|
||||||
|
author:
|
||||||
|
type: fixed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Fix scoped label markdown padding
|
||||||
|
merge_request: 45153
|
||||||
|
author:
|
||||||
|
type: fixed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add limit to number of test cases parsed by JUnit parser
|
||||||
|
merge_request: 44615
|
||||||
|
author:
|
||||||
|
type: changed
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add missing 90x avatar size for image scaling
|
||||||
|
merge_request: 45025
|
||||||
|
author:
|
||||||
|
type: fixed
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
name: merge_base_pipelines
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44648
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263724
|
||||||
|
type: development
|
||||||
|
group: group::testing
|
||||||
|
default_enabled: false
|
|
@ -13,6 +13,7 @@ ignorecase: true
|
||||||
swap:
|
swap:
|
||||||
frontmatter: front matter
|
frontmatter: front matter
|
||||||
GitLabber: GitLab team member
|
GitLabber: GitLab team member
|
||||||
|
GitLab-shell: GitLab Shell
|
||||||
gitlab omnibus: Omnibus GitLab
|
gitlab omnibus: Omnibus GitLab
|
||||||
param: parameter
|
param: parameter
|
||||||
params: parameters
|
params: parameters
|
||||||
|
|
|
@ -23,32 +23,34 @@ We currently distinguish between three different data types:
|
||||||
See the list below of each feature or component we replicate, its corresponding data type, replication, and
|
See the list below of each feature or component we replicate, its corresponding data type, replication, and
|
||||||
verification methods:
|
verification methods:
|
||||||
|
|
||||||
| Type | Feature / component | Replication method | Verification method |
|
| Type | Feature / component | Replication method | Verification method |
|
||||||
|:---------|:----------------------------------------------|:--------------------------------------|:-----------------------|
|
|:---------|:------------------------------------------------|:--------------------------------------|:-----------------------|
|
||||||
| Database | Application data in PostgreSQL | Native | Native |
|
| Database | Application data in PostgreSQL | Native | Native |
|
||||||
| Database | Redis | _N/A_ (*1*) | _N/A_ |
|
| Database | Redis | _N/A_ (*1*) | _N/A_ |
|
||||||
| Database | Elasticsearch | Native | Native |
|
| Database | Elasticsearch | Native | Native |
|
||||||
| Database | Personal snippets | PostgreSQL Replication | PostgreSQL Replication |
|
| Database | Personal snippets | PostgreSQL Replication | PostgreSQL Replication |
|
||||||
| Database | Project snippets | PostgreSQL Replication | PostgreSQL Replication |
|
| Database | Project snippets | PostgreSQL Replication | PostgreSQL Replication |
|
||||||
| Database | SSH public keys | PostgreSQL Replication | PostgreSQL Replication |
|
| Database | SSH public keys | PostgreSQL Replication | PostgreSQL Replication |
|
||||||
| Git | Project repository | Geo with Gitaly | Gitaly Checksum |
|
| Git | Project repository | Geo with Gitaly | Gitaly Checksum |
|
||||||
| Git | Project wiki repository | Geo with Gitaly | Gitaly Checksum |
|
| Git | Project wiki repository | Geo with Gitaly | Gitaly Checksum |
|
||||||
| Git | Project designs repository | Geo with Gitaly | Gitaly Checksum |
|
| Git | Project designs repository | Geo with Gitaly | Gitaly Checksum |
|
||||||
| Git | Object pools for forked project deduplication | Geo with Gitaly | _Not implemented_ |
|
| Git | Object pools for forked project deduplication | Geo with Gitaly | _Not implemented_ |
|
||||||
| Blobs | User uploads _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | User uploads _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
| Blobs | LFS objects _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | LFS objects _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
| Blobs | CI job artifacts _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | CI job artifacts _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
| Blobs | Archived CI build traces _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | Archived CI build traces _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | Archived CI build traces _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
| Blobs | Container registry _(filesystem)_ | Geo with API/Docker API | _Not implemented_ |
|
| Blobs | Container registry _(filesystem)_ | Geo with API/Docker API | _Not implemented_ |
|
||||||
| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _Not implemented_ |
|
| Blobs | Container registry _(object storage)_ | Geo with API/Managed/Docker API (*2*) | _Not implemented_ |
|
||||||
| Blobs | Package registry _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | Package registry _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | Package registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
| Blobs | Versioned Terraform State _(filesystem)_ | Geo with API | _Not implemented_ |
|
| Blobs | Versioned Terraform State _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
| Blobs | Versioned Terraform State _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
|
| Blobs | External Merge Request Diffs _(filesystem)_ | Geo with API | _Not implemented_ |
|
||||||
|
| Blobs | External Merge Request Diffs _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
|
||||||
|
|
||||||
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
|
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo nodes.
|
||||||
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
|
- (*2*): Object storage replication can be performed by Geo or by your object storage provider/appliance
|
||||||
|
@ -185,7 +187,7 @@ successfully, you must replicate their data using some other means.
|
||||||
| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
|
| [Composer Repository](../../../user/packages/composer_repository/index.md) | **Yes** (13.2) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
|
||||||
| [Generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
|
| [Generic packages](../../../user/packages/generic_packages/index.md) | **Yes** (13.5) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1817) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default |
|
||||||
| [Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default |
|
| [Versioned Terraform State](../../terraform_state.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_terraform_state_version_replication`, enabled by default |
|
||||||
| [External merge request diffs](../../merge_request_diffs.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/33817) | No | Via Object Storage provider if supported. Native Geo support (Beta). | |
|
| [External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Behind feature flag `geo_merge_request_diff_replication`, enabled by default | |
|
||||||
| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
|
| [Versioned snippets](../../../user/snippets.md#versioned-snippets) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [No](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | |
|
||||||
| [Server-side Git hooks](../../server_hooks.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | |
|
| [Server-side Git hooks](../../server_hooks.md) | [No](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | |
|
||||||
| [Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | |
|
| [Elasticsearch integration](../../../integration/elasticsearch.md) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | |
|
||||||
|
|
|
@ -7284,8 +7284,7 @@ type GeoNode {
|
||||||
internalUrl: String
|
internalUrl: String
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Find merge request diff registries on this Geo node. Available only when
|
Find merge request diff registries on this Geo node
|
||||||
feature flag `geo_merge_request_diff_replication` is enabled
|
|
||||||
"""
|
"""
|
||||||
mergeRequestDiffRegistries(
|
mergeRequestDiffRegistries(
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -20066,7 +20066,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mergeRequestDiffRegistries",
|
"name": "mergeRequestDiffRegistries",
|
||||||
"description": "Find merge request diff registries on this Geo node. Available only when feature flag `geo_merge_request_diff_replication` is enabled",
|
"description": "Find merge request diff registries on this Geo node",
|
||||||
"args": [
|
"args": [
|
||||||
{
|
{
|
||||||
"name": "ids",
|
"name": "ids",
|
||||||
|
|
|
@ -410,10 +410,12 @@ script:
|
||||||
|
|
||||||
> Introduced in GitLab 9.4.
|
> Introduced in GitLab 9.4.
|
||||||
|
|
||||||
You can define per-project or per-group variables
|
You can define per-project or per-group variables that are set in the pipeline environment. Group-level variables are stored out of the repository (not in `.gitlab-ci.yml`). They are securely passed to GitLab Runner, which makes them available during a pipeline run.
|
||||||
that are set in the pipeline environment. Group-level variables are stored out of
|
|
||||||
the repository (not in `.gitlab-ci.yml`) and are securely passed to GitLab Runner,
|
We recommend using group environment variables to store secrets (like passwords, SSH keys, and credentials) for Premium users who:
|
||||||
which makes them available during a pipeline run. For Premium users who do **not** use an external key store or who use GitLab's [integration with HashiCorp Vault](../secrets/index.md), we recommend using group environment variables to store secrets like passwords, SSH keys, and credentials.
|
|
||||||
|
- Do **not** use an external key store.
|
||||||
|
- Use GitLab's [integration with HashiCorp Vault](../secrets/index.md).
|
||||||
|
|
||||||
Group-level variables can be added by:
|
Group-level variables can be added by:
|
||||||
|
|
||||||
|
@ -547,8 +549,7 @@ variables take precedence over those defined in `.gitlab-ci.yml`.
|
||||||
|
|
||||||
Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html).
|
Variable names are limited by the underlying shell used to execute scripts (see [available shells](https://docs.gitlab.com/runner/shells/index.html).
|
||||||
Each shell has its own unique set of reserved variable names.
|
Each shell has its own unique set of reserved variable names.
|
||||||
You also want to keep in mind the [scope of environment variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope
|
Keep in mind the [scope of environment variables](where_variables_can_be_used.md) to ensure a variable is defined in the scope in which you wish to use it.
|
||||||
in which you wish to use it.
|
|
||||||
|
|
||||||
## Where variables can be used
|
## Where variables can be used
|
||||||
|
|
||||||
|
@ -682,9 +683,10 @@ Examples:
|
||||||
- `$VARIABLE == ""`
|
- `$VARIABLE == ""`
|
||||||
- `$VARIABLE != ""` (introduced in GitLab 11.11)
|
- `$VARIABLE != ""` (introduced in GitLab 11.11)
|
||||||
|
|
||||||
If you want to check whether a variable is defined, but is empty, you can
|
To check if a variable is defined but empty, compare it to:
|
||||||
simply compare it against an empty string, like `$VAR == ''` or non-empty
|
|
||||||
string `$VARIABLE != ""`.
|
- An empty string: `$VARIABLE == ''`
|
||||||
|
- A non-empty string: `$VARIABLE != ""`
|
||||||
|
|
||||||
#### Comparing two variables
|
#### Comparing two variables
|
||||||
|
|
||||||
|
@ -700,9 +702,8 @@ of these variables.
|
||||||
|
|
||||||
Example: `$STAGING`
|
Example: `$STAGING`
|
||||||
|
|
||||||
If you only want to create a job when there is some variable present,
|
To create a job when there is some variable present, meaning it is defined and non-empty,
|
||||||
which means that it is defined and non-empty, you can simply use
|
use the variable name as an expression, like `$STAGING`. If the `$STAGING` variable
|
||||||
variable name as an expression, like `$STAGING`. If `$STAGING` variable
|
|
||||||
is defined, and is non empty, expression evaluates to `true`.
|
is defined, and is non empty, expression evaluates to `true`.
|
||||||
`$STAGING` value needs to be a string, with length higher than zero.
|
`$STAGING` value needs to be a string, with length higher than zero.
|
||||||
Variable that contains only whitespace characters is not an empty variable.
|
Variable that contains only whitespace characters is not an empty variable.
|
||||||
|
@ -836,9 +837,7 @@ from being leaked into the log unless your script writes them to the screen.
|
||||||
|
|
||||||
If a job isn't working as expected, this can make the problem difficult to
|
If a job isn't working as expected, this can make the problem difficult to
|
||||||
investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
|
investigate; in these cases, you can enable debug tracing in `.gitlab-ci.yml`.
|
||||||
Available on GitLab Runner v1.7+, this feature enables the shell's execution
|
Available on GitLab Runner v1.7+, this feature enables the shell's execution log. This results in a verbose job log listing all commands that were run, variables that were set, and so on.
|
||||||
log, resulting in a verbose job log listing all commands that were run,
|
|
||||||
variables that were set, and so on.
|
|
||||||
|
|
||||||
Before enabling this, you should ensure jobs are visible to
|
Before enabling this, you should ensure jobs are visible to
|
||||||
[team members only](../../user/permissions.md#project-features). You should
|
[team members only](../../user/permissions.md#project-features). You should
|
||||||
|
|
|
@ -52,7 +52,7 @@ POST /internal/allowed
|
||||||
| `username` | string | no | Username from the certificate used to connect to GitLab Shell |
|
| `username` | string | no | Username from the certificate used to connect to GitLab Shell |
|
||||||
| `project` | string | no (if `gl_repository` is passed) | Path to the project |
|
| `project` | string | no (if `gl_repository` is passed) | Path to the project |
|
||||||
| `gl_repository` | string | no (if `project` is passed) | Repository identifier (e.g. `project-7`) |
|
| `gl_repository` | string | no (if `project` is passed) | Repository identifier (e.g. `project-7`) |
|
||||||
| `protocol` | string | yes | SSH when called from GitLab-shell, HTTP or SSH when called from Gitaly |
|
| `protocol` | string | yes | SSH when called from GitLab Shell, HTTP or SSH when called from Gitaly |
|
||||||
| `action` | string | yes | Git command being run (`git-upload-pack`, `git-receive-pack`, `git-upload-archive`) |
|
| `action` | string | yes | Git command being run (`git-upload-pack`, `git-receive-pack`, `git-upload-archive`) |
|
||||||
| `changes` | string | yes | `<oldrev> <newrev> <refname>` when called from Gitaly, the magic string `_any` when called from GitLab Shell |
|
| `changes` | string | yes | `<oldrev> <newrev> <refname>` when called from Gitaly, the magic string `_any` when called from GitLab Shell |
|
||||||
| `check_ip` | string | no | IP address from which call to GitLab Shell was made |
|
| `check_ip` | string | no | IP address from which call to GitLab Shell was made |
|
||||||
|
|
|
@ -96,6 +96,7 @@ Below are the current settings regarding [GitLab CI/CD](../../ci/README.md).
|
||||||
| [Max pipeline schedules in projects](../../administration/instance_limits.md#number-of-pipeline-schedules) | `10` for Free tier, `50` for all paid tiers | Unlimited |
|
| [Max pipeline schedules in projects](../../administration/instance_limits.md#number-of-pipeline-schedules) | `10` for Free tier, `50` for all paid tiers | Unlimited |
|
||||||
| [Max number of instance level variables](../../administration/instance_limits.md#number-of-instance-level-variables) | `25` | `25` |
|
| [Max number of instance level variables](../../administration/instance_limits.md#number-of-instance-level-variables) | `25` | `25` |
|
||||||
| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never |
|
| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never |
|
||||||
|
| Max test cases per [unit test report](../../ci/unit_test_reports.md) | `500_000` | Unlimited |
|
||||||
|
|
||||||
## Account and limit settings
|
## Account and limit settings
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,6 @@ according to the type of domain you want to use with your Pages site:
|
||||||
- [For subdomains](#for-subdomains), `subdomain.example.com`.
|
- [For subdomains](#for-subdomains), `subdomain.example.com`.
|
||||||
- [For both](#for-both-root-and-subdomains).
|
- [For both](#for-both-root-and-subdomains).
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
You can [configure IPv6 on self-managed instances](../../../../administration/pages/index.md#advanced-configuration),
|
You can [configure IPv6 on self-managed instances](../../../../administration/pages/index.md#advanced-configuration),
|
||||||
but IPv6 is not currently configured for Pages on GitLab.com.
|
but IPv6 is not currently configured for Pages on GitLab.com.
|
||||||
Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214718) for details.
|
Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/214718) for details.
|
||||||
|
@ -250,8 +249,8 @@ You can use any certificate satisfying the following requirements:
|
||||||
- **A private key**, it's an encrypted key which validates
|
- **A private key**, it's an encrypted key which validates
|
||||||
your PEM against your domain.
|
your PEM against your domain.
|
||||||
|
|
||||||
NOTE: **Note:**
|
For example, [Cloudflare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/)
|
||||||
[Cloudflare certificates](https://about.gitlab.com/blog/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/), for example, meet these requirements.
|
meet these requirements.
|
||||||
|
|
||||||
#### Steps
|
#### Steps
|
||||||
|
|
||||||
|
@ -269,7 +268,6 @@ NOTE: **Note:**
|
||||||
just jumping a line between them.
|
just jumping a line between them.
|
||||||
1. Copy your private key and paste it in the last field.
|
1. Copy your private key and paste it in the last field.
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
**Do not** open certificates or encryption keys in
|
**Do not** open certificates or encryption keys in
|
||||||
regular text editors. Always use code editors (such as
|
regular text editors. Always use code editors (such as
|
||||||
Sublime Text, Atom, Dreamweaver, Brackets, etc).
|
Sublime Text, Atom, Dreamweaver, Brackets, etc).
|
||||||
|
@ -290,8 +288,8 @@ To enable this setting:
|
||||||
1. Navigate to your project's **Settings > Pages**.
|
1. Navigate to your project's **Settings > Pages**.
|
||||||
1. Tick the checkbox **Force HTTPS (requires valid certificates)**.
|
1. Tick the checkbox **Force HTTPS (requires valid certificates)**.
|
||||||
|
|
||||||
NOTE: **Note:**
|
If you use Cloudflare CDN in front of GitLab Pages, make sure to set the SSL connection setting to
|
||||||
If you use Cloudflare CDN in front of GitLab Pages, make sure to set the SSL connection setting to `full` instead of `flexible`. For more details, see the [Cloudflare CDN directions](https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef).
|
`full` instead of `flexible`. For more details, see the [Cloudflare CDN directions](https://support.cloudflare.com/hc/en-us/articles/200170416-End-to-end-HTTPS-with-Cloudflare-Part-3-SSL-options#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef).
|
||||||
|
|
||||||
<!-- ## Troubleshooting
|
<!-- ## Troubleshooting
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,6 @@ Before you can enable automatic provisioning of an SSL certificate for your doma
|
||||||
and verified your ownership.
|
and verified your ownership.
|
||||||
- Verified your website is up and running, accessible through your custom domain.
|
- Verified your website is up and running, accessible through your custom domain.
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
GitLab's Let's Encrypt integration is enabled and available on GitLab.com.
|
GitLab's Let's Encrypt integration is enabled and available on GitLab.com.
|
||||||
For **self-managed** GitLab instances, make sure your administrator has
|
For **self-managed** GitLab instances, make sure your administrator has
|
||||||
[enabled it](../../../../administration/pages/index.md#lets-encrypt-integration).
|
[enabled it](../../../../administration/pages/index.md#lets-encrypt-integration).
|
||||||
|
|
|
@ -11,12 +11,9 @@ according to your intended website's URL.
|
||||||
|
|
||||||
## GitLab Pages default domain names
|
## GitLab Pages default domain names
|
||||||
|
|
||||||
NOTE: **Note:**
|
If you use your own GitLab instance to deploy your site with GitLab Pages, verify your Pages
|
||||||
If you use your own GitLab instance to deploy your
|
wildcard domain with your sysadmin. This guide is valid for any GitLab instance, provided that you
|
||||||
site with GitLab Pages, check with your sysadmin what's your
|
replace the Pages wildcard domain on GitLab.com (`*.gitlab.io`) with your own.
|
||||||
Pages wildcard domain. This guide is valid for any GitLab instance,
|
|
||||||
you just need to replace Pages wildcard domain on GitLab.com
|
|
||||||
(`*.gitlab.io`) with your own.
|
|
||||||
|
|
||||||
If you set up a GitLab Pages project on GitLab,
|
If you set up a GitLab Pages project on GitLab,
|
||||||
it will automatically be accessible under a
|
it will automatically be accessible under a
|
||||||
|
|
|
@ -259,9 +259,8 @@ instead. Here are some examples of what will happen given the above Pages site:
|
||||||
| `/other/index` | `200 OK` | `public/other/index.html` |
|
| `/other/index` | `200 OK` | `public/other/index.html` |
|
||||||
| `/other/index.html` | `200 OK` | `public/other/index.html` |
|
| `/other/index.html` | `200 OK` | `public/other/index.html` |
|
||||||
|
|
||||||
NOTE: **Note:**
|
Note that when `public/data/index.html` exists, it takes priority over the `public/data.html` file
|
||||||
When `public/data/index.html` exists, it takes priority over the `public/data.html`
|
for both the `/data` and `/data/` URL paths.
|
||||||
file for both the `/data` and `/data/` URL paths.
|
|
||||||
|
|
||||||
## Frequently Asked Questions
|
## Frequently Asked Questions
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,8 @@ To follow along with this tutorial, we assume you already have:
|
||||||
Once you have the requirements addressed, follow the instructions
|
Once you have the requirements addressed, follow the instructions
|
||||||
below to learn how to obtain the certificate.
|
below to learn how to obtain the certificate.
|
||||||
|
|
||||||
NOTE: **Note:**
|
Note that these instructions were tested on macOS Mojave. For other operating systems the steps
|
||||||
The instructions below were tested on macOS Mojave. For other
|
might be slightly different. Follow the
|
||||||
operating systems the steps might be slightly different. Follow the
|
|
||||||
[CertBot instructions](https://certbot.eff.org/) according to your OS.
|
[CertBot instructions](https://certbot.eff.org/) according to your OS.
|
||||||
|
|
||||||
1. On your computer, open a terminal and navigate to your repository's
|
1. On your computer, open a terminal and navigate to your repository's
|
||||||
|
|
|
@ -20,11 +20,9 @@ on your GitLab instance. When enabled, only
|
||||||
For a demonstration, see [Pages access controls](https://www.youtube.com/watch?v=tSPAr5mQYc8).
|
For a demonstration, see [Pages access controls](https://www.youtube.com/watch?v=tSPAr5mQYc8).
|
||||||
|
|
||||||
1. Navigate to your project's **Settings > General** and expand **Visibility, project features, permissions**.
|
1. Navigate to your project's **Settings > General** and expand **Visibility, project features, permissions**.
|
||||||
1. Toggle the **Pages** button to enable the access control.
|
|
||||||
|
|
||||||
NOTE: **Note:**
|
1. Toggle the **Pages** button to enable the access control. If you don't see the toggle button,
|
||||||
If you don't see the toggle button, that means that it's not enabled.
|
that means it isn't enabled. Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
|
||||||
Ask your administrator to [enable it](../../../administration/pages/index.md#access-control).
|
|
||||||
|
|
||||||
1. The Pages access control dropdown allows you to set who can view pages hosted
|
1. The Pages access control dropdown allows you to set who can view pages hosted
|
||||||
with GitLab Pages, depending on your project's visibility:
|
with GitLab Pages, depending on your project's visibility:
|
||||||
|
|
|
@ -22,8 +22,10 @@ GitLab Pages only supports the
|
||||||
[`_redirects` plain text file syntax](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file),
|
[`_redirects` plain text file syntax](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file),
|
||||||
and `.toml` files are not supported.
|
and `.toml` files are not supported.
|
||||||
|
|
||||||
Redirects are only supported at a basic level, and GitLab Pages doesn't support all
|
Redirects are only supported at a basic level. GitLab Pages doesn't support all
|
||||||
[special options offered by Netlify](https://docs.netlify.com/routing/redirects/redirect-options/):
|
[special options offered by Netlify](https://docs.netlify.com/routing/redirects/redirect-options/).
|
||||||
|
|
||||||
|
Note that supported paths must start with a forward slash `/`.
|
||||||
|
|
||||||
| Feature | Supported | Example |
|
| Feature | Supported | Example |
|
||||||
| ------- | --------- | ------- |
|
| ------- | --------- | ------- |
|
||||||
|
@ -37,9 +39,6 @@ Redirects are only supported at a basic level, and GitLab Pages doesn't support
|
||||||
| Redirect by country or language | **{dotted-circle}** No | `/ /anz 302 Country=au,nz` |
|
| Redirect by country or language | **{dotted-circle}** No | `/ /anz 302 Country=au,nz` |
|
||||||
| Redirect by role | **{dotted-circle}** No | `/admin/* 200! Role=admin` |
|
| Redirect by role | **{dotted-circle}** No | `/admin/* 200! Role=admin` |
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
Supported paths must start with a forward slash `/`.
|
|
||||||
|
|
||||||
## Create redirects
|
## Create redirects
|
||||||
|
|
||||||
To create redirects,
|
To create redirects,
|
||||||
|
@ -78,8 +77,7 @@ is ignored because `hello.html` exists:
|
||||||
/projectname/hello.html /projectname/world.html 302
|
/projectname/hello.html /projectname/world.html 302
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: **Note:**
|
GitLab doesn't support Netlify's
|
||||||
GitLab does not support Netlify's
|
|
||||||
[force option](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)
|
[force option](https://docs.netlify.com/routing/redirects/rewrites-proxies/#shadowing)
|
||||||
to change this behavior.
|
to change this behavior.
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,17 @@ module Gitlab
|
||||||
JunitParserError = Class.new(Gitlab::Ci::Parsers::ParserError)
|
JunitParserError = Class.new(Gitlab::Ci::Parsers::ParserError)
|
||||||
ATTACHMENT_TAG_REGEX = /\[\[ATTACHMENT\|(?<path>.+?)\]\]/.freeze
|
ATTACHMENT_TAG_REGEX = /\[\[ATTACHMENT\|(?<path>.+?)\]\]/.freeze
|
||||||
|
|
||||||
def parse!(xml_data, test_suite, **args)
|
def parse!(xml_data, test_suite, job:)
|
||||||
root = Hash.from_xml(xml_data)
|
root = Hash.from_xml(xml_data)
|
||||||
|
total_parsed = 0
|
||||||
|
max_test_cases = job.max_test_cases_per_report
|
||||||
|
|
||||||
all_cases(root) do |test_case|
|
all_cases(root) do |test_case|
|
||||||
test_case = create_test_case(test_case, test_suite, args)
|
test_case = create_test_case(test_case, test_suite, job)
|
||||||
test_suite.add_test_case(test_case)
|
test_suite.add_test_case(test_case)
|
||||||
|
total_parsed += 1
|
||||||
|
|
||||||
|
ensure_test_cases_limited!(total_parsed, max_test_cases)
|
||||||
end
|
end
|
||||||
rescue Nokogiri::XML::SyntaxError => e
|
rescue Nokogiri::XML::SyntaxError => e
|
||||||
test_suite.set_suite_error("JUnit XML parsing failed: #{e}")
|
test_suite.set_suite_error("JUnit XML parsing failed: #{e}")
|
||||||
|
@ -23,6 +28,12 @@ module Gitlab
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def ensure_test_cases_limited!(total_parsed, limit)
|
||||||
|
return unless limit > 0 && total_parsed > limit
|
||||||
|
|
||||||
|
raise JunitParserError.new("number of test cases exceeded the limit of #{limit}")
|
||||||
|
end
|
||||||
|
|
||||||
def all_cases(root, parent = nil, &blk)
|
def all_cases(root, parent = nil, &blk)
|
||||||
return unless root.present?
|
return unless root.present?
|
||||||
|
|
||||||
|
@ -50,7 +61,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_test_case(data, test_suite, args)
|
def create_test_case(data, test_suite, job)
|
||||||
if data.key?('failure')
|
if data.key?('failure')
|
||||||
status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
|
status = ::Gitlab::Ci::Reports::TestCase::STATUS_FAILED
|
||||||
system_output = data['failure']
|
system_output = data['failure']
|
||||||
|
@ -75,7 +86,7 @@ module Gitlab
|
||||||
status: status,
|
status: status,
|
||||||
system_output: system_output,
|
system_output: system_output,
|
||||||
attachment: attachment,
|
attachment: attachment,
|
||||||
job: args.fetch(:job)
|
job: job
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,10 @@ module Gitlab
|
||||||
|
|
||||||
return [] unless content
|
return [] unless content
|
||||||
|
|
||||||
|
# TODO: We could add some kind of flag to #initialize that would allow
|
||||||
|
# us to force re-caching
|
||||||
|
# https://gitlab.com/gitlab-org/gitlab/-/issues/263508
|
||||||
|
#
|
||||||
if content.empty? && recache_due_to_size?(diff_file)
|
if content.empty? && recache_due_to_size?(diff_file)
|
||||||
# If the file is missing from the cache and there's reason to believe
|
# If the file is missing from the cache and there's reason to believe
|
||||||
# it is uncached due to a size issue around changing the values for
|
# it is uncached due to a size issue around changing the values for
|
||||||
|
|
|
@ -118,11 +118,17 @@ module Gitlab
|
||||||
files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes
|
files >= safe_max_files || @line_count > safe_max_lines || @byte_count >= safe_max_bytes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def expand_diff?
|
||||||
|
# Force single-entry diff collections to always present as expanded
|
||||||
|
#
|
||||||
|
@iterator.size == 1 || !@enforce_limits || @expanded
|
||||||
|
end
|
||||||
|
|
||||||
def each_gitaly_patch
|
def each_gitaly_patch
|
||||||
i = @array.length
|
i = @array.length
|
||||||
|
|
||||||
@iterator.each do |raw|
|
@iterator.each do |raw|
|
||||||
diff = Gitlab::Git::Diff.new(raw, expanded: !@enforce_limits || @expanded)
|
diff = Gitlab::Git::Diff.new(raw, expanded: expand_diff?)
|
||||||
|
|
||||||
if raw.overflow_marker
|
if raw.overflow_marker
|
||||||
@overflow = true
|
@overflow = true
|
||||||
|
@ -145,11 +151,9 @@ module Gitlab
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
expanded = !@enforce_limits || @expanded
|
diff = Gitlab::Git::Diff.new(raw, expanded: expand_diff?)
|
||||||
|
|
||||||
diff = Gitlab::Git::Diff.new(raw, expanded: expanded)
|
if !expand_diff? && over_safe_limits?(i) && diff.line_count > 0
|
||||||
|
|
||||||
if !expanded && over_safe_limits?(i) && diff.line_count > 0
|
|
||||||
diff.collapse!
|
diff.collapse!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,10 @@ module Gitlab
|
||||||
class DiffStitcher
|
class DiffStitcher
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
def initialize(rpc_response)
|
delegate :size, to: :rpc_response
|
||||||
@rpc_response = rpc_response
|
|
||||||
|
def initialize(rpc_response_param)
|
||||||
|
@rpc_response = rpc_response_param
|
||||||
end
|
end
|
||||||
|
|
||||||
def each
|
def each
|
||||||
|
@ -31,6 +33,10 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_reader :rpc_response
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21253,7 +21253,7 @@ msgstr ""
|
||||||
msgid "ProtectedBranch|Code owner approval"
|
msgid "ProtectedBranch|Code owner approval"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ProtectedBranch|Does not apply to users allowed to merge or push."
|
msgid "ProtectedBranch|Does not apply to users allowed to push."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "ProtectedBranch|Protect"
|
msgid "ProtectedBranch|Protect"
|
||||||
|
@ -22312,6 +22312,9 @@ msgstr ""
|
||||||
msgid "Requirement %{reference} has been updated"
|
msgid "Requirement %{reference} has been updated"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Requirement title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Requirement title cannot have more than %{limit} characters."
|
msgid "Requirement title cannot have more than %{limit} characters."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -477,10 +477,16 @@ RSpec.describe RegistrationsController do
|
||||||
patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
|
patch :update_registration, params: { user: { role: 'software_developer', setup_for_company: 'false' } }
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
context 'without a signed in user' do
|
||||||
sign_in(create(:user))
|
it { is_expected.to redirect_to new_user_registration_path }
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to redirect_to(dashboard_projects_path)}
|
context 'with a signed in user' do
|
||||||
|
before do
|
||||||
|
sign_in(create(:user))
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to redirect_to(dashboard_projects_path)}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,11 +4,12 @@ require 'fast_spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
|
RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
|
||||||
describe '#parse!' do
|
describe '#parse!' do
|
||||||
subject { described_class.new.parse!(junit, test_suite, **args) }
|
subject { described_class.new.parse!(junit, test_suite, job: job) }
|
||||||
|
|
||||||
let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
|
let(:test_suite) { Gitlab::Ci::Reports::TestSuite.new('rspec') }
|
||||||
let(:test_cases) { flattened_test_cases(test_suite) }
|
let(:test_cases) { flattened_test_cases(test_suite) }
|
||||||
let(:args) { { job: { id: 1, project: "project" } } }
|
let(:job) { double(max_test_cases_per_report: max_test_cases) }
|
||||||
|
let(:max_test_cases) { 0 }
|
||||||
|
|
||||||
context 'when data is JUnit style XML' do
|
context 'when data is JUnit style XML' do
|
||||||
context 'when there are no <testcases> in <testsuite>' do
|
context 'when there are no <testcases> in <testsuite>' do
|
||||||
|
@ -230,6 +231,55 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when number of test cases exceeds the max_test_cases limit' do
|
||||||
|
let(:max_test_cases) { 1 }
|
||||||
|
|
||||||
|
shared_examples_for 'rejecting too many test cases' do
|
||||||
|
it 'attaches an error to the TestSuite object' do
|
||||||
|
expect { subject }.not_to raise_error
|
||||||
|
expect(test_suite.suite_error).to eq("JUnit data parsing failed: number of test cases exceeded the limit of #{max_test_cases}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and test cases are unique' do
|
||||||
|
let(:junit) do
|
||||||
|
<<-EOF.strip_heredoc
|
||||||
|
<testsuites>
|
||||||
|
<testsuite>
|
||||||
|
<testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
|
||||||
|
<testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite>
|
||||||
|
<testcase classname='Statemachine' name='happy path' time='100'></testcase>
|
||||||
|
<testcase classname='Statemachine' name='unhappy path' time='200'></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'rejecting too many test cases'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'and test cases are duplicates' do
|
||||||
|
let(:junit) do
|
||||||
|
<<-EOF.strip_heredoc
|
||||||
|
<testsuites>
|
||||||
|
<testsuite>
|
||||||
|
<testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
|
||||||
|
<testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
|
||||||
|
</testsuite>
|
||||||
|
<testsuite>
|
||||||
|
<testcase classname='Calculator' name='sumTest1' time='0.01'></testcase>
|
||||||
|
<testcase classname='Calculator' name='sumTest2' time='0.02'></testcase>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
EOF
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'rejecting too many test cases'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when data is not JUnit style XML' do
|
context 'when data is not JUnit style XML' do
|
||||||
|
@ -316,9 +366,7 @@ RSpec.describe Gitlab::Ci::Parsers::Test::Junit do
|
||||||
expect(test_cases[0].has_attachment?).to be_truthy
|
expect(test_cases[0].has_attachment?).to be_truthy
|
||||||
expect(test_cases[0].attachment).to eq("some/path.png")
|
expect(test_cases[0].attachment).to eq("some/path.png")
|
||||||
|
|
||||||
expect(test_cases[0].job).to be_present
|
expect(test_cases[0].job).to eq(job)
|
||||||
expect(test_cases[0].job[:id]).to eq(1)
|
|
||||||
expect(test_cases[0].job[:project]).to eq("project")
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,11 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
|
||||||
MutatingConstantIterator.class_eval do
|
MutatingConstantIterator.class_eval do
|
||||||
include Enumerable
|
include Enumerable
|
||||||
|
|
||||||
|
attr_reader :size
|
||||||
|
|
||||||
def initialize(count, value)
|
def initialize(count, value)
|
||||||
@count = count
|
@count = count
|
||||||
|
@size = count
|
||||||
@value = value
|
@value = value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -517,14 +520,30 @@ RSpec.describe Gitlab::Git::DiffCollection, :seed_helper do
|
||||||
.to yield_with_args(an_instance_of(Gitlab::Git::Diff))
|
.to yield_with_args(an_instance_of(Gitlab::Git::Diff))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'prunes diffs that are quite big' do
|
context 'single-file collections' do
|
||||||
diff = nil
|
it 'does not prune diffs' do
|
||||||
|
diff = nil
|
||||||
|
|
||||||
subject.each do |d|
|
subject.each do |d|
|
||||||
diff = d
|
diff = d
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(diff.diff).not_to eq('')
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
expect(diff.diff).to eq('')
|
context 'multi-file collections' do
|
||||||
|
let(:iterator) { [{ diff: 'b' }, { diff: 'a' * 20480 }]}
|
||||||
|
|
||||||
|
it 'prunes diffs that are quite big' do
|
||||||
|
diff = nil
|
||||||
|
|
||||||
|
subject.each do |d|
|
||||||
|
diff = d
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(diff.diff).to eq('')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when go over safe limits on files' do
|
context 'when go over safe limits on files' do
|
||||||
|
|
|
@ -3520,6 +3520,25 @@ RSpec.describe MergeRequest, factory_default: :keep do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#merge_base_pipeline' do
|
||||||
|
let(:merge_request) do
|
||||||
|
create(:merge_request, :with_merge_request_pipeline)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:merge_base_pipeline) do
|
||||||
|
create(:ci_pipeline, ref: merge_request.target_branch, sha: merge_request.target_branch_sha)
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
merge_base_pipeline
|
||||||
|
merge_request.update_head_pipeline
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns a pipeline pointing to a commit on the target ref' do
|
||||||
|
expect(merge_request.merge_base_pipeline).to eq(merge_base_pipeline)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#has_commits?' do
|
describe '#has_commits?' do
|
||||||
it 'returns true when merge request diff has commits' do
|
it 'returns true when merge request diff has commits' do
|
||||||
allow(subject.merge_request_diff).to receive(:commits_count)
|
allow(subject.merge_request_diff).to receive(:commits_count)
|
||||||
|
|
|
@ -2400,15 +2400,23 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'POST /users/:id/deactivate' do
|
describe 'POST /users/:id/deactivate' do
|
||||||
|
subject(:deactivate) { post api("/users/#{user_id}/deactivate", api_user) }
|
||||||
|
|
||||||
|
let(:user_id) { user.id }
|
||||||
|
|
||||||
context 'performed by a non-admin user' do
|
context 'performed by a non-admin user' do
|
||||||
|
let(:api_user) { user }
|
||||||
|
|
||||||
it 'is not authorized to perform the action' do
|
it 'is not authorized to perform the action' do
|
||||||
post api("/users/#{user.id}/deactivate", user)
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'performed by an admin user' do
|
context 'performed by an admin user' do
|
||||||
|
let(:api_user) { admin }
|
||||||
|
|
||||||
context 'for an active user' do
|
context 'for an active user' do
|
||||||
let(:activity) { {} }
|
let(:activity) { {} }
|
||||||
let(:user) { create(:user, **activity) }
|
let(:user) { create(:user, **activity) }
|
||||||
|
@ -2416,11 +2424,9 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
context 'with no recent activity' do
|
context 'with no recent activity' do
|
||||||
let(:activity) { { last_activity_on: ::User::MINIMUM_INACTIVE_DAYS.next.days.ago } }
|
let(:activity) { { last_activity_on: ::User::MINIMUM_INACTIVE_DAYS.next.days.ago } }
|
||||||
|
|
||||||
before do
|
|
||||||
post api("/users/#{user.id}/deactivate", admin)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'deactivates an active user' do
|
it 'deactivates an active user' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:created)
|
expect(response).to have_gitlab_http_status(:created)
|
||||||
expect(user.reload.state).to eq('deactivated')
|
expect(user.reload.state).to eq('deactivated')
|
||||||
end
|
end
|
||||||
|
@ -2429,11 +2435,9 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
context 'with recent activity' do
|
context 'with recent activity' do
|
||||||
let(:activity) { { last_activity_on: ::User::MINIMUM_INACTIVE_DAYS.pred.days.ago } }
|
let(:activity) { { last_activity_on: ::User::MINIMUM_INACTIVE_DAYS.pred.days.ago } }
|
||||||
|
|
||||||
before do
|
|
||||||
post api("/users/#{user.id}/deactivate", admin)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'does not deactivate an active user' do
|
it 'does not deactivate an active user' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
expect(json_response['message']).to eq("403 Forbidden - The user you are trying to deactivate has been active in the past #{::User::MINIMUM_INACTIVE_DAYS} days and cannot be deactivated")
|
expect(json_response['message']).to eq("403 Forbidden - The user you are trying to deactivate has been active in the past #{::User::MINIMUM_INACTIVE_DAYS} days and cannot be deactivated")
|
||||||
expect(user.reload.state).to eq('active')
|
expect(user.reload.state).to eq('active')
|
||||||
|
@ -2444,11 +2448,11 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
context 'for a deactivated user' do
|
context 'for a deactivated user' do
|
||||||
before do
|
before do
|
||||||
user.deactivate
|
user.deactivate
|
||||||
|
|
||||||
post api("/users/#{user.id}/deactivate", admin)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns 201' do
|
it 'returns 201' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:created)
|
expect(response).to have_gitlab_http_status(:created)
|
||||||
expect(user.reload.state).to eq('deactivated')
|
expect(user.reload.state).to eq('deactivated')
|
||||||
end
|
end
|
||||||
|
@ -2457,11 +2461,11 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
context 'for a blocked user' do
|
context 'for a blocked user' do
|
||||||
before do
|
before do
|
||||||
user.block
|
user.block
|
||||||
|
|
||||||
post api("/users/#{user.id}/deactivate", admin)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns 403' do
|
it 'returns 403' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
|
expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
|
||||||
expect(user.reload.state).to eq('blocked')
|
expect(user.reload.state).to eq('blocked')
|
||||||
|
@ -2471,11 +2475,11 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
context 'for a ldap blocked user' do
|
context 'for a ldap blocked user' do
|
||||||
before do
|
before do
|
||||||
user.ldap_block
|
user.ldap_block
|
||||||
|
|
||||||
post api("/users/#{user.id}/deactivate", admin)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns 403' do
|
it 'returns 403' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
|
expect(json_response['message']).to eq('403 Forbidden - A blocked user cannot be deactivated by the API')
|
||||||
expect(user.reload.state).to eq('ldap_blocked')
|
expect(user.reload.state).to eq('ldap_blocked')
|
||||||
|
@ -2483,10 +2487,10 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for an internal user' do
|
context 'for an internal user' do
|
||||||
it 'returns 403' do
|
let(:user) { User.alert_bot }
|
||||||
internal_user = User.alert_bot
|
|
||||||
|
|
||||||
post api("/users/#{internal_user.id}/deactivate", admin)
|
it 'returns 403' do
|
||||||
|
deactivate
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:forbidden)
|
expect(response).to have_gitlab_http_status(:forbidden)
|
||||||
expect(json_response['message']).to eq('403 Forbidden - An internal user cannot be deactivated by the API')
|
expect(json_response['message']).to eq('403 Forbidden - An internal user cannot be deactivated by the API')
|
||||||
|
@ -2494,8 +2498,10 @@ RSpec.describe API::Users, :do_not_mock_admin_mode do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'for a user that does not exist' do
|
context 'for a user that does not exist' do
|
||||||
|
let(:user_id) { 0 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
post api("/users/0/deactivate", admin)
|
deactivate
|
||||||
end
|
end
|
||||||
|
|
||||||
it_behaves_like '404'
|
it_behaves_like '404'
|
||||||
|
|
|
@ -88,25 +88,53 @@ RSpec.describe MergeRequestWidgetEntity do
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'codequality report artifacts', :request_store do
|
describe 'codequality report artifacts', :request_store do
|
||||||
|
let(:merge_base_pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
project.add_developer(user)
|
project.add_developer(user)
|
||||||
|
|
||||||
allow(resource).to receive_messages(
|
allow(resource).to receive_messages(
|
||||||
|
merge_base_pipeline: merge_base_pipeline,
|
||||||
base_pipeline: pipeline,
|
base_pipeline: pipeline,
|
||||||
head_pipeline: pipeline
|
head_pipeline: pipeline
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with report artifacts" do
|
context 'with report artifacts' do
|
||||||
let(:pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
|
let(:pipeline) { create(:ci_pipeline, :with_codequality_report, project: project) }
|
||||||
|
let(:generic_job_id) { pipeline.builds.first.id }
|
||||||
|
let(:merge_base_job_id) { merge_base_pipeline.builds.first.id }
|
||||||
|
|
||||||
it "has data entry" do
|
it 'has head_path and base_path entries' do
|
||||||
expect(subject).to include(:codeclimate)
|
expect(subject[:codeclimate][:head_path]).to be_present
|
||||||
|
expect(subject[:codeclimate][:base_path]).to be_present
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'on pipelines for merged results' do
|
||||||
|
let(:pipeline) { create(:ci_pipeline, :merged_result_pipeline, :with_codequality_report, project: project) }
|
||||||
|
|
||||||
|
context 'with merge_base_pipelines enabled' do
|
||||||
|
it 'returns URLs from the head_pipeline and merge_base_pipeline' do
|
||||||
|
expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
|
||||||
|
expect(subject[:codeclimate][:base_path]).to include("/jobs/#{merge_base_job_id}/artifacts/download?file_type=codequality")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with merge_base_pipelines disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(merge_base_pipelines: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns URLs from the head_pipeline and base_pipeline' do
|
||||||
|
expect(subject[:codeclimate][:head_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
|
||||||
|
expect(subject[:codeclimate][:base_path]).to include("/jobs/#{generic_job_id}/artifacts/download?file_type=codequality")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "without artifacts" do
|
context 'without artifacts' do
|
||||||
it "does not have data entry" do
|
it 'does not have data entry' do
|
||||||
expect(subject).not_to include(:codeclimate)
|
expect(subject).not_to include(:codeclimate)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -26,4 +26,14 @@ RSpec.describe GroupExportWorker do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'sidekiq options' do
|
||||||
|
it 'disables retry' do
|
||||||
|
expect(described_class.sidekiq_options['retry']).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'disables dead' do
|
||||||
|
expect(described_class.sidekiq_options['dead']).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,6 +16,16 @@ RSpec.describe GroupImportWorker do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'sidekiq options' do
|
||||||
|
it 'disables retry' do
|
||||||
|
expect(described_class.sidekiq_options['retry']).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'disables dead' do
|
||||||
|
expect(described_class.sidekiq_options['dead']).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '#perform' do
|
describe '#perform' do
|
||||||
context 'when it succeeds' do
|
context 'when it succeeds' do
|
||||||
before do
|
before do
|
||||||
|
|
|
@ -75,6 +75,10 @@ RSpec.describe ProjectExportWorker do
|
||||||
expect(described_class.sidekiq_options['retry']).to eq(false)
|
expect(described_class.sidekiq_options['retry']).to eq(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'disables dead' do
|
||||||
|
expect(described_class.sidekiq_options['dead']).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
it 'sets default status expiration' do
|
it 'sets default status expiration' do
|
||||||
expect(described_class.sidekiq_options['status_expiration']).to eq(StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION)
|
expect(described_class.sidekiq_options['status_expiration']).to eq(StuckExportJobsWorker::EXPORT_JOBS_EXPIRATION)
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue