Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7e064974b9
commit
a269fb8e7c
|
@ -182,6 +182,10 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
membersPagePath: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
const defaults = {
|
const defaults = {
|
||||||
|
@ -521,12 +525,22 @@ export default {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="!visibilityAllowed(visibilityLevel)" class="form-text text-muted">{{
|
<span
|
||||||
s__(
|
v-if="!visibilityAllowed(visibilityLevel)"
|
||||||
'ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project.',
|
class="gl-display-block gl-text-gray-500 gl-mt-2"
|
||||||
)
|
>{{
|
||||||
}}</span>
|
s__(
|
||||||
<span class="form-text text-muted">{{ visibilityLevelDescription }}</span>
|
'ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project.',
|
||||||
|
)
|
||||||
|
}}</span
|
||||||
|
>
|
||||||
|
<span class="gl-display-block gl-text-gray-500 gl-mt-2">
|
||||||
|
<gl-sprintf :message="visibilityLevelDescription">
|
||||||
|
<template #membersPageLink="{ content }">
|
||||||
|
<gl-link class="gl-link" :href="membersPagePath">{{ content }}</gl-link>
|
||||||
|
</template>
|
||||||
|
</gl-sprintf>
|
||||||
|
</span>
|
||||||
<div v-if="showAdditonalSettings" class="gl-mt-4">
|
<div v-if="showAdditonalSettings" class="gl-mt-4">
|
||||||
<strong class="gl-display-block">{{ s__('ProjectSettings|Additional options') }}</strong>
|
<strong class="gl-display-block">{{ s__('ProjectSettings|Additional options') }}</strong>
|
||||||
<label
|
<label
|
||||||
|
|
|
@ -8,12 +8,10 @@ export const visibilityOptions = {
|
||||||
|
|
||||||
export const visibilityLevelDescriptions = {
|
export const visibilityLevelDescriptions = {
|
||||||
[visibilityOptions.PRIVATE]: __(
|
[visibilityOptions.PRIVATE]: __(
|
||||||
'The project is accessible only by members of the project. Access must be granted explicitly to each user.',
|
`Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user.`,
|
||||||
),
|
|
||||||
[visibilityOptions.INTERNAL]: __('The project can be accessed by any user who is logged in.'),
|
|
||||||
[visibilityOptions.PUBLIC]: __(
|
|
||||||
'The project can be accessed by anyone, regardless of authentication.',
|
|
||||||
),
|
),
|
||||||
|
[visibilityOptions.INTERNAL]: __('Accessible by any user who is logged in.'),
|
||||||
|
[visibilityOptions.PUBLIC]: __('Accessible by anyone, regardless of authentication.'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const featureAccessLevel = {
|
export const featureAccessLevel = {
|
||||||
|
|
|
@ -7,6 +7,7 @@ module Projects
|
||||||
|
|
||||||
before_action :authorize_read_build!
|
before_action :authorize_read_build!
|
||||||
before_action :builds, only: [:show]
|
before_action :builds, only: [:show]
|
||||||
|
before_action :validate_test_reports!, only: [:show]
|
||||||
|
|
||||||
feature_category :code_testing
|
feature_category :code_testing
|
||||||
|
|
||||||
|
@ -23,19 +24,21 @@ module Projects
|
||||||
def show
|
def show
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
if pipeline.has_expired_test_reports?
|
render json: TestSuiteSerializer
|
||||||
render json: { errors: 'Test report artifacts have expired' }, status: :not_found
|
.new(project: project, current_user: @current_user)
|
||||||
else
|
.represent(test_suite, details: true)
|
||||||
render json: TestSuiteSerializer
|
|
||||||
.new(project: project, current_user: @current_user)
|
|
||||||
.represent(test_suite, details: true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def validate_test_reports!
|
||||||
|
unless pipeline.has_test_reports?
|
||||||
|
render json: { errors: 'Test report artifacts have expired' }, status: :not_found
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def builds
|
def builds
|
||||||
@builds ||= pipeline.latest_builds.id_in(build_ids).presence || render_404
|
@builds ||= pipeline.latest_builds.id_in(build_ids).presence || render_404
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,10 +70,10 @@ module Types
|
||||||
description: 'Indicates if shared runners are enabled for the project.'
|
description: 'Indicates if shared runners are enabled for the project.'
|
||||||
|
|
||||||
field :service_desk_enabled, GraphQL::Types::Boolean, null: true,
|
field :service_desk_enabled, GraphQL::Types::Boolean, null: true,
|
||||||
description: 'Indicates if the project has service desk enabled.'
|
description: 'Indicates if the project has Service Desk enabled.'
|
||||||
|
|
||||||
field :service_desk_address, GraphQL::Types::String, null: true,
|
field :service_desk_address, GraphQL::Types::String, null: true,
|
||||||
description: 'E-mail address of the service desk.'
|
description: 'E-mail address of the Service Desk.'
|
||||||
|
|
||||||
field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
|
field :avatar_url, GraphQL::Types::String, null: true, calls_gitaly: true,
|
||||||
description: 'URL to avatar image file of the project.'
|
description: 'URL to avatar image file of the project.'
|
||||||
|
|
|
@ -388,7 +388,8 @@ module ProjectsHelper
|
||||||
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
|
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
|
||||||
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
|
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
|
||||||
pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control'),
|
pagesHelpPath: help_page_path('user/project/pages/introduction', anchor: 'gitlab-pages-access-control'),
|
||||||
issuesHelpPath: help_page_path('user/project/issues/index')
|
issuesHelpPath: help_page_path('user/project/issues/index'),
|
||||||
|
membersPagePath: project_project_members_path(project)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1297,9 +1297,9 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def has_expired_test_reports?
|
def has_test_reports?
|
||||||
strong_memoize(:has_expired_test_reports) do
|
strong_memoize(:has_test_reports) do
|
||||||
has_reports?(::Ci::JobArtifact.test_reports.expired)
|
has_reports?(::Ci::JobArtifact.test_reports)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1567,6 +1567,7 @@ class MergeRequest < ApplicationRecord
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_PROJECT_PATH', value: project.full_path)
|
variables.append(key: 'CI_MERGE_REQUEST_PROJECT_PATH', value: project.full_path)
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_PROJECT_URL', value: project.web_url)
|
variables.append(key: 'CI_MERGE_REQUEST_PROJECT_URL', value: project.web_url)
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_NAME', value: target_branch.to_s)
|
variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_NAME', value: target_branch.to_s)
|
||||||
|
variables.append(key: 'CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED', value: ProtectedBranch.protected?(target_project, target_branch).to_s)
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_TITLE', value: title)
|
variables.append(key: 'CI_MERGE_REQUEST_TITLE', value: title)
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_ASSIGNEES', value: assignee_username_list) if assignees.present?
|
variables.append(key: 'CI_MERGE_REQUEST_ASSIGNEES', value: assignee_username_list) if assignees.present?
|
||||||
variables.append(key: 'CI_MERGE_REQUEST_MILESTONE', value: milestone.title) if milestone
|
variables.append(key: 'CI_MERGE_REQUEST_MILESTONE', value: milestone.title) if milestone
|
||||||
|
|
|
@ -128,7 +128,7 @@ class RemoteMirror < ApplicationRecord
|
||||||
def sync
|
def sync
|
||||||
return unless sync?
|
return unless sync?
|
||||||
|
|
||||||
if recently_scheduled?
|
if schedule_with_delay?
|
||||||
RepositoryUpdateRemoteMirrorWorker.perform_in(backoff_delay, self.id, Time.current)
|
RepositoryUpdateRemoteMirrorWorker.perform_in(backoff_delay, self.id, Time.current)
|
||||||
else
|
else
|
||||||
RepositoryUpdateRemoteMirrorWorker.perform_async(self.id, Time.current)
|
RepositoryUpdateRemoteMirrorWorker.perform_async(self.id, Time.current)
|
||||||
|
@ -261,7 +261,8 @@ class RemoteMirror < ApplicationRecord
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def recently_scheduled?
|
def schedule_with_delay?
|
||||||
|
return false if Feature.enabled?(:remote_mirror_no_delay, project, type: :ops)
|
||||||
return false unless self.last_update_started_at
|
return false unless self.last_update_started_at
|
||||||
|
|
||||||
self.last_update_started_at >= Time.current - backoff_delay
|
self.last_update_started_at >= Time.current - backoff_delay
|
||||||
|
|
|
@ -65,7 +65,10 @@ module Projects
|
||||||
# exception.
|
# exception.
|
||||||
relations_block: -> (project) { build_fork_network_member(project) },
|
relations_block: -> (project) { build_fork_network_member(project) },
|
||||||
skip_disk_validation: skip_disk_validation,
|
skip_disk_validation: skip_disk_validation,
|
||||||
external_authorization_classification_label: @project.external_authorization_classification_label
|
external_authorization_classification_label: @project.external_authorization_classification_label,
|
||||||
|
suggestion_commit_message: @project.suggestion_commit_message,
|
||||||
|
merge_commit_template: @project.merge_commit_template,
|
||||||
|
squash_commit_template: @project.squash_commit_template
|
||||||
}
|
}
|
||||||
|
|
||||||
if @project.avatar.present? && @project.avatar.image?
|
if @project.avatar.present? && @project.avatar.image?
|
||||||
|
|
|
@ -10,8 +10,8 @@ module ProtectedBranches
|
||||||
{
|
{
|
||||||
name: params[:name],
|
name: params[:name],
|
||||||
allow_force_push: allow_force_push?,
|
allow_force_push: allow_force_push?,
|
||||||
push_access_levels_attributes: AccessLevelParams.new(:push, params).access_levels,
|
push_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:push, params).access_levels,
|
||||||
merge_access_levels_attributes: AccessLevelParams.new(:merge, params).access_levels
|
merge_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:merge, params).access_levels
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
module ProtectedBranches
|
module ProtectedRefs
|
||||||
class AccessLevelParams
|
class AccessLevelParams
|
||||||
attr_reader :type, :params
|
attr_reader :type, :params
|
||||||
|
|
||||||
|
@ -34,4 +34,4 @@ module ProtectedBranches
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ProtectedBranches::AccessLevelParams.prepend_mod_with('ProtectedBranches::AccessLevelParams')
|
ProtectedRefs::AccessLevelParams.prepend_mod_with('ProtectedRefs::AccessLevelParams')
|
|
@ -1,7 +1,9 @@
|
||||||
- page_title _("Sign in")
|
- page_title _("Sign in")
|
||||||
- content_for :page_specific_javascripts do
|
- content_for :page_specific_javascripts do
|
||||||
|
= render "layouts/google_tag_manager_head"
|
||||||
= render "layouts/one_trust"
|
= render "layouts/one_trust"
|
||||||
= render "layouts/bizible"
|
= render "layouts/bizible"
|
||||||
|
= render "layouts/google_tag_manager_body"
|
||||||
|
|
||||||
#signin-container
|
#signin-container
|
||||||
- if any_form_based_providers_enabled?
|
- if any_form_based_providers_enabled?
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
name: remote_mirror_no_delay
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92093
|
||||||
|
milestone: '15.2'
|
||||||
|
type: ops
|
||||||
|
group: group::scalability
|
||||||
|
default_enabled: false
|
|
@ -0,0 +1,8 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class LimitProjectAndGroupVariables < Gitlab::Database::Migration[2.0]
|
||||||
|
def change
|
||||||
|
add_column(:plan_limits, :project_ci_variables, :integer, default: 200, null: false)
|
||||||
|
add_column(:plan_limits, :group_ci_variables, :integer, default: 200, null: false)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ValidateRequirementsIssueIdNotNull < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
constraint_name = 'check_requirement_issue_not_null'
|
||||||
|
|
||||||
|
validate_not_null_constraint(:requirements, :issue_id, constraint_name: constraint_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# No op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
dc449f4ea28da3662fce663dcd5cdc9e37417e14b39e26897cc35a2bebfa22f0
|
|
@ -0,0 +1 @@
|
||||||
|
755e06f8bd3a0a28820f6ec2ee52a39a7920eb9d8ae0315a8a179139c78645d9
|
|
@ -18834,7 +18834,9 @@ CREATE TABLE plan_limits (
|
||||||
repository_size bigint DEFAULT 0 NOT NULL,
|
repository_size bigint DEFAULT 0 NOT NULL,
|
||||||
security_policy_scan_execution_schedules integer DEFAULT 0 NOT NULL,
|
security_policy_scan_execution_schedules integer DEFAULT 0 NOT NULL,
|
||||||
web_hook_calls_mid integer DEFAULT 0 NOT NULL,
|
web_hook_calls_mid integer DEFAULT 0 NOT NULL,
|
||||||
web_hook_calls_low integer DEFAULT 0 NOT NULL
|
web_hook_calls_low integer DEFAULT 0 NOT NULL,
|
||||||
|
project_ci_variables integer DEFAULT 200 NOT NULL,
|
||||||
|
group_ci_variables integer DEFAULT 200 NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE plan_limits_id_seq
|
CREATE SEQUENCE plan_limits_id_seq
|
||||||
|
@ -20277,7 +20279,8 @@ CREATE TABLE requirements (
|
||||||
description text,
|
description text,
|
||||||
description_html text,
|
description_html text,
|
||||||
issue_id bigint,
|
issue_id bigint,
|
||||||
CONSTRAINT check_785ae25b9d CHECK ((char_length(description) <= 10000))
|
CONSTRAINT check_785ae25b9d CHECK ((char_length(description) <= 10000)),
|
||||||
|
CONSTRAINT check_requirement_issue_not_null CHECK ((issue_id IS NOT NULL))
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE requirements_id_seq
|
CREATE SEQUENCE requirements_id_seq
|
||||||
|
@ -24510,9 +24513,6 @@ ALTER TABLE sprints
|
||||||
ALTER TABLE projects
|
ALTER TABLE projects
|
||||||
ADD CONSTRAINT check_fa75869cb1 CHECK ((project_namespace_id IS NOT NULL)) NOT VALID;
|
ADD CONSTRAINT check_fa75869cb1 CHECK ((project_namespace_id IS NOT NULL)) NOT VALID;
|
||||||
|
|
||||||
ALTER TABLE requirements
|
|
||||||
ADD CONSTRAINT check_requirement_issue_not_null CHECK ((issue_id IS NOT NULL)) NOT VALID;
|
|
||||||
|
|
||||||
ALTER TABLE ONLY ci_build_needs
|
ALTER TABLE ONLY ci_build_needs
|
||||||
ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY (id);
|
ADD CONSTRAINT ci_build_needs_pkey PRIMARY KEY (id);
|
||||||
|
|
||||||
|
|
|
@ -15183,8 +15183,8 @@ Represents vulnerability finding of a security report on the pipeline.
|
||||||
| <a id="projectsecuritydashboardpath"></a>`securityDashboardPath` | [`String`](#string) | Path to project's security dashboard. |
|
| <a id="projectsecuritydashboardpath"></a>`securityDashboardPath` | [`String`](#string) | Path to project's security dashboard. |
|
||||||
| <a id="projectsecurityscanners"></a>`securityScanners` | [`SecurityScanners`](#securityscanners) | Information about security analyzers used in the project. |
|
| <a id="projectsecurityscanners"></a>`securityScanners` | [`SecurityScanners`](#securityscanners) | Information about security analyzers used in the project. |
|
||||||
| <a id="projectsentryerrors"></a>`sentryErrors` | [`SentryErrorCollection`](#sentryerrorcollection) | Paginated collection of Sentry errors on the project. |
|
| <a id="projectsentryerrors"></a>`sentryErrors` | [`SentryErrorCollection`](#sentryerrorcollection) | Paginated collection of Sentry errors on the project. |
|
||||||
| <a id="projectservicedeskaddress"></a>`serviceDeskAddress` | [`String`](#string) | E-mail address of the service desk. |
|
| <a id="projectservicedeskaddress"></a>`serviceDeskAddress` | [`String`](#string) | E-mail address of the Service Desk. |
|
||||||
| <a id="projectservicedeskenabled"></a>`serviceDeskEnabled` | [`Boolean`](#boolean) | Indicates if the project has service desk enabled. |
|
| <a id="projectservicedeskenabled"></a>`serviceDeskEnabled` | [`Boolean`](#boolean) | Indicates if the project has Service Desk enabled. |
|
||||||
| <a id="projectsharedrunnersenabled"></a>`sharedRunnersEnabled` | [`Boolean`](#boolean) | Indicates if shared runners are enabled for the project. |
|
| <a id="projectsharedrunnersenabled"></a>`sharedRunnersEnabled` | [`Boolean`](#boolean) | Indicates if shared runners are enabled for the project. |
|
||||||
| <a id="projectsnippetsenabled"></a>`snippetsEnabled` | [`Boolean`](#boolean) | Indicates if Snippets are enabled for the current user. |
|
| <a id="projectsnippetsenabled"></a>`snippetsEnabled` | [`Boolean`](#boolean) | Indicates if Snippets are enabled for the current user. |
|
||||||
| <a id="projectsquashcommittemplate"></a>`squashCommitTemplate` | [`String`](#string) | Template used to create squash commit message in merge requests. |
|
| <a id="projectsquashcommittemplate"></a>`squashCommitTemplate` | [`String`](#string) | Template used to create squash commit message in merge requests. |
|
||||||
|
|
|
@ -100,6 +100,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitla
|
||||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||||
| `name` | string | yes | The name of the tag or wildcard |
|
| `name` | string | yes | The name of the tag or wildcard |
|
||||||
| `create_access_level` | string | no | Access levels allowed to create (defaults: `40`, Maintainer role) |
|
| `create_access_level` | string | no | Access levels allowed to create (defaults: `40`, Maintainer role) |
|
||||||
|
| `allowed_to_create` | array | no | Array of access levels allowed to create tags, with each described by a hash of the form `{user_id: integer}`, `{group_id: integer}`, or `{access_level: integer}` |
|
||||||
|
|
||||||
Example response:
|
Example response:
|
||||||
|
|
||||||
|
|
|
@ -139,29 +139,30 @@ These variables are available when:
|
||||||
- The pipelines [are merge request pipelines](../pipelines/merge_request_pipelines.md).
|
- The pipelines [are merge request pipelines](../pipelines/merge_request_pipelines.md).
|
||||||
- The merge request is open.
|
- The merge request is open.
|
||||||
|
|
||||||
| Variable | GitLab | Runner | Description |
|
| Variable | GitLab | Runner | Description |
|
||||||
|----------------------------------------|--------|--------|-------------|
|
|---------------------------------------------|--------|--------|-------------|
|
||||||
| `CI_MERGE_REQUEST_APPROVED` | 14.1 | all | Approval status of the merge request. `true` when [merge request approvals](../../user/project/merge_requests/approvals/index.md) is available and the merge request has been approved. |
|
| `CI_MERGE_REQUEST_APPROVED` | 14.1 | all | Approval status of the merge request. `true` when [merge request approvals](../../user/project/merge_requests/approvals/index.md) is available and the merge request has been approved. |
|
||||||
| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of usernames of assignees for the merge request. |
|
| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of usernames of assignees for the merge request. |
|
||||||
| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. This is a unique ID across all projects on GitLab. |
|
| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. This is a unique ID across all projects on GitLab. |
|
||||||
| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. This ID is unique for the current project. |
|
| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. This ID is unique for the current project. |
|
||||||
| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request. |
|
| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request. |
|
| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request. |
|
| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request. For example `namespace/awesome-project`. |
|
| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request. For example `namespace/awesome-project`. |
|
||||||
| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request. For example, `http://192.168.10.15:3000/namespace/awesome-project`. |
|
| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request. For example, `http://192.168.10.15:3000/namespace/awesome-project`. |
|
||||||
| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request. For example, `refs/merge-requests/1/head`. |
|
| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request. For example, `refs/merge-requests/1/head`. |
|
||||||
| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request. |
|
| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
|
| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
|
||||||
| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request. |
|
| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request. |
|
| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request. |
|
| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request. |
|
| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
|
| `CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED` | 15.2 | all | The protection status for the target branch of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request. |
|
| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request. The variable is empty in merge request pipelines. The SHA is present only in [merged results pipelines](../pipelines/merged_results_pipelines.md). |
|
||||||
| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | The event type of the merge request. Can be `detached`, `merged_result` or `merge_train`. |
|
| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request. |
|
||||||
| `CI_MERGE_REQUEST_DIFF_ID` | 13.7 | all | The version of the merge request diff. |
|
| `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | The event type of the merge request. Can be `detached`, `merged_result` or `merge_train`. |
|
||||||
| `CI_MERGE_REQUEST_DIFF_BASE_SHA` | 13.7 | all | The base SHA of the merge request diff. |
|
| `CI_MERGE_REQUEST_DIFF_ID` | 13.7 | all | The version of the merge request diff. |
|
||||||
|
| `CI_MERGE_REQUEST_DIFF_BASE_SHA` | 13.7 | all | The base SHA of the merge request diff. |
|
||||||
|
|
||||||
## Predefined variables for external pull request pipelines
|
## Predefined variables for external pull request pipelines
|
||||||
|
|
||||||
|
|
|
@ -520,6 +520,8 @@ Feature.remove(:feature_flag_name)
|
||||||
```
|
```
|
||||||
|
|
||||||
- Any change behind a feature flag that is **enabled** by default **should** have a changelog entry.
|
- Any change behind a feature flag that is **enabled** by default **should** have a changelog entry.
|
||||||
|
- The changelog for a feature flag should describe the feature and not the
|
||||||
|
flag, unless a default on feature flag is removed keeping the new code (`other` in the flowchart above).
|
||||||
|
|
||||||
## Feature flags in tests
|
## Feature flags in tests
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module API
|
||||||
|
module Helpers
|
||||||
|
module ProtectedTagsHelpers
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
extend Grape::API::Helpers
|
||||||
|
|
||||||
|
params :optional_params_ee do
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
API::Helpers::ProtectedTagsHelpers.prepend_mod_with('API::Helpers::ProtectedTagsHelpers')
|
|
@ -10,6 +10,8 @@ module API
|
||||||
|
|
||||||
feature_category :source_code_management
|
feature_category :source_code_management
|
||||||
|
|
||||||
|
helpers Helpers::ProtectedTagsHelpers
|
||||||
|
|
||||||
params do
|
params do
|
||||||
requires :id, type: String, desc: 'The ID of a project'
|
requires :id, type: String, desc: 'The ID of a project'
|
||||||
end
|
end
|
||||||
|
@ -50,14 +52,15 @@ module API
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :name, type: String, desc: 'The name of the protected tag'
|
requires :name, type: String, desc: 'The name of the protected tag'
|
||||||
optional :create_access_level, type: Integer, default: Gitlab::Access::MAINTAINER,
|
optional :create_access_level, type: Integer,
|
||||||
values: ProtectedTag::CreateAccessLevel.allowed_access_levels,
|
values: ProtectedTag::CreateAccessLevel.allowed_access_levels,
|
||||||
desc: 'Access levels allowed to create (defaults: `40`, maintainer access level)'
|
desc: 'Access levels allowed to create (defaults: `40`, maintainer access level)'
|
||||||
|
use :optional_params_ee
|
||||||
end
|
end
|
||||||
post ':id/protected_tags' do
|
post ':id/protected_tags' do
|
||||||
protected_tags_params = {
|
protected_tags_params = {
|
||||||
name: params[:name],
|
name: params[:name],
|
||||||
create_access_levels_attributes: [{ access_level: params[:create_access_level] }]
|
create_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:create, params).access_levels
|
||||||
}
|
}
|
||||||
|
|
||||||
protected_tag = ::ProtectedTags::CreateService.new(user_project,
|
protected_tag = ::ProtectedTags::CreateService.new(user_project,
|
||||||
|
|
|
@ -1979,6 +1979,12 @@ msgstr ""
|
||||||
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
|
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Accessible by any user who is logged in."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Accessible by anyone, regardless of authentication."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Account"
|
msgid "Account"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -27093,6 +27099,9 @@ msgstr ""
|
||||||
msgid "Only Task can be assigned as a child in hierarchy."
|
msgid "Only Task can be assigned as a child in hierarchy."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Only active projects show up in the search and on the dashboard."
|
msgid "Only active projects show up in the search and on the dashboard."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -38859,21 +38868,12 @@ msgstr ""
|
||||||
msgid "The project can be accessed by any logged in user except external users."
|
msgid "The project can be accessed by any logged in user except external users."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The project can be accessed by any user who is logged in."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "The project can be accessed by anyone, regardless of authentication."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "The project can be accessed without any authentication."
|
msgid "The project can be accessed without any authentication."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The project has already been added to your dashboard."
|
msgid "The project has already been added to your dashboard."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The project is accessible only by members of the project. Access must be granted explicitly to each user."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "The project is still being deleted. Please try again later."
|
msgid "The project is still being deleted. Please try again later."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,21 @@ RSpec.describe Projects::Pipelines::TestsController do
|
||||||
pipeline.job_artifacts.first.update!(expire_at: Date.yesterday)
|
pipeline.job_artifacts.first.update!(expire_at: Date.yesterday)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'renders test suite', :aggregate_failures do
|
||||||
|
get_tests_show_json(build_ids)
|
||||||
|
|
||||||
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
|
expect(json_response['name']).to eq('test')
|
||||||
|
expect(json_response['total_count']).to eq(3)
|
||||||
|
expect(json_response['test_cases'].size).to eq(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when artifacts do not exist' do
|
||||||
|
before do
|
||||||
|
pipeline.job_artifacts.each(&:destroy)
|
||||||
|
end
|
||||||
|
|
||||||
it 'renders not_found errors', :aggregate_failures do
|
it 'renders not_found errors', :aggregate_failures do
|
||||||
get_tests_show_json(build_ids)
|
get_tests_show_json(build_ids)
|
||||||
|
|
||||||
|
@ -68,7 +83,6 @@ RSpec.describe Projects::Pipelines::TestsController do
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:ok)
|
expect(response).to have_gitlab_http_status(:ok)
|
||||||
expect(json_response['name']).to eq('test')
|
expect(json_response['name']).to eq('test')
|
||||||
expect(json_response['artifacts_expired']).to be_falsey
|
|
||||||
|
|
||||||
# Each test failure in this pipeline has a matching failure in the default branch
|
# Each test failure in this pipeline has a matching failure in the default branch
|
||||||
recent_failures = json_response['test_cases'].map { |tc| tc['recent_failures'] }
|
recent_failures = json_response['test_cases'].map { |tc| tc['recent_failures'] }
|
||||||
|
|
|
@ -16,7 +16,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
|
||||||
visibility_select_container = find('.project-visibility-setting')
|
visibility_select_container = find('.project-visibility-setting')
|
||||||
|
|
||||||
expect(visibility_select_container.find('select').value).to eq project.visibility_level.to_s
|
expect(visibility_select_container.find('select').value).to eq project.visibility_level.to_s
|
||||||
expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
|
expect(visibility_select_container).to have_content 'Accessible by anyone, regardless of authentication.'
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'project visibility description updates on change' do
|
it 'project visibility description updates on change' do
|
||||||
|
@ -25,7 +25,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
|
||||||
visibility_select.select('Private')
|
visibility_select.select('Private')
|
||||||
|
|
||||||
expect(visibility_select.value).to eq '0'
|
expect(visibility_select.value).to eq '0'
|
||||||
expect(visibility_select_container).to have_content 'Access must be granted explicitly to each user.'
|
expect(visibility_select_container).to have_content 'Only accessible by project members. Membership must be explicitly granted to each user.'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'merge requests select' do
|
context 'merge requests select' do
|
||||||
|
@ -86,7 +86,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
|
||||||
visibility_select_container = find('.project-visibility-setting')
|
visibility_select_container = find('.project-visibility-setting')
|
||||||
|
|
||||||
expect(visibility_select_container).to have_selector 'select[name="project[visibility_level]"]:disabled'
|
expect(visibility_select_container).to have_selector 'select[name="project[visibility_level]"]:disabled'
|
||||||
expect(visibility_select_container).to have_content 'The project can be accessed by anyone, regardless of authentication.'
|
expect(visibility_select_container).to have_content 'Accessible by anyone, regardless of authentication.'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'disable email notifications' do
|
context 'disable email notifications' do
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
// FIXME(vslobodin): Remove this stub once we have migrated to Jest 28.
|
||||||
|
// NOTE: Do not try to optimize these stubs as Jest 27 overwrites
|
||||||
|
// the "global.performance" object in every suite where fake timers are enabled.
|
||||||
|
export const stubPerformanceWebAPI = () => {
|
||||||
|
global.performance.getEntriesByName = () => [];
|
||||||
|
global.performance.mark = () => {};
|
||||||
|
global.performance.measure = () => {};
|
||||||
|
};
|
|
@ -1,6 +1,7 @@
|
||||||
import { GlIcon } from '@gitlab/ui';
|
import { GlIcon } from '@gitlab/ui';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import DesignImage from '~/design_management/components/image.vue';
|
import DesignImage from '~/design_management/components/image.vue';
|
||||||
|
|
||||||
describe('Design management large image component', () => {
|
describe('Design management large image component', () => {
|
||||||
|
@ -15,6 +16,10 @@ describe('Design management large image component', () => {
|
||||||
wrapper.setData(data);
|
wrapper.setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@ import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
|
||||||
|
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import * as urlUtils from '~/lib/utils/url_utility';
|
import * as urlUtils from '~/lib/utils/url_utility';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import createDiffsStore from '../create_diffs_store';
|
import createDiffsStore from '../create_diffs_store';
|
||||||
import diffsMockData from '../mock_data/merge_request_diffs';
|
import diffsMockData from '../mock_data/merge_request_diffs';
|
||||||
|
|
||||||
|
@ -79,6 +80,7 @@ describe('diffs/components/app', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
// setup globals (needed for component to mount :/)
|
// setup globals (needed for component to mount :/)
|
||||||
window.mrTabs = {
|
window.mrTabs = {
|
||||||
resetViewContainer: jest.fn(),
|
resetViewContainer: jest.fn(),
|
||||||
|
|
|
@ -67,12 +67,6 @@ class CustomEnvironment extends JSDOMEnvironment {
|
||||||
// Expose the jsdom (created in super class) to the global so that we can call reconfigure({ url: '' }) to properly set `window.location`
|
// Expose the jsdom (created in super class) to the global so that we can call reconfigure({ url: '' }) to properly set `window.location`
|
||||||
this.global.jsdom = this.dom;
|
this.global.jsdom = this.dom;
|
||||||
|
|
||||||
Object.assign(this.global.performance, {
|
|
||||||
mark: () => null,
|
|
||||||
measure: () => null,
|
|
||||||
getEntriesByName: () => [],
|
|
||||||
});
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Monaco-related environment variables
|
// Monaco-related environment variables
|
||||||
//
|
//
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
|
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
|
||||||
import ErrorMessage from '~/ide/components/error_message.vue';
|
import ErrorMessage from '~/ide/components/error_message.vue';
|
||||||
import Ide from '~/ide/components/ide.vue';
|
import Ide from '~/ide/components/ide.vue';
|
||||||
|
@ -40,6 +41,8 @@ describe('WebIDE', () => {
|
||||||
const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
|
const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
store = createStore();
|
store = createStore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import Vuex from 'vuex';
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils';
|
||||||
import '~/behaviors/markdown/render_gfm';
|
import '~/behaviors/markdown/render_gfm';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
|
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
|
||||||
import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
|
import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
|
||||||
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
|
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
|
||||||
|
@ -130,6 +131,8 @@ describe('RepoEditor', () => {
|
||||||
const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]');
|
const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]');
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
createInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_CODE_INSTANCE_FN);
|
createInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_CODE_INSTANCE_FN);
|
||||||
createDiffInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_DIFF_INSTANCE_FN);
|
createDiffInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_DIFF_INSTANCE_FN);
|
||||||
createModelSpy = jest.spyOn(monacoEditor, 'createModel');
|
createModelSpy = jest.spyOn(monacoEditor, 'createModel');
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import { createRouter } from '~/ide/ide_router';
|
import { createRouter } from '~/ide/ide_router';
|
||||||
import { createStore } from '~/ide/stores';
|
import { createStore } from '~/ide/stores';
|
||||||
|
|
||||||
|
@ -12,6 +13,8 @@ describe('IDE router', () => {
|
||||||
let router;
|
let router;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
window.history.replaceState({}, '', '/');
|
window.history.replaceState({}, '', '/');
|
||||||
store = createStore();
|
store = createStore();
|
||||||
router = createRouter(store, DEFAULT_BRANCH);
|
router = createRouter(store, DEFAULT_BRANCH);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { createStore } from '~/ide/stores';
|
||||||
import * as actions from '~/ide/stores/actions/file';
|
import * as actions from '~/ide/stores/actions/file';
|
||||||
import * as types from '~/ide/stores/mutation_types';
|
import * as types from '~/ide/stores/mutation_types';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import { file, createTriggerRenameAction, createTriggerUpdatePayload } from '../../helpers';
|
import { file, createTriggerRenameAction, createTriggerUpdatePayload } from '../../helpers';
|
||||||
|
|
||||||
const ORIGINAL_CONTENT = 'original content';
|
const ORIGINAL_CONTENT = 'original content';
|
||||||
|
@ -19,6 +20,8 @@ describe('IDE store file actions', () => {
|
||||||
let router;
|
let router;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
mock = new MockAdapter(axios);
|
mock = new MockAdapter(axios);
|
||||||
originalGon = window.gon;
|
originalGon = window.gon;
|
||||||
window.gon = {
|
window.gon = {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
import { range } from 'lodash';
|
import { range } from 'lodash';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import testAction from 'helpers/vuex_action_helper';
|
import testAction from 'helpers/vuex_action_helper';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
|
@ -35,6 +36,8 @@ describe('IDE store merge request actions', () => {
|
||||||
let mock;
|
let mock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
store = createStore();
|
store = createStore();
|
||||||
|
|
||||||
mock = new MockAdapter(axios);
|
mock = new MockAdapter(axios);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
import testAction from 'helpers/vuex_action_helper';
|
import testAction from 'helpers/vuex_action_helper';
|
||||||
import { createRouter } from '~/ide/ide_router';
|
import { createRouter } from '~/ide/ide_router';
|
||||||
|
@ -24,6 +25,8 @@ describe('Multi-file store tree actions', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
store = createStore();
|
store = createStore();
|
||||||
router = createRouter(store);
|
router = createRouter(store);
|
||||||
jest.spyOn(router, 'push').mockImplementation();
|
jest.spyOn(router, 'push').mockImplementation();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import MockAdapter from 'axios-mock-adapter';
|
import MockAdapter from 'axios-mock-adapter';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import testAction from 'helpers/vuex_action_helper';
|
import testAction from 'helpers/vuex_action_helper';
|
||||||
import eventHub from '~/ide/eventhub';
|
import eventHub from '~/ide/eventhub';
|
||||||
import { createRouter } from '~/ide/ide_router';
|
import { createRouter } from '~/ide/ide_router';
|
||||||
|
@ -34,6 +35,8 @@ describe('Multi-file store actions', () => {
|
||||||
let router;
|
let router;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
store = createStore();
|
store = createStore();
|
||||||
router = createRouter(store);
|
router = createRouter(store);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||||
import initMrPage from 'helpers/init_vue_mr_page_helper';
|
import initMrPage from 'helpers/init_vue_mr_page_helper';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import MergeRequestTabs from '~/merge_request_tabs';
|
import MergeRequestTabs from '~/merge_request_tabs';
|
||||||
import '~/lib/utils/common_utils';
|
import '~/lib/utils/common_utils';
|
||||||
|
@ -24,6 +25,8 @@ describe('MergeRequestTabs', () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
initMrPage();
|
initMrPage();
|
||||||
|
|
||||||
testContext.class = new MergeRequestTabs({ stubLocation });
|
testContext.class = new MergeRequestTabs({ stubLocation });
|
||||||
|
@ -350,10 +353,6 @@ describe('MergeRequestTabs', () => {
|
||||||
describe('when switching tabs', () => {
|
describe('when switching tabs', () => {
|
||||||
const SCROLL_TOP = 100;
|
const SCROLL_TOP = 100;
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
jest.useFakeTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
||||||
testContext.class.mergeRequestTabs = document.createElement('div');
|
testContext.class.mergeRequestTabs = document.createElement('div');
|
||||||
|
@ -362,10 +361,6 @@ describe('MergeRequestTabs', () => {
|
||||||
testContext.class.scrollPositions = { newTab: SCROLL_TOP };
|
testContext.class.scrollPositions = { newTab: SCROLL_TOP };
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('scrolls to the stored position, if one is stored', () => {
|
it('scrolls to the stored position, if one is stored', () => {
|
||||||
testContext.class.tabShown('newTab');
|
testContext.class.tabShown('newTab');
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@ const defaultProps = {
|
||||||
requestCveAvailable: true,
|
requestCveAvailable: true,
|
||||||
confirmationPhrase: 'my-fake-project',
|
confirmationPhrase: 'my-fake-project',
|
||||||
showVisibilityConfirmModal: false,
|
showVisibilityConfirmModal: false,
|
||||||
|
membersPagePath: '/my-fake-project/-/project_members',
|
||||||
};
|
};
|
||||||
|
|
||||||
const FEATURE_ACCESS_LEVEL_ANONYMOUS = 30;
|
const FEATURE_ACCESS_LEVEL_ANONYMOUS = 30;
|
||||||
|
@ -59,7 +60,7 @@ describe('Settings Panel', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
|
||||||
const mountComponent = (
|
const mountComponent = (
|
||||||
{ currentSettings = {}, glFeatures = {}, ...customProps } = {},
|
{ currentSettings = {}, glFeatures = {}, stubs = {}, ...customProps } = {},
|
||||||
mountFn = shallowMount,
|
mountFn = shallowMount,
|
||||||
) => {
|
) => {
|
||||||
const propsData = {
|
const propsData = {
|
||||||
|
@ -76,6 +77,7 @@ describe('Settings Panel', () => {
|
||||||
...glFeatures,
|
...glFeatures,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
stubs,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,7 +178,7 @@ describe('Settings Panel', () => {
|
||||||
);
|
);
|
||||||
|
|
||||||
it('should set the visibility level description based upon the selected visibility level', () => {
|
it('should set the visibility level description based upon the selected visibility level', () => {
|
||||||
wrapper = mountComponent();
|
wrapper = mountComponent({ stubs: { GlSprintf } });
|
||||||
|
|
||||||
findProjectVisibilityLevelInput().setValue(visibilityOptions.INTERNAL);
|
findProjectVisibilityLevelInput().setValue(visibilityOptions.INTERNAL);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.query.graphql';
|
||||||
import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
|
import getUserCallouts from '~/graphql_shared/queries/get_user_callouts.query.graphql';
|
||||||
|
@ -502,9 +503,7 @@ describe('Pipeline graph wrapper', () => {
|
||||||
|
|
||||||
describe('when no duration is obtained', () => {
|
describe('when no duration is obtained', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.spyOn(window.performance, 'getEntriesByName').mockImplementation(() => {
|
stubPerformanceWebAPI();
|
||||||
return [];
|
|
||||||
});
|
|
||||||
|
|
||||||
createComponentWithApollo({
|
createComponentWithApollo({
|
||||||
provide: {
|
provide: {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { merge } from 'lodash';
|
||||||
import VueApollo, { ApolloMutation } from 'vue-apollo';
|
import VueApollo, { ApolloMutation } from 'vue-apollo';
|
||||||
import { useFakeDate } from 'helpers/fake_date';
|
import { useFakeDate } from 'helpers/fake_date';
|
||||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||||
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
|
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
|
||||||
|
@ -96,6 +97,8 @@ describe('Snippet Edit app', () => {
|
||||||
const originalRelativeUrlRoot = gon.relative_url_root;
|
const originalRelativeUrlRoot = gon.relative_url_root;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
getSpy = jest.fn().mockResolvedValue(createQueryResponse());
|
getSpy = jest.fn().mockResolvedValue(createQueryResponse());
|
||||||
|
|
||||||
// See `mutateSpy` declaration comment for why we send a key
|
// See `mutateSpy` declaration comment for why we send a key
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
SNIPPET_VISIBILITY_PUBLIC,
|
SNIPPET_VISIBILITY_PUBLIC,
|
||||||
} from '~/snippets/constants';
|
} from '~/snippets/constants';
|
||||||
import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
|
import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
|
|
||||||
describe('Snippet view app', () => {
|
describe('Snippet view app', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
@ -45,6 +46,10 @@ describe('Snippet view app', () => {
|
||||||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||||
const findEmbedDropdown = () => wrapper.findComponent(EmbedDropdown);
|
const findEmbedDropdown = () => wrapper.findComponent(EmbedDropdown);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { waitFor } from '@testing-library/dom';
|
import { waitFor } from '@testing-library/dom';
|
||||||
import setWindowLocation from 'helpers/set_window_location_helper';
|
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||||
import { TEST_HOST } from 'helpers/test_constants';
|
import { TEST_HOST } from 'helpers/test_constants';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import initDiffsApp from '~/diffs';
|
import initDiffsApp from '~/diffs';
|
||||||
import { createStore } from '~/mr_notes/stores';
|
import { createStore } from '~/mr_notes/stores';
|
||||||
import {
|
import {
|
||||||
|
@ -74,6 +75,10 @@ const startDiffsApp = () => {
|
||||||
describe('diffs third party interoperability', () => {
|
describe('diffs third party interoperability', () => {
|
||||||
let vm;
|
let vm;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vm.$destroy();
|
vm.$destroy();
|
||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
|
|
|
@ -3,8 +3,9 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||||
import { setTestTimeout } from 'helpers/timeout';
|
import { setTestTimeout } from 'helpers/timeout';
|
||||||
import waitForPromises from 'helpers/wait_for_promises';
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
import { waitForText } from 'helpers/wait_for_text';
|
import { waitForText } from 'helpers/wait_for_text';
|
||||||
import { createCommitId } from 'test_helpers/factories/commit_id';
|
|
||||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||||
|
import { createCommitId } from 'test_helpers/factories/commit_id';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import * as ideHelper from './helpers/ide_helper';
|
import * as ideHelper from './helpers/ide_helper';
|
||||||
import startWebIDE from './helpers/start';
|
import startWebIDE from './helpers/start';
|
||||||
|
|
||||||
|
@ -15,6 +16,7 @@ describe('WebIDE', () => {
|
||||||
let container;
|
let container;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
// For some reason these tests were timing out in CI.
|
// For some reason these tests were timing out in CI.
|
||||||
// We will investigate in https://gitlab.com/gitlab-org/gitlab/-/issues/298714
|
// We will investigate in https://gitlab.com/gitlab-org/gitlab/-/issues/298714
|
||||||
setTestTimeout(20000);
|
setTestTimeout(20000);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { screen } from '@testing-library/dom';
|
import { screen } from '@testing-library/dom';
|
||||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import * as ideHelper from './helpers/ide_helper';
|
import * as ideHelper from './helpers/ide_helper';
|
||||||
import startWebIDE from './helpers/start';
|
import startWebIDE from './helpers/start';
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ describe('IDE: User opens a file in the Web IDE', () => {
|
||||||
let container;
|
let container;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
setHTMLFixture('<div class="webide-container"></div>');
|
setHTMLFixture('<div class="webide-container"></div>');
|
||||||
container = document.querySelector('.webide-container');
|
container = document.querySelector('.webide-container');
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { screen } from '@testing-library/dom';
|
import { screen } from '@testing-library/dom';
|
||||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import * as ideHelper from './helpers/ide_helper';
|
import * as ideHelper from './helpers/ide_helper';
|
||||||
import startWebIDE from './helpers/start';
|
import startWebIDE from './helpers/start';
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ describe('IDE: User opens IDE', () => {
|
||||||
let container;
|
let container;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
setHTMLFixture('<div class="webide-container"></div>');
|
setHTMLFixture('<div class="webide-container"></div>');
|
||||||
container = document.querySelector('.webide-container');
|
container = document.querySelector('.webide-container');
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { basename } from 'path';
|
||||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||||
import { getMergeRequests, getMergeRequestWithChanges } from 'test_helpers/fixtures';
|
import { getMergeRequests, getMergeRequestWithChanges } from 'test_helpers/fixtures';
|
||||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||||
|
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||||
import * as ideHelper from './helpers/ide_helper';
|
import * as ideHelper from './helpers/ide_helper';
|
||||||
import startWebIDE from './helpers/start';
|
import startWebIDE from './helpers/start';
|
||||||
|
|
||||||
|
@ -16,6 +17,8 @@ describe('IDE: User opens Merge Request', () => {
|
||||||
let changes;
|
let changes;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
stubPerformanceWebAPI();
|
||||||
|
|
||||||
const [{ iid: mrId }] = getMergeRequests();
|
const [{ iid: mrId }] = getMergeRequests();
|
||||||
|
|
||||||
changes = getRelevantChanges();
|
changes = getRelevantChanges();
|
||||||
|
|
|
@ -969,6 +969,10 @@ RSpec.describe ProjectsHelper do
|
||||||
containerRegistryAccessLevel: project.project_feature.container_registry_access_level
|
containerRegistryAccessLevel: project.project_feature.container_registry_access_level
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'includes membersPagePath' do
|
||||||
|
expect(subject).to include(membersPagePath: project_project_members_path(project))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#project_classes' do
|
describe '#project_classes' do
|
||||||
|
|
|
@ -1041,6 +1041,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
||||||
'CI_MERGE_REQUEST_PROJECT_PATH' => merge_request.project.full_path,
|
'CI_MERGE_REQUEST_PROJECT_PATH' => merge_request.project.full_path,
|
||||||
'CI_MERGE_REQUEST_PROJECT_URL' => merge_request.project.web_url,
|
'CI_MERGE_REQUEST_PROJECT_URL' => merge_request.project.web_url,
|
||||||
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => merge_request.target_branch.to_s,
|
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => merge_request.target_branch.to_s,
|
||||||
|
'CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED' => ProtectedBranch.protected?(merge_request.target_project, merge_request.target_branch).to_s,
|
||||||
'CI_MERGE_REQUEST_TARGET_BRANCH_SHA' => '',
|
'CI_MERGE_REQUEST_TARGET_BRANCH_SHA' => '',
|
||||||
'CI_MERGE_REQUEST_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
'CI_MERGE_REQUEST_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
||||||
'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH' => merge_request.source_project.full_path,
|
'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH' => merge_request.source_project.full_path,
|
||||||
|
@ -1137,6 +1138,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
||||||
'CI_MERGE_REQUEST_PROJECT_PATH' => merge_request.project.full_path,
|
'CI_MERGE_REQUEST_PROJECT_PATH' => merge_request.project.full_path,
|
||||||
'CI_MERGE_REQUEST_PROJECT_URL' => merge_request.project.web_url,
|
'CI_MERGE_REQUEST_PROJECT_URL' => merge_request.project.web_url,
|
||||||
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => merge_request.target_branch.to_s,
|
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => merge_request.target_branch.to_s,
|
||||||
|
'CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED' => ProtectedBranch.protected?(merge_request.target_project, merge_request.target_branch).to_s,
|
||||||
'CI_MERGE_REQUEST_TARGET_BRANCH_SHA' => merge_request.target_branch_sha,
|
'CI_MERGE_REQUEST_TARGET_BRANCH_SHA' => merge_request.target_branch_sha,
|
||||||
'CI_MERGE_REQUEST_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
'CI_MERGE_REQUEST_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
||||||
'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH' => merge_request.source_project.full_path,
|
'CI_MERGE_REQUEST_SOURCE_PROJECT_PATH' => merge_request.source_project.full_path,
|
||||||
|
@ -4851,13 +4853,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#has_expired_test_reports?' do
|
describe '#has_test_reports?' do
|
||||||
subject { pipeline.has_expired_test_reports? }
|
subject { pipeline.has_test_reports? }
|
||||||
|
|
||||||
let(:pipeline) { create(:ci_pipeline, :success, :with_test_reports) }
|
let(:pipeline) { create(:ci_pipeline, :success, :with_test_reports) }
|
||||||
|
|
||||||
context 'when artifacts are not expired' do
|
context 'when artifacts are not expired' do
|
||||||
it { is_expected.to be_falsey }
|
it { is_expected.to be_truthy }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when artifacts are expired' do
|
context 'when artifacts are expired' do
|
||||||
|
@ -4868,6 +4870,14 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
||||||
it { is_expected.to be_truthy }
|
it { is_expected.to be_truthy }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when artifacts are removed' do
|
||||||
|
before do
|
||||||
|
pipeline.job_artifacts.each(&:destroy)
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to be_falsey }
|
||||||
|
end
|
||||||
|
|
||||||
context 'when the pipeline is still running' do
|
context 'when the pipeline is still running' do
|
||||||
let(:pipeline) { create(:ci_pipeline, :running) }
|
let(:pipeline) { create(:ci_pipeline, :running) }
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ require 'spec_helper'
|
||||||
RSpec.describe RemoteMirror, :mailer do
|
RSpec.describe RemoteMirror, :mailer do
|
||||||
include GitHelpers
|
include GitHelpers
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_feature_flags(remote_mirror_no_delay: false)
|
||||||
|
end
|
||||||
|
|
||||||
describe 'URL validation' do
|
describe 'URL validation' do
|
||||||
context 'with a valid URL' do
|
context 'with a valid URL' do
|
||||||
it 'is valid' do
|
it 'is valid' do
|
||||||
|
@ -343,6 +347,20 @@ RSpec.describe RemoteMirror, :mailer do
|
||||||
|
|
||||||
remote_mirror.sync
|
remote_mirror.sync
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when remote_mirror_no_delay is enabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(remote_mirror_no_delay: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'schedules a RepositoryUpdateRemoteMirrorWorker to run now' do
|
||||||
|
remote_mirror.last_update_started_at = Time.current - 30.seconds
|
||||||
|
|
||||||
|
expect(RepositoryUpdateRemoteMirrorWorker).to receive(:perform_async).with(remote_mirror.id, Time.current)
|
||||||
|
|
||||||
|
remote_mirror.sync
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe API::ProtectedTags do
|
RSpec.describe API::ProtectedTags do
|
||||||
let(:user) { create(:user) }
|
let_it_be(:user) { create(:user) }
|
||||||
let!(:project) { create(:project, :repository) }
|
let_it_be(:project) { create(:project, :repository) }
|
||||||
let(:project2) { create(:project, path: 'project2', namespace: user.namespace) }
|
let_it_be(:project2) { create(:project, path: 'project2', namespace: user.namespace) }
|
||||||
|
|
||||||
let(:protected_name) { 'feature' }
|
let(:protected_name) { 'feature' }
|
||||||
let(:tag_name) { protected_name }
|
let(:tag_name) { protected_name }
|
||||||
let!(:protected_tag) do
|
let!(:protected_tag) do
|
||||||
|
|
|
@ -68,6 +68,9 @@ RSpec.describe Projects::ForkService do
|
||||||
it { expect(to_project.avatar.file).to be_exists }
|
it { expect(to_project.avatar.file).to be_exists }
|
||||||
it { expect(to_project.ci_config_path).to eq(@from_project.ci_config_path) }
|
it { expect(to_project.ci_config_path).to eq(@from_project.ci_config_path) }
|
||||||
it { expect(to_project.external_authorization_classification_label).to eq(@from_project.external_authorization_classification_label) }
|
it { expect(to_project.external_authorization_classification_label).to eq(@from_project.external_authorization_classification_label) }
|
||||||
|
it { expect(to_project.suggestion_commit_message).to eq(@from_project.suggestion_commit_message) }
|
||||||
|
it { expect(to_project.merge_commit_template).to eq(@from_project.merge_commit_template) }
|
||||||
|
it { expect(to_project.squash_commit_template).to eq(@from_project.squash_commit_template) }
|
||||||
|
|
||||||
# This test is here because we had a bug where the from-project lost its
|
# This test is here because we had a bug where the from-project lost its
|
||||||
# avatar after being forked.
|
# avatar after being forked.
|
||||||
|
|
|
@ -63,6 +63,36 @@ RSpec.describe 'devise/sessions/new' do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'Google Tag Manager' do
|
||||||
|
let!(:gtm_id) { 'GTM-WWKMTWS'}
|
||||||
|
|
||||||
|
subject { rendered }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_devise
|
||||||
|
disable_captcha
|
||||||
|
stub_config(extra: { google_tag_manager_id: gtm_id, google_tag_manager_nonce_id: gtm_id })
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when Google Tag Manager is enabled' do
|
||||||
|
before do
|
||||||
|
enable_gtm
|
||||||
|
render
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to match /www.googletagmanager.com/ }
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'when Google Tag Manager is disabled' do
|
||||||
|
before do
|
||||||
|
disable_gtm
|
||||||
|
render
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.not_to match /www.googletagmanager.com/ }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def disable_other_signin_methods
|
def disable_other_signin_methods
|
||||||
allow(view).to receive(:password_authentication_enabled_for_web?).and_return(false)
|
allow(view).to receive(:password_authentication_enabled_for_web?).and_return(false)
|
||||||
allow(view).to receive(:omniauth_enabled?).and_return(false)
|
allow(view).to receive(:omniauth_enabled?).and_return(false)
|
||||||
|
@ -94,4 +124,12 @@ RSpec.describe 'devise/sessions/new' do
|
||||||
allow(view).to receive(:captcha_enabled?).and_return(false)
|
allow(view).to receive(:captcha_enabled?).and_return(false)
|
||||||
allow(view).to receive(:captcha_on_login_required?).and_return(false)
|
allow(view).to receive(:captcha_on_login_required?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def disable_gtm
|
||||||
|
allow(view).to receive(:google_tag_manager_enabled?).and_return(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
def enable_gtm
|
||||||
|
allow(view).to receive(:google_tag_manager_enabled?).and_return(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue