Skip to content
Snippets Groups Projects
Commit 09ffaae1 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent b3e4ec8e
No related branches found
No related tags found
No related merge requests found
Showing
with 182 additions and 96 deletions
Loading
Loading
@@ -37,7 +37,6 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import { initUserTracking } from './tracking';
import { __ } from './locale';
import initPrivacyPolicyUpdateCallout from './privacy_policy_update_callout';
 
import 'ee_else_ce/main_ee';
 
Loading
Loading
@@ -97,7 +96,6 @@ function deferredInitialisation() {
initUsagePingConsent();
initUserPopovers();
initUserTracking();
initPrivacyPolicyUpdateCallout();
 
if (document.querySelector('.search')) initSearchAutocomplete();
 
Loading
Loading
import PersistentUserCallout from '~/persistent_user_callout';
function initPrivacyPolicyUpdateCallout() {
const callout = document.querySelector('.js-privacy-policy-update');
PersistentUserCallout.factory(callout);
}
export default initPrivacyPolicyUpdateCallout;
Loading
Loading
@@ -17,6 +17,4 @@
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
.content{ id: "content-body" }
= render "layouts/flash", extra_flash_class: 'limit-container-width'
- if Gitlab.com?
= render_if_exists "layouts/privacy_policy_update_callout"
= yield
---
title: Record latencies for Sidekiq failures
merge_request: 18909
author:
type: performance
---
title: Pipeline vulnerability dashboard sort vulnerabilities by severity then confidence
merge_request: 18863
author:
type: fixed
Loading
Loading
@@ -120,3 +120,4 @@
- [update_external_pull_requests, 3]
- [refresh_license_compliance_checks, 2]
- [design_management_new_version, 1]
- [epics, 2]
# frozen_string_literal: true
class AddSourcingEpicDates < ActiveRecord::Migration[5.1]
DOWNTIME = false
def change
add_column :epics, :start_date_sourcing_epic_id, :integer
add_column :epics, :due_date_sourcing_epic_id, :integer
end
end
# frozen_string_literal: true
class AddSourcingEpicDatesFks < ActiveRecord::Migration[5.1]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :epics, :start_date_sourcing_epic_id, where: 'start_date_sourcing_epic_id is not null'
add_concurrent_index :epics, :due_date_sourcing_epic_id, where: 'due_date_sourcing_epic_id is not null'
add_concurrent_foreign_key :epics, :epics, column: :start_date_sourcing_epic_id, on_delete: :nullify
add_concurrent_foreign_key :epics, :epics, column: :due_date_sourcing_epic_id, on_delete: :nullify
end
def down
remove_foreign_key_if_exists :epics, column: :start_date_sourcing_epic_id
remove_foreign_key_if_exists :epics, column: :due_date_sourcing_epic_id
remove_concurrent_index :epics, :start_date_sourcing_epic_id
remove_concurrent_index :epics, :due_date_sourcing_epic_id
end
end
Loading
Loading
@@ -1423,15 +1423,19 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do
t.integer "parent_id"
t.integer "relative_position"
t.integer "state_id", limit: 2, default: 1, null: false
t.integer "start_date_sourcing_epic_id"
t.integer "due_date_sourcing_epic_id"
t.index ["assignee_id"], name: "index_epics_on_assignee_id"
t.index ["author_id"], name: "index_epics_on_author_id"
t.index ["closed_by_id"], name: "index_epics_on_closed_by_id"
t.index ["due_date_sourcing_epic_id"], name: "index_epics_on_due_date_sourcing_epic_id", where: "(due_date_sourcing_epic_id IS NOT NULL)"
t.index ["end_date"], name: "index_epics_on_end_date"
t.index ["group_id"], name: "index_epics_on_group_id"
t.index ["iid"], name: "index_epics_on_iid"
t.index ["milestone_id"], name: "index_milestone"
t.index ["parent_id"], name: "index_epics_on_parent_id"
t.index ["start_date"], name: "index_epics_on_start_date"
t.index ["start_date_sourcing_epic_id"], name: "index_epics_on_start_date_sourcing_epic_id", where: "(start_date_sourcing_epic_id IS NOT NULL)"
end
 
create_table "events", id: :serial, force: :cascade do |t|
Loading
Loading
@@ -4158,7 +4162,9 @@ ActiveRecord::Schema.define(version: 2019_10_17_045817) do
add_foreign_key "epic_issues", "epics", on_delete: :cascade
add_foreign_key "epic_issues", "issues", on_delete: :cascade
add_foreign_key "epic_metrics", "epics", on_delete: :cascade
add_foreign_key "epics", "epics", column: "due_date_sourcing_epic_id", name: "fk_013c9f36ca", on_delete: :nullify
add_foreign_key "epics", "epics", column: "parent_id", name: "fk_25b99c1be3", on_delete: :cascade
add_foreign_key "epics", "epics", column: "start_date_sourcing_epic_id", name: "fk_9d480c64b2", on_delete: :nullify
add_foreign_key "epics", "milestones", on_delete: :nullify
add_foreign_key "epics", "namespaces", column: "group_id", name: "fk_f081aa4489", on_delete: :cascade
add_foreign_key "epics", "users", column: "assignee_id", name: "fk_dccd3f98fc", on_delete: :nullify
Loading
Loading
Loading
Loading
@@ -50,12 +50,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"labels": []
Loading
Loading
@@ -102,12 +104,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"labels": []
Loading
Loading
@@ -189,12 +193,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"labels": []
Loading
Loading
@@ -241,12 +247,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"labels": []
Loading
Loading
Loading
Loading
@@ -14,9 +14,13 @@ The [epic issues API](epic_issues.md) allows you to interact with issues associa
 
> [Introduced][ee-6448] in GitLab 11.3.
 
Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission, additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`, `start_date_from_milestones`, `due_date_fixed` and `due_date_from_milestones`.
Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission,
additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`,
and four date fields `start_date_fixed`, `start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`.
 
`end_date` has been deprecated in favor of `due_date`.
- `end_date` has been deprecated in favor of `due_date`.
- `start_date_from_milestones` has been deprecated in favor of `start_date_from_inherited_source`
- `due_date_from_milestones` has been deprecated in favor of `due_date_from_inherited_source`
 
## Epics pagination
 
Loading
Loading
@@ -80,12 +84,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z",
Loading
Loading
@@ -136,12 +142,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z",
Loading
Loading
@@ -204,12 +212,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z",
Loading
Loading
@@ -272,12 +282,14 @@ Example response:
"start_date": null,
"start_date_is_fixed": false,
"start_date_fixed": null,
"start_date_from_milestones": null,
"end_date": "2018-07-31",
"start_date_from_milestones": null, //deprecated in favor of start_date_from_inherited_source
"start_date_from_inherited_source": null,
"end_date": "2018-07-31", //deprecated in favor of due_date
"due_date": "2018-07-31",
"due_date_is_fixed": false,
"due_date_fixed": null,
"due_date_from_milestones": "2018-07-31",
"due_date_from_milestones": "2018-07-31", //deprecated in favor of start_date_from_inherited_source
"due_date_from_inherited_source": "2018-07-31",
"created_at": "2018-07-17T13:36:22.770Z",
"updated_at": "2018-07-18T12:22:05.239Z",
"closed_at": "2018-08-18T12:22:05.239Z",
Loading
Loading
Loading
Loading
@@ -43,14 +43,14 @@ a new presenter specifically for GraphQL.
The presenter is initialized using the object resolved by a field, and
the context.
 
### Exposing Global ids
### Exposing Global IDs
 
When exposing an `id` field on a type, we will by default try to
expose a global id by calling `to_global_id` on the resource being
When exposing an `ID` field on a type, we will by default try to
expose a global ID by calling `to_global_id` on the resource being
rendered.
 
To override this behaviour, you can implement an `id` method on the
type for which you are exposing an id. Please make sure that when
type for which you are exposing an ID. Please make sure that when
exposing a `GraphQL::ID_TYPE` using a custom method that it is
globally unique.
 
Loading
Loading
@@ -350,7 +350,10 @@ To find objects to display in a field, we can add resolvers to
`app/graphql/resolvers`.
 
Arguments can be defined within the resolver, those arguments will be
made available to the fields using the resolver.
made available to the fields using the resolver. When exposing a model
that had an internal ID (`iid`), prefer using that in combination with
the namespace path as arguments in a resolver over a database
ID. Othewise use a [globally unique ID](#exposing-global-ids).
 
We already have a `FullPathLoader` that can be included in other
resolvers to quickly find Projects and Namespaces which will have a
Loading
Loading
@@ -365,6 +368,10 @@ actions. In the same way a GET-request should not modify data, we
cannot modify data in a regular GraphQL-query. We can however in a
mutation.
 
To find objects for a mutation, arguments need to be specified. As with
[resolvers](#resolvers), prefer using internal ID or, if needed, a
global ID rather than the database ID.
### Fields
 
In the most common situations, a mutation would return 2 fields:
Loading
Loading
Loading
Loading
@@ -92,24 +92,44 @@ To remove a child epic from a parent epic:
 
## Start date and due date
 
To set a **Start date** and **Due date** for an epic, you can choose either of the following:
To set a **Start date** and **Due date** for an epic, select one of the following:
 
- **Fixed**: Enter a fixed value.
- **From milestones:** Inherit a dynamic value from the issues added to the epic.
- **From milestones**: Inherit a dynamic value from the issues added to the epic.
- **Inherited**: Inherit a dynamic value from the issues added to the epic. ([Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7332) in GitLab 12.5 to replace **From milestones**).
 
If you select **From milestones** for the start date, GitLab will automatically set the
date to be earliest start date across all milestones that are currently assigned
to the issues that are added to the epic. Similarly, if you select "From milestones"
for the due date, GitLab will set it to be the latest due date across all
milestones that are currently assigned to those issues.
### Milestones
 
These are dynamic dates which are recalculated immediately if any of the following occur:
If you select **From milestones** for the start date, GitLab will automatically set the date to be earliest
start date across all milestones that are currently assigned to the issues that are added to the epic.
Similarly, if you select **From milestones** for the due date, GitLab will set it to be the latest due date across
all milestones that are currently assigned to those issues.
These are dynamic dates which are recalculated if any of the following occur:
 
- Milestones are re-assigned to the issues.
- Milestone dates change.
- Issues are added or removed from the epic.
 
## Roadmap
### Inherited
If you select **Inherited** for the start date, GitLab will scan all child epics and issues assigned to the epic,
and will set the start date to match the earliest found start date or milestone. Similarly, if you select
**Inherited** for the due date, GitLab will set the due date to match the latest due date or milestone
found among its child epics and issues.
These are dynamic dates and recalculated if any of the following occur:
- A child epic's dates change.
- Milestones are reassigned to an issue.
- A milestone's dates change.
- Issues are added to, or removed from, the epic.
Because the epic's dates can inherit dates from its children, the start date and due date propagate from the bottom to the top.
If the start date of a child epic on the lowest level changes, that becomes the earliest possible start date for its parent epic,
then the parent epic's start date will reflect the change and this will propagate upwards to the top epic.
## Roadmap in epics
 
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/7327) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.10.
 
Loading
Loading
Loading
Loading
@@ -26,7 +26,7 @@ Epics in the view can be sorted by:
Each option contains a button that toggles the sort order between **ascending** and **descending**. The sort option and order will be persisted when browsing Epics,
including the [epics list view](../epics/index.md).
 
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap).
Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics).
 
## Timeline duration
 
Loading
Loading
Loading
Loading
@@ -21,29 +21,35 @@ module Gitlab
@metrics[:sidekiq_jobs_retried_total].increment(labels, 1)
end
 
job_succeeded = false
monotonic_time_start = Gitlab::Metrics::System.monotonic_time
job_thread_cputime_start = get_thread_cputime
realtime = Benchmark.realtime do
begin
yield
end
job_succeeded = true
ensure
monotonic_time_end = Gitlab::Metrics::System.monotonic_time
job_thread_cputime_end = get_thread_cputime
 
job_thread_cputime_end = get_thread_cputime
job_thread_cputime = job_thread_cputime_end - job_thread_cputime_start
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
monotonic_time = monotonic_time_end - monotonic_time_start
job_thread_cputime = job_thread_cputime_end - job_thread_cputime_start
 
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, realtime)
rescue Exception # rubocop: disable Lint/RescueException
@metrics[:sidekiq_jobs_failed_total].increment(labels, 1)
raise
ensure
@metrics[:sidekiq_running_jobs].increment(labels, -1)
# sidekiq_running_jobs, sidekiq_jobs_failed_total should not include the job_status label
@metrics[:sidekiq_running_jobs].increment(labels, -1)
@metrics[:sidekiq_jobs_failed_total].increment(labels, 1) unless job_succeeded
# job_status: done, fail match the job_status attribute in structured logging
labels[:job_status] = job_succeeded ? :done : :fail
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, monotonic_time)
end
end
 
private
 
def init_metrics
{
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_cpu_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_cpu_seconds, 'Seconds of cpu time to run sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_completion_seconds: ::Gitlab::Metrics.histogram(:sidekiq_jobs_completion_seconds, 'Seconds to complete sidekiq job', {}, SIDEKIQ_LATENCY_BUCKETS),
sidekiq_jobs_failed_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_failed_total, 'Sidekiq jobs failed'),
sidekiq_jobs_retried_total: ::Gitlab::Metrics.counter(:sidekiq_jobs_retried_total, 'Sidekiq jobs retried'),
Loading
Loading
Loading
Loading
@@ -29,7 +29,7 @@ module Gitlab
end
 
if fragments.any?
fragments.join("\n#{union_keyword}\n")
"(" + fragments.join(")\n#{union_keyword}\n(") + ")"
else
'NULL'
end
Loading
Loading
Loading
Loading
@@ -7427,9 +7427,6 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
 
msgid "From milestones:"
msgstr ""
msgid "From the Kubernetes cluster details view, install Runner from the applications list"
msgstr ""
 
Loading
Loading
@@ -9019,6 +9016,9 @@ msgstr ""
msgid "Information about additional Pages templates and how to install them can be found in our %{pages_getting_started_guide}."
msgstr ""
 
msgid "Inherited:"
msgstr ""
msgid "Inline"
msgstr ""
 
Loading
Loading
@@ -11522,9 +11522,6 @@ msgstr ""
msgid "Other visibility settings have been disabled by the administrator."
msgstr ""
 
msgid "Our Privacy Policy has changed, please visit %{privacy_policy_link} to review these changes."
msgstr ""
msgid "Outbound requests"
msgstr ""
 
Loading
Loading
Loading
Loading
@@ -96,30 +96,14 @@ describe ApplicationController do
request.path = '/-/peek'
end
 
# TODO:
# remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to
# to not setting any variables.
if Gitlab.ee?
it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
it_behaves_like 'not setting gon variables'
end
end
 
context 'with json format' do
let(:format) { :json }
 
# TODO:
# remove line below once `privacy_policy_update_callout`
# feature flag is removed and `gon` reverts back to
# to not setting any variables.
if Gitlab.ee?
it_behaves_like 'setting gon variables'
else
it_behaves_like 'not setting gon variables'
end
it_behaves_like 'not setting gon variables'
end
end
 
Loading
Loading
Loading
Loading
@@ -44,12 +44,14 @@ describe Gitlab::SidekiqMiddleware::Metrics do
 
it 'sets queue specific metrics' do
labels = { queue: :test }
labels_with_job_status = { queue: :test, job_status: :done }
allow(middleware).to receive(:get_thread_cputime).and_return(1, 3)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 3)
 
expect(user_execution_seconds_metric).to receive(:observe).with(labels, 2)
expect(running_jobs_metric).to receive(:increment).with(labels, 1)
expect(running_jobs_metric).to receive(:increment).with(labels, -1)
expect(completion_seconds_metric).to receive(:observe).with(labels, kind_of(Numeric))
expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 2)
expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 1)
 
middleware.call(worker, {}, :test) { nil }
end
Loading
Loading
@@ -74,8 +76,18 @@ describe Gitlab::SidekiqMiddleware::Metrics do
 
context 'when error is raised' do
it 'sets sidekiq_jobs_failed_total and reraises' do
expect(failed_total_metric).to receive(:increment)
expect { middleware.call(worker, {}, :test) { raise } }.to raise_error
labels = { queue: :test }
labels_with_job_status = { queue: :test, job_status: :fail }
allow(middleware).to receive(:get_thread_cputime).and_return(1, 4)
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(2, 6)
expect(running_jobs_metric).to receive(:increment).with(labels, 1)
expect(running_jobs_metric).to receive(:increment).with(labels, -1)
expect(failed_total_metric).to receive(:increment).with(labels, 1)
expect(user_execution_seconds_metric).to receive(:observe).with(labels_with_job_status, 3)
expect(completion_seconds_metric).to receive(:observe).with(labels_with_job_status, 4)
expect { middleware.call(worker, {}, :test) { raise StandardError, "Failed" } }.to raise_error(StandardError, "Failed")
end
end
end
Loading
Loading
Loading
Loading
@@ -20,7 +20,7 @@ describe Gitlab::SQL::RecursiveCTE do
[rel1.except(:order).to_sql, rel2.except(:order).to_sql]
end
 
expect(sql).to eq("#{name} AS (#{sql1}\nUNION\n#{sql2})")
expect(sql).to eq("#{name} AS ((#{sql1})\nUNION\n(#{sql2}))")
end
end
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment