summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-08-11 09:10:03 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-08-11 09:10:03 +0000
commite184bc1abfe4fe4fef8c25c0d2ccb4c0063e7d5e (patch)
treea3cb32545238fd46625485a482ef403de2d558b5
parent281f1b6ba36531122463afd6869ca5dcdd0b0e35 (diff)
downloadgitlab-ce-e184bc1abfe4fe4fef8c25c0d2ccb4c0063e7d5e.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/issue_templates/Feature proposal.md15
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--app/assets/javascripts/vue_shared/components/gl_mentions.vue7
-rw-r--r--app/models/resource_iteration_event.rb5
-rw-r--r--app/models/resource_milestone_event.rb19
-rw-r--r--app/models/resource_timebox_event.rb23
-rw-r--r--app/services/boards/issues/list_service.rb8
-rw-r--r--app/services/submit_usage_ping_service.rb14
-rw-r--r--app/views/projects/merge_requests/_how_to_merge.html.haml4
-rw-r--r--changelogs/unreleased/bump-gitlab-pages-1-22-0.yml5
-rw-r--r--changelogs/unreleased/create-resource-iteration-events-table.yml5
-rw-r--r--db/migrate/20200722131241_create_resource_iteration_events_table.rb16
-rw-r--r--db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb19
-rw-r--r--db/schema_migrations/202007221312411
-rw-r--r--db/schema_migrations/202007221320401
-rw-r--r--db/schema_migrations/202007221325401
-rw-r--r--db/schema_migrations/202007221330401
-rw-r--r--db/schema_migrations/202007221335401
-rw-r--r--db/structure.sql44
-rw-r--r--doc/api/graphql/reference/gitlab_schema.graphql72
-rw-r--r--doc/api/graphql/reference/gitlab_schema.json162
-rw-r--r--qa/qa/git/repository.rb8
-rw-r--r--qa/qa/resource/project.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb67
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb37
-rw-r--r--spec/db/schema_spec.rb3
-rw-r--r--spec/factories/resource_iteration_event.rb11
-rw-r--r--spec/models/resource_iteration_event_spec.rb17
-rw-r--r--spec/models/resource_milestone_event_spec.rb69
-rw-r--r--spec/services/submit_usage_ping_service_spec.rb2
-rw-r--r--spec/support/shared_examples/models/resource_event_shared_examples.rb (renamed from spec/support/shared_examples/resource_events.rb)0
-rw-r--r--spec/support/shared_examples/models/resource_timebox_event_shared_examples.rb75
-rw-r--r--spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb13
39 files changed, 668 insertions, 144 deletions
diff --git a/.gitlab/issue_templates/Feature proposal.md b/.gitlab/issue_templates/Feature proposal.md
index 60e55d4bcfe..4e894b8ce80 100644
--- a/.gitlab/issue_templates/Feature proposal.md
+++ b/.gitlab/issue_templates/Feature proposal.md
@@ -87,18 +87,7 @@ In which enterprise tier should this feature go? See https://about.gitlab.com/ha
### Links / references
-<!-- Label reminders - you should have one of each of the following labels if you can find the correct ones!
-
-Type - for example ~feature ~bug ~documentation ~meta /label ~"feature::addition" ~"feature::maintenance" ~tooling ~"tooling::pipelines" ~"tooling::workflow" per https://docs.gitlab.com/ee/development/contributing/issue_workflow.html#type-labels
-
-DevOps stage - for example ~"devops::secure"
-
-Group - for example ~"group::composition analysis"
-
-Category - for example ~"Category:Dependency Scanning"
-<!-- Label reminders - you should have one of each of the following labels if you can figure out the correct ones! -->
-/label ~"devops::
-/label ~"group::
-/label ~"Category:
+<!-- Label reminders - you should have one of each of the following labels if you can figure out the correct ones -->
+/label ~devops:: ~group: ~Category:
/label ~feature
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 3500250a4b0..57807d6d0d0 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.21.0
+1.22.0
diff --git a/app/assets/javascripts/vue_shared/components/gl_mentions.vue b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
index 1d8be1065e9..5d97d364e94 100644
--- a/app/assets/javascripts/vue_shared/components/gl_mentions.vue
+++ b/app/assets/javascripts/vue_shared/components/gl_mentions.vue
@@ -43,7 +43,12 @@ const autoCompleteMap = {
const fullText = this.$slots.default?.[0]?.elm?.value;
const selectionStart = this.$slots.default?.[0]?.elm?.selectionStart;
- if (!this.assignees) {
+ // Need to check whether sidebar store assignees has been updated
+ // in the case where the assignees AJAX response comes after the user does @ autocomplete
+ const isAssigneesLengthSame =
+ this.assignees?.length === SidebarMediator.singleton?.store?.assignees?.length;
+
+ if (!this.assignees || !isAssigneesLengthSame) {
this.assignees =
SidebarMediator.singleton?.store?.assignees?.map(assignee => assignee.username) || [];
}
diff --git a/app/models/resource_iteration_event.rb b/app/models/resource_iteration_event.rb
new file mode 100644
index 00000000000..78d85ea8b95
--- /dev/null
+++ b/app/models/resource_iteration_event.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+class ResourceIterationEvent < ResourceTimeboxEvent
+ belongs_to :iteration
+end
diff --git a/app/models/resource_milestone_event.rb b/app/models/resource_milestone_event.rb
index 36068cf508b..5fd71612de0 100644
--- a/app/models/resource_milestone_event.rb
+++ b/app/models/resource_milestone_event.rb
@@ -1,30 +1,17 @@
# frozen_string_literal: true
-class ResourceMilestoneEvent < ResourceEvent
+class ResourceMilestoneEvent < ResourceTimeboxEvent
include IgnorableColumns
- include IssueResourceEvent
- include MergeRequestResourceEvent
belongs_to :milestone
- validate :exactly_one_issuable
-
scope :include_relations, -> { includes(:user, milestone: [:project, :group]) }
- enum action: {
- add: 1,
- remove: 2
- }
-
# state is used for issue and merge request states.
enum state: Issue.available_states.merge(MergeRequest.available_states)
ignore_columns %i[reference reference_html cached_markdown_version], remove_with: '13.1', remove_after: '2020-06-22'
- def self.issuable_attrs
- %i(issue merge_request).freeze
- end
-
def milestone_title
milestone&.title
end
@@ -32,8 +19,4 @@ class ResourceMilestoneEvent < ResourceEvent
def milestone_parent
milestone&.parent
end
-
- def issuable
- issue || merge_request
- end
end
diff --git a/app/models/resource_timebox_event.rb b/app/models/resource_timebox_event.rb
new file mode 100644
index 00000000000..44f48915425
--- /dev/null
+++ b/app/models/resource_timebox_event.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ResourceTimeboxEvent < ResourceEvent
+ self.abstract_class = true
+
+ include IssueResourceEvent
+ include MergeRequestResourceEvent
+
+ validate :exactly_one_issuable
+
+ enum action: {
+ add: 1,
+ remove: 2
+ }
+
+ def self.issuable_attrs
+ %i(issue merge_request).freeze
+ end
+
+ def issuable
+ issue || merge_request
+ end
+end
diff --git a/app/services/boards/issues/list_service.rb b/app/services/boards/issues/list_service.rb
index fa86531018c..140420a32bd 100644
--- a/app/services/boards/issues/list_service.rb
+++ b/app/services/boards/issues/list_service.rb
@@ -45,6 +45,12 @@ module Boards
# rubocop: enable CodeReuse/ActiveRecord
def filter(issues)
+ # when grouping board issues by epics (used in board swimlanes)
+ # we need to get all issues in the board
+ # TODO: ignore hidden columns -
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/233870
+ return issues if params[:all_lists]
+
issues = without_board_labels(issues) unless list&.movable? || list&.closed?
issues = with_list_label(issues) if list&.label?
issues
@@ -87,6 +93,8 @@ module Boards
end
def set_state
+ return if params[:all_lists]
+
params[:state] = list && list.closed? ? 'closed' : 'opened'
end
diff --git a/app/services/submit_usage_ping_service.rb b/app/services/submit_usage_ping_service.rb
index 2846dd3a6fe..357a3fd7b7a 100644
--- a/app/services/submit_usage_ping_service.rb
+++ b/app/services/submit_usage_ping_service.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
class SubmitUsagePingService
- URL = 'https://version.gitlab.com/usage_data'
+ PRODUCTION_URL = 'https://version.gitlab.com/usage_data'
+ STAGING_URL = 'https://gitlab-services-version-gitlab-com-staging.gs-staging.gitlab.org/usage_data'
METRICS = %w[leader_issues instance_issues percentage_issues leader_notes instance_notes
percentage_notes leader_milestones instance_milestones percentage_milestones
@@ -23,7 +24,7 @@ class SubmitUsagePingService
raise SubmissionError.new('Usage data is blank') if payload.blank?
response = Gitlab::HTTP.post(
- URL,
+ url,
body: payload,
allow_local_requests: true,
headers: { 'Content-type' => 'application/json' }
@@ -45,4 +46,13 @@ class SubmitUsagePingService
metrics.slice(*METRICS)
)
end
+
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/233615 for details
+ def url
+ if Rails.env.production?
+ PRODUCTION_URL
+ else
+ STAGING_URL
+ end
+ end
end
diff --git a/app/views/projects/merge_requests/_how_to_merge.html.haml b/app/views/projects/merge_requests/_how_to_merge.html.haml
index a2da0e707d3..df81e608c3e 100644
--- a/app/views/projects/merge_requests/_how_to_merge.html.haml
+++ b/app/views/projects/merge_requests/_how_to_merge.html.haml
@@ -32,12 +32,12 @@
- if @merge_request.for_fork?
:preserve
git fetch origin
- git checkout "origin/#{h @merge_request.target_branch}"
+ git checkout "#{h @merge_request.target_branch}"
git merge --no-ff "#{h @merge_request.source_project_path}-#{h @merge_request.source_branch}"
- else
:preserve
git fetch origin
- git checkout "origin/#{h @merge_request.target_branch}"
+ git checkout "#{h @merge_request.target_branch}"
git merge --no-ff "#{h @merge_request.source_branch}"
%p
%strong Step 4.
diff --git a/changelogs/unreleased/bump-gitlab-pages-1-22-0.yml b/changelogs/unreleased/bump-gitlab-pages-1-22-0.yml
new file mode 100644
index 00000000000..30e25aa7ce9
--- /dev/null
+++ b/changelogs/unreleased/bump-gitlab-pages-1-22-0.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Pages to 1.22.0
+merge_request: 39172
+author:
+type: added
diff --git a/changelogs/unreleased/create-resource-iteration-events-table.yml b/changelogs/unreleased/create-resource-iteration-events-table.yml
new file mode 100644
index 00000000000..54f0e1a83e7
--- /dev/null
+++ b/changelogs/unreleased/create-resource-iteration-events-table.yml
@@ -0,0 +1,5 @@
+---
+title: Add DB table and model to track changes of the iterations on issues
+merge_request: 37617
+author:
+type: added
diff --git a/db/migrate/20200722131241_create_resource_iteration_events_table.rb b/db/migrate/20200722131241_create_resource_iteration_events_table.rb
new file mode 100644
index 00000000000..619faeaaadf
--- /dev/null
+++ b/db/migrate/20200722131241_create_resource_iteration_events_table.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class CreateResourceIterationEventsTable < ActiveRecord::Migration[6.0]
+ DOWNTIME = false
+
+ def change
+ create_table :resource_iteration_events do |t|
+ t.bigint :user_id, null: false, index: { name: 'index_resource_iteration_events_on_user_id' }
+ t.bigint :issue_id, null: true, index: { name: 'index_resource_iteration_events_on_issue_id' }
+ t.bigint :merge_request_id, null: true, index: { name: 'index_resource_iteration_events_on_merge_request_id' }
+ t.bigint :iteration_id, index: { name: 'index_resource_iteration_events_on_iteration_id' }
+ t.datetime_with_timezone :created_at, null: false
+ t.integer :action, limit: 2, null: false
+ end
+ end
+end
diff --git a/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb
new file mode 100644
index 00000000000..e28405be53d
--- /dev/null
+++ b/db/migrate/20200722132040_add_users_fk_to_resource_iteration_events_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddUsersFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :resource_iteration_events, :users, column: :user_id, on_delete: :nullify # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :resource_iteration_events, column: :user_id
+ end
+ end
+end
diff --git a/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb
new file mode 100644
index 00000000000..adb10aaa707
--- /dev/null
+++ b/db/migrate/20200722132540_add_issues_fk_to_resource_iteration_events_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIssuesFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :resource_iteration_events, :issues, column: :issue_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :resource_iteration_events, column: :issue_id
+ end
+ end
+end
diff --git a/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb
new file mode 100644
index 00000000000..8b1859bb253
--- /dev/null
+++ b/db/migrate/20200722133040_add_merge_requests_fk_to_resource_iteration_events_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddMergeRequestsFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :resource_iteration_events, :merge_requests, column: :merge_request_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :resource_iteration_events, column: :merge_request_id
+ end
+ end
+end
diff --git a/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb b/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb
new file mode 100644
index 00000000000..b42c29a0634
--- /dev/null
+++ b/db/migrate/20200722133540_add_iterations_fk_to_resource_iteration_events_table.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class AddIterationsFkToResourceIterationEventsTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ with_lock_retries do
+ add_foreign_key :resource_iteration_events, :sprints, column: :iteration_id, on_delete: :cascade # rubocop:disable Migration/AddConcurrentForeignKey
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :resource_iteration_events, column: :iteration_id
+ end
+ end
+end
diff --git a/db/schema_migrations/20200722131241 b/db/schema_migrations/20200722131241
new file mode 100644
index 00000000000..327486a7367
--- /dev/null
+++ b/db/schema_migrations/20200722131241
@@ -0,0 +1 @@
+5fc97e904844b43a331246c68b1d0a879f683d5b36fab6cd024f417922259864 \ No newline at end of file
diff --git a/db/schema_migrations/20200722132040 b/db/schema_migrations/20200722132040
new file mode 100644
index 00000000000..7993eaafe02
--- /dev/null
+++ b/db/schema_migrations/20200722132040
@@ -0,0 +1 @@
+7b33a7f96ea02e3d5510cb6a6d75a9c753c1bd24c93d9995f91596d6b1a44592 \ No newline at end of file
diff --git a/db/schema_migrations/20200722132540 b/db/schema_migrations/20200722132540
new file mode 100644
index 00000000000..683c61dd661
--- /dev/null
+++ b/db/schema_migrations/20200722132540
@@ -0,0 +1 @@
+543ebc8ab7fad96aeb5a8618bc954babb0eed1d252fe490aa6fab9b8e80ffbf1 \ No newline at end of file
diff --git a/db/schema_migrations/20200722133040 b/db/schema_migrations/20200722133040
new file mode 100644
index 00000000000..602ba562760
--- /dev/null
+++ b/db/schema_migrations/20200722133040
@@ -0,0 +1 @@
+4a6a322cf3f6e1622d3244f6faa99a1befcb8c626a8fea36b09d1910b770b88c \ No newline at end of file
diff --git a/db/schema_migrations/20200722133540 b/db/schema_migrations/20200722133540
new file mode 100644
index 00000000000..1a0385bcaea
--- /dev/null
+++ b/db/schema_migrations/20200722133540
@@ -0,0 +1 @@
+0307eb0f5082a5da84f5e94084b677d13e03f9cd5011efe3dc7e25645a00082d \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 7fd390b6ea4..86fa7a40734 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -15063,6 +15063,25 @@ CREATE SEQUENCE public.requirements_management_test_reports_id_seq
ALTER SEQUENCE public.requirements_management_test_reports_id_seq OWNED BY public.requirements_management_test_reports.id;
+CREATE TABLE public.resource_iteration_events (
+ id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ issue_id bigint,
+ merge_request_id bigint,
+ iteration_id bigint,
+ created_at timestamp with time zone NOT NULL,
+ action smallint NOT NULL
+);
+
+CREATE SEQUENCE public.resource_iteration_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE public.resource_iteration_events_id_seq OWNED BY public.resource_iteration_events.id;
+
CREATE TABLE public.resource_label_events (
id bigint NOT NULL,
action integer NOT NULL,
@@ -17214,6 +17233,8 @@ ALTER TABLE ONLY public.requirements ALTER COLUMN id SET DEFAULT nextval('public
ALTER TABLE ONLY public.requirements_management_test_reports ALTER COLUMN id SET DEFAULT nextval('public.requirements_management_test_reports_id_seq'::regclass);
+ALTER TABLE ONLY public.resource_iteration_events ALTER COLUMN id SET DEFAULT nextval('public.resource_iteration_events_id_seq'::regclass);
+
ALTER TABLE ONLY public.resource_label_events ALTER COLUMN id SET DEFAULT nextval('public.resource_label_events_id_seq'::regclass);
ALTER TABLE ONLY public.resource_milestone_events ALTER COLUMN id SET DEFAULT nextval('public.resource_milestone_events_id_seq'::regclass);
@@ -18440,6 +18461,9 @@ ALTER TABLE ONLY public.requirements_management_test_reports
ALTER TABLE ONLY public.requirements
ADD CONSTRAINT requirements_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY public.resource_iteration_events
+ ADD CONSTRAINT resource_iteration_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY public.resource_label_events
ADD CONSTRAINT resource_label_events_pkey PRIMARY KEY (id);
@@ -20526,6 +20550,14 @@ CREATE INDEX index_requirements_on_title_trigram ON public.requirements USING gi
CREATE INDEX index_requirements_on_updated_at ON public.requirements USING btree (updated_at);
+CREATE INDEX index_resource_iteration_events_on_issue_id ON public.resource_iteration_events USING btree (issue_id);
+
+CREATE INDEX index_resource_iteration_events_on_iteration_id ON public.resource_iteration_events USING btree (iteration_id);
+
+CREATE INDEX index_resource_iteration_events_on_merge_request_id ON public.resource_iteration_events USING btree (merge_request_id);
+
+CREATE INDEX index_resource_iteration_events_on_user_id ON public.resource_iteration_events USING btree (user_id);
+
CREATE INDEX index_resource_label_events_issue_id_label_id_action ON public.resource_label_events USING btree (issue_id, label_id, action);
CREATE INDEX index_resource_label_events_on_epic_id ON public.resource_label_events USING btree (epic_id);
@@ -22275,6 +22307,9 @@ ALTER TABLE ONLY public.security_scans
ALTER TABLE ONLY public.merge_request_diff_files
ADD CONSTRAINT fk_rails_501aa0a391 FOREIGN KEY (merge_request_diff_id) REFERENCES public.merge_request_diffs(id) ON DELETE CASCADE;
+ALTER TABLE ONLY public.resource_iteration_events
+ ADD CONSTRAINT fk_rails_501fa15d69 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY public.status_page_settings
ADD CONSTRAINT fk_rails_506e5ba391 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
@@ -22416,6 +22451,9 @@ ALTER TABLE ONLY public.web_hook_logs
ALTER TABLE ONLY public.jira_imports
ADD CONSTRAINT fk_rails_675d38c03b FOREIGN KEY (label_id) REFERENCES public.labels(id) ON DELETE SET NULL;
+ALTER TABLE ONLY public.resource_iteration_events
+ ADD CONSTRAINT fk_rails_6830c13ac1 FOREIGN KEY (merge_request_id) REFERENCES public.merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY public.geo_hashed_storage_migrated_events
ADD CONSTRAINT fk_rails_687ed7d7c5 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
@@ -22713,6 +22751,9 @@ ALTER TABLE ONLY public.x509_commit_signatures
ALTER TABLE ONLY public.ci_build_trace_sections
ADD CONSTRAINT fk_rails_ab7c104e26 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY public.resource_iteration_events
+ ADD CONSTRAINT fk_rails_abf5d4affa FOREIGN KEY (issue_id) REFERENCES public.issues(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY public.clusters
ADD CONSTRAINT fk_rails_ac3a663d79 FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
@@ -22869,6 +22910,9 @@ ALTER TABLE ONLY public.issue_tracker_data
ALTER TABLE ONLY public.resource_milestone_events
ADD CONSTRAINT fk_rails_cedf8cce4d FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY public.resource_iteration_events
+ ADD CONSTRAINT fk_rails_cee126f66c FOREIGN KEY (iteration_id) REFERENCES public.sprints(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY public.epic_metrics
ADD CONSTRAINT fk_rails_d071904753 FOREIGN KEY (epic_id) REFERENCES public.epics(id) ON DELETE CASCADE;
diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql
index 85633512323..61adc3283b9 100644
--- a/doc/api/graphql/reference/gitlab_schema.graphql
+++ b/doc/api/graphql/reference/gitlab_schema.graphql
@@ -998,6 +998,36 @@ type Board {
assignee: User
"""
+ Epics associated with board issues.
+ """
+ epics(
+ """
+ Returns the elements in the list that come after the specified cursor.
+ """
+ after: String
+
+ """
+ Returns the elements in the list that come before the specified cursor.
+ """
+ before: String
+
+ """
+ Returns the first _n_ elements from the list.
+ """
+ first: Int
+
+ """
+ Filters applied when selecting issues on the board
+ """
+ issueFilters: BoardEpicIssueInput
+
+ """
+ Returns the last _n_ elements from the list.
+ """
+ last: Int
+ ): EpicConnection
+
+ """
Whether or not backlog list is hidden.
"""
hideBacklogList: Boolean
@@ -1093,6 +1123,48 @@ type BoardEdge {
node: Board
}
+input BoardEpicIssueInput {
+ """
+ Username of a user assigned to issues
+ """
+ assigneeUsername: [String]
+
+ """
+ Username of the issues author
+ """
+ authorUsername: String
+
+ """
+ Epic ID applied to issues
+ """
+ epicId: String
+
+ """
+ Label applied to issues
+ """
+ labelName: [String]
+
+ """
+ Milestone applied to issues
+ """
+ milestoneTitle: String
+
+ """
+ Reaction emoji applied to issues
+ """
+ myReactionEmoji: String
+
+ """
+ Release applied to issues
+ """
+ releaseTag: String
+
+ """
+ Weight applied to issues
+ """
+ weight: String
+}
+
"""
Represents a list for an issue board
"""
diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json
index 6912f78ad0a..f61025aedc7 100644
--- a/doc/api/graphql/reference/gitlab_schema.json
+++ b/doc/api/graphql/reference/gitlab_schema.json
@@ -2676,6 +2676,69 @@
"deprecationReason": null
},
{
+ "name": "epics",
+ "description": "Epics associated with board issues.",
+ "args": [
+ {
+ "name": "issueFilters",
+ "description": "Filters applied when selecting issues on the board",
+ "type": {
+ "kind": "INPUT_OBJECT",
+ "name": "BoardEpicIssueInput",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "after",
+ "description": "Returns the elements in the list that come after the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "before",
+ "description": "Returns the elements in the list that come before the specified cursor.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "first",
+ "description": "Returns the first _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "last",
+ "description": "Returns the last _n_ elements from the list.",
+ "type": {
+ "kind": "SCALAR",
+ "name": "Int",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "type": {
+ "kind": "OBJECT",
+ "name": "EpicConnection",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
"name": "hideBacklogList",
"description": "Whether or not backlog list is hidden.",
"args": [
@@ -2947,6 +3010,105 @@
"possibleTypes": null
},
{
+ "kind": "INPUT_OBJECT",
+ "name": "BoardEpicIssueInput",
+ "description": null,
+ "fields": null,
+ "inputFields": [
+ {
+ "name": "labelName",
+ "description": "Label applied to issues",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "milestoneTitle",
+ "description": "Milestone applied to issues",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "assigneeUsername",
+ "description": "Username of a user assigned to issues",
+ "type": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "authorUsername",
+ "description": "Username of the issues author",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "releaseTag",
+ "description": "Release applied to issues",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "epicId",
+ "description": "Epic ID applied to issues",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "myReactionEmoji",
+ "description": "Reaction emoji applied to issues",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ },
+ {
+ "name": "weight",
+ "description": "Weight applied to issues",
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "defaultValue": null
+ }
+ ],
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": null
+ },
+ {
"kind": "OBJECT",
"name": "BoardList",
"description": "Represents a list for an issue board",
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index d662d846828..e0fcb9b0599 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -102,6 +102,10 @@ module QA
git_lfs_track_result.to_s + git_add_result.to_s
end
+ def add_tag(tag_name)
+ run("git tag #{tag_name}").to_s
+ end
+
def delete_tag(tag_name)
run(%Q{git push origin --delete #{tag_name}}, max_attempts: 3).to_s
end
@@ -122,6 +126,10 @@ module QA
run("git push --all").to_s
end
+ def push_tags_and_branches(branches)
+ run("git push --tags origin #{branches.join(' ')}").to_s
+ end
+
def merge(branch)
run("git merge #{branch}")
end
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index f4fe43aa3ab..eba8ada50ab 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -103,6 +103,20 @@ module QA
response.any? { |file| file[:path] == file_path }
end
+ def has_branches?(branches)
+ branches.all? do |branch|
+ response = get(Runtime::API::Request.new(api_client, "#{api_repository_branches_path}/#{branch}").url)
+ response.code == HTTP_STATUS_OK
+ end
+ end
+
+ def has_tags?(tags)
+ tags.all? do |tag|
+ response = get(Runtime::API::Request.new(api_client, "#{api_repository_tags_path}/#{tag}").url)
+ response.code == HTTP_STATUS_OK
+ end
+ end
+
def api_get_path
"/projects/#{CGI.escape(path_with_namespace)}"
end
@@ -131,6 +145,10 @@ module QA
"#{api_get_path}/repository/branches"
end
+ def api_repository_tags_path
+ "#{api_get_path}/repository/tags"
+ end
+
def api_repository_tree_path
"#{api_get_path}/repository/tree"
end
@@ -212,6 +230,10 @@ module QA
parse_body(get(Runtime::API::Request.new(api_client, api_repository_branches_path).url))
end
+ def repository_tags
+ parse_body(get(Runtime::API::Request.new(api_client, api_repository_tags_path).url))
+ end
+
def repository_tree
parse_body(get(Runtime::API::Request.new(api_client, api_repository_tree_path).url))
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index a002779d7d9..524cc3fc8a1 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -16,7 +16,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a basic merge request' do
+ it 'creates a basic merge request', :smoke do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = project
merge_request.title = merge_request_title
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index c01558d3702..ceacc73e3c3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -2,7 +2,7 @@
module QA
RSpec.describe 'Create' do
- describe 'Git push over HTTP', :ldap_no_tls do
+ describe 'Git push over HTTP', :ldap_no_tls, :smoke do
it 'user using a personal access token pushes code to the repository' do
Flow::Login.sign_in
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
index b918b2ff268..2baf1e1d8fd 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :ldap_no_tls do
- it 'user pushes code to the repository' do
+ it 'user pushes code to the repository', :smoke do
Flow::Login.sign_in
Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
new file mode 100644
index 00000000000..d0f0cabbbca
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Create' do
+ describe 'SSH key support' do
+ # Note: If you run these tests against GDK make sure you've enabled sshd
+ # See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md
+
+ let(:project) do
+ Resource::Project.fabricate! do |project|
+ project.name = 'ssh-tests'
+ end
+ end
+
+ before(:context) do
+ @key = Resource::SSHKey.fabricate_via_api! do |resource|
+ resource.title = "key for ssh tests #{Time.now.to_f}"
+ end
+ end
+
+ after(:context) do
+ @key.remove_via_api!
+ end
+
+ before do
+ Flow::Login.sign_in
+ end
+
+ it 'pushes code to the repository via SSH', :smoke do
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = project
+ push.ssh_key = @key
+ push.file_name = 'README.md'
+ push.file_content = '# Test Use SSH Key'
+ push.commit_message = 'Add README.md'
+ end.project.visit!
+
+ Page::Project::Show.perform do |project|
+ expect(project).to have_file('README.md')
+ expect(project).to have_readme_content('Test Use SSH Key')
+ end
+ end
+
+ it 'pushes multiple branches and tags together', :smoke do
+ branches = []
+ tags = []
+ Git::Repository.perform do |repository|
+ repository.uri = project.repository_ssh_location.uri
+ repository.use_ssh_key(@key)
+ repository.clone
+ repository.configure_identity('GitLab QA', 'root@gitlab.com')
+ 1.upto(3) do |i|
+ branches << "branch#{i}"
+ tags << "tag#{i}"
+ repository.checkout("branch#{i}", new_branch: true)
+ repository.commit_file("file#{i}", SecureRandom.random_bytes(10000), "Add file#{i}")
+ repository.add_tag("tag#{i}")
+ end
+ repository.push_tags_and_branches(branches)
+ end
+
+ expect(project).to have_branches(branches)
+ expect(project).to have_tags(tags)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
deleted file mode 100644
index e91717b0f5f..00000000000
--- a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Create' do
- describe 'SSH key support' do
- # Note: If you run this test against GDK make sure you've enabled sshd
- # See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md
-
- let(:key_title) { "key for ssh tests #{Time.now.to_f}" }
-
- it 'user adds an ssh key and pushes code to the repository' do
- Flow::Login.sign_in
-
- key = Resource::SSHKey.fabricate_via_api! do |resource|
- resource.title = key_title
- end
-
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.ssh_key = key
- push.file_name = 'README.md'
- push.file_content = '# Test Use SSH Key'
- push.commit_message = 'Add README.md'
- end.project.visit!
-
- expect(page).to have_content('README.md')
- expect(page).to have_content('Test Use SSH Key')
-
- Page::Main::Menu.perform(&:click_settings_link)
- Page::Profile::Menu.perform(&:click_ssh_keys)
-
- Page::Profile::SSHKeys.perform do |ssh_keys|
- ssh_keys.remove_key(key_title)
- end
- end
- end
- end
-end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index a2a95124b31..bbba17eddb7 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -165,6 +165,9 @@ RSpec.describe 'Database schema' do
context 'for enums' do
ApplicationRecord.descendants.each do |model|
+ # skip model if it is an abstract class as it would not have an associated DB table
+ next if model.abstract_class?
+
describe model do
let(:ignored_enums) { ignored_limit_enums(model.name) }
let(:enums) { model.defined_enums.keys - ignored_enums }
diff --git a/spec/factories/resource_iteration_event.rb b/spec/factories/resource_iteration_event.rb
new file mode 100644
index 00000000000..85e7320f7a7
--- /dev/null
+++ b/spec/factories/resource_iteration_event.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :resource_iteration_event do
+ issue { merge_request.nil? ? create(:issue) : nil }
+ merge_request { nil }
+ iteration
+ action { :add }
+ user { issue&.author || merge_request&.author || create(:user) }
+ end
+end
diff --git a/spec/models/resource_iteration_event_spec.rb b/spec/models/resource_iteration_event_spec.rb
new file mode 100644
index 00000000000..fe1310d7bf1
--- /dev/null
+++ b/spec/models/resource_iteration_event_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ResourceIterationEvent, type: :model do
+ it_behaves_like 'a resource event'
+ it_behaves_like 'a resource event for issues'
+ it_behaves_like 'a resource event for merge requests'
+
+ it_behaves_like 'having unique enum values'
+ it_behaves_like 'timebox resource event validations'
+ it_behaves_like 'timebox resource event actions'
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:iteration) }
+ end
+end
diff --git a/spec/models/resource_milestone_event_spec.rb b/spec/models/resource_milestone_event_spec.rb
index 76ffb358d80..0a5292b2d16 100644
--- a/spec/models/resource_milestone_event_spec.rb
+++ b/spec/models/resource_milestone_event_spec.rb
@@ -8,77 +8,14 @@ RSpec.describe ResourceMilestoneEvent, type: :model do
it_behaves_like 'a resource event for merge requests'
it_behaves_like 'having unique enum values'
+ it_behaves_like 'timebox resource event validations'
+ it_behaves_like 'timebox resource event states'
+ it_behaves_like 'timebox resource event actions'
describe 'associations' do
it { is_expected.to belong_to(:milestone) }
end
- describe 'validations' do
- context 'when issue and merge_request are both nil' do
- subject { build(described_class.name.underscore.to_sym, issue: nil, merge_request: nil) }
-
- it { is_expected.not_to be_valid }
- end
-
- context 'when issue and merge_request are both set' do
- subject { build(described_class.name.underscore.to_sym, issue: build(:issue), merge_request: build(:merge_request)) }
-
- it { is_expected.not_to be_valid }
- end
-
- context 'when issue is set' do
- subject { create(described_class.name.underscore.to_sym, issue: create(:issue), merge_request: nil) }
-
- it { is_expected.to be_valid }
- end
-
- context 'when merge_request is set' do
- subject { create(described_class.name.underscore.to_sym, issue: nil, merge_request: create(:merge_request)) }
-
- it { is_expected.to be_valid }
- end
- end
-
- describe 'states' do
- [Issue, MergeRequest].each do |klass|
- klass.available_states.each do |state|
- it "supports state #{state.first} for #{klass.name.underscore}" do
- model = create(klass.name.underscore, state: state[0])
- key = model.class.name.underscore
- event = build(described_class.name.underscore.to_sym, key => model, state: model.state)
-
- expect(event.state).to eq(state[0])
- end
- end
- end
- end
-
- shared_examples 'a milestone action queryable resource event' do |expected_results_for_actions|
- [Issue, MergeRequest].each do |klass|
- expected_results_for_actions.each do |action, expected_result|
- it "is #{expected_result} for action #{action} on #{klass.name.underscore}" do
- model = create(klass.name.underscore)
- key = model.class.name.underscore
- event = build(described_class.name.underscore.to_sym, key => model, action: action)
-
- expect(event.send(query_method)).to eq(expected_result)
- end
- end
- end
- end
-
- describe '#added?' do
- it_behaves_like 'a milestone action queryable resource event', { add: true, remove: false } do
- let(:query_method) { :add? }
- end
- end
-
- describe '#removed?' do
- it_behaves_like 'a milestone action queryable resource event', { add: false, remove: true } do
- let(:query_method) { :remove? }
- end
- end
-
describe '#milestone_title' do
let(:milestone) { create(:milestone, title: 'v2.3') }
let(:event) { create(:resource_milestone_event, milestone: milestone) }
diff --git a/spec/services/submit_usage_ping_service_spec.rb b/spec/services/submit_usage_ping_service_spec.rb
index e2ebf20c331..6031a71deef 100644
--- a/spec/services/submit_usage_ping_service_spec.rb
+++ b/spec/services/submit_usage_ping_service_spec.rb
@@ -164,7 +164,7 @@ RSpec.describe SubmitUsagePingService do
end
def stub_response(body:, status: 201)
- stub_full_request('https://version.gitlab.com/usage_data', method: :post)
+ stub_full_request(SubmitUsagePingService::STAGING_URL, method: :post)
.to_return(
headers: { 'Content-Type' => 'application/json' },
body: body.to_json,
diff --git a/spec/support/shared_examples/resource_events.rb b/spec/support/shared_examples/models/resource_event_shared_examples.rb
index c0158f9b24b..c0158f9b24b 100644
--- a/spec/support/shared_examples/resource_events.rb
+++ b/spec/support/shared_examples/models/resource_event_shared_examples.rb
diff --git a/spec/support/shared_examples/models/resource_timebox_event_shared_examples.rb b/spec/support/shared_examples/models/resource_timebox_event_shared_examples.rb
new file mode 100644
index 00000000000..07552b62cdd
--- /dev/null
+++ b/spec/support/shared_examples/models/resource_timebox_event_shared_examples.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'timebox resource event validations' do
+ describe 'validations' do
+ context 'when issue and merge_request are both nil' do
+ subject { build(described_class.name.underscore.to_sym, issue: nil, merge_request: nil) }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when issue and merge_request are both set' do
+ subject { build(described_class.name.underscore.to_sym, issue: build(:issue), merge_request: build(:merge_request)) }
+
+ it { is_expected.not_to be_valid }
+ end
+
+ context 'when issue is set' do
+ subject { create(described_class.name.underscore.to_sym, issue: create(:issue), merge_request: nil) }
+
+ it { is_expected.to be_valid }
+ end
+
+ context 'when merge_request is set' do
+ subject { create(described_class.name.underscore.to_sym, issue: nil, merge_request: create(:merge_request)) }
+
+ it { is_expected.to be_valid }
+ end
+ end
+end
+
+RSpec.shared_examples 'timebox resource event states' do
+ describe 'states' do
+ [Issue, MergeRequest].each do |klass|
+ klass.available_states.each do |state|
+ it "supports state #{state.first} for #{klass.name.underscore}" do
+ model = create(klass.name.underscore, state: state[0])
+ key = model.class.name.underscore
+ event = build(described_class.name.underscore.to_sym, key => model, state: model.state)
+
+ expect(event.state).to eq(state[0])
+ end
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'queryable timebox action resource event' do |expected_results_for_actions|
+ [Issue, MergeRequest].each do |klass|
+ expected_results_for_actions.each do |action, expected_result|
+ it "is #{expected_result} for action #{action} on #{klass.name.underscore}" do
+ model = build(klass.name.underscore)
+ key = model.class.name.underscore
+ event = build(described_class.name.underscore.to_sym, key => model, action: action)
+
+ expect(event.send(query_method)).to eq(expected_result)
+ end
+ end
+ end
+end
+
+RSpec.shared_examples 'timebox resource event actions' do
+ describe '#added?' do
+ it_behaves_like 'queryable timebox action resource event', { add: true, remove: false } do
+ let(:query_method) { :add? }
+ end
+ end
+
+ describe '#removed?' do
+ it_behaves_like 'queryable timebox action resource event', { add: false, remove: true } do
+ let(:query_method) { :remove? }
+ end
+ end
+end
diff --git a/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb b/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
index 2fcf439a6c6..06e2b715e6d 100644
--- a/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
+++ b/spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
@@ -80,4 +80,17 @@ RSpec.shared_examples 'issues list service' do
expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
end
end
+
+ context 'when :all_lists is used' do
+ it 'returns issues from all lists' do
+ params = { board_id: board.id, all_lists: true }
+
+ issues = described_class.new(parent, user, params).execute
+
+ expected = [opened_issue2, reopened_issue1, opened_issue1, list1_issue1,
+ list1_issue2, list1_issue3, list2_issue1, closed_issue1,
+ closed_issue2, closed_issue3, closed_issue4, closed_issue5]
+ expect(issues).to match_array(expected)
+ end
+ end
end