Commit b42f312d authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 57e3d49f
<script> <script>
import { mapActions, mapState } from 'vuex'; import { mapActions, mapState } from 'vuex';
import { GlButton, GlFormInput } from '@gitlab/ui'; import { GlFormInput } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
export default { export default {
components: { GlButton, GlFormInput, Icon }, components: { GlFormInput, Icon, LoadingButton },
computed: { computed: {
...mapState(['apiHost', 'connectError', 'connectSuccessful', 'token']), ...mapState(['apiHost', 'connectError', 'connectSuccessful', 'isLoadingProjects', 'token']),
tokenInputState() { tokenInputState() {
return this.connectError ? false : null; return this.connectError ? false : null;
}, },
...@@ -27,6 +28,7 @@ export default { ...@@ -27,6 +28,7 @@ export default {
<gl-form-input <gl-form-input
id="error-tracking-api-host" id="error-tracking-api-host"
:value="apiHost" :value="apiHost"
:disabled="isLoadingProjects"
placeholder="https://mysentryserver.com" placeholder="https://mysentryserver.com"
@input="updateApiHost" @input="updateApiHost"
/> />
...@@ -47,13 +49,17 @@ export default { ...@@ -47,13 +49,17 @@ export default {
id="error-tracking-token" id="error-tracking-token"
:value="token" :value="token"
:state="tokenInputState" :state="tokenInputState"
:disabled="isLoadingProjects"
@input="updateToken" @input="updateToken"
/> />
</div> </div>
<div class="col-4 col-md-3 gl-pl-0"> <div class="col-4 col-md-3 gl-pl-0">
<gl-button class="js-error-tracking-connect prepend-left-5" @click="fetchProjects">{{ <loading-button
__('Connect') class="js-error-tracking-connect prepend-left-5 d-inline-flex"
}}</gl-button> :label="isLoadingProjects ? __('Connecting') : __('Connect')"
:loading="isLoadingProjects"
@click="fetchProjects"
/>
<icon <icon
v-show="connectSuccessful" v-show="connectSuccessful"
class="js-error-tracking-connect-success prepend-left-5 text-success align-middle" class="js-error-tracking-connect-success prepend-left-5 text-success align-middle"
......
...@@ -6,17 +6,20 @@ import { transformFrontendSettings } from '../utils'; ...@@ -6,17 +6,20 @@ import { transformFrontendSettings } from '../utils';
import * as types from './mutation_types'; import * as types from './mutation_types';
export const requestProjects = ({ commit }) => { export const requestProjects = ({ commit }) => {
commit(types.SET_PROJECTS_LOADING, true);
commit(types.RESET_CONNECT); commit(types.RESET_CONNECT);
}; };
export const receiveProjectsSuccess = ({ commit }, projects) => { export const receiveProjectsSuccess = ({ commit }, projects) => {
commit(types.UPDATE_CONNECT_SUCCESS); commit(types.UPDATE_CONNECT_SUCCESS);
commit(types.RECEIVE_PROJECTS, projects); commit(types.RECEIVE_PROJECTS, projects);
commit(types.SET_PROJECTS_LOADING, false);
}; };
export const receiveProjectsError = ({ commit }) => { export const receiveProjectsError = ({ commit }) => {
commit(types.UPDATE_CONNECT_ERROR); commit(types.UPDATE_CONNECT_ERROR);
commit(types.CLEAR_PROJECTS); commit(types.CLEAR_PROJECTS);
commit(types.SET_PROJECTS_LOADING, false);
}; };
export const fetchProjects = ({ dispatch, state }) => { export const fetchProjects = ({ dispatch, state }) => {
......
...@@ -9,3 +9,4 @@ export const UPDATE_ENABLED = 'UPDATE_ENABLED'; ...@@ -9,3 +9,4 @@ export const UPDATE_ENABLED = 'UPDATE_ENABLED';
export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT'; export const UPDATE_SELECTED_PROJECT = 'UPDATE_SELECTED_PROJECT';
export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING'; export const UPDATE_SETTINGS_LOADING = 'UPDATE_SETTINGS_LOADING';
export const UPDATE_TOKEN = 'UPDATE_TOKEN'; export const UPDATE_TOKEN = 'UPDATE_TOKEN';
export const SET_PROJECTS_LOADING = 'SET_PROJECTS_LOADING';
...@@ -58,4 +58,7 @@ export default { ...@@ -58,4 +58,7 @@ export default {
state.connectSuccessful = false; state.connectSuccessful = false;
state.connectError = true; state.connectError = true;
}, },
[types.SET_PROJECTS_LOADING](state, loading) {
state.isLoadingProjects = loading;
},
}; };
...@@ -3,6 +3,7 @@ export default () => ({ ...@@ -3,6 +3,7 @@ export default () => ({
enabled: false, enabled: false,
token: '', token: '',
projects: [], projects: [],
isLoadingProjects: false,
selectedProject: null, selectedProject: null,
settingsLoading: false, settingsLoading: false,
connectSuccessful: false, connectSuccessful: false,
......
/* eslint-disable no-restricted-properties, func-names, no-var, camelcase, /* eslint-disable no-restricted-properties, no-var, camelcase,
no-unused-expressions, one-var, default-case, no-unused-expressions, one-var, default-case,
consistent-return, no-alert, no-return-assign, consistent-return, no-alert, no-param-reassign, no-else-return,
no-param-reassign, no-else-return, vars-on-top, vars-on-top, no-shadow, no-useless-escape,
no-shadow, no-useless-escape, class-methods-use-this */ class-methods-use-this */
/* global ResolveService */ /* global ResolveService */
...@@ -281,14 +281,7 @@ export default class Notes { ...@@ -281,14 +281,7 @@ export default class Notes {
if (Notes.interval) { if (Notes.interval) {
clearInterval(Notes.interval); clearInterval(Notes.interval);
} }
return (Notes.interval = setInterval( Notes.interval = setInterval(() => this.refresh(), this.pollingInterval);
(function(_this) {
return function() {
return _this.refresh();
};
})(this),
this.pollingInterval,
));
} }
refresh() { refresh() {
...@@ -847,57 +840,52 @@ export default class Notes { ...@@ -847,57 +840,52 @@ export default class Notes {
var noteElId, $note; var noteElId, $note;
$note = $(e.currentTarget).closest('.note'); $note = $(e.currentTarget).closest('.note');
noteElId = $note.attr('id'); noteElId = $note.attr('id');
$(`.note[id="${noteElId}"]`).each( $(`.note[id="${noteElId}"]`).each((i, el) => {
(function() { // A same note appears in the "Discussion" and in the "Changes" tab, we have
// A same note appears in the "Discussion" and in the "Changes" tab, we have // to remove all. Using $('.note[id='noteId']') ensure we get all the notes,
// to remove all. Using $('.note[id='noteId']') ensure we get all the notes, // where $('#noteId') would return only one.
// where $('#noteId') would return only one. const $note = $(el);
return function(i, el) { const $notes = $note.closest('.discussion-notes');
var $note, $notes; const discussionId = $('.notes', $notes).data('discussionId');
$note = $(el);
$notes = $note.closest('.discussion-notes'); if (typeof gl.diffNotesCompileComponents !== 'undefined') {
const discussionId = $('.notes', $notes).data('discussionId'); if (gl.diffNoteApps[noteElId]) {
gl.diffNoteApps[noteElId].$destroy();
if (typeof gl.diffNotesCompileComponents !== 'undefined') { }
if (gl.diffNoteApps[noteElId]) { }
gl.diffNoteApps[noteElId].$destroy();
}
}
$note.remove();
// check if this is the last note for this line $note.remove();
if ($notes.find('.note').length === 0) {
var notesTr = $notes.closest('tr');
// "Discussions" tab // check if this is the last note for this line
$notes.closest('.timeline-entry').remove(); if ($notes.find('.note').length === 0) {
const notesTr = $notes.closest('tr');
$(`.js-diff-avatars-${discussionId}`).trigger('remove.vue'); // "Discussions" tab
$notes.closest('.timeline-entry').remove();
// The notes tr can contain multiple lists of notes, like on the parallel diff $(`.js-diff-avatars-${discussionId}`).trigger('remove.vue');
// notesTr does not exist for image diffs
if (notesTr.find('.discussion-notes').length > 1 || notesTr.length === 0) {
const $diffFile = $notes.closest('.diff-file');
if ($diffFile.length > 0) {
const removeBadgeEvent = new CustomEvent('removeBadge.imageDiff', {
detail: {
// badgeNumber's start with 1 and index starts with 0
badgeNumber: $notes.index() + 1,
},
});
$diffFile[0].dispatchEvent(removeBadgeEvent); // The notes tr can contain multiple lists of notes, like on the parallel diff
} // notesTr does not exist for image diffs
if (notesTr.find('.discussion-notes').length > 1 || notesTr.length === 0) {
const $diffFile = $notes.closest('.diff-file');
if ($diffFile.length > 0) {
const removeBadgeEvent = new CustomEvent('removeBadge.imageDiff', {
detail: {
// badgeNumber's start with 1 and index starts with 0
badgeNumber: $notes.index() + 1,
},
});
$notes.remove(); $diffFile[0].dispatchEvent(removeBadgeEvent);
} else if (notesTr.length > 0) {
notesTr.remove();
}
} }
};
})(this), $notes.remove();
); } else if (notesTr.length > 0) {
notesTr.remove();
}
}
});
Notes.checkMergeRequestStatus(); Notes.checkMergeRequestStatus();
return this.updateNotesCount(-1); return this.updateNotesCount(-1);
......
...@@ -6,7 +6,7 @@ class Projects::ReleasesController < Projects::ApplicationController ...@@ -6,7 +6,7 @@ class Projects::ReleasesController < Projects::ApplicationController
before_action :release, only: %i[edit update] before_action :release, only: %i[edit update]
before_action :authorize_read_release! before_action :authorize_read_release!
before_action do before_action do
push_frontend_feature_flag(:release_edit_page, project) push_frontend_feature_flag(:release_edit_page, project, default_enabled: true)
push_frontend_feature_flag(:release_issue_summary, project) push_frontend_feature_flag(:release_issue_summary, project)
end end
before_action :authorize_update_release!, only: %i[edit update] before_action :authorize_update_release!, only: %i[edit update]
...@@ -35,7 +35,7 @@ class Projects::ReleasesController < Projects::ApplicationController ...@@ -35,7 +35,7 @@ class Projects::ReleasesController < Projects::ApplicationController
private private
def authorize_update_release! def authorize_update_release!
access_denied! unless Feature.enabled?(:release_edit_page, project) access_denied! unless Feature.enabled?(:release_edit_page, project, default_enabled: true)
access_denied! unless can?(current_user, :update_release, release) access_denied! unless can?(current_user, :update_release, release)
end end
......
...@@ -329,7 +329,7 @@ module ApplicationHelper ...@@ -329,7 +329,7 @@ module ApplicationHelper
if Rails.configuration.assets.compile if Rails.configuration.assets.compile
app.assets.find_asset(name).to_s app.assets.find_asset(name).to_s
else else
controller.view_context.render(file: File.join('public/assets', app.assets_manifest.assets[name])) controller.view_context.render(file: Rails.root.join('public/assets', app.assets_manifest.assets[name]).to_s)
end end
end end
......
...@@ -108,16 +108,6 @@ module TabHelper ...@@ -108,16 +108,6 @@ module TabHelper
current_controller?(c) && current_action?(a) current_controller?(c) && current_action?(a)
end end
def project_tab_class
if controller.controller_path.start_with?('projects')
return 'active'
end
if %w(services hooks deploy_keys protected_branches).include? controller.controller_name
"active"
end
end
def branches_tab_class def branches_tab_class
if current_controller?(:protected_branches) || if current_controller?(:protected_branches) ||
current_controller?(:branches) || current_controller?(:branches) ||
...@@ -125,14 +115,6 @@ module TabHelper ...@@ -125,14 +115,6 @@ module TabHelper
'active' 'active'
end end
end end
def profile_tab_class
if controller.controller_path.start_with?('profiles')
return 'active'
end
'active' if current_controller?('oauth/applications')
end
end end
TabHelper.prepend_if_ee('EE::TabHelper') TabHelper.prepend_if_ee('EE::TabHelper')
...@@ -52,6 +52,6 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated ...@@ -52,6 +52,6 @@ class ReleasePresenter < Gitlab::View::Presenter::Delegated
end end
def release_edit_page_available? def release_edit_page_available?
::Feature.enabled?(:release_edit_page, project) ::Feature.enabled?(:release_edit_page, project, default_enabled: true)
end end
end end
---
title: Add loading icon to error tracking settings page
merge_request: 19539
author:
type: changed
---
title: Remove local qualifier from geo sync indicators
merge_request: 20034
author: Lee Tickett
type: fixed
---
title: Remove unused image/screenshot
merge_request: 20030
author: Lee Tickett
type: fixed
...@@ -337,6 +337,7 @@ The following documentation relates to the DevOps **Monitor** stage: ...@@ -337,6 +337,7 @@ The following documentation relates to the DevOps **Monitor** stage:
| [Health check](user/admin_area/monitoring/health_check.md) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. | | [Health check](user/admin_area/monitoring/health_check.md) | GitLab provides liveness and readiness probes to indicate service health and reachability to required services. |
| [Prometheus project integration](user/project/integrations/prometheus.md) | Configure the Prometheus integration per project and monitor your CI/CD environments. | | [Prometheus project integration](user/project/integrations/prometheus.md) | Configure the Prometheus integration per project and monitor your CI/CD environments. |
| [Prometheus metrics](user/project/integrations/prometheus_library/index.md) | Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX Ingress controller, HAProxy, and Amazon Cloud Watch. | | [Prometheus metrics](user/project/integrations/prometheus_library/index.md) | Let Prometheus collect metrics from various services, like Kubernetes, NGINX, NGINX Ingress controller, HAProxy, and Amazon Cloud Watch. |
| [Incident management](user/incident_management/index.md) | Use GitLab to help you better respond to incidents that may occur in your systems. |
<div align="right"> <div align="right">
<a type="button" class="btn btn-default" href="#overview"> <a type="button" class="btn btn-default" href="#overview">
......
...@@ -78,6 +78,31 @@ To change the address/port that Prometheus listens on: ...@@ -78,6 +78,31 @@ To change the address/port that Prometheus listens on:
1. Save the file and [reconfigure GitLab][reconfigure] for the changes to 1. Save the file and [reconfigure GitLab][reconfigure] for the changes to
take effect take effect
### Adding custom scrape configs
You can configure additional scrape targets for the GitLab Omnibus-bundled
Prometheus by editing `prometheus['scrape_configs']` in `/etc/gitlab/gitlab.rb`
using the [Prometheus scrape target configuration](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#%3Cscrape_config%3E)
syntax.
Here is an example configuration to scrape `http://1.1.1.1:8060/probe?param_a=test&param_b=additional_test`:
```ruby
prometheus['scrape_configs'] = [
{
'job_name': 'custom-scrape',
'metrics_path': '/probe',
'params' => {
'param_a' => ['test'],
'param_b' => ['additional_test']
},
'static_configs' => [
'targets' => ['1.1.1.1:8060'],
],
},
]
```
### Using an external Prometheus server ### Using an external Prometheus server
NOTE: **Note:** NOTE: **Note:**
......
...@@ -141,6 +141,8 @@ have a [start or due date](#start-date-and-due-date), a ...@@ -141,6 +141,8 @@ have a [start or due date](#start-date-and-due-date), a
## Reordering issues and child epics ## Reordering issues and child epics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9367) in GitLab 12.5.
New issues and child epics are added to the top of their respective lists in the **Epics and Issues** tab. You can reorder the list of issues and the list of child epics. Issues and child epics cannot be intermingled. New issues and child epics are added to the top of their respective lists in the **Epics and Issues** tab. You can reorder the list of issues and the list of child epics. Issues and child epics cannot be intermingled.
To reorder issues assigned to an epic: To reorder issues assigned to an epic:
......
---
description: "GitLab - Incident Management. GitLab offers solutions for handling incidents in your applications and services"
---
# Incident Management
GitLab offers solutions for handling incidents in your applications and services,
from setting up an alert with Prometheus, to receiving a notification via a
monitoring tool like Slack, and automatically setting up Zoom calls with your
support team.
## Configuring incidents **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/4925) in GitLab Ultimate 11.11.
The Incident Management features can be enabled and disabled via your project's
**Settings > Operations > Incidents**.
![Incident Management Settings](img/incident_management_settings.png)
### Automatically create issues from alerts
GitLab issues can automatically be created as a result of an alert notification.
An issue created this way will contain the error information to help you further
debug it.
### Issue templates
You can create your own [issue templates](../project/description_templates.md#creating-issue-templates)
that can be [used within Incident Management](../project/integrations/prometheus.md#taking-action-on-incidents-ultimate).
To select your issue template for use within Incident Management:
1. Visit your project's **Settings > Operations > Incidents**.
1. Select the template from the **Issue Template** dropdown.
## Alerting
GitLab can react to the alerts that your applications and services may be
triggering by automatically creating issues, and alerting developers via email.
### Prometheus alerts
Prometheus alerts can be set up in both:
- [GitLab-managed Prometheus](../project/integrations/prometheus.md#setting-up-alerts-for-prometheus-metrics-ultimate) and
- [Self-managed Prometheus](../project/integrations/prometheus.md#external-prometheus-instances) installations.
### Alert endpoint
GitLab can accept alerts from any source via a generic webhook receiver. When
you set up the generic alerts integration, a unique endpoint will
be created which can receive a payload in JSON format.
[Read more on setting this up, including how to customize the payload](../project/integrations/generic_alerts.md).
### Recovery alerts
GitLab can [automatically close issues](../project/integrations/prometheus.md#taking-action-on-incidents-ultimate)
that have been automatically created when you receive notification that the
alert is resolved.
## Embedded metrics
Metrics can be embedded anywhere where GitLab Markdown is used, for example,
descriptions and comments on issues and merge requests.
TIP: **Tip:**
Both GitLab-hosted and Grafana metrics can also be
[embedded in issue templates](../project/integrations/prometheus.md#embedding-metrics-in-issue-templates).
### GitLab-hosted metrics
Learn how to embed [GitLab hosted metric charts](../project/integrations/prometheus.md#embedding-metric-charts-within-gitlab-flavored-markdown).
### Grafana metrics
Learn how to embed [Grafana hosted metric charts](../project/integrations/prometheus.md#embedding-live-grafana-charts).
## Slack integration
Slack slash commands allow you to control GitLab and view content right inside
Slack, without having to leave it.
Learn how to [set up Slack slash commands](../project/integrations/slack_slash_commands.md)
and how to [use them](../../integration/slash_commands.md).
### Slash commands
Please refer to a list of [available slash commands](../../integration/slash_commands.md) and associated descriptions.
## Zoom in issues
In order to communicate synchronously for incidents management, GitLab allows to
associate a Zoom meeting with an issue. Once you start a Zoom call for a fire-fight,
you need a way to associate the conference call with an issue, so that your team
members can join swiftly without requesting a link.
Read more how to [add or remove a zoom meeting](../project/issues/associate_zoom_meeting.md).
### Alerting
You can let GitLab know of alerts that may be triggering in your applications and services. GitLab can react to these by automatically creating Issues, and alerting developers via Email.
#### Prometheus Alerts
Prometheus alerts can be setup in both GitLab-managed Prometheus installs and self-managed Prometheus installs.
Documentation for each method can be found here:
- [GitLab-managed Prometheus](../project/integrations/prometheus.md#setting-up-alerts-for-prometheus-metrics-ultimate)
- [Self-managed Prometheus](../project/integrations/prometheus.md#external-prometheus-instances)
#### Alert Endpoint
GitLab can accept alerts from any source via a generic webhook receiver. When you set up the generic alerts integration, a unique endpoint will
be created which can receive a payload in JSON format.
More information on setting this up, including how to customize the payload [can be found here](../project/integrations/generic_alerts.md).
#### Recovery Alerts
Coming soon: GitLab can automatically close Issues that have been automatically created when we receive notification that the alert is resolved.
### Configuring Incidents
Incident Management features can be easily enabled & disabled via the Project settings page. Head to Project -> Settings -> Operations -> Incidents.
#### Auto-creation
GitLab Issues can automatically be created as a result of an Alert notification. An Issue created this way will contain error information to help you further debug the error.
...@@ -403,9 +403,12 @@ receivers: ...@@ -403,9 +403,12 @@ receivers:
... ...
``` ```
In order for GitLab to associate your alerts with an [environment](../../../ci/environments.md), you need to configure a `gitlab_environment_name` label on the alerts you set up in Prometheus. The value of this should match the name of your Environment in GitLab.
### Taking action on incidents **(ULTIMATE)** ### Taking action on incidents **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11. >- [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/4925) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.11.
>- [From GitLab Ultimate 12.5](https://gitlab.com/gitlab-org/gitlab/issues/13401), when GitLab receives a recovery alert, it will automatically close the associated issue.
Alerts can be used to trigger actions, like open an issue automatically (enabled by default since `12.1`). To configure the actions: Alerts can be used to trigger actions, like open an issue automatically (enabled by default since `12.1`). To configure the actions:
...@@ -426,7 +429,7 @@ Once enabled, an issue will be opened automatically when an alert is triggered w ...@@ -426,7 +429,7 @@ Once enabled, an issue will be opened automatically when an alert is triggered w
- Optional list of attached annotations extracted from `annotations/*` - Optional list of attached annotations extracted from `annotations/*`
- Alert [GFM](../../markdown.md): GitLab Flavored Markdown from `annotations/gitlab_incident_markdown` - Alert [GFM](../../markdown.md): GitLab Flavored Markdown from `annotations/gitlab_incident_markdown`
When GitLab recieves a **Recovery Alert**, it will automatically close the associated issue. This action will be recorded as a system message on the issue indicated that it was closed automatically by the GitLab Alert bot. When GitLab receives a **Recovery Alert**, it will automatically close the associated issue. This action will be recorded as a system message on the issue indicated that it was closed automatically by the GitLab Alert bot.
To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template, which will apply to all incidents. To limit quick actions or other information to only specific types of alerts, use the `annotations/gitlab_incident_markdown` field. To further customize the issue, you can add labels, mentions, or any other supported [quick action](../quick_actions.md) in the selected issue template, which will apply to all incidents. To limit quick actions or other information to only specific types of alerts, use the `annotations/gitlab_incident_markdown` field.
...@@ -487,6 +490,12 @@ The following requirements must be met for the metric to unfurl: ...@@ -487,6 +490,12 @@ The following requirements must be met for the metric to unfurl:
![Embedded Metrics](img/embed_metrics.png) ![Embedded Metrics](img/embed_metrics.png)
### Embedding metrics in issue templates
It is also possible to embed either a dashboard or individual metrics in issue templates. The entire dashboard can be embedded as well as individual metrics, separated by either a comma or a space.
![Embedded Metrics in issue templates](img/embed_metrics_issue_template.png)
### Embedding live Grafana charts ### Embedding live Grafana charts
It is also possible to embed live [Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html) charts within issues, as a [Direct Linked Rendered Image](https://grafana.com/docs/reference/sharing/#direct-link-rendered-image). It is also possible to embed live [Grafana](https://docs.gitlab.com/omnibus/settings/grafana.html) charts within issues, as a [Direct Linked Rendered Image](https://grafana.com/docs/reference/sharing/#direct-link-rendered-image).
......
# Associate a Zoom meeting with an issue
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/16609) in GitLab 12.4.
In order to communicate synchronously for incidents management,
GitLab allows to associate a Zoom meeting with an issue.
Once you start a Zoom call for a fire-fight, you need a way to
associate the conference call with an issue, so that your team
members can join swiftly without requesting a link.
## Adding a zoom meeting to an issue
To associate a zoom meeting with an issue, you can use GitLab's
[quick actions](../quick_actions.md#quick-actions-for-issues-merge-requests-and-epics).
In an issue, leave a comment using the `/zoom` quick action followed by a valid Zoom link:
```sh
/zoom https://zoom.us/j/123456789
```
If the Zoom meeting URL is valid and you have at least [Reporter permissions](../../permissions.md),
a system alert will notify you that the addition of the meeting URL was successful.
The issue's description will be automatically edited to include the Zoom link, and a button will
appear right under the issue's title.
![Link Zoom Call in Issue](img/zoom-quickaction-button.png)
You are only allowed to attach a single Zoom meeting to an issue. If you attempt
to add a second Zoom meeting using the `/zoom` quick action, it won't work, you
need to [remove it](#removing-an-existing-zoom-meeting-from-an-issue) first.
## Removing an existing Zoom meeting from an issue
Similarly to adding a zoom meeting, you can remove it with a quick action:
```sh
/remove_zoom
```
If you have at least [Reporter permissions](../../permissions.md),
a system alert will notify you that the meeting URL was successfully removed.
...@@ -257,4 +257,4 @@ You can attach and remove Zoom meetings to issues using the `/zoom` and `/remove ...@@ -257,4 +257,4 @@ You can attach and remove Zoom meetings to issues using the `/zoom` and `/remove
Attaching a [Zoom](https://zoom.us) call an issue Attaching a [Zoom](https://zoom.us) call an issue
results in a **Join Zoom meeting** button at the top of the issue, just under the header. results in a **Join Zoom meeting** button at the top of the issue, just under the header.
![Link Zoom Call in Issue](img/zoom-quickaction-button.png) Read more how to [add or remove a zoom meeting](associate_zoom_meeting.md).
...@@ -113,10 +113,9 @@ promoteBeta: ...@@ -113,10 +113,9 @@ promoteBeta:
promoteProduction: promoteProduction:
extends: .promote_job extends: .promote_job
stage: production stage: production
# We only allow production promotion on the default branch because # We only allow production promotion on `master` because
# it has its own production scoped secret variables # it has its own production scoped secret variables
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
script: script:
- bundle exec fastlane promote_beta_to_production - bundle exec fastlane promote_beta_to_production
...@@ -10,8 +10,7 @@ docker-build-master: ...@@ -10,8 +10,7 @@ docker-build-master:
- docker build --pull -t "$CI_REGISTRY_IMAGE" . - docker build --pull -t "$CI_REGISTRY_IMAGE" .
- docker push "$CI_REGISTRY_IMAGE" - docker push "$CI_REGISTRY_IMAGE"
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
docker-build: docker-build:
# Official docker image. # Official docker image.
...@@ -25,5 +24,4 @@ docker-build: ...@@ -25,5 +24,4 @@ docker-build:
- docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" . - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" .
- docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG" - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG"
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -24,8 +24,9 @@ review: ...@@ -24,8 +24,9 @@ review:
- tags - tags
kubernetes: active kubernetes: active
except: except:
refs:
- master
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $REVIEW_DISABLED - $REVIEW_DISABLED
stop_review: stop_review:
...@@ -47,8 +48,9 @@ stop_review: ...@@ -47,8 +48,9 @@ stop_review:
- tags - tags
kubernetes: active kubernetes: active
except: except:
refs:
- master
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $REVIEW_DISABLED - $REVIEW_DISABLED
# Staging deploys are disabled by default since # Staging deploys are disabled by default since
...@@ -71,9 +73,10 @@ staging: ...@@ -71,9 +73,10 @@ staging:
name: staging name: staging
url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN url: http://$CI_PROJECT_PATH_SLUG-staging.$KUBE_INGRESS_BASE_DOMAIN
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $STAGING_ENABLED - $STAGING_ENABLED
# Canaries are disabled by default, but if you want them, # Canaries are disabled by default, but if you want them,
...@@ -95,9 +98,10 @@ canary: ...@@ -95,9 +98,10 @@ canary:
url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN url: http://$CI_PROJECT_PATH_SLUG.$KUBE_INGRESS_BASE_DOMAIN
when: manual when: manual
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $CANARY_ENABLED - $CANARY_ENABLED
.production: &production_template .production: &production_template
...@@ -122,9 +126,9 @@ canary: ...@@ -122,9 +126,9 @@ canary:
production: production:
<<: *production_template <<: *production_template
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
except: except:
variables: variables:
- $STAGING_ENABLED - $STAGING_ENABLED
...@@ -137,9 +141,10 @@ production_manual: ...@@ -137,9 +141,10 @@ production_manual:
when: manual when: manual
allow_failure: false allow_failure: false
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $STAGING_ENABLED - $STAGING_ENABLED
- $CANARY_ENABLED - $CANARY_ENABLED
except: except:
...@@ -147,7 +152,7 @@ production_manual: ...@@ -147,7 +152,7 @@ production_manual:
- $INCREMENTAL_ROLLOUT_ENABLED - $INCREMENTAL_ROLLOUT_ENABLED
- $INCREMENTAL_ROLLOUT_MODE - $INCREMENTAL_ROLLOUT_MODE
# This job implements incremental rollout for every push to the default branch. # This job implements incremental rollout on for every push to `master`.
.rollout: &rollout_template .rollout: &rollout_template
extends: .auto-deploy extends: .auto-deploy
...@@ -173,9 +178,10 @@ production_manual: ...@@ -173,9 +178,10 @@ production_manual:
when: manual when: manual
# This selectors are backward compatible mode with $INCREMENTAL_ROLLOUT_ENABLED (before 11.4) # This selectors are backward compatible mode with $INCREMENTAL_ROLLOUT_ENABLED (before 11.4)
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $INCREMENTAL_ROLLOUT_MODE == "manual" - $INCREMENTAL_ROLLOUT_MODE == "manual"
- $INCREMENTAL_ROLLOUT_ENABLED - $INCREMENTAL_ROLLOUT_ENABLED
except: except:
...@@ -187,9 +193,10 @@ production_manual: ...@@ -187,9 +193,10 @@ production_manual:
when: delayed when: delayed
start_in: 5 minutes start_in: 5 minutes
only: only:
refs:
- master
kubernetes: active kubernetes: active
variables: variables:
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
- $INCREMENTAL_ROLLOUT_MODE == "timed" - $INCREMENTAL_ROLLOUT_MODE == "timed"
timed rollout 10%: timed rollout 10%:
......
...@@ -64,8 +64,7 @@ pages: ...@@ -64,8 +64,7 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
# WARNING: This template is using the `julia` images from [Docker # WARNING: This template is using the `julia` images from [Docker
# Hub][3]. One can use custom Julia images and/or the official ones found # Hub][3]. One can use custom Julia images and/or the official ones found
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# This template will build and test your projects # This template will build and test your projects
# * Caches downloaded dependencies and plugins between invocation. # * Caches downloaded dependencies and plugins between invocation.
# * Verify but don't deploy merge requests. # * Verify but don't deploy merge requests.
# * Deploy built artifacts from the default branch only. # * Deploy built artifacts from master branch only.
variables: variables:
# This will suppress any download for dependencies and plugins or upload messages which would clutter the console log. # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
...@@ -33,8 +33,7 @@ cache: ...@@ -33,8 +33,7 @@ cache:
script: script:
- 'mvn $MAVEN_CLI_OPTS verify' - 'mvn $MAVEN_CLI_OPTS verify'
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
# Verify merge requests using JDK8 # Verify merge requests using JDK8
verify:jdk8: verify:jdk8:
...@@ -43,7 +42,7 @@ verify:jdk8: ...@@ -43,7 +42,7 @@ verify:jdk8:
# To deploy packages from CI, create a ci_settings.xml file # To deploy packages from CI, create a ci_settings.xml file
# For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details. # For deploying packages to GitLab's Maven Repository: See https://docs.gitlab.com/ee/user/project/packages/maven_repository.html#creating-maven-packages-with-gitlab-cicd for more details.
# Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate. # Please note: The GitLab Maven Repository is currently only available in GitLab Premium / Ultimate.
# For the default branch run `mvn deploy` automatically. # For `master` branch run `mvn deploy` automatically.
deploy:jdk8: deploy:jdk8:
stage: deploy stage: deploy
script: script:
...@@ -52,5 +51,4 @@ deploy:jdk8: ...@@ -52,5 +51,4 @@ deploy:jdk8:
fi fi
- 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml' - 'mvn $MAVEN_CLI_OPTS deploy -s ci_settings.xml'
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -25,8 +25,7 @@ before_script: ...@@ -25,8 +25,7 @@ before_script:
release: release:
stage: deploy stage: deploy
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
artifacts: artifacts:
paths: paths:
- build/release/MyProject.exe - build/release/MyProject.exe
......
...@@ -49,8 +49,7 @@ review: ...@@ -49,8 +49,7 @@ review:
only: only:
- branches - branches
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
stop-review: stop-review:
<<: *deploy <<: *deploy
...@@ -67,8 +66,7 @@ stop-review: ...@@ -67,8 +66,7 @@ stop-review:
only: only:
- branches - branches
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
staging: staging:
<<: *deploy <<: *deploy
...@@ -80,8 +78,7 @@ staging: ...@@ -80,8 +78,7 @@ staging:
name: staging name: staging
url: http://$CI_PROJECT_NAME-staging.$OPENSHIFT_DOMAIN url: http://$CI_PROJECT_NAME-staging.$OPENSHIFT_DOMAIN
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
production: production:
<<: *deploy <<: *deploy
...@@ -94,5 +91,4 @@ production: ...@@ -94,5 +91,4 @@ production:
name: production name: production
url: http://$CI_PROJECT_NAME.$OPENSHIFT_DOMAIN url: http://$CI_PROJECT_NAME.$OPENSHIFT_DOMAIN
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -25,5 +25,4 @@ build: ...@@ -25,5 +25,4 @@ build:
- find . -maxdepth 1 -name '*.json' -print0 | xargs -t0n1 packer build - find . -maxdepth 1 -name '*.json' -print0 | xargs -t0n1 packer build
when: manual when: manual
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -12,5 +12,4 @@ pages: ...@@ -12,5 +12,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -10,5 +10,4 @@ pages: ...@@ -10,5 +10,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -14,5 +14,4 @@ pages: ...@@ -14,5 +14,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -9,5 +9,4 @@ pages: ...@@ -9,5 +9,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -12,5 +12,4 @@ pages: ...@@ -12,5 +12,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -14,5 +14,4 @@ pages: ...@@ -14,5 +14,4 @@ pages:
- node_modules - node_modules
key: project key: project
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -8,12 +8,10 @@ pages: ...@@ -8,12 +8,10 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
test: test:
script: script:
- hugo - hugo
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -11,8 +11,7 @@ test: ...@@ -11,8 +11,7 @@ test:
- pip install hyde - pip install hyde
- hyde gen - hyde gen
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
pages: pages:
stage: deploy stage: deploy
...@@ -23,5 +22,4 @@ pages: ...@@ -23,5 +22,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -17,8 +17,7 @@ test: ...@@ -17,8 +17,7 @@ test:
paths: paths:
- test - test
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
pages: pages:
stage: deploy stage: deploy
...@@ -28,5 +27,4 @@ pages: ...@@ -28,5 +27,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -34,5 +34,4 @@ pages: ...@@ -34,5 +34,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -9,5 +9,4 @@ pages: ...@@ -9,5 +9,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -13,5 +13,4 @@ pages: ...@@ -13,5 +13,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -12,8 +12,7 @@ test: ...@@ -12,8 +12,7 @@ test:
- bundle install --path vendor - bundle install --path vendor
- bundle exec middleman build - bundle exec middleman build
except: except:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
pages: pages:
script: script:
...@@ -25,5 +24,4 @@ pages: ...@@ -25,5 +24,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -9,5 +9,4 @@ pages: ...@@ -9,5 +9,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -12,5 +12,4 @@ pages: ...@@ -12,5 +12,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -26,5 +26,4 @@ pages: ...@@ -26,5 +26,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -48,5 +48,4 @@ pages: ...@@ -48,5 +48,4 @@ pages:
paths: paths:
- public - public
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -22,8 +22,7 @@ archive_project: ...@@ -22,8 +22,7 @@ archive_project:
- xcodebuild clean archive -archivePath build/ProjectName -scheme SchemeName - xcodebuild clean archive -archivePath build/ProjectName -scheme SchemeName
- xcodebuild -exportArchive -exportFormat ipa -archivePath "build/ProjectName.xcarchive" -exportPath "build/ProjectName.ipa" -exportProvisioningProfile "ProvisioningProfileName" - xcodebuild -exportArchive -exportFormat ipa -archivePath "build/ProjectName.xcarchive" -exportPath "build/ProjectName.ipa" -exportProvisioningProfile "ProvisioningProfileName"
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
artifacts: artifacts:
paths: paths:
- build/ProjectName.ipa - build/ProjectName.ipa
......
...@@ -53,5 +53,4 @@ apply: ...@@ -53,5 +53,4 @@ apply:
- plan - plan
when: manual when: manual
only: only:
variables: - master
- $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
...@@ -35,7 +35,7 @@ module Gitlab ...@@ -35,7 +35,7 @@ module Gitlab
def self.initialize_http_request_duration_seconds def self.initialize_http_request_duration_seconds
HTTP_METHODS.each do |method, statuses| HTTP_METHODS.each do |method, statuses|
statuses.each do |status| statuses.each do |status|
http_request_duration_seconds.get({ method: method, status: status.to_i }) http_request_duration_seconds.get({ method: method, status: status.to_s })
end end
end end
end end
...@@ -49,7 +49,7 @@ module Gitlab ...@@ -49,7 +49,7 @@ module Gitlab
status, headers, body = @app.call(env) status, headers, body = @app.call(env)
elapsed = Time.now.to_f - started elapsed = Time.now.to_f - started
RequestsRackMiddleware.http_request_duration_seconds.observe({ method: method, status: status }, elapsed) RequestsRackMiddleware.http_request_duration_seconds.observe({ method: method, status: status.to_s }, elapsed)
[status, headers, body] [status, headers, body]
rescue rescue
......
...@@ -4452,6 +4452,9 @@ msgstr "" ...@@ -4452,6 +4452,9 @@ msgstr ""
msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled." msgid "Connect your external repositories, and CI/CD pipelines will run for new commits. A GitLab project will be created with only CI/CD features enabled."
msgstr "" msgstr ""
msgid "Connecting"
msgstr ""
msgid "Connecting to terminal sync service" msgid "Connecting to terminal sync service"
msgstr "" msgstr ""
...@@ -7683,9 +7686,15 @@ msgstr "" ...@@ -7683,9 +7686,15 @@ msgstr ""
msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage." msgid "GeoNodeSyncStatus|Node is slow, overloaded, or it just recovered after an outage."
msgstr "" msgstr ""
msgid "GeoNodes|Attachments"
msgstr ""
msgid "GeoNodes|Checksummed" msgid "GeoNodes|Checksummed"
msgstr "" msgstr ""
msgid "GeoNodes|Container repositories"
msgstr ""
msgid "GeoNodes|Data is out of date from %{timeago}" msgid "GeoNodes|Data is out of date from %{timeago}"
msgstr "" msgstr ""
...@@ -7716,6 +7725,12 @@ msgstr "" ...@@ -7716,6 +7725,12 @@ msgstr ""
msgid "GeoNodes|Internal URL" msgid "GeoNodes|Internal URL"
msgstr "" msgstr ""
msgid "GeoNodes|Job artifacts"
msgstr ""
msgid "GeoNodes|LFS objects"
msgstr ""
msgid "GeoNodes|Last event ID processed by cursor" msgid "GeoNodes|Last event ID processed by cursor"
msgstr "" msgstr ""
...@@ -7737,18 +7752,6 @@ msgstr "" ...@@ -7737,18 +7752,6 @@ msgstr ""
msgid "GeoNodes|Loading nodes" msgid "GeoNodes|Loading nodes"
msgstr "" msgstr ""
msgid "GeoNodes|Local LFS objects"
msgstr ""
msgid "GeoNodes|Local attachments"
msgstr ""
msgid "GeoNodes|Local container repositories"
msgstr ""
msgid "GeoNodes|Local job artifacts"
msgstr ""
msgid "GeoNodes|New node" msgid "GeoNodes|New node"
msgstr "" msgstr ""
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlButton, GlFormInput } from '@gitlab/ui'; import { GlFormInput } from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue';
import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue'; import ErrorTrackingForm from '~/error_tracking_settings/components/error_tracking_form.vue';
import createStore from '~/error_tracking_settings/store'; import createStore from '~/error_tracking_settings/store';
import { defaultProps } from '../mock'; import { defaultProps } from '../mock';
...@@ -42,7 +43,7 @@ describe('error tracking settings form', () => { ...@@ -42,7 +43,7 @@ describe('error tracking settings form', () => {
.attributes('id'), .attributes('id'),
).toBe('error-tracking-token'); ).toBe('error-tracking-token');
expect(wrapper.findAll(GlButton).exists()).toBe(true); expect(wrapper.findAll(LoadingButton).exists()).toBe(true);
}); });
it('is rendered with labels and placeholders', () => { it('is rendered with labels and placeholders', () => {
...@@ -63,6 +64,18 @@ describe('error tracking settings form', () => { ...@@ -63,6 +64,18 @@ describe('error tracking settings form', () => {
}); });
}); });
describe('loading projects', () => {
beforeEach(() => {
store.state.isLoadingProjects = true;
});
it('shows loading spinner', () => {
const { label, loading } = wrapper.find(LoadingButton).props();
expect(loading).toBe(true);
expect(label).toBe('Connecting');
});
});
describe('after a successful connection', () => { describe('after a successful connection', () => {
beforeEach(() => { beforeEach(() => {
store.state.connectSuccessful = true; store.state.connectSuccessful = true;
......
...@@ -69,7 +69,14 @@ describe('error tracking settings actions', () => { ...@@ -69,7 +69,14 @@ describe('error tracking settings actions', () => {
}); });
it('should request projects correctly', done => { it('should request projects correctly', done => {
testAction(actions.requestProjects, null, state, [{ type: types.RESET_CONNECT }], [], done); testAction(
actions.requestProjects,
null,
state,
[{ type: types.SET_PROJECTS_LOADING, payload: true }, { type: types.RESET_CONNECT }],
[],
done,
);
}); });
it('should receive projects correctly', done => { it('should receive projects correctly', done => {
...@@ -81,6 +88,7 @@ describe('error tracking settings actions', () => { ...@@ -81,6 +88,7 @@ describe('error tracking settings actions', () => {
[ [
{ type: types.UPDATE_CONNECT_SUCCESS }, { type: types.UPDATE_CONNECT_SUCCESS },
{ type: types.RECEIVE_PROJECTS, payload: testPayload }, { type: types.RECEIVE_PROJECTS, payload: testPayload },
{ type: types.SET_PROJECTS_LOADING, payload: false },
], ],
[], [],
done, done,
...@@ -93,7 +101,11 @@ describe('error tracking settings actions', () => { ...@@ -93,7 +101,11 @@ describe('error tracking settings actions', () => {
actions.receiveProjectsError, actions.receiveProjectsError,
testPayload, testPayload,
state, state,
[{ type: types.UPDATE_CONNECT_ERROR }, { type: types.CLEAR_PROJECTS }], [
{ type: types.UPDATE_CONNECT_ERROR },
{ type: types.CLEAR_PROJECTS },
{ type: types.SET_PROJECTS_LOADING, payload: false },
],
[], [],
done, done,
); );
......
...@@ -31,7 +31,7 @@ describe Gitlab::Metrics::RequestsRackMiddleware do ...@@ -31,7 +31,7 @@ describe Gitlab::Metrics::RequestsRackMiddleware do
end end
it 'measures execution time' do it 'measures execution time' do
expect(described_class).to receive_message_chain(:http_request_duration_seconds, :observe).with({ status: 200, method: 'get' }, a_positive_execution_time) expect(described_class).to receive_message_chain(:http_request_duration_seconds, :observe).with({ status: '200', method: 'get' }, a_positive_execution_time)
Timecop.scale(3600) { subject.call(env) } Timecop.scale(3600) { subject.call(env) }
end end
...@@ -69,7 +69,7 @@ describe Gitlab::Metrics::RequestsRackMiddleware do ...@@ -69,7 +69,7 @@ describe Gitlab::Metrics::RequestsRackMiddleware do
expected_labels = [] expected_labels = []
described_class::HTTP_METHODS.each do |method, statuses| described_class::HTTP_METHODS.each do |method, statuses|
statuses.each do |status| statuses.each do |status|
expected_labels << { method: method, status: status.to_i } expected_labels << { method: method, status: status.to_s }
end end
end end
......
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