summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-21 15:09:05 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-21 15:09:05 +0000
commitcf6a3e7ed4cb10a3e9fcbda810601387afc8b8d6 (patch)
treebda3707e95a53cb225793fded61d5073950b0b68
parent2a040e2655fe0a99df61ad0a7bd0c27e68af0c38 (diff)
downloadgitlab-ce-cf6a3e7ed4cb10a3e9fcbda810601387afc8b8d6.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue134
-rw-r--r--app/assets/javascripts/notifications_dropdown.js2
-rw-r--r--app/assets/stylesheets/pages/error_details.scss20
-rw-r--r--app/controllers/sessions_controller.rb2
-rw-r--r--app/models/commit.rb1
-rw-r--r--app/models/project_services/chat_message/base_message.rb2
-rw-r--r--app/models/project_services/chat_message/push_message.rb11
-rw-r--r--app/models/project_services/microsoft_teams_service.rb2
-rw-r--r--changelogs/unreleased/199908-use-only-the-first-line-of-the-commit-message-on-chat-service-noti.yml5
-rw-r--r--changelogs/unreleased/202271-migrate-fa-spinner-for-notifications_dropdown-js.yml5
-rw-r--r--changelogs/unreleased/38414.yml5
-rw-r--r--changelogs/unreleased/refactor-disable-csrf-in-session-destroy.yml5
-rw-r--r--doc/development/migration_style_guide.md8
-rw-r--r--lib/gitlab/data_builder/push.rb3
-rw-r--r--qa/qa/git/repository.rb2
-rw-r--r--qa/spec/git/repository_spec.rb8
-rw-r--r--spec/javascripts/boards/list_spec.js17
-rw-r--r--spec/models/project_services/chat_message/push_message_spec.rb34
-rw-r--r--spec/requests/sessions_spec.rb17
19 files changed, 186 insertions, 97 deletions
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 7abe3be3e99..89d32efec6d 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -10,6 +10,9 @@ import {
GlBadge,
GlAlert,
GlSprintf,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
} from '@gitlab/ui';
import { __, sprintf, n__ } from '~/locale';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
@@ -36,6 +39,9 @@ export default {
GlBadge,
GlAlert,
GlSprintf,
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownDivider,
},
directives: {
TrackEvent: TrackEventDirective,
@@ -108,7 +114,7 @@ export default {
return sprintf(
__('Reported %{timeAgo} by %{reportedBy}'),
{
- reportedBy: `<strong>${this.error.culprit}</strong>`,
+ reportedBy: `<strong class="error-details-meta-culprit">${this.error.culprit}</strong>`,
timeAgo: this.timeFormatted(this.stacktraceData.date_received),
},
false,
@@ -144,6 +150,11 @@ export default {
false,
);
},
+ issueUpdateInProgress() {
+ return (
+ this.updatingIgnoreStatus || this.updatingResolveStatus || this.issueCreationInProgress
+ );
+ },
errorLevel() {
return sprintf(__('level: %{level}'), { level: this.error.tags.level });
},
@@ -217,54 +228,90 @@ export default {
</gl-sprintf>
</gl-alert>
- <div class="top-area align-items-center justify-content-between py-3">
- <span v-if="!loadingStacktrace && stacktrace" v-html="reported"></span>
- <div class="d-inline-flex ml-lg-auto">
- <loading-button
- :label="ignoreBtnLabel"
- :loading="updatingIgnoreStatus"
- data-qa-selector="update_ignore_status_button"
- @click="onIgnoreStatusUpdate"
- />
- <loading-button
- class="btn-outline-info ml-2"
- :label="resolveBtnLabel"
- :loading="updatingResolveStatus"
- data-qa-selector="update_resolve_status_button"
- @click="onResolveStatusUpdate"
- />
- <gl-button
- v-if="error.gitlabIssuePath"
- class="ml-2"
- data-qa-selector="view_issue_button"
- :href="error.gitlabIssuePath"
- variant="success"
- >
- {{ __('View issue') }}
- </gl-button>
- <form
- ref="sentryIssueForm"
- :action="projectIssuesPath"
- method="POST"
- class="d-inline-block ml-2"
- >
- <gl-form-input class="hidden" name="issue[title]" :value="issueTitle" />
- <input name="issue[description]" :value="issueDescription" type="hidden" />
- <gl-form-input
- :value="error.sentryId"
- class="hidden"
- name="issue[sentry_issue_attributes][sentry_issue_identifier]"
+ <div class="error-details-header d-flex py-2 justify-content-between">
+ <div class="error-details-meta my-auto">
+ <span v-if="!loadingStacktrace && stacktrace" v-html="reported"></span>
+ </div>
+ <div class="error-details-actions">
+ <div class="d-inline-flex bv-d-sm-down-none">
+ <loading-button
+ :label="ignoreBtnLabel"
+ :loading="updatingIgnoreStatus"
+ data-qa-selector="update_ignore_status_button"
+ @click="onIgnoreStatusUpdate"
/>
- <gl-form-input :value="csrfToken" class="hidden" name="authenticity_token" />
<loading-button
+ class="btn-outline-info ml-2"
+ :label="resolveBtnLabel"
+ :loading="updatingResolveStatus"
+ data-qa-selector="update_resolve_status_button"
+ @click="onResolveStatusUpdate"
+ />
+ <gl-button
+ v-if="error.gitlabIssuePath"
+ class="ml-2"
+ data-qa-selector="view_issue_button"
+ :href="error.gitlabIssuePath"
+ variant="success"
+ >
+ {{ __('View issue') }}
+ </gl-button>
+ <form
+ ref="sentryIssueForm"
+ :action="projectIssuesPath"
+ method="POST"
+ class="d-inline-block ml-2"
+ >
+ <gl-form-input class="hidden" name="issue[title]" :value="issueTitle" />
+ <input name="issue[description]" :value="issueDescription" type="hidden" />
+ <gl-form-input
+ :value="error.sentryId"
+ class="hidden"
+ name="issue[sentry_issue_attributes][sentry_issue_identifier]"
+ />
+ <gl-form-input :value="csrfToken" class="hidden" name="authenticity_token" />
+ <loading-button
+ v-if="!error.gitlabIssuePath"
+ class="btn-success"
+ :label="__('Create issue')"
+ :loading="issueCreationInProgress"
+ data-qa-selector="create_issue_button"
+ @click="createIssue"
+ />
+ </form>
+ </div>
+ <gl-dropdown
+ text="Options"
+ class="error-details-options d-md-none"
+ right
+ :disabled="issueUpdateInProgress"
+ >
+ <gl-dropdown-item
+ data-qa-selector="update_ignore_status_button"
+ @click="onIgnoreStatusUpdate"
+ >{{ ignoreBtnLabel }}</gl-dropdown-item
+ >
+ <gl-dropdown-item
+ data-qa-selector="update_resolve_status_button"
+ @click="onResolveStatusUpdate"
+ >{{ resolveBtnLabel }}</gl-dropdown-item
+ >
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-if="error.gitlabIssuePath"
+ data-qa-selector="view_issue_button"
+ :href="error.gitlabIssuePath"
+ variant="success"
+ >{{ __('View issue') }}</gl-dropdown-item
+ >
+ <gl-dropdown-item
v-if="!error.gitlabIssuePath"
- class="btn-success"
- :label="__('Create issue')"
:loading="issueCreationInProgress"
data-qa-selector="create_issue_button"
@click="createIssue"
- />
- </form>
+ >{{ __('Create issue') }}</gl-dropdown-item
+ >
+ </gl-dropdown>
</div>
</div>
<div>
@@ -300,7 +347,6 @@ export default {
<strong class="bold">{{ __('Sentry event') }}:</strong>
<gl-link
v-track-event="trackClickErrorLinkToSentryOptions(error.externalUrl)"
- class="d-inline-flex align-items-center"
:href="error.externalUrl"
target="_blank"
>
diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js
index ab87b0d973c..07e69fa297a 100644
--- a/app/assets/javascripts/notifications_dropdown.js
+++ b/app/assets/javascripts/notifications_dropdown.js
@@ -15,7 +15,7 @@ export default function notificationsDropdown() {
.parents('.notification-form')
.first();
- form.find('.js-notification-loading').toggleClass('fa-bell fa-spin fa-spinner');
+ form.find('.js-notification-loading').toggleClass('spinner');
if (form.hasClass('no-label')) {
form.find('.js-notification-loading').toggleClass('hidden');
form.find('.js-notifications-icon').toggleClass('hidden');
diff --git a/app/assets/stylesheets/pages/error_details.scss b/app/assets/stylesheets/pages/error_details.scss
index 61e2df7ea26..78cac12d6be 100644
--- a/app/assets/stylesheets/pages/error_details.scss
+++ b/app/assets/stylesheets/pages/error_details.scss
@@ -7,6 +7,26 @@
color: $blue-500;
border-color: $blue-500;
}
+
+ .error-details-header {
+ border-bottom: 1px solid $border-color;
+
+ @include media-breakpoint-down(xs) {
+ flex-flow: column;
+
+ .error-details-meta-culprit {
+ display: flex;
+ }
+
+ .error-details-options {
+ width: 100%;
+
+ .dropdown-toggle {
+ text-align: center;
+ }
+ }
+ }
+ }
}
.stacktrace {
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index c29e9d3843b..e2dd2d77a30 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -39,7 +39,7 @@ class SessionsController < Devise::SessionsController
# would cause the CSRF token to be cleared and then
# RequestForgeryProtection#verify_authenticity_token would fail because of
# token mismatch.
- protect_from_forgery with: :exception, prepend: true
+ protect_from_forgery with: :exception, prepend: true, except: :destroy
CAPTCHA_HEADER = 'X-GitLab-Show-Login-Captcha'
MAX_FAILED_LOGIN_ATTEMPTS = 5
diff --git a/app/models/commit.rb b/app/models/commit.rb
index d8a3bbfeeb2..8068c4a07a2 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -226,6 +226,7 @@ class Commit
data = {
id: id,
message: safe_message,
+ title: title,
timestamp: committed_date.xmlschema,
url: Gitlab::UrlBuilder.build(self),
author: {
diff --git a/app/models/project_services/chat_message/base_message.rb b/app/models/project_services/chat_message/base_message.rb
index 5c39a80b32d..49151ad24cb 100644
--- a/app/models/project_services/chat_message/base_message.rb
+++ b/app/models/project_services/chat_message/base_message.rb
@@ -12,7 +12,6 @@ module ChatMessage
attr_reader :user_avatar
attr_reader :project_name
attr_reader :project_url
- attr_reader :commit_message_html
def initialize(params)
@markdown = params[:markdown] || false
@@ -21,7 +20,6 @@ module ChatMessage
@user_full_name = params.dig(:user, :name) || params[:user_full_name]
@user_name = params.dig(:user, :username) || params[:user_name]
@user_avatar = params.dig(:user, :avatar_url) || params[:user_avatar]
- @commit_message_html = params[:commit_message_html] || false
end
def user_combined_name
diff --git a/app/models/project_services/chat_message/push_message.rb b/app/models/project_services/chat_message/push_message.rb
index 07622f570c2..41b0cbb2c4d 100644
--- a/app/models/project_services/chat_message/push_message.rb
+++ b/app/models/project_services/chat_message/push_message.rb
@@ -52,8 +52,7 @@ module ChatMessage
end
def commit_messages
- linebreak_chars = commit_message_html ? "<br/>\n<br/>\n" : "\n\n"
- commits.map { |commit| compose_commit_message(commit) }.join(linebreak_chars)
+ commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
def commit_message_attachments
@@ -63,15 +62,11 @@ module ChatMessage
def compose_commit_message(commit)
author = commit[:author][:name]
id = Commit.truncate_sha(commit[:id])
- message = commit[:message]
-
- if commit_message_html
- message = message.gsub(Gitlab::Regex.breakline_regex, "<br/>\n")
- end
+ title = commit[:title]
url = commit[:url]
- "[#{id}](#{url}): #{message} - #{author}"
+ "[#{id}](#{url}): #{title} - #{author}"
end
def new_branch?
diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb
index 5cabce1376b..111d010d672 100644
--- a/app/models/project_services/microsoft_teams_service.rb
+++ b/app/models/project_services/microsoft_teams_service.rb
@@ -58,6 +58,6 @@ class MicrosoftTeamsService < ChatNotificationService
end
def custom_data(data)
- super(data).merge(markdown: true, commit_message_html: true)
+ super(data).merge(markdown: true)
end
end
diff --git a/changelogs/unreleased/199908-use-only-the-first-line-of-the-commit-message-on-chat-service-noti.yml b/changelogs/unreleased/199908-use-only-the-first-line-of-the-commit-message-on-chat-service-noti.yml
new file mode 100644
index 00000000000..a0924d76513
--- /dev/null
+++ b/changelogs/unreleased/199908-use-only-the-first-line-of-the-commit-message-on-chat-service-noti.yml
@@ -0,0 +1,5 @@
+---
+title: Use only the first line of the commit message on chat service notification
+merge_request: 25224
+author: Takuya Noguchi
+type: changed
diff --git a/changelogs/unreleased/202271-migrate-fa-spinner-for-notifications_dropdown-js.yml b/changelogs/unreleased/202271-migrate-fa-spinner-for-notifications_dropdown-js.yml
new file mode 100644
index 00000000000..9dbfcd33188
--- /dev/null
+++ b/changelogs/unreleased/202271-migrate-fa-spinner-for-notifications_dropdown-js.yml
@@ -0,0 +1,5 @@
+---
+title: migrate fa spinner for notification_dropdown.js
+merge_request: 25141
+author: minghuan
+type: other
diff --git a/changelogs/unreleased/38414.yml b/changelogs/unreleased/38414.yml
new file mode 100644
index 00000000000..759319e7f68
--- /dev/null
+++ b/changelogs/unreleased/38414.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error details layout and alignment for mobile view
+merge_request: 24390
+author:
+type: fixed
diff --git a/changelogs/unreleased/refactor-disable-csrf-in-session-destroy.yml b/changelogs/unreleased/refactor-disable-csrf-in-session-destroy.yml
new file mode 100644
index 00000000000..57bf2e816b4
--- /dev/null
+++ b/changelogs/unreleased/refactor-disable-csrf-in-session-destroy.yml
@@ -0,0 +1,5 @@
+---
+title: Disable CSRF protection on logout endpoint
+merge_request: 25521
+author: Diego Louzán
+type: changed
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 1570f9e4096..d31729d2b0f 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -15,8 +15,8 @@ offline unless _absolutely necessary_.
When downtime is necessary the migration has to be approved by:
1. The VP of Engineering
-1. A Backend Lead
-1. A Database Specialist
+1. A Backend Maintainer
+1. A Database Maintainer
An up-to-date list of people holding these titles can be found at
<https://about.gitlab.com/company/team/>.
@@ -29,6 +29,10 @@ Please don't depend on GitLab-specific code since it can change in future
versions. If needed copy-paste GitLab code into the migration to make it forward
compatible.
+For GitLab.com, please take into consideration that regular migrations (under `db/migrate`)
+are run before [Canary is deployed](https://about.gitlab.com/handbook/engineering/infrastructure/library/canary/#configuration-and-deployment),
+and post-deployment migrations (`db/post_migrate`) are run after the deployment to production has finished.
+
## Schema Changes
Migrations that make changes to the database schema (e.g. adding a column) can
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index 41ceeb329b3..af363705bed 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -35,7 +35,8 @@ module Gitlab
commits: [
{
id: "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
- message: "Add simple search to projects in public area",
+ message: "Add simple search to projects in public area\n\ncommit message body",
+ title: "Add simple search to projects in public area",
timestamp: "2013-05-13T18:18:08+00:00",
url: "https://test.example.com/gitlab/gitlab/-/commit/c5feabde2d8cd023215af4d2ceeb7a64839fc428",
author: {
diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb
index f56fab63198..771f135a95c 100644
--- a/qa/qa/git/repository.rb
+++ b/qa/qa/git/repository.rb
@@ -165,7 +165,7 @@ module QA
# ls-remote is one command known to respond to Git protocol v2 so we use
# it to get output including the version reported via Git tracing
output = run("git ls-remote #{uri}", "GIT_TRACE_PACKET=1")
- output[/git< version (\d+)/, 1] || 'unknown'
+ output.response[/git< version (\d+)/, 1] || 'unknown'
end
def try_add_credentials_to_netrc
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index 5198eb6f58b..6cca9f55e11 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -69,18 +69,20 @@ describe QA::Git::Repository do
end
describe '#fetch_supported_git_protocol' do
+ Result = Struct.new(:response)
+
it "reports the detected version" do
- expect(repository).to receive(:run).and_return("packet: git< version 2")
+ expect(repository).to receive(:run).and_return(Result.new("packet: git< version 2"))
expect(repository.fetch_supported_git_protocol).to eq('2')
end
it 'reports unknown if version is unknown' do
- expect(repository).to receive(:run).and_return("packet: git< version -1")
+ expect(repository).to receive(:run).and_return(Result.new("packet: git< version -1"))
expect(repository.fetch_supported_git_protocol).to eq('unknown')
end
it 'reports unknown if content does not identify a version' do
- expect(repository).to receive(:run).and_return("foo")
+ expect(repository).to receive(:run).and_return(Result.new("foo"))
expect(repository.fetch_supported_git_protocol).to eq('unknown')
end
end
diff --git a/spec/javascripts/boards/list_spec.js b/spec/javascripts/boards/list_spec.js
index c340b62730c..7385bfb0e5f 100644
--- a/spec/javascripts/boards/list_spec.js
+++ b/spec/javascripts/boards/list_spec.js
@@ -4,7 +4,6 @@
/* global ListLabel */
import MockAdapter from 'axios-mock-adapter';
-import _ from 'underscore';
import axios from '~/lib/utils/axios_utils';
import '~/boards/models/label';
import '~/boards/models/assignee';
@@ -40,7 +39,7 @@ describe('List model', () => {
list = new List({
title: 'test',
label: {
- id: _.random(10000),
+ id: 1,
title: 'test',
color: 'red',
text_color: 'white',
@@ -96,8 +95,8 @@ describe('List model', () => {
const listDup = new List(listObjDuplicate);
const issue = new ListIssue({
title: 'Testing',
- id: _.random(10000),
- iid: _.random(10000),
+ id: 1,
+ iid: 1,
confidential: false,
labels: [list.label, listDup.label],
assignees: [],
@@ -129,8 +128,8 @@ describe('List model', () => {
list.issues.push(
new ListIssue({
title: 'Testing',
- id: _.random(10000) + i,
- iid: _.random(10000) + i,
+ id: i,
+ iid: i,
confidential: false,
labels: [list.label],
assignees: [],
@@ -151,7 +150,7 @@ describe('List model', () => {
list.issues.push(
new ListIssue({
title: 'Testing',
- id: _.random(10000),
+ id: 1,
confidential: false,
labels: [list.label],
assignees: [],
@@ -192,7 +191,7 @@ describe('List model', () => {
list.issues.push(
new ListIssue({
title: 'Testing',
- id: _.random(10000),
+ id: 1,
confidential: false,
labels: [new ListLabel(list.label)],
assignees: [],
@@ -200,7 +199,7 @@ describe('List model', () => {
);
const dummyIssue = new ListIssue({
title: 'new issue',
- id: _.random(10000),
+ id: 2,
confidential: false,
labels: [new ListLabel(list.label)],
assignees: [user],
diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb
index fe0b2fe3440..9d990508ab2 100644
--- a/spec/models/project_services/chat_message/push_message_spec.rb
+++ b/spec/models/project_services/chat_message/push_message_spec.rb
@@ -22,8 +22,14 @@ describe ChatMessage::PushMessage do
context 'push' do
before do
args[:commits] = [
- { message: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } },
- { message: "message2\nsecondline", url: 'http://url2.com', id: '123456789012', author: { name: 'author2' } }
+ { message: 'message1', title: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } },
+ {
+ message: 'message2' + ' w' * 100 + "\nsecondline",
+ title: 'message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ...',
+ url: 'http://url2.com',
+ id: '123456789012',
+ author: { name: 'author2' }
+ }
]
end
@@ -34,7 +40,7 @@ describe ChatMessage::PushMessage do
'<http://url.com|project_name> (<http://url.com/compare/before...after|Compare changes>)')
expect(subject.attachments).to eq([{
text: "<http://url1.com|abcdefgh>: message1 - author1\n\n"\
- "<http://url2.com|12345678>: message2\nsecondline - author2",
+ "<http://url2.com|12345678>: message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ... - author2",
color: color
}])
end
@@ -49,27 +55,7 @@ describe ChatMessage::PushMessage do
expect(subject.pretext).to eq(
'test.user pushed to branch [master](http://url.com/commits/master) of [project_name](http://url.com) ([Compare changes](http://url.com/compare/before...after))')
expect(subject.attachments).to eq(
- "[abcdefgh](http://url1.com): message1 - author1\n\n[12345678](http://url2.com): message2\nsecondline - author2")
- expect(subject.activity).to eq(
- title: 'test.user pushed to branch [master](http://url.com/commits/master)',
- subtitle: 'in [project_name](http://url.com)',
- text: '[Compare changes](http://url.com/compare/before...after)',
- image: 'http://someavatar.com'
- )
- end
- end
-
- context 'with markdown and commit message html' do
- before do
- args[:commit_message_html] = true
- args[:markdown] = true
- end
-
- it 'returns a message regarding pushes' do
- expect(subject.pretext).to eq(
- 'test.user pushed to branch [master](http://url.com/commits/master) of [project_name](http://url.com) ([Compare changes](http://url.com/compare/before...after))')
- expect(subject.attachments).to eq(
- "[abcdefgh](http://url1.com): message1 - author1<br/>\n<br/>\n[12345678](http://url2.com): message2<br/>\nsecondline - author2")
+ "[abcdefgh](http://url1.com): message1 - author1\n\n[12345678](http://url2.com): message2 w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w w ... - author2")
expect(subject.activity).to eq(
title: 'test.user pushed to branch [master](http://url.com/commits/master)',
subtitle: 'in [project_name](http://url.com)',
diff --git a/spec/requests/sessions_spec.rb b/spec/requests/sessions_spec.rb
new file mode 100644
index 00000000000..6697700c37d
--- /dev/null
+++ b/spec/requests/sessions_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe 'Sessions' do
+ context 'authentication', :allow_forgery_protection do
+ let(:user) { create(:user) }
+
+ it 'logout does not require a csrf token' do
+ login_as(user)
+
+ post(destroy_user_session_path, headers: { 'X-CSRF-Token' => 'invalid' })
+
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+end