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,
|
||||
default: false,
|
||||
},
|
||||
membersPagePath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
const defaults = {
|
||||
|
@ -521,12 +525,22 @@ export default {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span v-if="!visibilityAllowed(visibilityLevel)" class="form-text text-muted">{{
|
||||
s__(
|
||||
'ProjectSettings|Visibility options for this fork are limited by the current visibility of the source project.',
|
||||
)
|
||||
}}</span>
|
||||
<span class="form-text text-muted">{{ visibilityLevelDescription }}</span>
|
||||
<span
|
||||
v-if="!visibilityAllowed(visibilityLevel)"
|
||||
class="gl-display-block gl-text-gray-500 gl-mt-2"
|
||||
>{{
|
||||
s__(
|
||||
'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">
|
||||
<strong class="gl-display-block">{{ s__('ProjectSettings|Additional options') }}</strong>
|
||||
<label
|
||||
|
|
|
@ -8,12 +8,10 @@ export const visibilityOptions = {
|
|||
|
||||
export const visibilityLevelDescriptions = {
|
||||
[visibilityOptions.PRIVATE]: __(
|
||||
'The project is accessible only by members of the project. Access must be granted explicitly 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.',
|
||||
`Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user.`,
|
||||
),
|
||||
[visibilityOptions.INTERNAL]: __('Accessible by any user who is logged in.'),
|
||||
[visibilityOptions.PUBLIC]: __('Accessible by anyone, regardless of authentication.'),
|
||||
};
|
||||
|
||||
export const featureAccessLevel = {
|
||||
|
|
|
@ -7,6 +7,7 @@ module Projects
|
|||
|
||||
before_action :authorize_read_build!
|
||||
before_action :builds, only: [:show]
|
||||
before_action :validate_test_reports!, only: [:show]
|
||||
|
||||
feature_category :code_testing
|
||||
|
||||
|
@ -23,19 +24,21 @@ module Projects
|
|||
def show
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
if pipeline.has_expired_test_reports?
|
||||
render json: { errors: 'Test report artifacts have expired' }, status: :not_found
|
||||
else
|
||||
render json: TestSuiteSerializer
|
||||
.new(project: project, current_user: @current_user)
|
||||
.represent(test_suite, details: true)
|
||||
end
|
||||
render json: TestSuiteSerializer
|
||||
.new(project: project, current_user: @current_user)
|
||||
.represent(test_suite, details: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
@builds ||= pipeline.latest_builds.id_in(build_ids).presence || render_404
|
||||
end
|
||||
|
|
|
@ -70,10 +70,10 @@ module Types
|
|||
description: 'Indicates if shared runners are enabled for the project.'
|
||||
|
||||
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,
|
||||
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,
|
||||
description: 'URL to avatar image file of the project.'
|
||||
|
|
|
@ -388,7 +388,8 @@ module ProjectsHelper
|
|||
pagesAccessControlEnabled: Gitlab.config.pages.access_control,
|
||||
pagesAccessControlForced: ::Gitlab::Pages.access_control_is_forced?,
|
||||
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
|
||||
|
||||
|
|
|
@ -1297,9 +1297,9 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def has_expired_test_reports?
|
||||
strong_memoize(:has_expired_test_reports) do
|
||||
has_reports?(::Ci::JobArtifact.test_reports.expired)
|
||||
def has_test_reports?
|
||||
strong_memoize(:has_test_reports) do
|
||||
has_reports?(::Ci::JobArtifact.test_reports)
|
||||
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_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_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_ASSIGNEES', value: assignee_username_list) if assignees.present?
|
||||
variables.append(key: 'CI_MERGE_REQUEST_MILESTONE', value: milestone.title) if milestone
|
||||
|
|
|
@ -128,7 +128,7 @@ class RemoteMirror < ApplicationRecord
|
|||
def sync
|
||||
return unless sync?
|
||||
|
||||
if recently_scheduled?
|
||||
if schedule_with_delay?
|
||||
RepositoryUpdateRemoteMirrorWorker.perform_in(backoff_delay, self.id, Time.current)
|
||||
else
|
||||
RepositoryUpdateRemoteMirrorWorker.perform_async(self.id, Time.current)
|
||||
|
@ -261,7 +261,8 @@ class RemoteMirror < ApplicationRecord
|
|||
super
|
||||
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
|
||||
|
||||
self.last_update_started_at >= Time.current - backoff_delay
|
||||
|
|
|
@ -65,7 +65,10 @@ module Projects
|
|||
# exception.
|
||||
relations_block: -> (project) { build_fork_network_member(project) },
|
||||
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?
|
||||
|
|
|
@ -10,8 +10,8 @@ module ProtectedBranches
|
|||
{
|
||||
name: params[:name],
|
||||
allow_force_push: allow_force_push?,
|
||||
push_access_levels_attributes: AccessLevelParams.new(:push, params).access_levels,
|
||||
merge_access_levels_attributes: AccessLevelParams.new(:merge, params).access_levels
|
||||
push_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:push, params).access_levels,
|
||||
merge_access_levels_attributes: ::ProtectedRefs::AccessLevelParams.new(:merge, params).access_levels
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ProtectedBranches
|
||||
module ProtectedRefs
|
||||
class AccessLevelParams
|
||||
attr_reader :type, :params
|
||||
|
||||
|
@ -34,4 +34,4 @@ module ProtectedBranches
|
|||
end
|
||||
end
|
||||
|
||||
ProtectedBranches::AccessLevelParams.prepend_mod_with('ProtectedBranches::AccessLevelParams')
|
||||
ProtectedRefs::AccessLevelParams.prepend_mod_with('ProtectedRefs::AccessLevelParams')
|
|
@ -1,7 +1,9 @@
|
|||
- page_title _("Sign in")
|
||||
- content_for :page_specific_javascripts do
|
||||
= render "layouts/google_tag_manager_head"
|
||||
= render "layouts/one_trust"
|
||||
= render "layouts/bizible"
|
||||
= render "layouts/google_tag_manager_body"
|
||||
|
||||
#signin-container
|
||||
- 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,
|
||||
security_policy_scan_execution_schedules 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
|
||||
|
@ -20277,7 +20279,8 @@ CREATE TABLE requirements (
|
|||
description text,
|
||||
description_html text,
|
||||
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
|
||||
|
@ -24510,9 +24513,6 @@ ALTER TABLE sprints
|
|||
ALTER TABLE projects
|
||||
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
|
||||
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="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="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="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="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="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 |
|
||||
| `name` | string | yes | The name of the tag or wildcard |
|
||||
| `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:
|
||||
|
||||
|
|
|
@ -139,29 +139,30 @@ These variables are available when:
|
|||
- The pipelines [are merge request pipelines](../pipelines/merge_request_pipelines.md).
|
||||
- The merge request is open.
|
||||
|
||||
| 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_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_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_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_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_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_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_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_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_TITLE` | 11.9 | all | The title of the merge request. |
|
||||
| `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_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. |
|
||||
| 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_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_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_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_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_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_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_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_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request. |
|
||||
| `CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED` | 15.2 | all | The protection status for the target branch 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_TITLE` | 11.9 | all | The title of the merge request. |
|
||||
| `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_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
|
||||
|
||||
|
|
|
@ -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.
|
||||
- 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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
helpers Helpers::ProtectedTagsHelpers
|
||||
|
||||
params do
|
||||
requires :id, type: String, desc: 'The ID of a project'
|
||||
end
|
||||
|
@ -50,14 +52,15 @@ module API
|
|||
end
|
||||
params do
|
||||
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,
|
||||
desc: 'Access levels allowed to create (defaults: `40`, maintainer access level)'
|
||||
use :optional_params_ee
|
||||
end
|
||||
post ':id/protected_tags' do
|
||||
protected_tags_params = {
|
||||
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,
|
||||
|
|
|
@ -1979,6 +1979,12 @@ msgstr ""
|
|||
msgid "AccessibilityReport|The accessibility scanning found an error of the following type: %{code}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Accessible by any user who is logged in."
|
||||
msgstr ""
|
||||
|
||||
msgid "Accessible by anyone, regardless of authentication."
|
||||
msgstr ""
|
||||
|
||||
msgid "Account"
|
||||
msgstr ""
|
||||
|
||||
|
@ -27093,6 +27099,9 @@ msgstr ""
|
|||
msgid "Only Task can be assigned as a child in hierarchy."
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
|
@ -38859,21 +38868,12 @@ msgstr ""
|
|||
msgid "The project can be accessed by any logged in user except external users."
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
msgid "The project has already been added to your dashboard."
|
||||
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."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -45,6 +45,21 @@ RSpec.describe Projects::Pipelines::TestsController do
|
|||
pipeline.job_artifacts.first.update!(expire_at: Date.yesterday)
|
||||
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
|
||||
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(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
|
||||
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')
|
||||
|
||||
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
|
||||
|
||||
it 'project visibility description updates on change' do
|
||||
|
@ -25,7 +25,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
|
|||
visibility_select.select('Private')
|
||||
|
||||
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
|
||||
|
||||
context 'merge requests select' do
|
||||
|
@ -86,7 +86,7 @@ RSpec.describe 'Projects > Settings > Visibility settings', :js do
|
|||
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_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
|
||||
|
||||
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 { shallowMount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import DesignImage from '~/design_management/components/image.vue';
|
||||
|
||||
describe('Design management large image component', () => {
|
||||
|
@ -15,6 +16,10 @@ describe('Design management large image component', () => {
|
|||
wrapper.setData(data);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ import HiddenFilesWarning from '~/diffs/components/hidden_files_warning.vue';
|
|||
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import * as urlUtils from '~/lib/utils/url_utility';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import createDiffsStore from '../create_diffs_store';
|
||||
import diffsMockData from '../mock_data/merge_request_diffs';
|
||||
|
||||
|
@ -79,6 +80,7 @@ describe('diffs/components/app', () => {
|
|||
}
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
// setup globals (needed for component to mount :/)
|
||||
window.mrTabs = {
|
||||
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`
|
||||
this.global.jsdom = this.dom;
|
||||
|
||||
Object.assign(this.global.performance, {
|
||||
mark: () => null,
|
||||
measure: () => null,
|
||||
getEntriesByName: () => [],
|
||||
});
|
||||
|
||||
//
|
||||
// Monaco-related environment variables
|
||||
//
|
||||
|
|
|
@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
|
|||
import Vue from 'vue';
|
||||
import Vuex from 'vuex';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import CannotPushCodeAlert from '~/ide/components/cannot_push_code_alert.vue';
|
||||
import ErrorMessage from '~/ide/components/error_message.vue';
|
||||
import Ide from '~/ide/components/ide.vue';
|
||||
|
@ -40,6 +41,8 @@ describe('WebIDE', () => {
|
|||
const findAlert = () => wrapper.findComponent(CannotPushCodeAlert);
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
store = createStore();
|
||||
});
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import Vuex from 'vuex';
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import '~/behaviors/markdown/render_gfm';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
|
||||
import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
|
||||
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
|
||||
|
@ -130,6 +131,8 @@ describe('RepoEditor', () => {
|
|||
const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]');
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
createInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_CODE_INSTANCE_FN);
|
||||
createDiffInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_DIFF_INSTANCE_FN);
|
||||
createModelSpy = jest.spyOn(monacoEditor, 'createModel');
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import { createRouter } from '~/ide/ide_router';
|
||||
import { createStore } from '~/ide/stores';
|
||||
|
||||
|
@ -12,6 +13,8 @@ describe('IDE router', () => {
|
|||
let router;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
window.history.replaceState({}, '', '/');
|
||||
store = createStore();
|
||||
router = createRouter(store, DEFAULT_BRANCH);
|
||||
|
|
|
@ -7,6 +7,7 @@ import { createStore } from '~/ide/stores';
|
|||
import * as actions from '~/ide/stores/actions/file';
|
||||
import * as types from '~/ide/stores/mutation_types';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import { file, createTriggerRenameAction, createTriggerUpdatePayload } from '../../helpers';
|
||||
|
||||
const ORIGINAL_CONTENT = 'original content';
|
||||
|
@ -19,6 +20,8 @@ describe('IDE store file actions', () => {
|
|||
let router;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
mock = new MockAdapter(axios);
|
||||
originalGon = window.gon;
|
||||
window.gon = {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { range } from 'lodash';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import createFlash from '~/flash';
|
||||
|
@ -35,6 +36,8 @@ describe('IDE store merge request actions', () => {
|
|||
let mock;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
store = createStore();
|
||||
|
||||
mock = new MockAdapter(axios);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import { createRouter } from '~/ide/ide_router';
|
||||
|
@ -24,6 +25,8 @@ describe('Multi-file store tree actions', () => {
|
|||
};
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
store = createStore();
|
||||
router = createRouter(store);
|
||||
jest.spyOn(router, 'push').mockImplementation();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import MockAdapter from 'axios-mock-adapter';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import testAction from 'helpers/vuex_action_helper';
|
||||
import eventHub from '~/ide/eventhub';
|
||||
import { createRouter } from '~/ide/ide_router';
|
||||
|
@ -34,6 +35,8 @@ describe('Multi-file store actions', () => {
|
|||
let router;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
store = createStore();
|
||||
router = createRouter(store);
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import $ from 'jquery';
|
||||
import { loadHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import initMrPage from 'helpers/init_vue_mr_page_helper';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import MergeRequestTabs from '~/merge_request_tabs';
|
||||
import '~/lib/utils/common_utils';
|
||||
|
@ -24,6 +25,8 @@ describe('MergeRequestTabs', () => {
|
|||
};
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
initMrPage();
|
||||
|
||||
testContext.class = new MergeRequestTabs({ stubLocation });
|
||||
|
@ -350,10 +353,6 @@ describe('MergeRequestTabs', () => {
|
|||
describe('when switching tabs', () => {
|
||||
const SCROLL_TOP = 100;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.useFakeTimers();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
||||
testContext.class.mergeRequestTabs = document.createElement('div');
|
||||
|
@ -362,10 +361,6 @@ describe('MergeRequestTabs', () => {
|
|||
testContext.class.scrollPositions = { newTab: SCROLL_TOP };
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.useRealTimers();
|
||||
});
|
||||
|
||||
it('scrolls to the stored position, if one is stored', () => {
|
||||
testContext.class.tabShown('newTab');
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@ const defaultProps = {
|
|||
requestCveAvailable: true,
|
||||
confirmationPhrase: 'my-fake-project',
|
||||
showVisibilityConfirmModal: false,
|
||||
membersPagePath: '/my-fake-project/-/project_members',
|
||||
};
|
||||
|
||||
const FEATURE_ACCESS_LEVEL_ANONYMOUS = 30;
|
||||
|
@ -59,7 +60,7 @@ describe('Settings Panel', () => {
|
|||
let wrapper;
|
||||
|
||||
const mountComponent = (
|
||||
{ currentSettings = {}, glFeatures = {}, ...customProps } = {},
|
||||
{ currentSettings = {}, glFeatures = {}, stubs = {}, ...customProps } = {},
|
||||
mountFn = shallowMount,
|
||||
) => {
|
||||
const propsData = {
|
||||
|
@ -76,6 +77,7 @@ describe('Settings Panel', () => {
|
|||
...glFeatures,
|
||||
},
|
||||
},
|
||||
stubs,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -176,7 +178,7 @@ describe('Settings Panel', () => {
|
|||
);
|
||||
|
||||
it('should set the visibility level description based upon the selected visibility level', () => {
|
||||
wrapper = mountComponent();
|
||||
wrapper = mountComponent({ stubs: { GlSprintf } });
|
||||
|
||||
findProjectVisibilityLevelInput().setValue(visibilityOptions.INTERNAL);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import Vue from 'vue';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import getPipelineDetails from 'shared_queries/pipelines/get_pipeline_details.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', () => {
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(window.performance, 'getEntriesByName').mockImplementation(() => {
|
||||
return [];
|
||||
});
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
createComponentWithApollo({
|
||||
provide: {
|
||||
|
|
|
@ -5,6 +5,7 @@ import { merge } from 'lodash';
|
|||
import VueApollo, { ApolloMutation } from 'vue-apollo';
|
||||
import { useFakeDate } from 'helpers/fake_date';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import GetSnippetQuery from 'shared_queries/snippet/snippet.query.graphql';
|
||||
|
@ -96,6 +97,8 @@ describe('Snippet Edit app', () => {
|
|||
const originalRelativeUrlRoot = gon.relative_url_root;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
getSpy = jest.fn().mockResolvedValue(createQueryResponse());
|
||||
|
||||
// See `mutateSpy` declaration comment for why we send a key
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
SNIPPET_VISIBILITY_PUBLIC,
|
||||
} from '~/snippets/constants';
|
||||
import CloneDropdownButton from '~/vue_shared/components/clone_dropdown.vue';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
|
||||
describe('Snippet view app', () => {
|
||||
let wrapper;
|
||||
|
@ -45,6 +46,10 @@ describe('Snippet view app', () => {
|
|||
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
|
||||
const findEmbedDropdown = () => wrapper.findComponent(EmbedDropdown);
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { waitFor } from '@testing-library/dom';
|
||||
import setWindowLocation from 'helpers/set_window_location_helper';
|
||||
import { TEST_HOST } from 'helpers/test_constants';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import initDiffsApp from '~/diffs';
|
||||
import { createStore } from '~/mr_notes/stores';
|
||||
import {
|
||||
|
@ -74,6 +75,10 @@ const startDiffsApp = () => {
|
|||
describe('diffs third party interoperability', () => {
|
||||
let vm;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vm.$destroy();
|
||||
document.body.innerHTML = '';
|
||||
|
|
|
@ -3,8 +3,9 @@ import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
|||
import { setTestTimeout } from 'helpers/timeout';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { waitForText } from 'helpers/wait_for_text';
|
||||
import { createCommitId } from 'test_helpers/factories/commit_id';
|
||||
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 startWebIDE from './helpers/start';
|
||||
|
||||
|
@ -15,6 +16,7 @@ describe('WebIDE', () => {
|
|||
let container;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
// For some reason these tests were timing out in CI.
|
||||
// We will investigate in https://gitlab.com/gitlab-org/gitlab/-/issues/298714
|
||||
setTestTimeout(20000);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { screen } from '@testing-library/dom';
|
||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import * as ideHelper from './helpers/ide_helper';
|
||||
import startWebIDE from './helpers/start';
|
||||
|
||||
|
@ -11,6 +12,7 @@ describe('IDE: User opens a file in the Web IDE', () => {
|
|||
let container;
|
||||
|
||||
beforeEach(async () => {
|
||||
stubPerformanceWebAPI();
|
||||
setHTMLFixture('<div class="webide-container"></div>');
|
||||
container = document.querySelector('.webide-container');
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { screen } from '@testing-library/dom';
|
||||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import * as ideHelper from './helpers/ide_helper';
|
||||
import startWebIDE from './helpers/start';
|
||||
|
||||
|
@ -11,6 +12,8 @@ describe('IDE: User opens IDE', () => {
|
|||
let container;
|
||||
|
||||
beforeEach(() => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
setHTMLFixture('<div class="webide-container"></div>');
|
||||
container = document.querySelector('.webide-container');
|
||||
});
|
||||
|
|
|
@ -2,6 +2,7 @@ import { basename } from 'path';
|
|||
import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures';
|
||||
import { getMergeRequests, getMergeRequestWithChanges } from 'test_helpers/fixtures';
|
||||
import { useOverclockTimers } from 'test_helpers/utils/overclock_timers';
|
||||
import { stubPerformanceWebAPI } from 'helpers/performance';
|
||||
import * as ideHelper from './helpers/ide_helper';
|
||||
import startWebIDE from './helpers/start';
|
||||
|
||||
|
@ -16,6 +17,8 @@ describe('IDE: User opens Merge Request', () => {
|
|||
let changes;
|
||||
|
||||
beforeEach(async () => {
|
||||
stubPerformanceWebAPI();
|
||||
|
||||
const [{ iid: mrId }] = getMergeRequests();
|
||||
|
||||
changes = getRelevantChanges();
|
||||
|
|
|
@ -969,6 +969,10 @@ RSpec.describe ProjectsHelper do
|
|||
containerRegistryAccessLevel: project.project_feature.container_registry_access_level
|
||||
)
|
||||
end
|
||||
|
||||
it 'includes membersPagePath' do
|
||||
expect(subject).to include(membersPagePath: project_project_members_path(project))
|
||||
end
|
||||
end
|
||||
|
||||
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_URL' => merge_request.project.web_url,
|
||||
'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_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
||||
'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_URL' => merge_request.project.web_url,
|
||||
'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_SOURCE_PROJECT_ID' => merge_request.source_project.id.to_s,
|
||||
'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
|
||||
|
||||
describe '#has_expired_test_reports?' do
|
||||
subject { pipeline.has_expired_test_reports? }
|
||||
describe '#has_test_reports?' do
|
||||
subject { pipeline.has_test_reports? }
|
||||
|
||||
let(:pipeline) { create(:ci_pipeline, :success, :with_test_reports) }
|
||||
|
||||
context 'when artifacts are not expired' do
|
||||
it { is_expected.to be_falsey }
|
||||
it { is_expected.to be_truthy }
|
||||
end
|
||||
|
||||
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 }
|
||||
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
|
||||
let(:pipeline) { create(:ci_pipeline, :running) }
|
||||
|
||||
|
|
|
@ -5,6 +5,10 @@ require 'spec_helper'
|
|||
RSpec.describe RemoteMirror, :mailer do
|
||||
include GitHelpers
|
||||
|
||||
before do
|
||||
stub_feature_flags(remote_mirror_no_delay: false)
|
||||
end
|
||||
|
||||
describe 'URL validation' do
|
||||
context 'with a valid URL' do
|
||||
it 'is valid' do
|
||||
|
@ -343,6 +347,20 @@ RSpec.describe RemoteMirror, :mailer do
|
|||
|
||||
remote_mirror.sync
|
||||
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
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe API::ProtectedTags do
|
||||
let(:user) { create(:user) }
|
||||
let!(:project) { create(:project, :repository) }
|
||||
let(:project2) { create(:project, path: 'project2', namespace: user.namespace) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:project2) { create(:project, path: 'project2', namespace: user.namespace) }
|
||||
|
||||
let(:protected_name) { 'feature' }
|
||||
let(:tag_name) { protected_name }
|
||||
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.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.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
|
||||
# avatar after being forked.
|
||||
|
|
|
@ -63,6 +63,36 @@ RSpec.describe 'devise/sessions/new' do
|
|||
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
|
||||
allow(view).to receive(:password_authentication_enabled_for_web?).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_on_login_required?).and_return(false)
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue