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

Add latest changes from gitlab-org/gitlab@master

parent 33185181
No related branches found
No related tags found
No related merge requests found
Showing
with 84 additions and 222 deletions
Loading
Loading
@@ -11,7 +11,7 @@ import {
GlModalDirective,
GlTooltipDirective,
} from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { s__ } from '~/locale';
import createFlash from '~/flash';
import Icon from '~/vue_shared/components/icon.vue';
import { getParameterValues, mergeUrlParams, redirectTo } from '~/lib/utils/url_utility';
Loading
Loading
@@ -167,6 +167,7 @@ export default {
formIsValid: null,
selectedTimeWindow: {},
isRearrangingPanels: false,
hasValidDates: true,
};
},
computed: {
Loading
Loading
@@ -185,7 +186,9 @@ export default {
'additionalPanelTypesEnabled',
]),
firstDashboard() {
return this.allDashboards[0] || {};
return this.environmentsEndpoint.length > 0 && this.allDashboards.length > 0
? this.allDashboards[0]
: {};
},
selectedDashboard() {
return this.allDashboards.find(d => d.path === this.currentDashboard) || this.firstDashboard;
Loading
Loading
@@ -199,9 +202,6 @@ export default {
addingMetricsAvailable() {
return IS_EE && this.canAddMetrics && !this.showEmptyState;
},
alertWidgetAvailable() {
return IS_EE && this.prometheusAlertsAvailable && this.alertsEndpoint;
},
hasHeaderButtons() {
return (
this.addingMetricsAvailable ||
Loading
Loading
@@ -237,8 +237,10 @@ export default {
this.selectedTimeWindow = range;
 
if (!isValidDate(start) || !isValidDate(end)) {
this.hasValidDates = false;
this.showInvalidDateError();
} else {
this.hasValidDates = true;
this.fetchData(range);
}
}
Loading
Loading
@@ -248,44 +250,13 @@ export default {
'fetchData',
'setGettingStartedEmptyState',
'setEndpoints',
'setDashboardEnabled',
'setPanelGroupMetrics',
]),
chartsWithData(charts) {
if (!this.useDashboardEndpoint) {
return charts;
}
return charts.filter(chart =>
chart.metrics.some(metric => this.metricsWithData.includes(metric.metric_id)),
);
},
csvText(graphData) {
const chartData = graphData.queries[0].result[0].values;
const yLabel = graphData.y_label;
const header = `timestamp,${yLabel}\r\n`; // eslint-disable-line @gitlab/i18n/no-non-i18n-strings
return chartData.reduce((csv, data) => {
const row = data.join(',');
return `${csv}${row}\r\n`;
}, header);
},
downloadCsv(graphData) {
const data = new Blob([this.csvText(graphData)], { type: 'text/plain' });
return window.URL.createObjectURL(data);
},
// TODO: BEGIN, Duplicated code with panel_type until feature flag is removed
// Issue number: https://gitlab.com/gitlab-org/gitlab-foss/issues/63845
getGraphAlerts(queries) {
if (!this.allAlerts) return {};
const metricIdsForChart = queries.map(q => q.metricId);
return _.pick(this.allAlerts, alert => metricIdsForChart.includes(alert.metricId));
},
getGraphAlertValues(queries) {
return Object.values(this.getGraphAlerts(queries));
},
showToast() {
this.$toast.show(__('Link copied'));
},
// TODO: END
updateMetrics(key, metrics) {
this.setPanelGroupMetrics({
metrics,
Loading
Loading
@@ -298,6 +269,11 @@ export default {
key,
});
},
removeGraph(metrics, graphIndex) {
// At present graphs will not be removed, they should removed using the vuex store
// See https://gitlab.com/gitlab-org/gitlab/issues/27835
metrics.splice(graphIndex, 1);
},
showInvalidDateError() {
createFlash(s__('Metrics|Link contains an invalid time window.'));
},
Loading
Loading
@@ -387,7 +363,7 @@ export default {
</gl-form-group>
 
<gl-form-group
v-if="!showEmptyState"
v-if="hasValidDates"
:label="s__('Metrics|Show last')"
label-size="sm"
label-for="monitor-time-window-dropdown"
Loading
Loading
@@ -480,109 +456,40 @@ export default {
:show-panels="showPanels"
:collapse-group="groupHasData(groupData)"
>
<template v-if="additionalPanelTypesEnabled">
<vue-draggable
:value="groupData.metrics"
group="metrics-dashboard"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:disabled="!isRearrangingPanels"
@input="updateMetrics(groupData.key, $event)"
<vue-draggable
:value="groupData.metrics"
group="metrics-dashboard"
:component-data="{ attrs: { class: 'row mx-0 w-100' } }"
:disabled="!isRearrangingPanels"
@input="updateMetrics(groupData.key, $event)"
>
<div
v-for="(graphData, graphIndex) in groupData.metrics"
:key="`panel-type-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
>
<div
v-for="(graphData, graphIndex) in groupData.metrics"
:key="`panel-type-${graphIndex}`"
class="col-12 col-lg-6 px-2 mb-2 draggable"
:class="{ 'draggable-enabled': isRearrangingPanels }"
>
<div class="position-relative draggable-panel js-draggable-panel">
<div
v-if="isRearrangingPanels"
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removeMetric(groupData.key, groupData.metrics, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
><icon name="close"
/></a>
</div>
<panel-type
:clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
:prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`"
/>
<div class="position-relative draggable-panel js-draggable-panel">
<div
v-if="isRearrangingPanels"
class="draggable-remove js-draggable-remove p-2 w-100 position-absolute d-flex justify-content-end"
@click="removeGraph(groupData.metrics, graphIndex)"
>
<a class="mx-2 p-2 draggable-remove-link" :aria-label="__('Remove')"
><icon name="close"
/></a>
</div>
</div>
</vue-draggable>
</template>
<template v-else>
<monitor-time-series-chart
v-for="(graphData, graphIndex) in chartsWithData(groupData.metrics)"
:key="graphIndex"
class="col-12 col-lg-6 pb-3"
:graph-data="graphData"
:deployment-data="deploymentData"
:thresholds="getGraphAlertValues(graphData.queries)"
:project-path="projectPath"
group-id="monitor-time-series-chart"
>
<div
class="d-flex align-items-center"
:class="alertWidgetAvailable ? 'justify-content-between' : 'justify-content-end'"
>
<alert-widget
v-if="alertWidgetAvailable && graphData"
:modal-id="`alert-modal-${index}-${graphIndex}`"
<panel-type
:clipboard-text="generateLink(groupData.group, graphData.title, graphData.y_label)"
:graph-data="graphData"
:alerts-endpoint="alertsEndpoint"
:relevant-queries="graphData.queries"
:alerts-to-manage="getGraphAlerts(graphData.queries)"
@setAlerts="setAlerts"
:prometheus-alerts-available="prometheusAlertsAvailable"
:index="`${index}-${graphIndex}`"
/>
<gl-dropdown
v-gl-tooltip
class="ml-2 mr-3"
toggle-class="btn btn-transparent border-0"
:right="true"
:no-caret="true"
:title="__('More actions')"
>
<template slot="button-content">
<icon name="ellipsis_v" class="text-secondary" />
</template>
<gl-dropdown-item
v-track-event="downloadCSVOptions(graphData.title)"
:href="downloadCsv(graphData)"
download="chart_metrics.csv"
>
{{ __('Download CSV') }}
</gl-dropdown-item>
<gl-dropdown-item
v-track-event="
generateLinkToChartOptions(
generateLink(groupData.group, graphData.title, graphData.y_label),
)
"
class="js-chart-link"
:data-clipboard-text="
generateLink(groupData.group, graphData.title, graphData.y_label)
"
@click="showToast"
>
{{ __('Generate link to chart') }}
</gl-dropdown-item>
<gl-dropdown-item
v-if="alertWidgetAvailable"
v-gl-modal="`alert-modal-${index}-${graphIndex}`"
>
{{ __('Alerts') }}
</gl-dropdown-item>
</gl-dropdown>
</div>
</monitor-time-series-chart>
</template>
</div>
</vue-draggable>
</graph-group>
</div>
<empty-state
Loading
Loading
Loading
Loading
@@ -56,16 +56,10 @@ export default {
},
},
mounted() {
const range = getTimeWindow(this.selectedTimeWindow);
if (range) {
this.selectedTimeWindowText = this.timeWindows[range];
} else {
this.customTime = {
from: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.start)),
to: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.end)),
};
this.selectedTimeWindowText = sprintf(s__('%{from} to %{to}'), this.customTime);
}
this.verifyTimeRange();
},
updated() {
this.verifyTimeRange();
},
methods: {
activeTimeWindow(key) {
Loading
Loading
@@ -87,6 +81,18 @@ export default {
closeDropdown() {
this.$refs.dropdown.hide();
},
verifyTimeRange() {
const range = getTimeWindow(this.selectedTimeWindow);
if (range) {
this.selectedTimeWindowText = this.timeWindows[range];
} else {
this.customTime = {
from: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.start)),
to: truncateZerosInDateTime(ISODateToString(this.selectedTimeWindow.end)),
};
this.selectedTimeWindowText = sprintf(s__('%{from} to %{to}'), this.customTime);
}
},
},
};
</script>
Loading
Loading
Loading
Loading
@@ -78,9 +78,6 @@ export default {
}, sidebarAnimationDuration);
},
setInitialState() {
this.setFeatureFlags({
prometheusEndpointEnabled: true,
});
this.setEndpoints({
dashboardEndpoint: removeParams(['start', 'end'], this.dashboardUrl),
});
Loading
Loading
Loading
Loading
@@ -11,13 +11,6 @@ export default (props = {}) => {
const el = document.getElementById('prometheus-graphs');
 
if (el && el.dataset) {
if (gon.features) {
store.dispatch('monitoringDashboard/setFeatureFlags', {
prometheusEndpointEnabled: gon.features.environmentMetricsUsePrometheusEndpoint,
additionalPanelTypesEnabled: gon.features.environmentMetricsAdditionalPanelTypes,
});
}
const [currentDashboard] = getParameterValues('dashboard');
 
// eslint-disable-next-line no-new
Loading
Loading
Loading
Loading
@@ -35,14 +35,6 @@ export const setEndpoints = ({ commit }, endpoints) => {
commit(types.SET_ENDPOINTS, endpoints);
};
 
export const setFeatureFlags = (
{ commit },
{ prometheusEndpointEnabled, additionalPanelTypesEnabled },
) => {
commit(types.SET_DASHBOARD_ENABLED, prometheusEndpointEnabled);
commit(types.SET_ADDITIONAL_PANEL_TYPES_ENABLED, additionalPanelTypesEnabled);
};
export const setShowErrorBanner = ({ commit }, enabled) => {
commit(types.SET_SHOW_ERROR_BANNER, enabled);
};
Loading
Loading
@@ -79,29 +71,7 @@ export const fetchData = ({ dispatch }, params) => {
dispatch('fetchEnvironmentsData');
};
 
export const fetchMetricsData = ({ state, dispatch }, params) => {
if (state.useDashboardEndpoint) {
return dispatch('fetchDashboard', params);
}
dispatch('requestMetricsData');
return backOffRequest(() => axios.get(state.metricsEndpoint, { params }))
.then(resp => resp.data)
.then(response => {
if (!response || !response.data || !response.success) {
dispatch('receiveMetricsDataFailure', null);
createFlash(s__('Metrics|Unexpected metrics data response from prometheus endpoint'));
}
dispatch('receiveMetricsDataSuccess', response.data);
})
.catch(error => {
dispatch('receiveMetricsDataFailure', error);
if (state.setShowErrorBanner) {
createFlash(s__('Metrics|There was an error while retrieving metrics'));
}
});
};
export const fetchMetricsData = ({ dispatch }, params) => dispatch('fetchDashboard', params);
 
export const fetchDashboard = ({ state, dispatch }, params) => {
dispatch('requestMetricsDashboard');
Loading
Loading
Loading
Loading
@@ -9,8 +9,6 @@ export const RECEIVE_ENVIRONMENTS_DATA_SUCCESS = 'RECEIVE_ENVIRONMENTS_DATA_SUCC
export const RECEIVE_ENVIRONMENTS_DATA_FAILURE = 'RECEIVE_ENVIRONMENTS_DATA_FAILURE';
export const SET_QUERY_RESULT = 'SET_QUERY_RESULT';
export const SET_TIME_WINDOW = 'SET_TIME_WINDOW';
export const SET_DASHBOARD_ENABLED = 'SET_DASHBOARD_ENABLED';
export const SET_ADDITIONAL_PANEL_TYPES_ENABLED = 'SET_ADDITIONAL_PANEL_TYPES_ENABLED';
export const SET_ALL_DASHBOARDS = 'SET_ALL_DASHBOARDS';
export const SET_ENDPOINTS = 'SET_ENDPOINTS';
export const SET_GETTING_STARTED_EMPTY_STATE = 'SET_GETTING_STARTED_EMPTY_STATE';
Loading
Loading
Loading
Loading
@@ -25,12 +25,10 @@ export default {
// for backwards compatibility, and to limit Vue template changes:
// for each group alias panels to metrics
// for each panel alias metrics to queries
if (state.useDashboardEndpoint) {
metrics = panels.map(panel => ({
...panel,
queries: panel.metrics,
}));
}
metrics = panels.map(panel => ({
...panel,
queries: panel.metrics,
}));
 
return {
...group,
Loading
Loading
@@ -42,8 +40,6 @@ export default {
 
if (!state.dashboard.panel_groups.length) {
state.emptyState = 'noData';
} else {
state.showEmptyState = false;
}
},
[types.RECEIVE_METRICS_DATA_FAILURE](state, error) {
Loading
Loading
@@ -90,9 +86,6 @@ export default {
state.currentDashboard = endpoints.currentDashboard;
state.projectPath = endpoints.projectPath;
},
[types.SET_DASHBOARD_ENABLED](state, enabled) {
state.useDashboardEndpoint = enabled;
},
[types.SET_GETTING_STARTED_EMPTY_STATE](state) {
state.emptyState = 'gettingStarted';
},
Loading
Loading
@@ -103,9 +96,6 @@ export default {
[types.SET_ALL_DASHBOARDS](state, dashboards) {
state.allDashboards = dashboards;
},
[types.SET_ADDITIONAL_PANEL_TYPES_ENABLED](state, enabled) {
state.additionalPanelTypesEnabled = enabled;
},
[types.SET_SHOW_ERROR_BANNER](state, enabled) {
state.showErrorBanner = enabled;
},
Loading
Loading
Loading
Loading
@@ -7,8 +7,6 @@ export default () => ({
environmentsEndpoint: null,
deploymentsEndpoint: null,
dashboardEndpoint: invalidUrl,
useDashboardEndpoint: false,
additionalPanelTypesEnabled: false,
emptyState: 'gettingStarted',
showEmptyState: true,
showErrorBanner: true,
Loading
Loading
Loading
Loading
@@ -88,7 +88,7 @@ export default {
:title="tooltipText"
:class="cssClass"
:disabled="isDisabled"
class="js-ci-action btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper"
class="js-ci-action btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper d-flex align-items-center justify-content-center"
@click="onClickAction"
>
<gl-loading-icon v-if="isLoading" class="js-action-icon-loading" />
Loading
Loading
Loading
Loading
@@ -871,7 +871,7 @@ button.mini-pipeline-graph-dropdown-toggle {
height: $ci-action-dropdown-svg-size;
fill: $gl-text-color-secondary;
position: relative;
top: 1px;
top: auto;
vertical-align: initial;
}
}
Loading
Loading
Loading
Loading
@@ -13,8 +13,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
before_action :verify_api_request!, only: :terminal_websocket_authorize
before_action :expire_etag_cache, only: [:index]
before_action only: [:metrics, :additional_metrics, :metrics_dashboard] do
push_frontend_feature_flag(:environment_metrics_use_prometheus_endpoint, default_enabled: true)
push_frontend_feature_flag(:environment_metrics_additional_panel_types)
push_frontend_feature_flag(:prometheus_computed_alerts)
end
 
Loading
Loading
Loading
Loading
@@ -16,6 +16,8 @@ class GrafanaIntegration < ApplicationRecord
 
validates :enabled, inclusion: { in: [true, false] }
 
scope :enabled, -> { where(enabled: true) }
def client
return unless enabled?
 
Loading
Loading
Loading
Loading
@@ -16,7 +16,7 @@ In addition to this page, the following resources can help you craft and contrib
 
## Source files and rendered web locations
 
Documentation for GitLab, GitLab Runner, Omnibus GitLab and Charts are published to <https://docs.gitlab.com>. Documentation for GitLab is also published within the application at `/help` on the domain of the GitLab instance.
Documentation for GitLab, GitLab Runner, Omnibus GitLab and Charts is published to <https://docs.gitlab.com>. Documentation for GitLab is also published within the application at `/help` on the domain of the GitLab instance.
At `/help`, only help for your current edition and version is included. Help for other versions is available at <https://docs.gitlab.com/archives/>.
 
The source of the documentation exists within the codebase of each GitLab application in the following repository locations:
Loading
Loading
Loading
Loading
@@ -588,7 +588,7 @@ You can specify a different Git repository by providing it as an extra parameter
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse,https://example.com/gitlab-workhorse.git]" RAILS_ENV=production
```
 
### Install GitLab-Elasticsearch-indexer`
### Install GitLab-Elasticsearch-indexer
 
GitLab-Elasticsearch-Indexer uses [GNU Make](https://www.gnu.org/software/make/). The
following command-line will install GitLab-Elasticsearch-Indexer in `/home/git/gitlab-elasticsearch-indexer`
Loading
Loading
Loading
Loading
@@ -123,7 +123,7 @@ For more details on creating groups, watch the video [GitLab Namespaces (users,
## Add users to a group
 
A benefit of putting multiple projects in one group is that you can
give a user to access to all projects in the group with one action.
give a user access to all projects in the group with one action.
 
Add members to a group by navigating to the group's dashboard and clicking **Members**.
 
Loading
Loading
@@ -135,14 +135,14 @@ Consider a group with two projects:
 
- On the **Group Members** page, you can now add a new user to the group.
- Now, because this user is a **Developer** member of the group, they automatically
gets **Developer** access to **all projects** within that group.
get **Developer** access to **all projects** within that group.
 
To increase the access level of an existing user for a specific project,
add them again as a new member to the project with the desired permission level.
 
## Request access to a group
 
As a group owner, you can enable or disable the ability for non members to request access to
As a group owner, you can enable or disable the ability for non-members to request access to
your group. Go to the group settings, and click **Allow users to request access**.
 
As a user, you can request to be a member of a group, if that setting is enabled. Go to the group for which you'd like to be a member, and click the **Request Access** button on the right
Loading
Loading
@@ -356,7 +356,7 @@ Restriction currently applies to:
- [From GitLab 12.3](https://gitlab.com/gitlab-org/gitlab/issues/12874), API access.
- [From GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/issues/32113), Git actions via SSH.
 
To avoid accidental lock-out, admins and group owners are are able to access
To avoid accidental lock-out, admins and group owners are able to access
the group regardless of the IP restriction.
 
#### Allowed domain restriction **(PREMIUM)**
Loading
Loading
@@ -385,7 +385,7 @@ Some domains cannot be restricted. These are the most popular public email domai
To enable this feature:
 
1. Navigate to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section, and enter domain name into **Restrict membership by email** field.
1. Expand the **Permissions, LFS, 2FA** section, and enter the domain name into **Restrict membership by email** field.
1. Click **Save changes**.
 
This will enable the domain-checking for all new users added to the group from this moment on.
Loading
Loading
@@ -445,7 +445,7 @@ To enable this feature:
 
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/13294) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.0.
 
A group owner can check the aggregated storage usage for all the project in a group, sub-groups included, in the **Storage** tab of the **Usage Quotas** page available to the group page settings list.
A group owner can check the aggregated storage usage for all the projects in a group, sub-groups included, in the **Storage** tab of the **Usage Quotas** page available to the group page settings list.
 
![Group storage usage quota](img/group_storage_usage_quota.png)
 
Loading
Loading
Loading
Loading
@@ -405,6 +405,7 @@ GFM will recognize the following:
| label by ID | `~123` | `namespace/project~123` | `project~123` |
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
Loading
Loading
doc/user/search/img/issue_search_filter_v12_5.png

493 KiB

Loading
Loading
@@ -32,13 +32,14 @@ on the search field on the top-right of your screen:
If you want to search for issues present in a specific project, navigate to
a project's **Issues** tab, and click on the field **Search or filter results...**. It will
display a dropdown menu, from which you can add filters per author, assignee, milestone,
label, weight, and 'my-reaction' (based on your emoji votes). When done, press **Enter** on your keyboard to filter the issues.
release, label, weight, confidentiality, and "my-reaction" (based on your emoji votes).
When done, press **Enter** on your keyboard to filter the issues.
 
![filter issues in a project](img/issue_search_filter.png)
![filter issues in a project](img/issue_search_filter_v12_5.png)
 
The same process is valid for merge requests. Navigate to your project's **Merge Requests** tab,
and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
milestone, and label.
approver, milestone, release, label, "my-reaction", "work in progess" status, and target branch.
 
### Filtering by **None** / **Any**
 
Loading
Loading
.auto-deploy:
.dast-auto-deploy:
image: "registry.gitlab.com/gitlab-org/cluster-integration/auto-deploy-image:v0.4.0"
 
dast_environment_deploy:
extends: .auto-deploy
extends: .dast-auto-deploy
stage: review
script:
- auto-deploy check_kube_domain
Loading
Loading
@@ -31,7 +31,7 @@ dast_environment_deploy:
- $DAST_WEBSITE # we don't need to create a review app if a URL is already given
 
stop_dast_environment:
extends: .auto-deploy
extends: .dast-auto-deploy
stage: cleanup
variables:
GIT_STRATEGY: none
Loading
Loading
Loading
Loading
@@ -78,6 +78,7 @@ module Gitlab
clusters_applications_knative: count(::Clusters::Applications::Knative.available),
clusters_applications_elastic_stack: count(::Clusters::Applications::ElasticStack.available),
in_review_folder: count(::Environment.in_review_folder),
grafana_integrated_projects: count(GrafanaIntegration.enabled),
groups: count(Group),
issues: count(Issue),
issues_with_associated_zoom_link: count(ZoomMeeting.added_to_issue),
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment