Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a59d305223
commit
39fa1b5987
|
|
@ -11,6 +11,10 @@ class Projects::RefsController < Projects::ApplicationController
|
|||
before_action :assign_ref_vars
|
||||
before_action :authorize_download_code!
|
||||
|
||||
before_action only: [:logs_tree] do
|
||||
push_frontend_feature_flag(:vue_file_list_lfs_badge)
|
||||
end
|
||||
|
||||
def switch
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module BlobHelper
|
|||
options[:link_opts])
|
||||
end
|
||||
|
||||
def ide_edit_path(project = @project, ref = @ref, path = @path, options = {})
|
||||
def ide_edit_path(project = @project, ref = @ref, path = @path)
|
||||
project_path =
|
||||
if !current_user || can?(current_user, :push_code, project)
|
||||
project.full_path
|
||||
|
|
@ -52,28 +52,25 @@ module BlobHelper
|
|||
edit_button_tag(blob,
|
||||
common_classes,
|
||||
_('Edit'),
|
||||
Feature.enabled?(:web_ide_default) ? ide_edit_path(project, ref, path, options) : edit_blob_path(project, ref, path, options),
|
||||
Feature.enabled?(:web_ide_default) ? ide_edit_path(project, ref, path) : edit_blob_path(project, ref, path, options),
|
||||
project,
|
||||
ref)
|
||||
end
|
||||
|
||||
def ide_edit_button(project = @project, ref = @ref, path = @path, options = {})
|
||||
def ide_edit_button(project = @project, ref = @ref, path = @path, blob:)
|
||||
return if Feature.enabled?(:web_ide_default)
|
||||
return unless blob = readable_blob(options, path, project, ref)
|
||||
return unless blob
|
||||
|
||||
edit_button_tag(blob,
|
||||
'btn btn-inverted btn-primary ide-edit-button ml-2',
|
||||
_('Web IDE'),
|
||||
ide_edit_path(project, ref, path, options),
|
||||
ide_edit_path(project, ref, path),
|
||||
project,
|
||||
ref)
|
||||
end
|
||||
|
||||
def modify_file_button(project = @project, ref = @ref, path = @path, label:, action:, btn_class:, modal_type:)
|
||||
def modify_file_button(project = @project, ref = @ref, path = @path, blob:, label:, action:, btn_class:, modal_type:)
|
||||
return unless current_user
|
||||
|
||||
blob = project.repository.blob_at(ref, path) rescue nil
|
||||
|
||||
return unless blob
|
||||
|
||||
common_classes = "btn btn-#{btn_class}"
|
||||
|
|
@ -89,11 +86,12 @@ module BlobHelper
|
|||
end
|
||||
end
|
||||
|
||||
def replace_blob_link(project = @project, ref = @ref, path = @path)
|
||||
def replace_blob_link(project = @project, ref = @ref, path = @path, blob:)
|
||||
modify_file_button(
|
||||
project,
|
||||
ref,
|
||||
path,
|
||||
blob: blob,
|
||||
label: _("Replace"),
|
||||
action: "replace",
|
||||
btn_class: "default",
|
||||
|
|
@ -101,11 +99,12 @@ module BlobHelper
|
|||
)
|
||||
end
|
||||
|
||||
def delete_blob_link(project = @project, ref = @ref, path = @path)
|
||||
def delete_blob_link(project = @project, ref = @ref, path = @path, blob:)
|
||||
modify_file_button(
|
||||
project,
|
||||
ref,
|
||||
path,
|
||||
blob: blob,
|
||||
label: _("Delete"),
|
||||
action: "delete",
|
||||
btn_class: "default",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,18 @@
|
|||
module InternalIdEnums
|
||||
def self.usage_resources
|
||||
# when adding new resource, make sure it doesn't conflict with EE usage_resources
|
||||
{ issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4, ci_pipelines: 5, operations_feature_flags: 6, operations_user_lists: 7, alert_management_alerts: 8 }
|
||||
{
|
||||
issues: 0,
|
||||
merge_requests: 1,
|
||||
deployments: 2,
|
||||
milestones: 3,
|
||||
epics: 4,
|
||||
ci_pipelines: 5,
|
||||
operations_feature_flags: 6,
|
||||
operations_user_lists: 7,
|
||||
alert_management_alerts: 8,
|
||||
sprints: 9
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class Issue < ApplicationRecord
|
|||
belongs_to :project
|
||||
belongs_to :duplicated_to, class_name: 'Issue'
|
||||
belongs_to :closed_by, class_name: 'User'
|
||||
belongs_to :sprint
|
||||
|
||||
belongs_to :moved_to, class_name: 'Issue'
|
||||
has_one :moved_from, class_name: 'Issue', foreign_key: :moved_to_id
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class MergeRequest < ApplicationRecord
|
|||
belongs_to :target_project, class_name: "Project"
|
||||
belongs_to :source_project, class_name: "Project"
|
||||
belongs_to :merge_user, class_name: "User"
|
||||
belongs_to :sprint
|
||||
|
||||
has_internal_id :iid, scope: :target_project, track_if: -> { !importing? }, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Sprint < ApplicationRecord
|
||||
STATE_ID_MAP = {
|
||||
active: 1,
|
||||
closed: 2
|
||||
}.with_indifferent_access.freeze
|
||||
|
||||
include AtomicInternalId
|
||||
|
||||
has_many :issues
|
||||
has_many :merge_requests
|
||||
|
||||
belongs_to :project
|
||||
belongs_to :group
|
||||
|
||||
has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.sprints&.maximum(:iid) }
|
||||
has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.sprints&.maximum(:iid) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
.file-actions<
|
||||
= render 'projects/blob/viewer_switcher', blob: blob unless blame
|
||||
= edit_blob_button
|
||||
= ide_edit_button
|
||||
= edit_blob_button(@project, @ref, @path, blob: blob)
|
||||
= ide_edit_button(@project, @ref, @path, blob: blob)
|
||||
.btn-group.ml-2{ role: "group" }>
|
||||
= render_if_exists 'projects/blob/header_file_locks_link'
|
||||
- if current_user
|
||||
= replace_blob_link
|
||||
= delete_blob_link
|
||||
= replace_blob_link(@project, @ref, @path, blob: blob)
|
||||
= delete_blob_link(@project, @ref, @path, blob: blob)
|
||||
.btn-group.ml-2{ role: "group" }
|
||||
= copy_blob_source_button(blob) unless blame
|
||||
= open_raw_blob_button(blob)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
%li
|
||||
.monospace
|
||||
= File.basename(file)
|
||||
- if File.dirname(file).ends_with?('plugins')
|
||||
.text-warning
|
||||
= _('Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory.')
|
||||
|
||||
- else
|
||||
.card.bg-light.text-center
|
||||
.nothing-here-block= _('No file hooks found.')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Flesh out Sprints relationships and constraints
|
||||
merge_request: 30127
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Map labels from Jira to labels in GitLab
|
||||
merge_request: 29970
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add clusters index to improve usage data queries
|
||||
merge_request: 28626
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Deprecate /plugins directory
|
||||
merge_request: 29678
|
||||
author:
|
||||
type: deprecated
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add LFS badge feature flag to RefsController#logs_tree
|
||||
merge_request: 30442
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddSprintToIssues < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
# index will be added in another migration with `add_concurrent_index`
|
||||
add_column :issues, :sprint_id, :bigint
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_column :issues, :sprint_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddSprintToMergeRequests < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
# index will be added in another migration with `add_concurrent_index`
|
||||
add_column :merge_requests, :sprint_id, :bigint
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_column :merge_requests, :sprint_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddSprintIdIndexToIssues < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :issues, :sprint_id
|
||||
add_concurrent_foreign_key :issues, :sprints, column: :sprint_id
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do # rubocop:disable Migration/WithLockRetriesWithoutDdlTransaction
|
||||
remove_foreign_key :issues, column: :sprint_id
|
||||
end
|
||||
remove_concurrent_index :issues, :sprint_id
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddSprintIdIndexToMergeRequests < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :merge_requests, :sprint_id
|
||||
add_concurrent_foreign_key :merge_requests, :sprints, column: :sprint_id
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do # rubocop:disable Migration/WithLockRetriesWithoutDdlTransaction
|
||||
remove_foreign_key :merge_requests, column: :sprint_id
|
||||
end
|
||||
remove_concurrent_index :merge_requests, :sprint_id
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddClusterTypeIndexToClusters < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
# Set this constant to true if this migration requires downtime.
|
||||
DOWNTIME = false
|
||||
INDEX_NAME = 'index_clusters_on_enabled_cluster_type_id_and_created_at'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :clusters, [:enabled, :cluster_type, :id, :created_at], name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :clusters, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddCheckConstraintToSprintMustBelongToProjectOrGroup < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
CONSTRAINT_NAME = 'sprints_must_belong_to_project_or_group'
|
||||
|
||||
def up
|
||||
add_check_constraint :sprints, '(project_id != NULL AND group_id IS NULL) OR (group_id != NULL AND project_id IS NULL)', CONSTRAINT_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_check_constraint :sprints, CONSTRAINT_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -3357,7 +3357,8 @@ CREATE TABLE public.issues (
|
|||
duplicated_to_id integer,
|
||||
promoted_to_epic_id integer,
|
||||
health_status smallint,
|
||||
external_key character varying(255)
|
||||
external_key character varying(255),
|
||||
sprint_id bigint
|
||||
);
|
||||
|
||||
CREATE SEQUENCE public.issues_id_seq
|
||||
|
|
@ -3932,7 +3933,8 @@ CREATE TABLE public.merge_requests (
|
|||
allow_maintainer_to_push boolean,
|
||||
state_id smallint DEFAULT 1 NOT NULL,
|
||||
rebase_jid character varying,
|
||||
squash_commit_sha bytea
|
||||
squash_commit_sha bytea,
|
||||
sprint_id bigint
|
||||
);
|
||||
|
||||
CREATE TABLE public.merge_requests_closing_issues (
|
||||
|
|
@ -6106,6 +6108,7 @@ CREATE TABLE public.sprints (
|
|||
title_html text,
|
||||
description text,
|
||||
description_html text,
|
||||
CONSTRAINT sprints_must_belong_to_project_or_group CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL)))),
|
||||
CONSTRAINT sprints_title CHECK ((char_length(title) <= 255))
|
||||
);
|
||||
|
||||
|
|
@ -9208,6 +9211,8 @@ CREATE INDEX index_clusters_kubernetes_namespaces_on_project_id ON public.cluste
|
|||
|
||||
CREATE INDEX index_clusters_on_enabled_and_provider_type_and_id ON public.clusters USING btree (enabled, provider_type, id);
|
||||
|
||||
CREATE INDEX index_clusters_on_enabled_cluster_type_id_and_created_at ON public.clusters USING btree (enabled, cluster_type, id, created_at);
|
||||
|
||||
CREATE INDEX index_clusters_on_management_project_id ON public.clusters USING btree (management_project_id) WHERE (management_project_id IS NOT NULL);
|
||||
|
||||
CREATE INDEX index_clusters_on_user_id ON public.clusters USING btree (user_id);
|
||||
|
|
@ -9598,6 +9603,8 @@ CREATE INDEX index_issues_on_promoted_to_epic_id ON public.issues USING btree (p
|
|||
|
||||
CREATE INDEX index_issues_on_relative_position ON public.issues USING btree (relative_position);
|
||||
|
||||
CREATE INDEX index_issues_on_sprint_id ON public.issues USING btree (sprint_id);
|
||||
|
||||
CREATE INDEX index_issues_on_title_trigram ON public.issues USING gin (title public.gin_trgm_ops);
|
||||
|
||||
CREATE INDEX index_issues_on_updated_at ON public.issues USING btree (updated_at);
|
||||
|
|
@ -9760,6 +9767,8 @@ CREATE INDEX index_merge_requests_on_source_branch ON public.merge_requests USIN
|
|||
|
||||
CREATE INDEX index_merge_requests_on_source_project_id_and_source_branch ON public.merge_requests USING btree (source_project_id, source_branch);
|
||||
|
||||
CREATE INDEX index_merge_requests_on_sprint_id ON public.merge_requests USING btree (sprint_id);
|
||||
|
||||
CREATE INDEX index_merge_requests_on_target_branch ON public.merge_requests USING btree (target_branch);
|
||||
|
||||
CREATE UNIQUE INDEX index_merge_requests_on_target_project_id_and_iid ON public.merge_requests USING btree (target_project_id, iid);
|
||||
|
|
@ -10849,6 +10858,9 @@ ALTER TABLE ONLY public.push_event_payloads
|
|||
ALTER TABLE ONLY public.ci_builds
|
||||
ADD CONSTRAINT fk_3a9eaa254d FOREIGN KEY (stage_id) REFERENCES public.ci_stages(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY public.issues
|
||||
ADD CONSTRAINT fk_3b8c72ea56 FOREIGN KEY (sprint_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY public.epics
|
||||
ADD CONSTRAINT fk_3c1fd1cccc FOREIGN KEY (due_date_sourcing_milestone_id) REFERENCES public.milestones(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
@ -10966,6 +10978,9 @@ ALTER TABLE ONLY public.vulnerabilities
|
|||
ALTER TABLE ONLY public.labels
|
||||
ADD CONSTRAINT fk_7de4989a69 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY public.merge_requests
|
||||
ADD CONSTRAINT fk_7e85395a64 FOREIGN KEY (sprint_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY public.merge_request_metrics
|
||||
ADD CONSTRAINT fk_7f28d925f3 FOREIGN KEY (merged_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
@ -13285,6 +13300,10 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200303055348
|
||||
20200303074328
|
||||
20200303181648
|
||||
20200304023245
|
||||
20200304023851
|
||||
20200304024025
|
||||
20200304024042
|
||||
20200304085423
|
||||
20200304090155
|
||||
20200304121828
|
||||
|
|
@ -13394,6 +13413,7 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200401091051
|
||||
20200401095430
|
||||
20200401211005
|
||||
20200402001106
|
||||
20200402123926
|
||||
20200402124802
|
||||
20200402135250
|
||||
|
|
@ -13457,6 +13477,7 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200420172113
|
||||
20200420172752
|
||||
20200420172927
|
||||
20200420201933
|
||||
20200421233150
|
||||
20200423075720
|
||||
20200423080334
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ excluded_attributes:
|
|||
- :merge_request_diff_id
|
||||
issues:
|
||||
- :milestone_id
|
||||
- :sprint_id
|
||||
- :moved_to_id
|
||||
- :sent_notifications
|
||||
- :state_id
|
||||
|
|
@ -197,6 +198,7 @@ excluded_attributes:
|
|||
- :promoted_to_epic_id
|
||||
merge_request:
|
||||
- :milestone_id
|
||||
- :sprint_id
|
||||
- :ref_fetched
|
||||
- :merge_jid
|
||||
- :rebase_jid
|
||||
|
|
@ -205,6 +207,7 @@ excluded_attributes:
|
|||
- :state_id
|
||||
merge_requests:
|
||||
- :milestone_id
|
||||
- :sprint_id
|
||||
- :ref_fetched
|
||||
- :merge_jid
|
||||
- :rebase_jid
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module JiraImport
|
||||
class HandleLabelsService
|
||||
def initialize(project, jira_labels)
|
||||
@project = project
|
||||
@jira_labels = jira_labels
|
||||
end
|
||||
|
||||
def execute
|
||||
return if jira_labels.blank?
|
||||
|
||||
existing_labels = LabelsFinder.new(nil, project: project, title: jira_labels)
|
||||
.execute(skip_authorization: true).select(:id, :name)
|
||||
new_labels = create_missing_labels(existing_labels)
|
||||
|
||||
label_ids = existing_labels.map(&:id)
|
||||
label_ids += new_labels if new_labels.present?
|
||||
label_ids
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :project, :jira_labels
|
||||
|
||||
def create_missing_labels(existing_labels)
|
||||
labels_to_create = jira_labels - existing_labels.map(&:name)
|
||||
return if labels_to_create.empty?
|
||||
|
||||
new_labels_hash = labels_to_create.map do |title|
|
||||
{ project_id: project.id, title: title, type: 'ProjectLabel' }
|
||||
end
|
||||
|
||||
Label.insert_all(new_labels_hash).rows.flatten
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -21,7 +21,8 @@ module Gitlab
|
|||
state_id: map_status(jira_issue.status.statusCategory),
|
||||
updated_at: jira_issue.updated,
|
||||
created_at: jira_issue.created,
|
||||
author_id: project.creator_id # TODO: map actual author: https://gitlab.com/gitlab-org/gitlab/-/issues/210580
|
||||
author_id: project.creator_id, # TODO: map actual author: https://gitlab.com/gitlab-org/gitlab/-/issues/210580
|
||||
label_ids: label_ids
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -49,6 +50,15 @@ module Gitlab
|
|||
Issuable::STATE_ID_MAP[:opened]
|
||||
end
|
||||
end
|
||||
|
||||
# We already create labels in Gitlab::JiraImport::LabelsImporter stage but
|
||||
# there is a possibility it may fail or
|
||||
# new labels were created on the Jira in the meantime
|
||||
def label_ids
|
||||
return if jira_issue.fields['labels'].blank?
|
||||
|
||||
Gitlab::JiraImport::HandleLabelsService.new(project, jira_issue.fields['labels']).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ module Gitlab
|
|||
class LabelsImporter < BaseImporter
|
||||
attr_reader :job_waiter
|
||||
|
||||
MAX_LABELS = 500
|
||||
|
||||
def initialize(project)
|
||||
super
|
||||
@job_waiter = JobWaiter.new
|
||||
|
|
@ -25,9 +27,29 @@ module Gitlab
|
|||
end
|
||||
|
||||
def import_jira_labels
|
||||
# todo: import jira labels, see https://gitlab.com/gitlab-org/gitlab/-/issues/212651
|
||||
start_at = 0
|
||||
loop do
|
||||
break if process_jira_page(start_at)
|
||||
|
||||
start_at += MAX_LABELS
|
||||
end
|
||||
|
||||
job_waiter
|
||||
end
|
||||
|
||||
def process_jira_page(start_at)
|
||||
request = "/rest/api/2/label?maxResults=#{MAX_LABELS}&startAt=#{start_at}"
|
||||
response = JSON.parse(client.get(request))
|
||||
|
||||
return true if response['values'].blank?
|
||||
return true unless response.key?('isLast')
|
||||
|
||||
Gitlab::JiraImport::HandleLabelsService.new(project, response['values']).execute
|
||||
|
||||
response['isLast']
|
||||
rescue => e
|
||||
Gitlab::ErrorTracking.track_exception(e, project_id: project.id, request: request)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ module Gitlab
|
|||
def execute
|
||||
add_field(%w(issuetype name), 'Issue type')
|
||||
add_field(%w(priority name), 'Priority')
|
||||
add_labels
|
||||
add_field('environment', 'Environment')
|
||||
add_field('duedate', 'Due date')
|
||||
add_parent
|
||||
|
|
@ -33,12 +32,6 @@ module Gitlab
|
|||
metadata << "- #{field_label}: #{value}"
|
||||
end
|
||||
|
||||
def add_labels
|
||||
return if fields['labels'].blank? || !fields['labels'].is_a?(Array)
|
||||
|
||||
metadata << "- Labels: #{fields['labels'].join(', ')}"
|
||||
end
|
||||
|
||||
def add_parent
|
||||
parent_issue_key = fields.dig('parent', 'key')
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def ensure_deadline_not_exceeded!
|
||||
return unless enabled?
|
||||
return unless request_deadline
|
||||
return if Gitlab::Metrics::System.real_time < request_deadline
|
||||
|
||||
|
|
@ -36,5 +37,9 @@ module Gitlab
|
|||
def max_request_duration_seconds
|
||||
Settings.gitlab.max_request_duration_seconds
|
||||
end
|
||||
|
||||
def enabled?
|
||||
!Rails.env.test?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ namespace :file_hooks do
|
|||
puts 'Validating file hooks from /file_hooks and /plugins directories'
|
||||
|
||||
Gitlab::FileHook.files.each do |file|
|
||||
if File.dirname(file).ends_with?('plugins')
|
||||
puts 'DEPRECATED: /plugins directory is deprecated and will be removed in 14.0. ' \
|
||||
'Please move your files into /file_hooks directory.'
|
||||
end
|
||||
|
||||
success, message = Gitlab::FileHook.execute(file, Gitlab::DataBuilder::Push::SAMPLE_DATA)
|
||||
|
||||
if success
|
||||
|
|
|
|||
|
|
@ -8834,6 +8834,12 @@ msgstr ""
|
|||
msgid "Failed to load groups & users."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to load labels. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to load milestones. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Failed to load related branches"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -15190,6 +15196,9 @@ msgstr ""
|
|||
msgid "Please wait while we import the repository for you. Refresh at will."
|
||||
msgstr ""
|
||||
|
||||
msgid "Plugins directory is deprecated and will be removed in 14.0. Please move this file into /file_hooks directory."
|
||||
msgstr ""
|
||||
|
||||
msgid "Pod does not exist"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ describe SearchController do
|
|||
with_them do
|
||||
it do
|
||||
project_wiki = create(:project_wiki, project: project, user: user)
|
||||
create(:wiki_page, wiki: project_wiki, attrs: { title: 'merge', content: 'merge' })
|
||||
create(:wiki_page, wiki: project_wiki, title: 'merge', content: 'merge')
|
||||
|
||||
expect(subject).to render_template("search/results/#{partial}")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
FactoryBot.define do
|
||||
factory :sprint do
|
||||
title
|
||||
|
||||
transient do
|
||||
project { nil }
|
||||
group { nil }
|
||||
project_id { nil }
|
||||
group_id { nil }
|
||||
resource_parent { nil }
|
||||
end
|
||||
|
||||
trait :active do
|
||||
state { Sprint::STATE_ID_MAP[:active] }
|
||||
end
|
||||
|
||||
trait :closed do
|
||||
state { Sprint::STATE_ID_MAP[:closed] }
|
||||
end
|
||||
|
||||
trait :with_dates do
|
||||
start_date { Date.new(2000, 1, 1) }
|
||||
due_date { Date.new(2000, 1, 30) }
|
||||
end
|
||||
|
||||
after(:build, :stub) do |sprint, evaluator|
|
||||
if evaluator.group
|
||||
sprint.group = evaluator.group
|
||||
elsif evaluator.group_id
|
||||
sprint.group_id = evaluator.group_id
|
||||
elsif evaluator.project
|
||||
sprint.project = evaluator.project
|
||||
elsif evaluator.project_id
|
||||
sprint.project_id = evaluator.project_id
|
||||
elsif evaluator.resource_parent
|
||||
id = evaluator.resource_parent.id
|
||||
evaluator.resource_parent.is_a?(Group) ? evaluator.group_id = id : evaluator.project_id = id
|
||||
else
|
||||
sprint.project = create(:project)
|
||||
end
|
||||
end
|
||||
|
||||
factory :active_sprint, traits: [:active]
|
||||
factory :closed_sprint, traits: [:closed]
|
||||
end
|
||||
end
|
||||
|
|
@ -7,11 +7,17 @@ FactoryBot.define do
|
|||
transient do
|
||||
title { generate(:wiki_page_title) }
|
||||
content { 'Content for wiki page' }
|
||||
format { 'markdown' }
|
||||
format { :markdown }
|
||||
message { nil }
|
||||
project { association(:project, :wiki_repo) }
|
||||
container { project }
|
||||
attrs do
|
||||
{
|
||||
wiki { association(:wiki, container: container) }
|
||||
page { OpenStruct.new(url_path: title) }
|
||||
end
|
||||
|
||||
initialize_with do
|
||||
new(wiki, page).tap do |page|
|
||||
page.attributes = {
|
||||
title: title,
|
||||
content: content,
|
||||
format: format
|
||||
|
|
@ -19,25 +25,13 @@ FactoryBot.define do
|
|||
end
|
||||
end
|
||||
|
||||
page { OpenStruct.new(url_path: 'some-name') }
|
||||
wiki { association(:wiki, container: container) }
|
||||
|
||||
initialize_with { new(wiki, page) }
|
||||
|
||||
before(:create) do |page, evaluator|
|
||||
page.attributes = evaluator.attrs
|
||||
# Clear our default @page, except when using build_stubbed
|
||||
after(:build) do |page|
|
||||
page.instance_variable_set('@page', nil)
|
||||
end
|
||||
|
||||
to_create do |page|
|
||||
page.create
|
||||
end
|
||||
|
||||
trait :with_real_page do
|
||||
page do
|
||||
wiki.create_page(title, content)
|
||||
page_title, page_dir = wiki.page_title_and_dir(title)
|
||||
wiki.wiki.page(title: page_title, dir: page_dir, version: nil)
|
||||
end
|
||||
to_create do |page, evaluator|
|
||||
page.create(message: evaluator.message)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,24 @@ describe 'Admin::Hooks' do
|
|||
expect(page).to have_content('foo.rb')
|
||||
expect(page).to have_content('bar.clj')
|
||||
end
|
||||
|
||||
context 'deprecation warning' do
|
||||
it 'shows warning for plugins directory' do
|
||||
allow(Gitlab::FileHook).to receive(:files).and_return(['plugins/foo.rb'])
|
||||
|
||||
visit admin_hooks_path
|
||||
|
||||
expect(page).to have_content('Plugins directory is deprecated and will be removed in 14.0')
|
||||
end
|
||||
|
||||
it 'does not show warning for file_hooks directory' do
|
||||
allow(Gitlab::FileHook).to receive(:files).and_return(['file_hooks/foo.rb'])
|
||||
|
||||
visit admin_hooks_path
|
||||
|
||||
expect(page).not_to have_content('Plugins directory is deprecated and will be removed in 14.0')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'New Hook' do
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
describe 'Projects > Wiki > User previews markdown changes', :js do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') }
|
||||
let(:wiki_content) do
|
||||
<<-HEREDOC
|
||||
[regular link](regular)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
describe 'Wiki shortcuts', :js do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: 'Home page' }) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: 'Home page') }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ describe "User creates wiki page" do
|
|||
|
||||
context "when wiki is not empty", :js do
|
||||
before do
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: 'home', content: 'Home page' })
|
||||
create(:wiki_page, wiki: wiki, title: 'home', content: 'Home page')
|
||||
|
||||
visit(project_wikis_path(project))
|
||||
end
|
||||
|
|
@ -304,8 +304,8 @@ describe "User creates wiki page" do
|
|||
describe 'sidebar feature' do
|
||||
context 'when there are some existing pages' do
|
||||
before do
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: 'home', content: 'home' })
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: 'another', content: 'another' })
|
||||
create(:wiki_page, wiki: wiki, title: 'home', content: 'home')
|
||||
create(:wiki_page, wiki: wiki, title: 'another', content: 'another')
|
||||
end
|
||||
|
||||
it 'renders a default sidebar when there is no customized sidebar' do
|
||||
|
|
@ -316,7 +316,7 @@ describe "User creates wiki page" do
|
|||
|
||||
context 'when there is a customized sidebar' do
|
||||
before do
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: '_sidebar', content: 'My customized sidebar' })
|
||||
create(:wiki_page, wiki: wiki, title: '_sidebar', content: 'My customized sidebar')
|
||||
end
|
||||
|
||||
it 'renders my customized sidebar instead of the default one' do
|
||||
|
|
@ -330,8 +330,8 @@ describe "User creates wiki page" do
|
|||
|
||||
context 'when there are more than 15 existing pages' do
|
||||
before do
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: 'home', content: 'home' })
|
||||
(1..14).each { |i| create(:wiki_page, wiki: wiki, attrs: { title: "page-#{i}", content: "page #{i}" }) }
|
||||
create(:wiki_page, wiki: wiki, title: 'home', content: 'home')
|
||||
(1..14).each { |i| create(:wiki_page, wiki: wiki, title: "page-#{i}", content: "page #{i}") }
|
||||
end
|
||||
|
||||
it 'renders a default sidebar when there is no customized sidebar' do
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
describe 'Projects > Wiki > User views Git access wiki page' do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :wiki_repo, :public) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' }) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)') }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ describe 'User updates wiki page' do
|
|||
|
||||
context 'when wiki is not empty' do
|
||||
let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: 'home', content: 'Home page' }) }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, title: 'home', content: 'Home page') }
|
||||
|
||||
before do
|
||||
visit(project_wikis_path(project))
|
||||
|
|
@ -168,7 +168,7 @@ describe 'User updates wiki page' do
|
|||
let(:project_wiki) { create(:project_wiki, project: project, user: project.creator) }
|
||||
let(:page_name) { 'page_name' }
|
||||
let(:page_dir) { "foo/bar/#{page_name}" }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, attrs: { title: page_dir, content: 'Home page' }) }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project_wiki, title: page_dir, content: 'Home page') }
|
||||
|
||||
before do
|
||||
visit(project_wiki_edit_path(project, wiki_page))
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ describe 'Projects > Wiki > User views wiki in project page' do
|
|||
|
||||
context 'when wiki homepage contains a link' do
|
||||
before do
|
||||
create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: '[some link](other-page)' })
|
||||
create(:wiki_page, wiki: project.wiki, title: 'home', content: '[some link](other-page)')
|
||||
end
|
||||
|
||||
it 'displays the correct URL for the link' do
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ describe 'User views a wiki page' do
|
|||
let(:wiki_page) do
|
||||
create(:wiki_page,
|
||||
wiki: project.wiki,
|
||||
attrs: { title: 'home', content: "Look at this [image](#{path})\n\n " })
|
||||
title: 'home', content: "Look at this [image](#{path})\n\n ")
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@ describe 'User views wiki pages' do
|
|||
let(:project) { create(:project, :wiki_repo, namespace: user.namespace) }
|
||||
|
||||
let!(:wiki_page1) do
|
||||
create(:wiki_page, wiki: project.wiki, attrs: { title: '3 home', content: '3' })
|
||||
create(:wiki_page, wiki: project.wiki, title: '3 home', content: '3')
|
||||
end
|
||||
let!(:wiki_page2) do
|
||||
create(:wiki_page, wiki: project.wiki, attrs: { title: '1 home', content: '1' })
|
||||
create(:wiki_page, wiki: project.wiki, title: '1 home', content: '1')
|
||||
end
|
||||
let!(:wiki_page3) do
|
||||
create(:wiki_page, wiki: project.wiki, attrs: { title: '2 home', content: '2' })
|
||||
create(:wiki_page, wiki: project.wiki, title: '2 home', content: '2')
|
||||
end
|
||||
|
||||
let(:pages) do
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ describe 'User views AsciiDoc page with includes', :js do
|
|||
format: :asciidoc
|
||||
}
|
||||
|
||||
create(:wiki_page, wiki: project.wiki, attrs: attrs)
|
||||
create(:wiki_page, wiki: project.wiki, **attrs)
|
||||
end
|
||||
|
||||
before do
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
describe 'User searches for wiki pages', :js do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project, :repository, :wiki_repo, namespace: user.namespace) }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: { title: 'directory/title', content: 'Some Wiki content' }) }
|
||||
let!(:wiki_page) { create(:wiki_page, wiki: project.wiki, title: 'directory/title', content: 'Some Wiki content') }
|
||||
|
||||
before do
|
||||
project.add_maintainer(user)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ describe Banzai::Pipeline::WikiPipeline do
|
|||
let(:namespace) { create(:namespace, name: "wiki_link_ns") }
|
||||
let(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
|
||||
let(:project_wiki) { ProjectWiki.new(project, double(:user)) }
|
||||
let(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
|
||||
let(:page) { build(:wiki_page, wiki: project_wiki, title: 'nested/twice/start-page') }
|
||||
|
||||
{ 'when GitLab is hosted at a root URL' => '',
|
||||
'when GitLab is hosted at a relative URL' => '/nested/relative/gitlab' }.each do |test_name, relative_url_root|
|
||||
|
|
@ -264,7 +264,7 @@ describe Banzai::Pipeline::WikiPipeline do
|
|||
let_it_be(:namespace) { create(:namespace, name: "wiki_link_ns") }
|
||||
let_it_be(:project) { create(:project, :public, name: "wiki_link_project", namespace: namespace) }
|
||||
let_it_be(:project_wiki) { ProjectWiki.new(project, double(:user)) }
|
||||
let_it_be(:page) { build(:wiki_page, wiki: project_wiki, page: OpenStruct.new(url_path: 'nested/twice/start-page')) }
|
||||
let_it_be(:page) { build(:wiki_page, wiki: project_wiki, title: 'nested/twice/start-page') }
|
||||
|
||||
it 'generates video html structure' do
|
||||
markdown = ""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ issues:
|
|||
- assignees
|
||||
- updated_by
|
||||
- milestone
|
||||
- sprint
|
||||
- notes
|
||||
- resource_label_events
|
||||
- resource_weight_events
|
||||
|
|
@ -113,6 +114,7 @@ merge_requests:
|
|||
- assignee
|
||||
- updated_by
|
||||
- milestone
|
||||
- sprint
|
||||
- notes
|
||||
- resource_label_events
|
||||
- resource_milestone_events
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::JiraImport::HandleLabelsService do
|
||||
describe '#execute' do
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
|
||||
let_it_be(:project_label) { create(:label, project: project, title: 'bug') }
|
||||
let_it_be(:other_project_label) { create(:label, title: 'feature') }
|
||||
let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') }
|
||||
let(:jira_labels) { %w(bug feature dev group::new) }
|
||||
|
||||
subject { described_class.new(project, jira_labels).execute }
|
||||
|
||||
context 'when some provided jira labels are missing' do
|
||||
def created_labels
|
||||
project.labels.reorder(id: :desc).first(2)
|
||||
end
|
||||
|
||||
it 'creates the missing labels on the project level' do
|
||||
expect { subject }.to change { Label.count }.from(3).to(5)
|
||||
|
||||
expect(created_labels.map(&:title)).to match_array(%w(feature group::new))
|
||||
end
|
||||
|
||||
it 'returns the id of all labels matching the title' do
|
||||
expect(subject).to match_array([project_label.id, group_label.id] + created_labels.map(&:id))
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no provided jira labels are missing' do
|
||||
let(:jira_labels) { %w(bug dev) }
|
||||
|
||||
it 'does not create any new labels' do
|
||||
expect { subject }.not_to change { Label.count }.from(3)
|
||||
end
|
||||
|
||||
it 'returns the id of all labels matching the title' do
|
||||
expect(subject).to match_array([project_label.id, group_label.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no labels are provided' do
|
||||
let(:jira_labels) { [] }
|
||||
|
||||
it 'does not create any new labels' do
|
||||
expect { subject }.not_to change { Label.count }.from(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,11 @@ require 'spec_helper'
|
|||
|
||||
describe Gitlab::JiraImport::IssueSerializer do
|
||||
describe '#execute' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
let_it_be(:project_label) { create(:label, project: project, title: 'bug') }
|
||||
let_it_be(:other_project_label) { create(:label, project: project, title: 'feature') }
|
||||
let_it_be(:group_label) { create(:group_label, group: group, title: 'dev') }
|
||||
|
||||
let(:iid) { 5 }
|
||||
let(:key) { 'PROJECT-5' }
|
||||
|
|
@ -19,11 +23,13 @@ describe Gitlab::JiraImport::IssueSerializer do
|
|||
{ 'key' => 'FOO-2', 'id' => '1050', 'fields' => { 'summary' => 'parent issue FOO' } }
|
||||
end
|
||||
let(:priority_field) { { 'name' => 'Medium' } }
|
||||
let(:labels_field) { %w(bug dev backend frontend) }
|
||||
|
||||
let(:fields) do
|
||||
{
|
||||
'parent' => parent_field,
|
||||
'priority' => priority_field
|
||||
'priority' => priority_field,
|
||||
'labels' => labels_field
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -73,9 +79,33 @@ describe Gitlab::JiraImport::IssueSerializer do
|
|||
state_id: 1,
|
||||
updated_at: updated_at,
|
||||
created_at: created_at,
|
||||
author_id: project.creator_id
|
||||
author_id: project.creator_id,
|
||||
label_ids: [project_label.id, group_label.id] + Label.reorder(id: :asc).last(2).pluck(:id)
|
||||
)
|
||||
end
|
||||
|
||||
it 'creates a hash for valid issue' do
|
||||
expect(Issue.new(subject)).to be_valid
|
||||
end
|
||||
|
||||
it 'creates all missing labels (on project level)' do
|
||||
expect { subject }.to change { Label.count }.from(3).to(5)
|
||||
|
||||
expect(Label.find_by(title: 'frontend').project).to eq(project)
|
||||
expect(Label.find_by(title: 'backend').project).to eq(project)
|
||||
end
|
||||
|
||||
context 'when there are no new labels' do
|
||||
let(:labels_field) { %w(bug dev) }
|
||||
|
||||
it 'assigns the labels to the Issue hash' do
|
||||
expect(subject[:label_ids]).to match_array([project_label.id, group_label.id])
|
||||
end
|
||||
|
||||
it 'does not create new labels' do
|
||||
expect { subject }.not_to change { Label.count }.from(3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with done status' do
|
||||
|
|
|
|||
|
|
@ -3,18 +3,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::JiraImport::LabelsImporter do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
let_it_be(:jira_service) { create(:jira_service, project: project) }
|
||||
|
||||
subject { described_class.new(project).execute }
|
||||
|
||||
before do
|
||||
stub_feature_flags(jira_issue_import: true)
|
||||
stub_const('Gitlab::JiraImport::LabelsImporter::MAX_LABELS', 2)
|
||||
|
||||
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
|
||||
.to_return(body: { url: 'http://url' }.to_json )
|
||||
end
|
||||
|
||||
describe '#execute', :clean_gitlab_redis_cache do
|
||||
context 'when label is missing from jira import' do
|
||||
context 'when jira import label is missing from jira import' do
|
||||
let_it_be(:no_label_jira_import) { create(:jira_import_state, label: nil, project: project) }
|
||||
|
||||
it 'raises error' do
|
||||
|
|
@ -22,16 +27,71 @@ describe Gitlab::JiraImport::LabelsImporter do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when label exists' do
|
||||
let_it_be(:label) { create(:label) }
|
||||
context 'when jira import label exists' do
|
||||
let_it_be(:label) { create(:label) }
|
||||
let_it_be(:jira_import_with_label) { create(:jira_import_state, label: label, project: project) }
|
||||
let_it_be(:issue_label) { create(:label, project: project, title: 'bug') }
|
||||
|
||||
it 'caches import label' do
|
||||
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.import_label_cache_key(project.id))).to be nil
|
||||
let(:jira_labels_1) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "isLast" => false, "values" => %w(backend bug) } }
|
||||
let(:jira_labels_2) { { "maxResults" => 2, "startAt" => 2, "total" => 3, "isLast" => true, "values" => %w(feature) } }
|
||||
|
||||
subject
|
||||
before do
|
||||
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=2&startAt=0')
|
||||
.to_return(body: jira_labels_1.to_json )
|
||||
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=2&startAt=2')
|
||||
.to_return(body: jira_labels_2.to_json )
|
||||
end
|
||||
|
||||
expect(Gitlab::JiraImport.get_import_label_id(project.id).to_i).to eq(label.id)
|
||||
context 'when labels are returned from jira' do
|
||||
it 'caches import label' do
|
||||
expect(Gitlab::Cache::Import::Caching.read(Gitlab::JiraImport.import_label_cache_key(project.id))).to be nil
|
||||
|
||||
subject
|
||||
|
||||
expect(Gitlab::JiraImport.get_import_label_id(project.id).to_i).to eq(label.id)
|
||||
end
|
||||
|
||||
it 'calls Gitlab::JiraImport::HandleLabelsService' do
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w(backend bug)).and_return(double(execute: [1, 2]))
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).to receive(:new).with(project, %w(feature)).and_return(double(execute: [3]))
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there are no labels to be handled' do
|
||||
shared_examples 'no labels handling' do
|
||||
it 'does not call Gitlab::JiraImport::HandleLabelsService' do
|
||||
expect(Gitlab::JiraImport::HandleLabelsService).not_to receive(:new)
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "values" => [] } }
|
||||
|
||||
before do
|
||||
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=2&startAt=0')
|
||||
.to_return(body: jira_labels.to_json )
|
||||
end
|
||||
|
||||
context 'when the labels field is empty' do
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "isLast" => true, "total" => 3, "values" => [] } }
|
||||
|
||||
it_behaves_like 'no labels handling'
|
||||
end
|
||||
|
||||
context 'when the labels field is missing' do
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "isLast" => true, "total" => 3 } }
|
||||
|
||||
it_behaves_like 'no labels handling'
|
||||
end
|
||||
|
||||
context 'when the isLast argument is missing' do
|
||||
let(:jira_labels) { { "maxResults" => 2, "startAt" => 0, "total" => 3, "values" => %w(bug dev) } }
|
||||
|
||||
it_behaves_like 'no labels handling'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
let(:description) { 'basic description' }
|
||||
let(:created_at) { '2020-01-01 20:00:00' }
|
||||
let(:updated_at) { '2020-01-10 20:00:00' }
|
||||
let(:assignee) { double(displayName: 'Solver') }
|
||||
let(:jira_status) { 'new' }
|
||||
|
||||
let(:parent_field) do
|
||||
|
|
@ -18,7 +17,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
let(:issue_type_field) { { 'name' => 'Task' } }
|
||||
let(:fix_versions_field) { [{ 'name' => '1.0' }, { 'name' => '1.1' }] }
|
||||
let(:priority_field) { { 'name' => 'Medium' } }
|
||||
let(:labels_field) { %w(bug backend) }
|
||||
let(:environment_field) { 'staging' }
|
||||
let(:duedate_field) { '2020-03-01' }
|
||||
|
||||
|
|
@ -28,7 +26,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
'issuetype' => issue_type_field,
|
||||
'fixVersions' => fix_versions_field,
|
||||
'priority' => priority_field,
|
||||
'labels' => labels_field,
|
||||
'environment' => environment_field,
|
||||
'duedate' => duedate_field
|
||||
}
|
||||
|
|
@ -41,8 +38,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
description: description,
|
||||
created: created_at,
|
||||
updated: updated_at,
|
||||
assignee: assignee,
|
||||
reporter: double(displayName: 'Reporter'),
|
||||
status: double(statusCategory: { 'key' => jira_status }),
|
||||
fields: fields
|
||||
)
|
||||
|
|
@ -59,7 +54,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
|
||||
- Issue type: Task
|
||||
- Priority: Medium
|
||||
- Labels: bug, backend
|
||||
- Environment: staging
|
||||
- Due date: 2020-03-01
|
||||
- Parent issue: [FOO-2] parent issue FOO
|
||||
|
|
@ -71,11 +65,9 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
end
|
||||
|
||||
context 'when some fields are in incorrect format' do
|
||||
let(:assignee) { nil }
|
||||
let(:parent_field) { nil }
|
||||
let(:fix_versions_field) { [] }
|
||||
let(:priority_field) { nil }
|
||||
let(:labels_field) { [] }
|
||||
let(:environment_field) { nil }
|
||||
let(:duedate_field) { nil }
|
||||
|
||||
|
|
@ -112,22 +104,6 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when a labels field is not an array' do
|
||||
let(:labels_field) { { 'first' => 'bug' } }
|
||||
|
||||
it 'skips the labels' do
|
||||
expected_result = <<~MD
|
||||
---
|
||||
|
||||
**Issue metadata**
|
||||
|
||||
- Issue type: Task
|
||||
MD
|
||||
|
||||
expect(subject.strip).to eq(expected_result.strip)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a parent field has incorrectly formatted summary' do
|
||||
let(:parent_field) do
|
||||
{ 'key' => 'FOO-2', 'id' => '1050', 'other_field' => { 'summary' => 'parent issue FOO' } }
|
||||
|
|
@ -167,10 +143,8 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
end
|
||||
|
||||
context 'when some metadata fields are missing' do
|
||||
let(:assignee) { nil }
|
||||
let(:parent_field) { nil }
|
||||
let(:fix_versions_field) { [] }
|
||||
let(:labels_field) { [] }
|
||||
let(:environment_field) { nil }
|
||||
|
||||
it 'skips the missing fields' do
|
||||
|
|
@ -189,12 +163,10 @@ describe Gitlab::JiraImport::MetadataCollector do
|
|||
end
|
||||
|
||||
context 'when all metadata fields are missing' do
|
||||
let(:assignee) { nil }
|
||||
let(:parent_field) { nil }
|
||||
let(:issue_type_field) { nil }
|
||||
let(:fix_versions_field) { [] }
|
||||
let(:priority_field) { nil }
|
||||
let(:labels_field) { [] }
|
||||
let(:environment_field) { nil }
|
||||
let(:duedate_field) { nil }
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ require 'spec_helper'
|
|||
describe Gitlab::RequestContext, :request_store do
|
||||
subject { described_class.instance }
|
||||
|
||||
before do
|
||||
allow(subject).to receive(:enabled?).and_return(true)
|
||||
end
|
||||
|
||||
it { is_expected.to have_attributes(client_ip: nil, start_thread_cpu_time: nil, request_start_time: nil) }
|
||||
|
||||
describe '#request_deadline' do
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ describe BlobViewer::Readme do
|
|||
|
||||
context 'when the wiki is not empty' do
|
||||
before do
|
||||
create(:wiki_page, wiki: project.wiki, attrs: { title: 'home', content: 'Home page' })
|
||||
create(:wiki_page, wiki: project.wiki, title: 'home', content: 'Home page')
|
||||
end
|
||||
|
||||
it 'returns nil' do
|
||||
|
|
|
|||
|
|
@ -490,7 +490,7 @@ describe Event do
|
|||
|
||||
context 'for a wiki page event' do
|
||||
let(:wiki_page) do
|
||||
create(:wiki_page, :with_real_page, project: project)
|
||||
create(:wiki_page, project: project)
|
||||
end
|
||||
|
||||
subject(:event) { create(:wiki_page_event, project: project, wiki_page: wiki_page) }
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ describe Group do
|
|||
it { is_expected.to have_many(:cluster_groups).class_name('Clusters::Group') }
|
||||
it { is_expected.to have_many(:clusters).class_name('Clusters::Cluster') }
|
||||
it { is_expected.to have_many(:container_repositories) }
|
||||
it { is_expected.to have_many(:milestones) }
|
||||
it { is_expected.to have_many(:sprints) }
|
||||
|
||||
it_behaves_like 'model with wiki' do
|
||||
let(:container) { create(:group, :nested, :wiki_repo) }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ describe Issue do
|
|||
|
||||
describe "Associations" do
|
||||
it { is_expected.to belong_to(:milestone) }
|
||||
it { is_expected.to belong_to(:sprint) }
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:moved_to).class_name('Issue') }
|
||||
it { is_expected.to have_one(:moved_from).class_name('Issue') }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ describe MergeRequest do
|
|||
it { is_expected.to have_many(:assignees).through(:merge_request_assignees) }
|
||||
it { is_expected.to have_many(:merge_request_diffs) }
|
||||
it { is_expected.to have_many(:user_mentions).class_name("MergeRequestUserMention") }
|
||||
it { is_expected.to belong_to(:milestone) }
|
||||
it { is_expected.to belong_to(:sprint) }
|
||||
|
||||
context 'for forks' do
|
||||
let!(:project) { create(:project) }
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ describe MicrosoftTeamsService do
|
|||
message: "user created page: Awesome wiki_page"
|
||||
}
|
||||
end
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
|
||||
let(:wiki_page_sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, 'create') }
|
||||
|
||||
it "calls Microsoft Teams API" do
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ describe Project do
|
|||
it { is_expected.to have_many(:merge_requests) }
|
||||
it { is_expected.to have_many(:issues) }
|
||||
it { is_expected.to have_many(:milestones) }
|
||||
it { is_expected.to have_many(:sprints) }
|
||||
it { is_expected.to have_many(:project_members).dependent(:delete_all) }
|
||||
it { is_expected.to have_many(:users).through(:project_members) }
|
||||
it { is_expected.to have_many(:requesters).dependent(:delete_all) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Sprint do
|
||||
let!(:project) { create(:project) }
|
||||
let!(:group) { create(:group) }
|
||||
|
||||
describe 'modules' do
|
||||
context 'with a project' do
|
||||
it_behaves_like 'AtomicInternalId' do
|
||||
let(:internal_id_attribute) { :iid }
|
||||
let(:instance) { build(:sprint, project: build(:project), group: nil) }
|
||||
let(:scope) { :project }
|
||||
let(:scope_attrs) { { project: instance.project } }
|
||||
let(:usage) {:sprints }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a group' do
|
||||
it_behaves_like 'AtomicInternalId' do
|
||||
let(:internal_id_attribute) { :iid }
|
||||
let(:instance) { build(:sprint, project: nil, group: build(:group)) }
|
||||
let(:scope) { :group }
|
||||
let(:scope_attrs) { { namespace: instance.group } }
|
||||
let(:usage) {:sprints }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Associations" do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:group) }
|
||||
it { is_expected.to have_many(:issues) }
|
||||
it { is_expected.to have_many(:merge_requests) }
|
||||
end
|
||||
|
||||
describe "#iid" do
|
||||
it "is properly scoped on project and group" do
|
||||
sprint1 = create(:sprint, project: project)
|
||||
sprint2 = create(:sprint, project: project)
|
||||
sprint3 = create(:sprint, group: group)
|
||||
sprint4 = create(:sprint, group: group)
|
||||
sprint5 = create(:sprint, project: project)
|
||||
|
||||
want = {
|
||||
sprint1: 1,
|
||||
sprint2: 2,
|
||||
sprint3: 1,
|
||||
sprint4: 2,
|
||||
sprint5: 3
|
||||
}
|
||||
got = {
|
||||
sprint1: sprint1.iid,
|
||||
sprint2: sprint2.iid,
|
||||
sprint3: sprint3.iid,
|
||||
sprint4: sprint4.iid,
|
||||
sprint5: sprint5.iid
|
||||
}
|
||||
expect(got).to eq(want)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -6,17 +6,8 @@ describe WikiPage do
|
|||
let_it_be(:user) { create(:user) }
|
||||
let(:container) { create(:project, :wiki_repo) }
|
||||
let(:wiki) { Wiki.for_container(container, user) }
|
||||
|
||||
let(:new_page) do
|
||||
described_class.new(wiki).tap do |page|
|
||||
page.attributes = { title: 'test page', content: 'test content' }
|
||||
end
|
||||
end
|
||||
|
||||
let(:existing_page) do
|
||||
create_page('test page', 'test content')
|
||||
wiki.find_page('test page')
|
||||
end
|
||||
let(:new_page) { build(:wiki_page, wiki: wiki, title: 'test page', content: 'test content') }
|
||||
let(:existing_page) { create(:wiki_page, wiki: wiki, title: 'test page', content: 'test content', message: 'test commit') }
|
||||
|
||||
subject { new_page }
|
||||
|
||||
|
|
@ -41,13 +32,13 @@ describe WikiPage do
|
|||
|
||||
context 'when there are pages' do
|
||||
before do
|
||||
create_page('dir_1/dir_1_1/page_3', 'content')
|
||||
create_page('page_1', 'content')
|
||||
create_page('dir_1/page_2', 'content')
|
||||
create_page('dir_2', 'page with dir name')
|
||||
create_page('dir_2/page_5', 'content')
|
||||
create_page('page_6', 'content')
|
||||
create_page('dir_2/page_4', 'content')
|
||||
wiki.create_page('dir_1/dir_1_1/page_3', 'content')
|
||||
wiki.create_page('page_1', 'content')
|
||||
wiki.create_page('dir_1/page_2', 'content')
|
||||
wiki.create_page('dir_2', 'page with dir name')
|
||||
wiki.create_page('dir_2/page_5', 'content')
|
||||
wiki.create_page('page_6', 'content')
|
||||
wiki.create_page('dir_2/page_4', 'content')
|
||||
end
|
||||
|
||||
let(:page_1) { wiki.find_page('page_1') }
|
||||
|
|
@ -353,7 +344,7 @@ describe WikiPage do
|
|||
context 'with an existing page title exceeding the limit' do
|
||||
subject do
|
||||
title = 'a' * (max_title + 1)
|
||||
create_page(title, 'content')
|
||||
wiki.create_page(title, 'content')
|
||||
wiki.find_page(title)
|
||||
end
|
||||
|
||||
|
|
@ -397,6 +388,20 @@ describe WikiPage do
|
|||
|
||||
expect(wiki.find_page("Index").message).to eq 'Custom Commit Message'
|
||||
end
|
||||
|
||||
it 'if the title is preceded by a / it is removed' do
|
||||
subject.create(attributes.merge(title: '/New Page'))
|
||||
|
||||
expect(wiki.find_page('New Page')).not_to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid attributes" do
|
||||
it 'does not create the page' do
|
||||
subject.create(title: '')
|
||||
|
||||
expect(wiki.find_page('New Page')).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -419,14 +424,11 @@ describe WikiPage do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
subject do
|
||||
create_page(title, "content")
|
||||
wiki.find_page(title)
|
||||
end
|
||||
describe '#update' do
|
||||
subject { create(:wiki_page, wiki: wiki, title: title) }
|
||||
|
||||
it "updates the content of the page" do
|
||||
subject.update(content: "new content")
|
||||
it 'updates the content of the page' do
|
||||
subject.update(content: 'new content')
|
||||
page = wiki.find_page(title)
|
||||
|
||||
expect([subject.content, page.content]).to all(eq('new content'))
|
||||
|
|
@ -438,24 +440,6 @@ describe WikiPage do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
context 'with valid attributes' do
|
||||
it 'raises an error if a page with the same path already exists' do
|
||||
create_page('New Page', 'content')
|
||||
create_page('foo/bar', 'content')
|
||||
|
||||
expect { create_page('New Page', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
|
||||
expect { create_page('foo/bar', 'other content') }.to raise_error Gitlab::Git::Wiki::DuplicatePageError
|
||||
end
|
||||
|
||||
it 'if the title is preceded by a / it is removed' do
|
||||
create_page('/New Page', 'content')
|
||||
|
||||
expect(wiki.find_page('New Page')).not_to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#update" do
|
||||
subject { existing_page }
|
||||
|
||||
|
|
@ -573,7 +557,7 @@ describe WikiPage do
|
|||
|
||||
context 'when renaming a page' do
|
||||
it 'raises an error if the page already exists' do
|
||||
create_page('Existing Page', 'content')
|
||||
wiki.create_page('Existing Page', 'content')
|
||||
|
||||
expect { subject.update(title: 'Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
|
||||
expect(subject.title).to eq 'test page'
|
||||
|
|
@ -595,7 +579,7 @@ describe WikiPage do
|
|||
|
||||
context 'when moving a page' do
|
||||
it 'raises an error if the page already exists' do
|
||||
create_page('foo/Existing Page', 'content')
|
||||
wiki.create_page('foo/Existing Page', 'content')
|
||||
|
||||
expect { subject.update(title: 'foo/Existing Page', content: 'new_content') }.to raise_error(WikiPage::PageRenameError)
|
||||
expect(subject.title).to eq 'test page'
|
||||
|
|
@ -615,10 +599,7 @@ describe WikiPage do
|
|||
end
|
||||
|
||||
context 'in subdir' do
|
||||
subject do
|
||||
create_page('foo/Existing Page', 'content')
|
||||
wiki.find_page('foo/Existing Page')
|
||||
end
|
||||
subject { create(:wiki_page, wiki: wiki, title: 'foo/Existing Page') }
|
||||
|
||||
it 'moves the page to the root folder if the title is preceded by /' do
|
||||
expect(subject.slug).to eq 'foo/Existing-Page'
|
||||
|
|
@ -656,7 +637,7 @@ describe WikiPage do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#destroy" do
|
||||
describe "#delete" do
|
||||
subject { existing_page }
|
||||
|
||||
it "deletes the page" do
|
||||
|
|
@ -688,10 +669,7 @@ describe WikiPage do
|
|||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:untitled_page) { described_class.new(wiki) }
|
||||
let(:directory_page) do
|
||||
create_page('parent directory/child page', 'test content')
|
||||
wiki.find_page('parent directory/child page')
|
||||
end
|
||||
let(:directory_page) { create(:wiki_page, title: 'parent directory/child page') }
|
||||
|
||||
where(:page, :title, :changed) do
|
||||
:untitled_page | nil | false
|
||||
|
|
@ -754,10 +732,7 @@ describe WikiPage do
|
|||
end
|
||||
|
||||
context 'when the page is inside an actual directory' do
|
||||
subject do
|
||||
create_page('dir_1/dir_1_1/file', 'content')
|
||||
wiki.find_page('dir_1/dir_1_1/file')
|
||||
end
|
||||
subject { create(:wiki_page, title: 'dir_1/dir_1_1/file') }
|
||||
|
||||
it 'returns the full directory hierarchy' do
|
||||
expect(subject.directory).to eq('dir_1/dir_1_1')
|
||||
|
|
@ -804,6 +779,16 @@ describe WikiPage do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#persisted?' do
|
||||
it 'returns true for a persisted page' do
|
||||
expect(existing_page).to be_persisted
|
||||
end
|
||||
|
||||
it 'returns false for an unpersisted page' do
|
||||
expect(new_page).not_to be_persisted
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_partial_path' do
|
||||
it 'returns the relative path to the partial to be used' do
|
||||
expect(subject.to_partial_path).to eq('projects/wikis/wiki_page')
|
||||
|
|
@ -886,18 +871,6 @@ describe WikiPage do
|
|||
|
||||
private
|
||||
|
||||
def remove_temp_repo(path)
|
||||
FileUtils.rm_rf path
|
||||
end
|
||||
|
||||
def commit_details
|
||||
Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.email, "test commit")
|
||||
end
|
||||
|
||||
def create_page(name, content)
|
||||
wiki.wiki.write_page(name, :markdown, content, commit_details)
|
||||
end
|
||||
|
||||
def get_slugs(page_or_dir)
|
||||
if page_or_dir.is_a? WikiPage
|
||||
[page_or_dir.slug]
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ describe API::Search do
|
|||
context 'for wiki_blobs scope' do
|
||||
before do
|
||||
wiki = create(:project_wiki, project: project)
|
||||
create(:wiki_page, wiki: wiki, attrs: { title: 'home', content: "Awesome page" })
|
||||
create(:wiki_page, wiki: wiki, title: 'home', content: "Awesome page")
|
||||
|
||||
get api("/projects/#{project.id}/search", user), params: { scope: 'wiki_blobs', search: 'awesome' }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ describe API::Wikis do
|
|||
shared_examples_for 'returns list of wiki pages' do
|
||||
context 'when wiki has pages' do
|
||||
let!(:pages) do
|
||||
[create(:wiki_page, wiki: project_wiki, attrs: { title: 'page1', content: 'content of page1' }),
|
||||
create(:wiki_page, wiki: project_wiki, attrs: { title: 'page2.with.dot', content: 'content of page2' })]
|
||||
[create(:wiki_page, wiki: project_wiki, title: 'page1', content: 'content of page1'),
|
||||
create(:wiki_page, wiki: project_wiki, title: 'page2.with.dot', content: 'content of page2')]
|
||||
end
|
||||
|
||||
it 'returns the list of wiki pages without content' do
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ RSpec.shared_examples "chat service" do |service_name|
|
|||
message: "user created page: Awesome wiki_page"
|
||||
}
|
||||
end
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, attrs: opts) }
|
||||
let(:wiki_page) { create(:wiki_page, wiki: project.wiki, **opts) }
|
||||
let(:sample_data) { Gitlab::DataBuilder::WikiPage.build(wiki_page, user, "create") }
|
||||
|
||||
it_behaves_like "triggered #{service_name} service"
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ RSpec.shared_examples 'slack or mattermost notifications' do |service_name|
|
|||
message: "user created page: Awesome wiki_page"
|
||||
}
|
||||
|
||||
@wiki_page = create(:wiki_page, wiki: project.wiki, attrs: opts)
|
||||
@wiki_page = create(:wiki_page, wiki: project.wiki, **opts)
|
||||
@wiki_page_sample_data = Gitlab::DataBuilder::WikiPage.build(@wiki_page, user, 'create')
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -95,13 +95,14 @@ RSpec.shared_examples 'wiki model' do
|
|||
let(:wiki_pages) { subject.list_pages }
|
||||
|
||||
before do
|
||||
create_page('index', 'This is an index')
|
||||
create_page('index2', 'This is an index2')
|
||||
create_page('an index3', 'This is an index3')
|
||||
subject.create_page('index', 'This is an index')
|
||||
subject.create_page('index2', 'This is an index2')
|
||||
subject.create_page('an index3', 'This is an index3')
|
||||
end
|
||||
|
||||
it 'returns an array of WikiPage instances' do
|
||||
expect(wiki_pages.first).to be_a WikiPage
|
||||
expect(wiki_pages).to be_present
|
||||
expect(wiki_pages).to all(be_a(WikiPage))
|
||||
end
|
||||
|
||||
it 'does not load WikiPage content by default' do
|
||||
|
|
@ -149,7 +150,7 @@ RSpec.shared_examples 'wiki model' do
|
|||
|
||||
describe '#find_page' do
|
||||
before do
|
||||
create_page('index page', 'This is an awesome Gollum Wiki')
|
||||
subject.create_page('index page', 'This is an awesome Gollum Wiki')
|
||||
end
|
||||
|
||||
it 'returns the latest version of the page if it exists' do
|
||||
|
|
@ -176,7 +177,7 @@ RSpec.shared_examples 'wiki model' do
|
|||
|
||||
context 'pages with multibyte-character title' do
|
||||
before do
|
||||
create_page('autre pagé', "C'est un génial Gollum Wiki")
|
||||
subject.create_page('autre pagé', "C'est un génial Gollum Wiki")
|
||||
end
|
||||
|
||||
it 'can find a page by slug' do
|
||||
|
|
@ -188,7 +189,7 @@ RSpec.shared_examples 'wiki model' do
|
|||
|
||||
context 'pages with invalidly-encoded content' do
|
||||
before do
|
||||
create_page('encoding is fun', "f\xFCr".b)
|
||||
subject.create_page('encoding is fun', "f\xFCr".b)
|
||||
end
|
||||
|
||||
it 'can find the page' do
|
||||
|
|
@ -201,11 +202,11 @@ RSpec.shared_examples 'wiki model' do
|
|||
|
||||
describe '#find_sidebar' do
|
||||
before do
|
||||
create_page(described_class::SIDEBAR, 'This is an awesome Sidebar')
|
||||
subject.create_page(described_class::SIDEBAR, 'This is an awesome Sidebar')
|
||||
end
|
||||
|
||||
it 'finds the page defined as _sidebar' do
|
||||
page = subject.find_page('_sidebar')
|
||||
page = subject.find_sidebar
|
||||
|
||||
expect(page.content).to eq('This is an awesome Sidebar')
|
||||
end
|
||||
|
|
@ -284,58 +285,59 @@ RSpec.shared_examples 'wiki model' do
|
|||
end
|
||||
|
||||
describe '#update_page' do
|
||||
before do
|
||||
create_page('update-page', 'some content')
|
||||
@gitlab_git_wiki_page = subject.wiki.page(title: 'update-page')
|
||||
let(:page) { create(:wiki_page, wiki: subject, title: 'update-page') }
|
||||
|
||||
def update_page
|
||||
subject.update_page(
|
||||
@gitlab_git_wiki_page,
|
||||
page.page,
|
||||
content: 'some other content',
|
||||
format: :markdown,
|
||||
message: 'updated page'
|
||||
)
|
||||
@page = subject.list_pages(load_content: true).first.page
|
||||
end
|
||||
|
||||
it 'updates the content of the page' do
|
||||
expect(@page.raw_data).to eq('some other content')
|
||||
update_page
|
||||
page = subject.find_page('update-page')
|
||||
|
||||
expect(page.raw_content).to eq('some other content')
|
||||
end
|
||||
|
||||
it 'sets the correct commit message' do
|
||||
expect(@page.version.message).to eq('updated page')
|
||||
update_page
|
||||
page = subject.find_page('update-page')
|
||||
|
||||
expect(page.version.message).to eq('updated page')
|
||||
end
|
||||
|
||||
it 'sets the correct commit email' do
|
||||
update_page
|
||||
|
||||
expect(user.commit_email).not_to eq(user.email)
|
||||
expect(commit.author_email).to eq(user.commit_email)
|
||||
expect(commit.committer_email).to eq(user.commit_email)
|
||||
end
|
||||
|
||||
it 'updates container activity' do
|
||||
page
|
||||
|
||||
expect(subject).to receive(:update_container_activity)
|
||||
|
||||
subject.update_page(
|
||||
@gitlab_git_wiki_page,
|
||||
content: 'Yet more content',
|
||||
format: :markdown,
|
||||
message: 'Updated page again'
|
||||
)
|
||||
update_page
|
||||
end
|
||||
end
|
||||
|
||||
describe '#delete_page' do
|
||||
before do
|
||||
create_page('index', 'some content')
|
||||
@page = subject.wiki.page(title: 'index')
|
||||
end
|
||||
let(:page) { create(:wiki_page, wiki: wiki) }
|
||||
|
||||
it 'deletes the page' do
|
||||
subject.delete_page(@page)
|
||||
subject.delete_page(page)
|
||||
|
||||
expect(subject.list_pages.count).to eq(0)
|
||||
end
|
||||
|
||||
it 'sets the correct commit email' do
|
||||
subject.delete_page(@page)
|
||||
subject.delete_page(page)
|
||||
|
||||
expect(user.commit_email).not_to eq(user.email)
|
||||
expect(commit.author_email).to eq(user.commit_email)
|
||||
|
|
@ -343,9 +345,11 @@ RSpec.shared_examples 'wiki model' do
|
|||
end
|
||||
|
||||
it 'updates container activity' do
|
||||
page
|
||||
|
||||
expect(subject).to receive(:update_container_activity)
|
||||
|
||||
subject.delete_page(@page)
|
||||
subject.delete_page(page)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -378,23 +382,4 @@ RSpec.shared_examples 'wiki model' do
|
|||
expect(subject.hook_attrs.keys).to contain_exactly(:web_url, :git_ssh_url, :git_http_url, :path_with_namespace, :default_branch)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_temp_repo(path)
|
||||
FileUtils.mkdir_p path
|
||||
system(*%W(#{Gitlab.config.git.bin_path} init --quiet --bare -- #{path}))
|
||||
end
|
||||
|
||||
def remove_temp_repo(path)
|
||||
FileUtils.rm_rf path
|
||||
end
|
||||
|
||||
def commit_details
|
||||
Gitlab::Git::Wiki::CommitDetails.new(user.id, user.username, user.name, user.commit_email, 'test commit')
|
||||
end
|
||||
|
||||
def create_page(name, content)
|
||||
subject.wiki.write_page(name, :markdown, content, commit_details)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ describe Gitlab::JiraImport::Stage::ImportLabelsWorker do
|
|||
|
||||
before do
|
||||
jira_import.start!
|
||||
|
||||
WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/label?maxResults=500&startAt=0')
|
||||
.to_return(body: {}.to_json )
|
||||
end
|
||||
|
||||
it_behaves_like 'advance to next stage', :issues
|
||||
|
|
|
|||
Loading…
Reference in New Issue