Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-04-23 00:10:00 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-04-23 00:10:00 +0300
commit22e60f1c61443a7efd8a2334f61556d19d6630be (patch)
tree57ffc5cda535d1d664f84689c1d42855334fb410
parentdb061f44328ca45f713eaf22d92aae8e76148fda (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.rubocop_todo.yml12
-rw-r--r--app/assets/javascripts/boards/components/board_column.vue2
-rw-r--r--app/assets/javascripts/boards/constants.js2
-rw-r--r--app/assets/javascripts/ide/stores/mutations.js5
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/dashboard_panel.vue (renamed from app/assets/javascripts/monitoring/components/panel_type.vue)39
-rw-r--r--app/assets/javascripts/monitoring/components/embeds/metric_embed.vue8
-rw-r--r--app/assets/javascripts/monitoring/components/panel_type_with_alerts.vue55
-rw-r--r--app/assets/javascripts/pages/admin/services/edit/index.js9
-rw-r--r--app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue2
-rw-r--r--app/assets/javascripts/search_autocomplete.js2
-rw-r--r--app/finders/projects_finder.rb4
-rw-r--r--app/helpers/namespaces_helper.rb4
-rw-r--r--changelogs/unreleased/208171-clicking-on-search-results-does-not-follow-link.yml5
-rw-r--r--changelogs/unreleased/213239-fix-newly-added-deleted-files-in-ide.yml5
-rw-r--r--changelogs/unreleased/214007-example-expiration-regex.yml5
-rw-r--r--changelogs/unreleased/215041-active-checkbox-not-showing-on-service-templates-form.yml5
-rw-r--r--doc/api/api_resources.md2
-rw-r--r--doc/api/metrics_dashboard_annotations.md1
-rw-r--r--doc/ci/yaml/README.md10
-rw-r--r--doc/development/documentation/styleguide.md3
-rw-r--r--doc/user/packages/container_registry/img/expiration-policy-app.pngbin32054 -> 0 bytes
-rw-r--r--doc/user/packages/container_registry/img/expiration_policy_app_v13_0.pngbin0 -> 59340 bytes
-rw-r--r--doc/user/packages/container_registry/index.md2
-rw-r--r--doc/user/project/integrations/prometheus.md18
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata/entry.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/qa/page/project/operations/metrics/show.rb2
-rw-r--r--spec/features/ide/user_commits_changes_spec.rb10
-rw-r--r--spec/frontend/ide/stores/mutations_spec.js4
-rw-r--r--spec/frontend/monitoring/components/dashboard_panel_spec.js (renamed from spec/frontend/monitoring/components/panel_type_spec.js)61
-rw-r--r--spec/frontend/monitoring/components/dashboard_spec.js45
-rw-r--r--spec/frontend/monitoring/components/dashboard_url_time_spec.js2
-rw-r--r--spec/frontend/monitoring/components/embeds/metric_embed_spec.js10
-rw-r--r--spec/frontend/monitoring/components/panel_type_with_alerts_spec.js73
-rw-r--r--spec/javascripts/search_autocomplete_spec.js24
-rw-r--r--spec/requests/api/pipeline_schedules_spec.rb2
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/helpers/features/web_ide_spec_helpers.rb14
39 files changed, 251 insertions, 214 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 344a880760e..bd0f9184cd6 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -613,18 +613,6 @@ Style/StringLiteralsInInterpolation:
Style/SymbolProc:
Enabled: false
-# Offense count: 7
-# Cop supports --auto-correct.
-# Configuration parameters: EnforcedStyle, AllowSafeAssignment.
-# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
-Style/TernaryParentheses:
- Exclude:
- - 'app/finders/projects_finder.rb'
- - 'app/helpers/namespaces_helper.rb'
- - 'lib/gitlab/ci/build/artifacts/metadata/entry.rb'
- - 'spec/requests/api/pipeline_schedules_spec.rb'
- - 'spec/support/capybara.rb'
-
# Offense count: 99
# Cop supports --auto-correct.
Style/UnneededInterpolation:
diff --git a/app/assets/javascripts/boards/components/board_column.vue b/app/assets/javascripts/boards/components/board_column.vue
index 10c855675db..faecd77d598 100644
--- a/app/assets/javascripts/boards/components/board_column.vue
+++ b/app/assets/javascripts/boards/components/board_column.vue
@@ -353,7 +353,7 @@ export default {
v-if="isSettingsShown"
ref="settingsBtn"
:aria-label="__(`List settings`)"
- class="no-drag rounded-right"
+ class="no-drag rounded-right js-board-settings-button"
title="List settings"
type="button"
@click="openSidebarSettings"
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index dcecfe5e1bb..40f79a44b51 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -8,6 +8,8 @@ export const ListType = {
blank: 'blank',
};
+export const inactiveListId = 0;
+
export default {
ListType,
};
diff --git a/app/assets/javascripts/ide/stores/mutations.js b/app/assets/javascripts/ide/stores/mutations.js
index 49485f4d575..5d567d9b169 100644
--- a/app/assets/javascripts/ide/stores/mutations.js
+++ b/app/assets/javascripts/ide/stores/mutations.js
@@ -216,7 +216,12 @@ export default {
if (entry.type === 'blob') {
if (tempFile) {
+ // Since we only support one list of file changes, it's safe to just remove from both
+ // changed and staged. Otherwise, we'd need to somehow evaluate the difference between
+ // changed and HEAD.
+ // https://gitlab.com/gitlab-org/create-stage/-/issues/12669
state.changedFiles = state.changedFiles.filter(f => f.path !== path);
+ state.stagedFiles = state.stagedFiles.filter(f => f.path !== path);
} else {
state.changedFiles = state.changedFiles.concat(entry);
}
diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue
index 85306023d7d..571da30675d 100644
--- a/app/assets/javascripts/monitoring/components/dashboard.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard.vue
@@ -14,7 +14,7 @@ import {
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
-import PanelType from './panel_type_with_alerts.vue';
+import DashboardPanel from './dashboard_panel.vue';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -37,7 +37,7 @@ import { defaultTimeRange, timeRanges } from '~/vue_shared/constants';
export default {
components: {
VueDraggable,
- PanelType,
+ DashboardPanel,
Icon,
GlDeprecatedButton,
GlDropdown,
@@ -558,7 +558,7 @@ export default {
>
<div
v-for="(graphData, graphIndex) in groupData.panels"
- :key="`panel-type-${graphIndex}`"
+ :key="`dashboard-panel-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
>
@@ -573,7 +573,7 @@ export default {
</a>
</div>
- <panel-type
+ <dashboard-panel
:clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
diff --git a/app/assets/javascripts/monitoring/components/panel_type.vue b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
index eed41b94cd3..7b09c78aae2 100644
--- a/app/assets/javascripts/monitoring/components/panel_type.vue
+++ b/app/assets/javascripts/monitoring/components/dashboard_panel.vue
@@ -26,6 +26,7 @@ import MonitorBarChart from './charts/bar.vue';
import MonitorStackedColumnChart from './charts/stacked_column.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
+import AlertWidget from './alert_widget.vue';
import { timeRangeToUrl, downloadCSVOptions, generateLinkToChartOptions } from '../utils';
const events = {
@@ -40,6 +41,7 @@ export default {
MonitorColumnChart,
MonitorBarChart,
MonitorStackedColumnChart,
+ AlertWidget,
GlIcon,
GlLoadingIcon,
GlTooltip,
@@ -78,11 +80,22 @@ export default {
required: false,
default: 'monitoringDashboard',
},
+ alertsEndpoint: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ prometheusAlertsAvailable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
showTitleTooltip: false,
zoomedTimeRange: null,
+ allAlerts: {},
};
},
computed: {
@@ -104,14 +117,13 @@ export default {
timeRange(state) {
return state[this.namespace].timeRange;
},
+ metricsSavedToDb(state, getters) {
+ return getters[`${this.namespace}/metricsSavedToDb`];
+ },
}),
title() {
return this.graphData.title || '';
},
- alertWidgetAvailable() {
- // This method is extended by ee functionality
- return false;
- },
graphDataHasResult() {
return (
this.graphData.metrics &&
@@ -165,6 +177,18 @@ export default {
editCustomMetricLinkText() {
return n__('Metrics|Edit metric', 'Metrics|Edit metrics', this.graphData.metrics.length);
},
+ hasMetricsInDb() {
+ const { metrics = [] } = this.graphData;
+ return metrics.some(({ metricId }) => this.metricsSavedToDb.includes(metricId));
+ },
+ alertWidgetAvailable() {
+ return (
+ this.prometheusAlertsAvailable &&
+ this.alertsEndpoint &&
+ this.graphData &&
+ this.hasMetricsInDb
+ );
+ },
},
mounted() {
this.refreshTitleTooltip();
@@ -200,6 +224,13 @@ export default {
this.zoomedTimeRange = { start, end };
this.$emit(events.timeRangeZoom, { start, end });
},
+ setAlerts(alertPath, alertAttributes) {
+ if (alertAttributes) {
+ this.$set(this.allAlerts, alertPath, alertAttributes);
+ } else {
+ this.$delete(this.allAlerts, alertPath);
+ }
+ },
},
panelTypes,
};
diff --git a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
index 129de6cc2f6..1557a49137e 100644
--- a/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
+++ b/app/assets/javascripts/monitoring/components/embeds/metric_embed.vue
@@ -1,6 +1,6 @@
<script>
import { mapState, mapActions } from 'vuex';
-import PanelType from '~/monitoring/components/panel_type_with_alerts.vue';
+import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { convertToFixedRange } from '~/lib/utils/datetime_range';
import { defaultTimeRange } from '~/vue_shared/constants';
import { timeRangeFromUrl, removeTimeRangeParams } from '../../utils';
@@ -10,7 +10,7 @@ let sidebarMutationObserver;
export default {
components: {
- PanelType,
+ DashboardPanel,
},
props: {
containerClass: {
@@ -113,9 +113,9 @@ export default {
</script>
<template>
<div class="metrics-embed p-0 d-flex flex-wrap" :class="embedClass">
- <panel-type
+ <dashboard-panel
v-for="(graphData, graphIndex) in charts"
- :key="`panel-type-${graphIndex}`"
+ :key="`dashboard-panel-${graphIndex}`"
:class="panelClass"
:graph-data="graphData"
:group-id="dashboardUrl"
diff --git a/app/assets/javascripts/monitoring/components/panel_type_with_alerts.vue b/app/assets/javascripts/monitoring/components/panel_type_with_alerts.vue
deleted file mode 100644
index ca81242af2e..00000000000
--- a/app/assets/javascripts/monitoring/components/panel_type_with_alerts.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<script>
-import { mapGetters } from 'vuex';
-import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
-import CePanelType from '~/monitoring/components/panel_type.vue';
-import AlertWidget from './alert_widget.vue';
-
-export default {
- components: {
- AlertWidget,
- CustomMetricsFormFields,
- },
- extends: CePanelType,
- props: {
- alertsEndpoint: {
- type: String,
- required: false,
- default: null,
- },
- prometheusAlertsAvailable: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- allAlerts: {},
- };
- },
- computed: {
- ...mapGetters('monitoringDashboard', ['metricsSavedToDb']),
- hasMetricsInDb() {
- const { metrics = [] } = this.graphData;
- return metrics.some(({ metricId }) => this.metricsSavedToDb.includes(metricId));
- },
- alertWidgetAvailable() {
- return (
- this.prometheusAlertsAvailable &&
- this.alertsEndpoint &&
- this.graphData &&
- this.hasMetricsInDb
- );
- },
- },
- methods: {
- setAlerts(alertPath, alertAttributes) {
- if (alertAttributes) {
- this.$set(this.allAlerts, alertPath, alertAttributes);
- } else {
- this.$delete(this.allAlerts, alertPath);
- }
- },
- },
-};
-</script>
diff --git a/app/assets/javascripts/pages/admin/services/edit/index.js b/app/assets/javascripts/pages/admin/services/edit/index.js
new file mode 100644
index 00000000000..e5e80d2f566
--- /dev/null
+++ b/app/assets/javascripts/pages/admin/services/edit/index.js
@@ -0,0 +1,9 @@
+import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initAlertsSettings from '~/alerts_service_settings';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+ integrationSettingsForm.init();
+
+ initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
+});
diff --git a/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue b/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
index 3e212f09e35..26dfd11b55c 100644
--- a/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
+++ b/app/assets/javascripts/registry/shared/components/expiration_policy_fields.vue
@@ -182,7 +182,7 @@ export default {
<gl-sprintf
:message="
s__(
- 'ContainerRegistry|Wildcards such as %{codeStart}.*-stable%{codeEnd} or %{codeStart}production/.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
+ 'ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}',
)
"
>
diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js
index cacaa585b5d..d8eb981c106 100644
--- a/app/assets/javascripts/search_autocomplete.js
+++ b/app/assets/javascripts/search_autocomplete.js
@@ -407,7 +407,7 @@ export class SearchAutocomplete {
disableAutocomplete() {
if (!this.searchInput.hasClass('js-autocomplete-disabled') && this.dropdown.hasClass('show')) {
this.searchInput.addClass('js-autocomplete-disabled');
- this.dropdown.dropdown('toggle');
+ this.dropdownToggle.dropdown('toggle');
this.restoreMenu();
}
}
diff --git a/app/finders/projects_finder.rb b/app/finders/projects_finder.rb
index 3a84600b09f..8846ff54eb2 100644
--- a/app/finders/projects_finder.rb
+++ b/app/finders/projects_finder.rb
@@ -151,11 +151,11 @@ class ProjectsFinder < UnionFinder
end
def by_personal(items)
- (params[:personal].present? && current_user) ? items.personal(current_user) : items
+ params[:personal].present? && current_user ? items.personal(current_user) : items
end
def by_starred(items)
- (params[:starred].present? && current_user) ? items.starred_by(current_user) : items
+ params[:starred].present? && current_user ? items.starred_by(current_user) : items
end
def by_trending(items)
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 9de28fb3ed9..228dc2cc27f 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -80,8 +80,8 @@ module NamespacesHelper
visibility_level: n.visibility_level_value,
visibility: n.visibility,
name: n.name,
- show_path: (type == 'group') ? group_path(n) : user_path(n),
- edit_path: (type == 'group') ? edit_group_path(n) : nil
+ show_path: type == 'group' ? group_path(n) : user_path(n),
+ edit_path: type == 'group' ? edit_group_path(n) : nil
}]
end
diff --git a/changelogs/unreleased/208171-clicking-on-search-results-does-not-follow-link.yml b/changelogs/unreleased/208171-clicking-on-search-results-does-not-follow-link.yml
new file mode 100644
index 00000000000..0ef8666e10e
--- /dev/null
+++ b/changelogs/unreleased/208171-clicking-on-search-results-does-not-follow-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fix an issue where the Search dropdown results would not be clickable.
+merge_request: 30087
+author: mbergeron
+type: fixed
diff --git a/changelogs/unreleased/213239-fix-newly-added-deleted-files-in-ide.yml b/changelogs/unreleased/213239-fix-newly-added-deleted-files-in-ide.yml
new file mode 100644
index 00000000000..ae346e7f507
--- /dev/null
+++ b/changelogs/unreleased/213239-fix-newly-added-deleted-files-in-ide.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Web IDE handling of deleting newly added files
+merge_request: 29783
+author:
+type: fixed
diff --git a/changelogs/unreleased/214007-example-expiration-regex.yml b/changelogs/unreleased/214007-example-expiration-regex.yml
new file mode 100644
index 00000000000..43db738ed0f
--- /dev/null
+++ b/changelogs/unreleased/214007-example-expiration-regex.yml
@@ -0,0 +1,5 @@
+---
+title: Update the example regex in the image expiration policy UI
+merge_request: 29348
+author:
+type: changed
diff --git a/changelogs/unreleased/215041-active-checkbox-not-showing-on-service-templates-form.yml b/changelogs/unreleased/215041-active-checkbox-not-showing-on-service-templates-form.yml
new file mode 100644
index 00000000000..84ff3d7b68d
--- /dev/null
+++ b/changelogs/unreleased/215041-active-checkbox-not-showing-on-service-templates-form.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Service Templates missing Active toggle
+merge_request: 29936
+author:
+type: fixed
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index c871e57666f..34b4bf934bc 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -132,7 +132,7 @@ The following API resources are available outside of project and group contexts
| [License](license.md) **(CORE ONLY)** | `/license` |
| [Markdown](markdown.md) | `/markdown` |
| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
-| [Metrics dashboard annotations](metrics_dashboard_annotations.md) | `/environments/:id/metrics_dashboard/annotations` |
+| [Metrics dashboard annotations](metrics_dashboard_annotations.md) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` |
| [Namespaces](namespaces.md) | `/namespaces` |
| [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) |
| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
diff --git a/doc/api/metrics_dashboard_annotations.md b/doc/api/metrics_dashboard_annotations.md
index d8a018fe6c3..8cfd4dc8eed 100644
--- a/doc/api/metrics_dashboard_annotations.md
+++ b/doc/api/metrics_dashboard_annotations.md
@@ -18,6 +18,7 @@ Feature.enable(:metrics_dashboard_annotations)
```plaintext
POST /environments/:id/metrics_dashboard/annotations/
+POST /clusters/:id/metrics_dashboard/annotations/
```
Parameters:
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 9da1224a9b9..f7d9430433e 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -107,7 +107,7 @@ The following table lists available parameters for jobs:
| [`when`](#when) | When to run job. Also available: `when:manual` and `when:delayed`. |
| [`environment`](#environment) | Name of an environment to which the job deploys. Also available: `environment:name`, `environment:url`, `environment:on_stop`, `environment:auto_stop_in` and `environment:action`. |
| [`cache`](#cache) | List of files that should be cached between subsequent runs. Also available: `cache:paths`, `cache:key`, `cache:untracked`, and `cache:policy`. |
-| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, `artifacts:reports:junit`, and `artifacts:reports:cobertura`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_management`, `artifacts:reports:performance` and `artifacts:reports:metrics`. |
+| [`artifacts`](#artifacts) | List of files and directories to attach to a job on success. Also available: `artifacts:paths`, `artifacts:expose_as`, `artifacts:name`, `artifacts:untracked`, `artifacts:when`, `artifacts:expire_in`, `artifacts:reports`, `artifacts:reports:junit`, `artifacts:reports:cobertura`, and `artifacts:reports:terraform`.<br><br>In GitLab [Enterprise Edition](https://about.gitlab.com/pricing/), these are available: `artifacts:reports:codequality`, `artifacts:reports:sast`, `artifacts:reports:dependency_scanning`, `artifacts:reports:container_scanning`, `artifacts:reports:dast`, `artifacts:reports:license_management`, `artifacts:reports:performance` and `artifacts:reports:metrics`. |
| [`dependencies`](#dependencies) | Restrict which artifacts are passed to a specific job by providing a list of jobs to fetch artifacts from. |
| [`coverage`](#coverage) | Code coverage settings for a given job. |
| [`retry`](#retry) | When and how many times a job can be auto-retried in case of a failure. |
@@ -3004,6 +3004,14 @@ and will be automatically shown in merge requests.
Cobertura was originally developed for Java, but there are many
third party ports for other languages like JavaScript, Python, Ruby, etc.
+##### `artifacts:reports:terraform`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/207527) in GitLab 12.10. Requires [GitLab Runner](https://docs.gitlab.com/runner/) 11.5 and above.
+
+The `terraform` report collects Terraform `tfplan.json` files. The
+collected Terraform plan reports will be uploaded to GitLab as
+artifacts and will be automatically shown in merge requests.
+
##### `artifacts:reports:codequality` **(STARTER)**
> Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above.
diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md
index 3431456363b..d6f4289e4b5 100644
--- a/doc/development/documentation/styleguide.md
+++ b/doc/development/documentation/styleguide.md
@@ -300,6 +300,9 @@ as even native users of English might misunderstand them.
- Instead of "i.e.," use "that is."
- Instead of "e.g.," use "for example," "such as," "for instance," or "like."
- Instead of "etc.," either use "and so on" or consider editing it out, since it can be vague.
+- Avoid using the word *Currently* when talking about the product or its
+ features. The documentation describes the product as it is, and not as it
+ will be at some indeterminate point in the future.
### Contractions
diff --git a/doc/user/packages/container_registry/img/expiration-policy-app.png b/doc/user/packages/container_registry/img/expiration-policy-app.png
deleted file mode 100644
index e2d3d668e38..00000000000
--- a/doc/user/packages/container_registry/img/expiration-policy-app.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/packages/container_registry/img/expiration_policy_app_v13_0.png b/doc/user/packages/container_registry/img/expiration_policy_app_v13_0.png
new file mode 100644
index 00000000000..a38014a2b9b
--- /dev/null
+++ b/doc/user/packages/container_registry/img/expiration_policy_app_v13_0.png
Binary files differ
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 5505a4503ca..9d50c23b780 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -511,7 +511,7 @@ then goes through a process of excluding tags from it until only the ones to be
To manage project expiration policy, navigate to **{settings}** **Settings > CI/CD > Container Registry tag expiration policy**.
-![Expiration Policy App](img/expiration-policy-app.png)
+![Expiration Policy App](img/expiration_policy_app_v13_0.png)
The UI allows you to configure the following:
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index 82e2dfaaca2..6b8ec3c4abd 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -123,6 +123,24 @@ to integrate with.
1. Provide the domain name or IP address of your server, for example `http://thanos.example.com/` or `http://192.0.2.1/`.
1. Click **Save changes**.
+### Precedence with multiple Prometheus configurations
+
+Although you can enable both a [manual configuration](#manual-configuration-of-prometheus)
+and [auto configuration](#managed-prometheus-on-kubernetes) of Prometheus, only
+one of them will be used:
+
+- If you have enabled a
+ [Prometheus manual configuration](#manual-configuration-of-prometheus)
+ and a [managed Prometheus on Kubernetes](#managed-prometheus-on-kubernetes),
+ the manual configuration takes precedence and is used to run queries from
+ [dashboards](#defining-custom-dashboards-per-project) and [custom metrics](#adding-custom-metrics).
+- If you have managed Prometheus applications installed on Kubernetes clusters
+ at **different** levels (project, group, instance), the order of precedence is described in
+ [Cluster precedence](../../instance/clusters/index.md#cluster-precedence).
+- If you have managed Prometheus applications installed on multiple Kubernetes
+ clusters at the **same** level, the Prometheus application of a cluster with a
+ matching [environment scope](../../../ci/environments.md#scoping-environments-with-specs) is used.
+
## Monitoring CI/CD Environments
Once configured, GitLab will attempt to retrieve performance metrics for any
diff --git a/lib/gitlab/ci/build/artifacts/metadata/entry.rb b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
index 80e69cdcc95..ef354832e8e 100644
--- a/lib/gitlab/ci/build/artifacts/metadata/entry.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata/entry.rb
@@ -50,7 +50,7 @@ module Gitlab
end
def basename
- (directory? && !blank_node?) ? name + '/' : name
+ directory? && !blank_node? ? name + '/' : name
end
def name
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 17227e32548..11e0b54f4eb 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -5600,6 +5600,9 @@ msgstr ""
msgid "ContainerRegistry|Quick Start"
msgstr ""
+msgid "ContainerRegistry|Regular expressions such as %{codeStart}.*-test%{codeEnd} or %{codeStart}dev-.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
+msgstr ""
+
msgid "ContainerRegistry|Remove repository"
msgstr ""
@@ -5686,9 +5689,6 @@ msgstr ""
msgid "ContainerRegistry|We are having trouble connecting to Docker, which could be due to an issue with your project name or path. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
-msgid "ContainerRegistry|Wildcards such as %{codeStart}.*-stable%{codeEnd} or %{codeStart}production/.*%{codeEnd} are supported. To select all tags, use %{codeStart}.*%{codeEnd}"
-msgstr ""
-
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr ""
diff --git a/qa/qa/page/project/operations/metrics/show.rb b/qa/qa/page/project/operations/metrics/show.rb
index 020a3a1d5f8..d44b31aebf9 100644
--- a/qa/qa/page/project/operations/metrics/show.rb
+++ b/qa/qa/page/project/operations/metrics/show.rb
@@ -21,7 +21,7 @@ module QA
element :duplicate_dashboard_filename_field
end
- view 'app/assets/javascripts/monitoring/components/panel_type.vue' do
+ view 'app/assets/javascripts/monitoring/components/dashboard_panel.vue' do
element :prometheus_graph_widgets
element :prometheus_widgets_dropdown
element :alert_widget_menu_item
diff --git a/spec/features/ide/user_commits_changes_spec.rb b/spec/features/ide/user_commits_changes_spec.rb
index f53abde1523..56f2c6b8afc 100644
--- a/spec/features/ide/user_commits_changes_spec.rb
+++ b/spec/features/ide/user_commits_changes_spec.rb
@@ -30,4 +30,14 @@ describe 'IDE user commits changes', :js do
expect(project.repository.blob_at('master', 'foo/bar/.gitkeep')).to be_nil
expect(project.repository.blob_at('master', 'foo/bar/lorem_ipsum.md').data).to eql(content)
end
+
+ it 'user adds then deletes new file' do
+ ide_create_new_file('foo/bar/lorem_ipsum.md')
+
+ expect(page).to have_selector(ide_commit_tab_selector)
+
+ ide_delete_file('foo/bar/lorem_ipsum.md')
+
+ expect(page).not_to have_selector(ide_commit_tab_selector)
+ end
end
diff --git a/spec/frontend/ide/stores/mutations_spec.js b/spec/frontend/ide/stores/mutations_spec.js
index d9ce59ad378..5d0fe35a10e 100644
--- a/spec/frontend/ide/stores/mutations_spec.js
+++ b/spec/frontend/ide/stores/mutations_spec.js
@@ -273,7 +273,7 @@ describe('Multi-file store mutations', () => {
expect(localState.changedFiles).toEqual([]);
});
- it('removes tempFile from changedFiles when deleted', () => {
+ it('removes tempFile from changedFiles and stagedFiles when deleted', () => {
localState.entries.filePath = {
path: 'filePath',
deleted: false,
@@ -282,10 +282,12 @@ describe('Multi-file store mutations', () => {
};
localState.changedFiles.push({ ...localState.entries.filePath });
+ localState.stagedFiles.push({ ...localState.entries.filePath });
mutations.DELETE_ENTRY(localState, 'filePath');
expect(localState.changedFiles).toEqual([]);
+ expect(localState.stagedFiles).toEqual([]);
});
it('bursts unused seal', () => {
diff --git a/spec/frontend/monitoring/components/panel_type_spec.js b/spec/frontend/monitoring/components/dashboard_panel_spec.js
index 753d5caba69..3c0292e016d 100644
--- a/spec/frontend/monitoring/components/panel_type_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_panel_spec.js
@@ -1,10 +1,13 @@
+import Vuex from 'vuex';
import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { setTestTimeout } from 'helpers/timeout';
import invalidUrl from '~/lib/utils/invalid_url';
import axios from '~/lib/utils/axios_utils';
+import { GlDropdownItem } from '@gitlab/ui';
+import AlertWidget from '~/monitoring/components/alert_widget.vue';
-import PanelType from '~/monitoring/components/panel_type.vue';
+import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import {
anomalyMockGraphData,
mockLogsHref,
@@ -40,7 +43,7 @@ const mocks = {
},
};
-describe('Panel Type component', () => {
+describe('Dashboard Panel', () => {
let axiosMock;
let store;
let state;
@@ -54,7 +57,7 @@ describe('Panel Type component', () => {
const findContextualMenu = () => wrapper.find({ ref: 'contextualMenu' });
const createWrapper = props => {
- wrapper = shallowMount(PanelType, {
+ wrapper = shallowMount(DashboardPanel, {
propsData: {
graphData,
...props,
@@ -343,7 +346,7 @@ describe('Panel Type component', () => {
describe('when downloading metrics data as CSV', () => {
beforeEach(() => {
- wrapper = shallowMount(PanelType, {
+ wrapper = shallowMount(DashboardPanel, {
propsData: {
clipboardText: exampleText,
graphData: {
@@ -392,7 +395,7 @@ describe('Panel Type component', () => {
store.registerModule(mockNamespace, monitoringDashboard);
store.state.embedGroup.modules.push(mockNamespace);
- wrapper = shallowMount(PanelType, {
+ wrapper = shallowMount(DashboardPanel, {
propsData: {
graphData,
namespace: mockNamespace,
@@ -432,4 +435,52 @@ describe('Panel Type component', () => {
expect(wrapper.find(MonitorTimeSeriesChart).exists()).toBe(true);
});
});
+
+ describe('panel alerts', () => {
+ const setMetricsSavedToDb = val =>
+ monitoringDashboard.getters.metricsSavedToDb.mockReturnValue(val);
+ const findAlertsWidget = () => wrapper.find(AlertWidget);
+ const findMenuItemAlert = () =>
+ wrapper.findAll(GlDropdownItem).filter(i => i.text() === 'Alerts');
+
+ beforeEach(() => {
+ jest.spyOn(monitoringDashboard.getters, 'metricsSavedToDb').mockReturnValue([]);
+
+ store = new Vuex.Store({
+ modules: {
+ monitoringDashboard,
+ },
+ });
+
+ createWrapper();
+ });
+
+ describe.each`
+ desc | metricsSavedToDb | propsData | isShown
+ ${'with permission and no metrics in db'} | ${[]} | ${{}} | ${false}
+ ${'with permission and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{}} | ${true}
+ ${'without permission and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{ prometheusAlertsAvailable: false }} | ${false}
+ ${'with permission and unrelated metrics in db'} | ${['another_metric_id']} | ${{}} | ${false}
+ `('$desc', ({ metricsSavedToDb, isShown, propsData }) => {
+ const showsDesc = isShown ? 'shows' : 'does not show';
+
+ beforeEach(() => {
+ setMetricsSavedToDb(metricsSavedToDb);
+ createWrapper({
+ alertsEndpoint: '/endpoint',
+ prometheusAlertsAvailable: true,
+ ...propsData,
+ });
+ return wrapper.vm.$nextTick();
+ });
+
+ it(`${showsDesc} alert widget`, () => {
+ expect(findAlertsWidget().exists()).toBe(isShown);
+ });
+
+ it(`${showsDesc} alert configuration`, () => {
+ expect(findMenuItemAlert().exists()).toBe(isShown);
+ });
+ });
+ });
});
diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js
index ad48874014e..d8c9af59f90 100644
--- a/spec/frontend/monitoring/components/dashboard_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_spec.js
@@ -12,7 +12,7 @@ import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_p
import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue';
import DashboardsDropdown from '~/monitoring/components/dashboards_dropdown.vue';
import GroupEmptyState from '~/monitoring/components/group_empty_state.vue';
-import PanelType from '~/monitoring/components/panel_type_with_alerts.vue';
+import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { createStore } from '~/monitoring/stores';
import * as types from '~/monitoring/stores/mutation_types';
import { setupStoreWithDashboard, setMetricResult, setupStoreWithData } from '../store_utils';
@@ -48,6 +48,7 @@ describe('Dashboard', () => {
fetchData: jest.fn(),
},
store,
+ stubs: ['graph-group', 'dashboard-panel'],
...options,
});
};
@@ -126,10 +127,7 @@ describe('Dashboard', () => {
});
it('hides the group panels when showPanels is false', () => {
- createMountedWrapper(
- { hasMetrics: true, showPanels: false },
- { stubs: ['graph-group', 'panel-type'] },
- );
+ createMountedWrapper({ hasMetrics: true, showPanels: false });
setupStoreWithData(wrapper.vm.$store);
@@ -142,7 +140,7 @@ describe('Dashboard', () => {
it('fetches the metrics data with proper time window', () => {
jest.spyOn(store, 'dispatch');
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
wrapper.vm.$store.commit(
`monitoringDashboard/${types.RECEIVE_ENVIRONMENTS_DATA_SUCCESS}`,
@@ -157,7 +155,7 @@ describe('Dashboard', () => {
describe('when all requests have been commited by the store', () => {
beforeEach(() => {
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
setupStoreWithData(wrapper.vm.$store);
@@ -186,7 +184,7 @@ describe('Dashboard', () => {
});
it('hides the environments dropdown list when there is no environments', () => {
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
setupStoreWithDashboard(wrapper.vm.$store);
@@ -196,7 +194,7 @@ describe('Dashboard', () => {
});
it('renders the datetimepicker dropdown', () => {
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
setupStoreWithData(wrapper.vm.$store);
@@ -206,7 +204,7 @@ describe('Dashboard', () => {
});
it('renders the refresh dashboard button', () => {
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
setupStoreWithData(wrapper.vm.$store);
@@ -249,13 +247,7 @@ describe('Dashboard', () => {
describe('searchable environments dropdown', () => {
beforeEach(() => {
- createMountedWrapper(
- { hasMetrics: true },
- {
- attachToDocument: true,
- stubs: ['graph-group', 'panel-type'],
- },
- );
+ createMountedWrapper({ hasMetrics: true }, { attachToDocument: true });
setupStoreWithData(wrapper.vm.$store);
@@ -465,7 +457,7 @@ describe('Dashboard', () => {
describe('Dashboard dropdown', () => {
beforeEach(() => {
- createMountedWrapper({ hasMetrics: true }, { stubs: ['graph-group', 'panel-type'] });
+ createMountedWrapper({ hasMetrics: true });
wrapper.vm.$store.commit(
`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`,
@@ -484,15 +476,12 @@ describe('Dashboard', () => {
describe('external dashboard link', () => {
beforeEach(() => {
- createMountedWrapper(
- {
- hasMetrics: true,
- showPanels: false,
- showTimeWindowDropdown: false,
- externalDashboardUrl: '/mockUrl',
- },
- { stubs: ['graph-group', 'panel-type'] },
- );
+ createMountedWrapper({
+ hasMetrics: true,
+ showPanels: false,
+ showTimeWindowDropdown: false,
+ externalDashboardUrl: '/mockUrl',
+ });
return wrapper.vm.$nextTick();
});
@@ -511,7 +500,7 @@ describe('Dashboard', () => {
const getClipboardTextAt = i =>
wrapper
- .findAll(PanelType)
+ .findAll(DashboardPanel)
.at(i)
.props('clipboardText');
diff --git a/spec/frontend/monitoring/components/dashboard_url_time_spec.js b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
index 65e9d036d1a..9bba5280007 100644
--- a/spec/frontend/monitoring/components/dashboard_url_time_spec.js
+++ b/spec/frontend/monitoring/components/dashboard_url_time_spec.js
@@ -27,7 +27,7 @@ describe('dashboard invalid url parameters', () => {
wrapper = mount(Dashboard, {
propsData: { ...propsData, ...props },
store,
- stubs: ['graph-group', 'panel-type'],
+ stubs: ['graph-group', 'dashboard-panel'],
...options,
});
};
diff --git a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
index b6734ede63e..f23823ccad6 100644
--- a/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
+++ b/spec/frontend/monitoring/components/embeds/metric_embed_spec.js
@@ -1,6 +1,6 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
-import PanelType from '~/monitoring/components/panel_type_with_alerts.vue';
+import DashboardPanel from '~/monitoring/components/dashboard_panel.vue';
import { TEST_HOST } from 'helpers/test_constants';
import MetricEmbed from '~/monitoring/components/embeds/metric_embed.vue';
import { groups, initialState, metricsData, metricsWithData } from './mock_data';
@@ -62,7 +62,7 @@ describe('MetricEmbed', () => {
it('shows an empty state when no metrics are present', () => {
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
- expect(wrapper.find(PanelType).exists()).toBe(false);
+ expect(wrapper.find(DashboardPanel).exists()).toBe(false);
});
});
@@ -90,12 +90,12 @@ describe('MetricEmbed', () => {
it('shows a chart when metrics are present', () => {
expect(wrapper.find('.metrics-embed').exists()).toBe(true);
- expect(wrapper.find(PanelType).exists()).toBe(true);
- expect(wrapper.findAll(PanelType).length).toBe(2);
+ expect(wrapper.find(DashboardPanel).exists()).toBe(true);
+ expect(wrapper.findAll(DashboardPanel).length).toBe(2);
});
it('includes groupId with dashboardUrl', () => {
- expect(wrapper.find(PanelType).props('groupId')).toBe(TEST_HOST);
+ expect(wrapper.find(DashboardPanel).props('groupId')).toBe(TEST_HOST);
});
});
});
diff --git a/spec/frontend/monitoring/components/panel_type_with_alerts_spec.js b/spec/frontend/monitoring/components/panel_type_with_alerts_spec.js
deleted file mode 100644
index 3374fe4b55f..00000000000
--- a/spec/frontend/monitoring/components/panel_type_with_alerts_spec.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import Vuex from 'vuex';
-import { shallowMount } from '@vue/test-utils';
-import { GlDropdownItem } from '@gitlab/ui';
-import { monitoringDashboard } from '~/monitoring/stores';
-import PanelType from '~/monitoring/components/panel_type_with_alerts.vue';
-import AlertWidget from '~/monitoring/components/alert_widget.vue';
-import { graphData } from 'jest/monitoring/fixture_data';
-
-global.URL.createObjectURL = jest.fn();
-
-describe('Panel Type', () => {
- let store;
- let wrapper;
-
- const setMetricsSavedToDb = val =>
- monitoringDashboard.getters.metricsSavedToDb.mockReturnValue(val);
- const findAlertsWidget = () => wrapper.find(AlertWidget);
- const findMenuItemAlert = () =>
- wrapper.findAll(GlDropdownItem).filter(i => i.text() === 'Alerts');
-
- const mockPropsData = {
- graphData,
- clipboardText: 'example_text',
- alertsEndpoint: '/endpoint',
- prometheusAlertsAvailable: true,
- };
-
- const createWrapper = propsData => {
- wrapper = shallowMount(PanelType, {
- propsData: {
- ...mockPropsData,
- ...propsData,
- },
- store,
- });
- };
-
- beforeEach(() => {
- jest.spyOn(monitoringDashboard.getters, 'metricsSavedToDb').mockReturnValue([]);
-
- store = new Vuex.Store({
- modules: {
- monitoringDashboard,
- },
- });
- });
-
- describe('panel type alerts', () => {
- describe.each`
- desc | metricsSavedToDb | propsData | isShown
- ${'with license and no metrics in db'} | ${[]} | ${{}} | ${false}
- ${'with license and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{}} | ${true}
- ${'without license and related metrics in db'} | ${[graphData.metrics[0].metricId]} | ${{ prometheusAlertsAvailable: false }} | ${false}
- ${'with license and unrelated metrics in db'} | ${['another_metric_id']} | ${{}} | ${false}
- `('$desc', ({ metricsSavedToDb, isShown, propsData }) => {
- const showsDesc = isShown ? 'shows' : 'does not show';
-
- beforeEach(() => {
- setMetricsSavedToDb(metricsSavedToDb);
- createWrapper(propsData);
- return wrapper.vm.$nextTick();
- });
-
- it(`${showsDesc} alert widget`, () => {
- expect(findAlertsWidget().exists()).toBe(isShown);
- });
-
- it(`${showsDesc} alert configuration`, () => {
- expect(findMenuItemAlert().exists()).toBe(isShown);
- });
- });
- });
-});
diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js
index e9bc1fc51e8..4f42d4880e8 100644
--- a/spec/javascripts/search_autocomplete_spec.js
+++ b/spec/javascripts/search_autocomplete_spec.js
@@ -188,4 +188,28 @@ describe('Search autocomplete dropdown', () => {
// example) on JavaScript-created keypresses.
expect(submitSpy).not.toHaveBeenTriggered();
});
+
+ describe('disableAutocomplete', function() {
+ beforeEach(function() {
+ widget.enableAutocomplete();
+ });
+
+ it('should close the Dropdown', function() {
+ const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
+
+ widget.dropdown.addClass('show');
+ widget.disableAutocomplete();
+
+ expect(toggleSpy).toHaveBeenCalledWith('toggle');
+ });
+ });
+
+ describe('enableAutocomplete', function() {
+ it('should open the Dropdown', function() {
+ const toggleSpy = spyOn(widget.dropdownToggle, 'dropdown');
+ widget.enableAutocomplete();
+
+ expect(toggleSpy).toHaveBeenCalledWith('toggle');
+ });
+ });
});
diff --git a/spec/requests/api/pipeline_schedules_spec.rb b/spec/requests/api/pipeline_schedules_spec.rb
index 14b292db045..98eaf36b14e 100644
--- a/spec/requests/api/pipeline_schedules_spec.rb
+++ b/spec/requests/api/pipeline_schedules_spec.rb
@@ -67,7 +67,7 @@ describe API::PipelineSchedules do
end
def active?(str)
- (str == 'active') ? true : false
+ str == 'active'
end
end
end
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index 90adfb1a2ee..e80b69e4fd5 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -7,7 +7,7 @@ require 'capybara-screenshot/rspec'
require 'selenium-webdriver'
# Give CI some extra time
-timeout = (ENV['CI'] || ENV['CI_SERVER']) ? 60 : 30
+timeout = ENV['CI'] || ENV['CI_SERVER'] ? 60 : 30
# Define an error class for JS console messages
JSConsoleError = Class.new(StandardError)
diff --git a/spec/support/helpers/features/web_ide_spec_helpers.rb b/spec/support/helpers/features/web_ide_spec_helpers.rb
index 37c8345a4e5..123bd9b5070 100644
--- a/spec/support/helpers/features/web_ide_spec_helpers.rb
+++ b/spec/support/helpers/features/web_ide_spec_helpers.rb
@@ -32,6 +32,10 @@ module WebIdeSpecHelpers
page.find('.ide-tree-actions')
end
+ def ide_tab_selector(mode)
+ ".js-ide-#{mode}-mode"
+ end
+
def ide_file_row_open?(row)
row.matches_css?('.is-open')
end
@@ -106,16 +110,16 @@ module WebIdeSpecHelpers
evaluate_script("monaco.editor.getModel('#{uri}').getValue()")
end
+ def ide_commit_tab_selector
+ ide_tab_selector('commit')
+ end
+
def ide_commit
- ide_switch_mode('commit')
+ find(ide_commit_tab_selector).click
commit_to_current_branch
end
- def ide_switch_mode(mode)
- find(".js-ide-#{mode}-mode").click
- end
-
private
def file_row_container(row)