Commit 53925593 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents b8c6eb48 35f6ccda
641e24107a6f4f8593b87ed55c3aa7cd76010963 3627c14a64ce48446e8a67299c3161ff7290d1ad
...@@ -6,7 +6,7 @@ import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/const ...@@ -6,7 +6,7 @@ import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/const
import Poll from '~/lib/utils/poll'; import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import { IssueTypePath, IncidentTypePath, IncidentType, POLLING_DELAY } from '../constants'; import { ISSUE_TYPE_PATH, INCIDENT_TYPE_PATH, INCIDENT_TYPE, POLLING_DELAY } from '../constants';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import getIssueStateQuery from '../queries/get_issue_state.query.graphql'; import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
import Service from '../services/index'; import Service from '../services/index';
...@@ -378,15 +378,15 @@ export default { ...@@ -378,15 +378,15 @@ export default {
.then((data) => { .then((data) => {
if ( if (
!window.location.pathname.includes(data.web_url) && !window.location.pathname.includes(data.web_url) &&
issueState.issueType !== IncidentType issueState.issueType !== INCIDENT_TYPE
) { ) {
visitUrl(data.web_url); visitUrl(data.web_url);
} }
if (issueState.isDirty) { if (issueState.isDirty) {
const URI = const URI =
issueState.issueType === IncidentType issueState.issueType === INCIDENT_TYPE
? data.web_url.replace(IssueTypePath, IncidentTypePath) ? data.web_url.replace(ISSUE_TYPE_PATH, INCIDENT_TYPE_PATH)
: data.web_url; : data.web_url;
visitUrl(URI); visitUrl(URI);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui'; import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { capitalize } from 'lodash'; import { capitalize } from 'lodash';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { IssuableTypes, IncidentType } from '../../constants'; import { issuableTypes, INCIDENT_TYPE } from '../../constants';
import getIssueStateQuery from '../../queries/get_issue_state.query.graphql'; import getIssueStateQuery from '../../queries/get_issue_state.query.graphql';
import updateIssueStateMutation from '../../queries/update_issue_state.mutation.graphql'; import updateIssueStateMutation from '../../queries/update_issue_state.mutation.graphql';
...@@ -12,7 +12,7 @@ export const i18n = { ...@@ -12,7 +12,7 @@ export const i18n = {
export default { export default {
i18n, i18n,
IssuableTypes, issuableTypes,
components: { components: {
GlFormGroup, GlFormGroup,
GlIcon, GlIcon,
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
return capitalize(issueType); return capitalize(issueType);
}, },
shouldShowIncident() { shouldShowIncident() {
return this.issueType === IncidentType || this.canCreateIncident; return this.issueType === INCIDENT_TYPE || this.canCreateIncident;
}, },
}, },
methods: { methods: {
...@@ -59,7 +59,7 @@ export default { ...@@ -59,7 +59,7 @@ export default {
}); });
}, },
isShown(type) { isShown(type) {
return type.value !== IncidentType || this.shouldShowIncident; return type.value !== INCIDENT_TYPE || this.shouldShowIncident;
}, },
}, },
}; };
...@@ -81,7 +81,7 @@ export default { ...@@ -81,7 +81,7 @@ export default {
toggle-class="dropdown-menu-toggle" toggle-class="dropdown-menu-toggle"
> >
<gl-dropdown-item <gl-dropdown-item
v-for="type in $options.IssuableTypes" v-for="type in $options.issuableTypes"
v-show="isShown(type)" v-show="isShown(type)"
:key="type.value" :key="type.value"
:is-checked="issueState.issueType === type.value" :is-checked="issueState.issueType === type.value"
......
...@@ -13,7 +13,7 @@ import createFlash, { FLASH_TYPES } from '~/flash'; ...@@ -13,7 +13,7 @@ import createFlash, { FLASH_TYPES } from '~/flash';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants'; import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
import { IssuableType } from '~/vue_shared/issuable/show/constants'; import { IssuableType } from '~/vue_shared/issuable/show/constants';
import { IssuableStatus } from '~/issues/constants'; import { IssuableStatus } from '~/issues/constants';
import { IssueStateEvent } from '~/issues/show/constants'; import { ISSUE_STATE_EVENT_CLOSE, ISSUE_STATE_EVENT_REOPEN } from '~/issues/show/constants';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility'; import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility'; import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale'; import { s__, __, sprintf } from '~/locale';
...@@ -163,7 +163,7 @@ export default { ...@@ -163,7 +163,7 @@ export default {
input: { input: {
iid: this.iid.toString(), iid: this.iid.toString(),
projectPath: this.projectPath, projectPath: this.projectPath,
stateEvent: this.isClosed ? IssueStateEvent.Reopen : IssueStateEvent.Close, stateEvent: this.isClosed ? ISSUE_STATE_EVENT_REOPEN : ISSUE_STATE_EVENT_CLOSE,
}, },
}, },
}) })
......
import { __ } from '~/locale'; import { __ } from '~/locale';
export const IssueStateEvent = { export const INCIDENT_TYPE = 'incident';
Close: 'CLOSE', export const INCIDENT_TYPE_PATH = 'issues/incident';
Reopen: 'REOPEN', export const ISSUE_STATE_EVENT_CLOSE = 'CLOSE';
}; export const ISSUE_STATE_EVENT_REOPEN = 'REOPEN';
export const ISSUE_TYPE_PATH = 'issues';
export const STATUS_PAGE_PUBLISHED = __('Published on status page');
export const JOIN_ZOOM_MEETING = __('Join Zoom meeting'); export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
export const POLLING_DELAY = 2000;
export const STATUS_PAGE_PUBLISHED = __('Published on status page');
export const IssuableTypes = [ export const issuableTypes = [
{ value: 'issue', text: __('Issue'), icon: 'issue-type-issue' }, { value: 'issue', text: __('Issue'), icon: 'issue-type-issue' },
{ value: 'incident', text: __('Incident'), icon: 'issue-type-incident' }, { value: 'incident', text: __('Incident'), icon: 'issue-type-incident' },
]; ];
export const IssueTypePath = 'issues'; export const issueState = {
export const IncidentTypePath = 'issues/incident'; issueType: undefined,
export const IncidentType = 'incident'; isDirty: false,
};
export const issueState = { issueType: undefined, isDirty: false };
export const POLLING_DELAY = 2000;
...@@ -6,7 +6,7 @@ import IssueApp from './components/app.vue'; ...@@ -6,7 +6,7 @@ import IssueApp from './components/app.vue';
import HeaderActions from './components/header_actions.vue'; import HeaderActions from './components/header_actions.vue';
import IncidentTabs from './components/incidents/incident_tabs.vue'; import IncidentTabs from './components/incidents/incident_tabs.vue';
import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue'; import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
import { IncidentType, issueState } from './constants'; import { INCIDENT_TYPE, issueState } from './constants';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
import getIssueStateQuery from './queries/get_issue_state.query.graphql'; import getIssueStateQuery from './queries/get_issue_state.query.graphql';
...@@ -45,7 +45,7 @@ export function initIncidentApp(issueData = {}) { ...@@ -45,7 +45,7 @@ export function initIncidentApp(issueData = {}) {
el, el,
apolloProvider, apolloProvider,
provide: { provide: {
issueType: IncidentType, issueType: INCIDENT_TYPE,
canCreateIncident, canCreateIncident,
canUpdate, canUpdate,
fullPath, fullPath,
...@@ -111,7 +111,7 @@ export function initHeaderActions(store, type = '') { ...@@ -111,7 +111,7 @@ export function initHeaderActions(store, type = '') {
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType }); bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
const canCreate = const canCreate =
type === IncidentType ? el.dataset.canCreateIncident : el.dataset.canCreateIssue; type === INCIDENT_TYPE ? el.dataset.canCreateIncident : el.dataset.canCreateIssue;
return new Vue({ return new Vue({
el, el,
......
= form_for [:admin, @label], html: { class: 'label-form js-requires-input' } do |f|
= form_errors(@label)
.form-group.row
.col-sm-2.col-form-label
= f.label :title
.col-sm-10
= f.text_field :title, class: "form-control gl-form-input", required: true
.form-group.row
.col-sm-2.col-form-label
= f.label :description
.col-sm-10
= f.text_field :description, class: "form-control gl-form-input js-quick-submit"
.form-group.row
.col-sm-2.col-form-label
= f.label :color, _("Background color")
.col-sm-10
.input-group
.input-group-prepend
.input-group-text.label-color-preview &nbsp;
= f.text_field :color, class: "form-control gl-form-input"
.form-text.text-muted
= _('Choose any color.')
%br
= _("Or you can choose one of the suggested colors below")
= render_suggested_colors
.form-actions
= f.submit _('Save'), class: 'btn gl-button btn-confirm js-save-button'
= link_to _("Cancel"), admin_labels_path, class: 'btn gl-button btn-default btn-cancel'
...@@ -4,4 +4,4 @@ ...@@ -4,4 +4,4 @@
%h3.page-title %h3.page-title
= _('Edit Label') = _('Edit Label')
%hr %hr
= render 'form' = render 'shared/labels/form', url: admin_label_path(@label), back_path: admin_labels_path
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
%h3.page-title %h3.page-title
= _('New Label') = _('New Label')
%hr %hr
= render 'form' = render 'shared/labels/form', url: admin_labels_path, back_path: admin_labels_path
...@@ -5,30 +5,30 @@ ...@@ -5,30 +5,30 @@
.col-sm-2.col-form-label .col-sm-2.col-form-label
= f.label :title = f.label :title
.col-sm-10 .col-sm-10
= f.text_field :title, class: "form-control js-label-title qa-label-title", required: true, autofocus: true = f.text_field :title, class: "gl-form-input form-control js-label-title qa-label-title", required: true, autofocus: true
= render_if_exists 'shared/labels/create_label_help_text' = render_if_exists 'shared/labels/create_label_help_text'
.form-group.row .form-group.row
.col-sm-2.col-form-label .col-sm-2.col-form-label
= f.label :description = f.label :description
.col-sm-10 .col-sm-10
= f.text_field :description, class: "form-control js-quick-submit qa-label-description" = f.text_field :description, class: "gl-form-input form-control js-quick-submit qa-label-description"
.form-group.row .form-group.row
.col-sm-2.col-form-label .col-sm-2.col-form-label
= f.label :color, "Background color" = f.label :color, _("Background color")
.col-sm-10 .col-sm-10
.input-group .input-group
.input-group-prepend .input-group-prepend
.input-group-text.label-color-preview &nbsp; .input-group-text.label-color-preview &nbsp;
= f.text_field :color, class: "form-control qa-label-color" = f.text_field :color, class: "gl-form-input form-control qa-label-color"
.form-text.text-muted .form-text.text-muted
Choose any color. = _('Choose any color.')
%br %br
Or you can choose one of the suggested colors below = _("Or you can choose one of the suggested colors below")
= render_suggested_colors = render_suggested_colors
.form-actions .form-actions
- if @label.persisted? - if @label.persisted?
= f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button' = f.submit _('Save changes'), class: 'btn gl-button btn-confirm js-save-button'
- else - else
= f.submit 'Create label', class: 'btn gl-button btn-confirm js-save-button qa-label-create-button' = f.submit _('Create label'), class: 'btn gl-button btn-confirm js-save-button qa-label-create-button'
= link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel' = link_to _('Cancel'), back_path, class: 'btn gl-button btn-default btn-cancel'
...@@ -4,12 +4,14 @@ ...@@ -4,12 +4,14 @@
= form.label :url, s_('Webhooks|URL'), class: 'label-bold' = form.label :url, s_('Webhooks|URL'), class: 'label-bold'
= form.text_field :url, class: 'form-control gl-form-input', placeholder: 'http://example.com/trigger-ci.json' = form.text_field :url, class: 'form-control gl-form-input', placeholder: 'http://example.com/trigger-ci.json'
%p.form-text.text-muted %p.form-text.text-muted
= s_('Webhooks|URL must be percent-encoded if neccessary.') = s_('Webhooks|URL must be percent-encoded if it contains one or more special characters.')
.form-group .form-group
= form.label :token, s_('Webhooks|Secret token'), class: 'label-bold' = form.label :token, s_('Webhooks|Secret token'), class: 'label-bold'
= form.text_field :token, class: 'form-control gl-form-input', placeholder: '' = form.text_field :token, class: 'form-control gl-form-input', placeholder: ''
%p.form-text.text-muted %p.form-text.text-muted
= s_('Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header.') - code_start = '<code>'.html_safe
- code_end = '</code>'.html_safe
= s_('Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header.').html_safe % { code_start: code_start, code_end: code_end }
.form-group .form-group
= form.label :url, s_('Webhooks|Trigger'), class: 'label-bold' = form.label :url, s_('Webhooks|Trigger'), class: 'label-bold'
%ul.list-unstyled.gl-ml-6 %ul.list-unstyled.gl-ml-6
...@@ -19,37 +21,37 @@ ...@@ -19,37 +21,37 @@
%strong= s_('Webhooks|Push events') %strong= s_('Webhooks|Push events')
= form.text_field :push_events_branch_filter, class: 'form-control gl-form-input', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)' = form.text_field :push_events_branch_filter, class: 'form-control gl-form-input', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered by a push to the repository') = s_('Webhooks|Push to the repository.')
%li %li
= form.check_box :tag_push_events, class: 'form-check-input' = form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label gl-ml-1' do = form.label :tag_push_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Tag push events') %strong= s_('Webhooks|Tag push events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a new tag is pushed to the repository') = s_('Webhooks|A new tag is pushed to the repository.')
%li %li
= form.check_box :note_events, class: 'form-check-input' = form.check_box :note_events, class: 'form-check-input'
= form.label :note_events, class: 'list-label form-check-label gl-ml-1' do = form.label :note_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Comments') %strong= s_('Webhooks|Comments')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when someone adds a comment') = s_('Webhooks|A comment is added to an issue.')
%li %li
= form.check_box :confidential_note_events, class: 'form-check-input' = form.check_box :confidential_note_events, class: 'form-check-input'
= form.label :confidential_note_events, class: 'list-label form-check-label gl-ml-1' do = form.label :confidential_note_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Confidential comments') %strong= s_('Webhooks|Confidential comments')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when someone adds a comment on a confidential issue') = s_('Webhooks|A comment is added to a confidential issue.')
%li %li
= form.check_box :issues_events, class: 'form-check-input' = form.check_box :issues_events, class: 'form-check-input'
= form.label :issues_events, class: 'list-label form-check-label gl-ml-1' do = form.label :issues_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Issues events') %strong= s_('Webhooks|Issues events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when an issue is created, updated, closed, or reopened') = s_('Webhooks|An issue is created, updated, closed, or reopened.')
%li %li
= form.check_box :confidential_issues_events, class: 'form-check-input' = form.check_box :confidential_issues_events, class: 'form-check-input'
= form.label :confidential_issues_events, class: 'list-label form-check-label gl-ml-1' do = form.label :confidential_issues_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Confidential issues events') %strong= s_('Webhooks|Confidential issues events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened') = s_('Webhooks|A confidential issue is created, updated, closed, or reopened.')
- if @group - if @group
= render_if_exists 'groups/hooks/member_events', form: form = render_if_exists 'groups/hooks/member_events', form: form
= render_if_exists 'groups/hooks/subgroup_events', form: form = render_if_exists 'groups/hooks/subgroup_events', form: form
...@@ -58,43 +60,43 @@ ...@@ -58,43 +60,43 @@
= form.label :merge_requests_events, class: 'list-label form-check-label gl-ml-1' do = form.label :merge_requests_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Merge request events') %strong= s_('Webhooks|Merge request events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a merge request is created, updated, or merged') = s_('Webhooks|A merge request is created, updated, or merged.')
%li %li
= form.check_box :job_events, class: 'form-check-input' = form.check_box :job_events, class: 'form-check-input'
= form.label :job_events, class: 'list-label form-check-label gl-ml-1' do = form.label :job_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Job events') %strong= s_('Webhooks|Job events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when the job status changes') = s_("Webhooks|A job's status changes.")
%li %li
= form.check_box :pipeline_events, class: 'form-check-input' = form.check_box :pipeline_events, class: 'form-check-input'
= form.label :pipeline_events, class: 'list-label form-check-label gl-ml-1' do = form.label :pipeline_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Pipeline events') %strong= s_('Webhooks|Pipeline events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when the pipeline status changes') = s_("Webhooks|A pipeline's status changes.")
%li %li
= form.check_box :wiki_page_events, class: 'form-check-input' = form.check_box :wiki_page_events, class: 'form-check-input'
= form.label :wiki_page_events, class: 'list-label form-check-label gl-ml-1' do = form.label :wiki_page_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Wiki page events') %strong= s_('Webhooks|Wiki page events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a wiki page is created or updated') = s_('Webhooks|A wiki page is created or updated.')
%li %li
= form.check_box :deployment_events, class: 'form-check-input' = form.check_box :deployment_events, class: 'form-check-input'
= form.label :deployment_events, class: 'list-label form-check-label gl-ml-1' do = form.label :deployment_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Deployment events') %strong= s_('Webhooks|Deployment events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled') = s_('Webhooks|A deployment starts, finishes, fails, or is canceled.')
%li %li
= form.check_box :feature_flag_events, class: 'form-check-input' = form.check_box :feature_flag_events, class: 'form-check-input'
= form.label :feature_flag_events, class: 'list-label form-check-label gl-ml-1' do = form.label :feature_flag_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Feature flag events') %strong= s_('Webhooks|Feature flag events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a feature flag is turned on or off') = s_('Webhooks|A feature flag is turned on or off.')
%li %li
= form.check_box :releases_events, class: 'form-check-input' = form.check_box :releases_events, class: 'form-check-input'
= form.label :releases_events, class: 'list-label form-check-label gl-ml-1' do = form.label :releases_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Releases events') %strong= s_('Webhooks|Releases events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a release is created or updated') = s_('Webhooks|A release is created or updated.')
.form-group .form-group
= form.label :enable_ssl_verification, s_('Webhooks|SSL verification'), class: 'label-bold checkbox' = form.label :enable_ssl_verification, s_('Webhooks|SSL verification'), class: 'label-bold checkbox'
.form-check .form-check
......
...@@ -11,4 +11,4 @@ ...@@ -11,4 +11,4 @@
= render 'shared/web_hooks/hook', hook: hook = render 'shared/web_hooks/hook', hook: hook
- else - else
%p.text-center.gl-mt-3.gl-mb-3 %p.text-center.gl-mt-3.gl-mb-3
= _('No webhooks found, add one in the form above.') = _('No webhooks enabled. Select trigger events above.')
...@@ -21,11 +21,10 @@ you can use webhooks to: ...@@ -21,11 +21,10 @@ you can use webhooks to:
every time an issue is created for a specific project or group in GitLab. every time an issue is created for a specific project or group in GitLab.
- [Automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/). - [Automatically assign labels to merge requests](https://about.gitlab.com/blog/2016/08/19/applying-gitlab-labels-automatically/).
You can configure your GitLab project or [group](#group-webhooks) to trigger You can configure your GitLab project or [group](#group-webhooks) to trigger a
a percent-encoded webhook URL when an event occurs. For example, when new code [percent-encoded](https://developer.mozilla.org/en-US/docs/Glossary/percent-encoding) webhook URL
is pushed or a new issue is created. when an event occurs. For example, when new code is pushed or a new issue is created. The webhook
The webhook listens for specific [events](#events) and listens for specific [events](#events) and GitLab sends a POST request with data to the webhook URL.
GitLab sends a POST request with data to the webhook URL.
Usually, you set up your own [webhook receiver](#create-an-example-webhook-receiver) Usually, you set up your own [webhook receiver](#create-an-example-webhook-receiver)
to receive information from GitLab and send it to another app, according to your requirements. to receive information from GitLab and send it to another app, according to your requirements.
...@@ -55,7 +54,7 @@ You can configure a webhook for a group or a project. ...@@ -55,7 +54,7 @@ You can configure a webhook for a group or a project.
1. In your project or group, on the left sidebar, select **Settings > Webhooks**. 1. In your project or group, on the left sidebar, select **Settings > Webhooks**.
1. In **URL**, enter the URL of the webhook endpoint. 1. In **URL**, enter the URL of the webhook endpoint.
The URL must be percentage-encoded, if necessary. The URL must be percent-encoded if it contains one or more special characters.
1. In **Secret token**, enter the [secret token](#validate-payloads-by-using-a-secret-token) to validate payloads. 1. In **Secret token**, enter the [secret token](#validate-payloads-by-using-a-secret-token) to validate payloads.
1. In the **Trigger** section, select the [events](webhook_events.md) to trigger the webhook. 1. In the **Trigger** section, select the [events](webhook_events.md) to trigger the webhook.
1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](#verify-an-ssl-certificate). 1. Optional. Clear the **Enable SSL verification** checkbox to disable [SSL verification](#verify-an-ssl-certificate).
......
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
= form.label :member_events, class: 'list-label form-check-label gl-ml-1' do = form.label :member_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Member events') %strong= s_('Webhooks|Member events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a group member is created, updated, or removed') = s_('Webhooks|A group member is created, updated, or removed.')
...@@ -3,4 +3,4 @@ ...@@ -3,4 +3,4 @@
= form.label :subgroup_events, class: 'list-label form-check-label gl-ml-1' do = form.label :subgroup_events, class: 'list-label form-check-label gl-ml-1' do
%strong= s_('Webhooks|Subgroup events') %strong= s_('Webhooks|Subgroup events')
%p.text-muted.gl-ml-1 %p.text-muted.gl-ml-1
= s_('Webhooks|URL is triggered when a subgroup is created or removed') = s_('Webhooks|A subgroup is created or removed.')
- if @label.subject.feature_available?(:scoped_labels) - if @label.respond_to?(:subject) && @label.subject.feature_available?(:scoped_labels)
- docs_url = help_page_path('user/project/labels.md', anchor: 'scoped-labels') - docs_url = help_page_path('user/project/labels.md', anchor: 'scoped-labels')
- docs_link_start = "<a href='#{docs_url}' target='_blank' rel='noreferrer noopener'>".html_safe - docs_link_start = "<a href='#{docs_url}' target='_blank' rel='noreferrer noopener'>".html_safe
- docs_link_end = '</a>'.html_safe - docs_link_end = '</a>'.html_safe
......
...@@ -10039,6 +10039,9 @@ msgstr "" ...@@ -10039,6 +10039,9 @@ msgstr ""
msgid "Create iteration" msgid "Create iteration"
msgstr "" msgstr ""
msgid "Create label"
msgstr ""
msgid "Create list" msgid "Create list"
msgstr "" msgstr ""
...@@ -24101,7 +24104,7 @@ msgstr "" ...@@ -24101,7 +24104,7 @@ msgstr ""
msgid "No webhook events" msgid "No webhook events"
msgstr "" msgstr ""
msgid "No webhooks found, add one in the form above." msgid "No webhooks enabled. Select trigger events above."
msgstr "" msgstr ""
msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription." msgid "No worries, you can still use all the %{strong}%{plan_name}%{strong_close} features for now. You have %{remaining_days} day to renew your subscription."
...@@ -39779,127 +39782,127 @@ msgstr "" ...@@ -39779,127 +39782,127 @@ msgstr ""
msgid "Webhooks Help" msgid "Webhooks Help"
msgstr "" msgstr ""
msgid "Webhooks|Comments" msgid "Webhooks|A comment is added to a confidential issue."
msgstr "" msgstr ""
msgid "Webhooks|Confidential comments" msgid "Webhooks|A comment is added to an issue."
msgstr "" msgstr ""
msgid "Webhooks|Confidential issues events" msgid "Webhooks|A confidential issue is created, updated, closed, or reopened."
msgstr "" msgstr ""
msgid "Webhooks|Deployment events" msgid "Webhooks|A deployment starts, finishes, fails, or is canceled."
msgstr "" msgstr ""
msgid "Webhooks|Enable SSL verification" msgid "Webhooks|A feature flag is turned on or off."
msgstr "" msgstr ""
msgid "Webhooks|Failed to connect" msgid "Webhooks|A group member is created, updated, or removed."
msgstr "" msgstr ""
msgid "Webhooks|Fails to connect" msgid "Webhooks|A job's status changes."
msgstr "" msgstr ""
msgid "Webhooks|Feature flag events" msgid "Webhooks|A merge request is created, updated, or merged."
msgstr "" msgstr ""
msgid "Webhooks|Issues events" msgid "Webhooks|A new tag is pushed to the repository."
msgstr "" msgstr ""
msgid "Webhooks|Job events" msgid "Webhooks|A pipeline's status changes."
msgstr "" msgstr ""
msgid "Webhooks|Member events" msgid "Webhooks|A release is created or updated."
msgstr "" msgstr ""
msgid "Webhooks|Merge request events" msgid "Webhooks|A subgroup is created or removed."
msgstr "" msgstr ""
msgid "Webhooks|Pipeline events" msgid "Webhooks|A wiki page is created or updated."
msgstr "" msgstr ""
msgid "Webhooks|Push events" msgid "Webhooks|An issue is created, updated, closed, or reopened."
msgstr "" msgstr ""
msgid "Webhooks|Releases events" msgid "Webhooks|Comments"
msgstr "" msgstr ""
msgid "Webhooks|SSL verification" msgid "Webhooks|Confidential comments"
msgstr "" msgstr ""
msgid "Webhooks|Secret token" msgid "Webhooks|Confidential issues events"
msgstr "" msgstr ""
msgid "Webhooks|Subgroup events" msgid "Webhooks|Deployment events"
msgstr "" msgstr ""
msgid "Webhooks|Tag push events" msgid "Webhooks|Enable SSL verification"
msgstr "" msgstr ""
msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below." msgid "Webhooks|Failed to connect"
msgstr "" msgstr ""
msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below." msgid "Webhooks|Fails to connect"
msgstr "" msgstr ""
msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook." msgid "Webhooks|Feature flag events"
msgstr "" msgstr ""
msgid "Webhooks|Trigger" msgid "Webhooks|Issues events"
msgstr "" msgstr ""
msgid "Webhooks|URL" msgid "Webhooks|Job events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered by a push to the repository" msgid "Webhooks|Member events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a confidential issue is created, updated, closed, or reopened" msgid "Webhooks|Merge request events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a deployment starts, finishes, fails, or is canceled" msgid "Webhooks|Pipeline events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a feature flag is turned on or off" msgid "Webhooks|Push events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a group member is created, updated, or removed" msgid "Webhooks|Push to the repository."
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a merge request is created, updated, or merged" msgid "Webhooks|Releases events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a new tag is pushed to the repository" msgid "Webhooks|SSL verification"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a release is created or updated" msgid "Webhooks|Secret token"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a subgroup is created or removed" msgid "Webhooks|Subgroup events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when a wiki page is created or updated" msgid "Webhooks|Tag push events"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when an issue is created, updated, closed, or reopened" msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when someone adds a comment" msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when someone adds a comment on a confidential issue" msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when the job status changes" msgid "Webhooks|Trigger"
msgstr "" msgstr ""
msgid "Webhooks|URL is triggered when the pipeline status changes" msgid "Webhooks|URL"
msgstr "" msgstr ""
msgid "Webhooks|URL must be percent-encoded if neccessary." msgid "Webhooks|URL must be percent-encoded if it contains one or more special characters."
msgstr "" msgstr ""
msgid "Webhooks|Use this token to validate received payloads. It is sent with the request in the X-Gitlab-Token HTTP header." msgid "Webhooks|Used to validate received payloads. Sent with the request in the %{code_start}X-Gitlab-Token HTTP%{code_end} header."
msgstr "" msgstr ""
msgid "Webhooks|Webhook failed to connect" msgid "Webhooks|Webhook failed to connect"
......
...@@ -59,7 +59,7 @@ RSpec.describe 'admin issues labels' do ...@@ -59,7 +59,7 @@ RSpec.describe 'admin issues labels' do
it 'creates new label' do it 'creates new label' do
fill_in 'Title', with: 'support' fill_in 'Title', with: 'support'
fill_in 'Background color', with: '#F95610' fill_in 'Background color', with: '#F95610'
click_button 'Save' click_button 'Create label'
page.within '.manage-labels-list' do page.within '.manage-labels-list' do
expect(page).to have_content('support') expect(page).to have_content('support')
...@@ -69,7 +69,7 @@ RSpec.describe 'admin issues labels' do ...@@ -69,7 +69,7 @@ RSpec.describe 'admin issues labels' do
it 'does not creates label with invalid color' do it 'does not creates label with invalid color' do
fill_in 'Title', with: 'support' fill_in 'Title', with: 'support'
fill_in 'Background color', with: '#12' fill_in 'Background color', with: '#12'
click_button 'Save' click_button 'Create label'
page.within '.label-form' do page.within '.label-form' do
expect(page).to have_content('Color must be a valid color code') expect(page).to have_content('Color must be a valid color code')
...@@ -79,7 +79,7 @@ RSpec.describe 'admin issues labels' do ...@@ -79,7 +79,7 @@ RSpec.describe 'admin issues labels' do
it 'does not creates label if label already exists' do it 'does not creates label if label already exists' do
fill_in 'Title', with: 'bug' fill_in 'Title', with: 'bug'
fill_in 'Background color', with: '#F95610' fill_in 'Background color', with: '#F95610'
click_button 'Save' click_button 'Create label'
page.within '.label-form' do page.within '.label-form' do
expect(page).to have_content 'Title has already been taken' expect(page).to have_content 'Title has already been taken'
...@@ -93,7 +93,7 @@ RSpec.describe 'admin issues labels' do ...@@ -93,7 +93,7 @@ RSpec.describe 'admin issues labels' do
fill_in 'Title', with: 'fix' fill_in 'Title', with: 'fix'
fill_in 'Background color', with: '#F15610' fill_in 'Background color', with: '#F15610'
click_button 'Save' click_button 'Save changes'
page.within '.manage-labels-list' do page.within '.manage-labels-list' do
expect(page).to have_content('fix') expect(page).to have_content('fix')
......
...@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo'; ...@@ -4,7 +4,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper'; import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises'; import waitForPromises from 'helpers/wait_for_promises';
import IssueTypeField, { i18n } from '~/issues/show/components/fields/type.vue'; import IssueTypeField, { i18n } from '~/issues/show/components/fields/type.vue';
import { IssuableTypes } from '~/issues/show/constants'; import { issuableTypes } from '~/issues/show/constants';
import { import {
getIssueStateQueryResponse, getIssueStateQueryResponse,
updateIssueStateQueryResponse, updateIssueStateQueryResponse,
...@@ -69,8 +69,8 @@ describe('Issue type field component', () => { ...@@ -69,8 +69,8 @@ describe('Issue type field component', () => {
it.each` it.each`
at | text | icon at | text | icon
${0} | ${IssuableTypes[0].text} | ${IssuableTypes[0].icon} ${0} | ${issuableTypes[0].text} | ${issuableTypes[0].icon}
${1} | ${IssuableTypes[1].text} | ${IssuableTypes[1].icon} ${1} | ${issuableTypes[1].text} | ${issuableTypes[1].icon}
`(`renders the issue type $text with an icon in the dropdown`, ({ at, text, icon }) => { `(`renders the issue type $text with an icon in the dropdown`, ({ at, text, icon }) => {
expect(findTypeFromDropDownItemIconAt(at).attributes('name')).toBe(icon); expect(findTypeFromDropDownItemIconAt(at).attributes('name')).toBe(icon);
expect(findTypeFromDropDownItemAt(at).text()).toBe(text); expect(findTypeFromDropDownItemAt(at).text()).toBe(text);
...@@ -81,20 +81,20 @@ describe('Issue type field component', () => { ...@@ -81,20 +81,20 @@ describe('Issue type field component', () => {
}); });
it('renders a form select with the `issue_type` value', () => { it('renders a form select with the `issue_type` value', () => {
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.issue);
}); });
describe('with Apollo cache mock', () => { describe('with Apollo cache mock', () => {
it('renders the selected issueType', async () => { it('renders the selected issueType', async () => {
mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse); mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
await waitForPromises(); await waitForPromises();
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.issue);
}); });
it('updates the `issue_type` in the apollo cache when the value is changed', async () => { it('updates the `issue_type` in the apollo cache when the value is changed', async () => {
findTypeFromDropDownItems().at(1).vm.$emit('click', IssuableTypes.incident); findTypeFromDropDownItems().at(1).vm.$emit('click', issuableTypes.incident);
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.incident);
}); });
describe('when user is a guest', () => { describe('when user is a guest', () => {
...@@ -104,7 +104,7 @@ describe('Issue type field component', () => { ...@@ -104,7 +104,7 @@ describe('Issue type field component', () => {
expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true); expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(false); expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(false);
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.issue);
}); });
it('and incident is selected, includes incident in the dropdown', async () => { it('and incident is selected, includes incident in the dropdown', async () => {
...@@ -113,7 +113,7 @@ describe('Issue type field component', () => { ...@@ -113,7 +113,7 @@ describe('Issue type field component', () => {
expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true); expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(true); expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(true);
expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident); expect(findTypeFromDropDown().attributes('value')).toBe(issuableTypes.incident);
}); });
}); });
}); });
......
...@@ -8,7 +8,7 @@ import { IssuableType } from '~/vue_shared/issuable/show/constants'; ...@@ -8,7 +8,7 @@ import { IssuableType } from '~/vue_shared/issuable/show/constants';
import DeleteIssueModal from '~/issues/show/components/delete_issue_modal.vue'; import DeleteIssueModal from '~/issues/show/components/delete_issue_modal.vue';
import HeaderActions from '~/issues/show/components/header_actions.vue'; import HeaderActions from '~/issues/show/components/header_actions.vue';
import { IssuableStatus } from '~/issues/constants'; import { IssuableStatus } from '~/issues/constants';
import { IssueStateEvent } from '~/issues/show/constants'; import { ISSUE_STATE_EVENT_CLOSE, ISSUE_STATE_EVENT_REOPEN } from '~/issues/show/constants';
import promoteToEpicMutation from '~/issues/show/queries/promote_to_epic.mutation.graphql'; import promoteToEpicMutation from '~/issues/show/queries/promote_to_epic.mutation.graphql';
import * as urlUtility from '~/lib/utils/url_utility'; import * as urlUtility from '~/lib/utils/url_utility';
import eventHub from '~/notes/event_hub'; import eventHub from '~/notes/event_hub';
...@@ -118,8 +118,8 @@ describe('HeaderActions component', () => { ...@@ -118,8 +118,8 @@ describe('HeaderActions component', () => {
describe('close/reopen button', () => { describe('close/reopen button', () => {
describe.each` describe.each`
description | issueState | buttonText | newIssueState description | issueState | buttonText | newIssueState
${`when the ${issueType} is open`} | ${IssuableStatus.Open} | ${`Close ${issueType}`} | ${IssueStateEvent.Close} ${`when the ${issueType} is open`} | ${IssuableStatus.Open} | ${`Close ${issueType}`} | ${ISSUE_STATE_EVENT_CLOSE}
${`when the ${issueType} is closed`} | ${IssuableStatus.Closed} | ${`Reopen ${issueType}`} | ${IssueStateEvent.Reopen} ${`when the ${issueType} is closed`} | ${IssuableStatus.Closed} | ${`Reopen ${issueType}`} | ${ISSUE_STATE_EVENT_REOPEN}
`('$description', ({ issueState, buttonText, newIssueState }) => { `('$description', ({ issueState, buttonText, newIssueState }) => {
beforeEach(() => { beforeEach(() => {
dispatchEventSpy = jest.spyOn(document, 'dispatchEvent'); dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
...@@ -306,7 +306,7 @@ describe('HeaderActions component', () => { ...@@ -306,7 +306,7 @@ describe('HeaderActions component', () => {
input: { input: {
iid: defaultProps.iid, iid: defaultProps.iid,
projectPath: defaultProps.projectPath, projectPath: defaultProps.projectPath,
stateEvent: IssueStateEvent.Close, stateEvent: ISSUE_STATE_EVENT_CLOSE,
}, },
}, },
}), }),
...@@ -345,7 +345,7 @@ describe('HeaderActions component', () => { ...@@ -345,7 +345,7 @@ describe('HeaderActions component', () => {
input: { input: {
iid: defaultProps.iid.toString(), iid: defaultProps.iid.toString(),
projectPath: defaultProps.projectPath, projectPath: defaultProps.projectPath,
stateEvent: IssueStateEvent.Close, stateEvent: ISSUE_STATE_EVENT_CLOSE,
}, },
}, },
}), }),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment