Commit 93dcf45d authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 0e68afab
......@@ -394,6 +394,7 @@ export default {
>
<dashboards-dropdown
id="monitor-dashboards-dropdown"
data-qa-selector="dashboards_filter_dropdown"
class="mb-0 d-flex"
toggle-class="dropdown-menu-toggle"
:default-branch="defaultBranch"
......@@ -458,6 +459,7 @@ export default {
label-size="sm"
label-for="monitor-time-window-dropdown"
class="col-sm-auto col-md-auto col-lg-auto"
data-qa-selector="show_last_dropdown"
>
<date-time-picker
ref="dateTimePicker"
......@@ -533,6 +535,7 @@ export default {
v-if="selectedDashboard.can_edit"
class="mt-1 js-edit-link"
:href="selectedDashboard.project_blob_path"
data-qa-selector="edit_dashboard_button"
>{{ __('Edit dashboard') }}</gl-button
>
......
......@@ -92,8 +92,7 @@ export default {
<p class="text-muted">
{{
s__(`Metrics|You can save a copy of this dashboard to your repository
so it can be customized. Select a file name and branch to
save it.`)
so it can be customized. Select a file name and branch to save it.`)
}}
</p>
<gl-form-group
......@@ -104,7 +103,13 @@ export default {
label-size="sm"
label-for="fileName"
>
<gl-form-input id="fileName" ref="fileName" v-model="form.fileName" :required="true" />
<gl-form-input
id="fileName"
ref="fileName"
v-model="form.fileName"
data-qa-selector="duplicate_dashboard_filename_field"
:required="true"
/>
</gl-form-group>
<gl-form-group :label="__('Branch')" label-size="sm" label-for="branch">
<gl-form-radio-group
......
import IntegrationSettingsForm from '~/integrations/integration_settings_form';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
import PrometheusAlerts from '~/prometheus_alerts';
import initAlertsSettings from '~/alerts_service_settings';
document.addEventListener('DOMContentLoaded', () => {
......@@ -12,5 +13,6 @@ document.addEventListener('DOMContentLoaded', () => {
prometheusMetrics.loadActiveMetrics();
}
PrometheusAlerts();
initAlertsSettings(document.querySelector('.js-alerts-service-settings'));
});
<script>
import { GlButton, GlFormGroup, GlFormInput, GlModal, GlModalDirective } from '@gitlab/ui';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import axios from '~/lib/utils/axios_utils';
import { __, sprintf } from '~/locale';
import createFlash from '~/flash';
export default {
copyToClipboard: __('Copy'),
components: {
GlButton,
GlFormGroup,
GlFormInput,
GlModal,
ClipboardButton,
},
directives: {
'gl-modal': GlModalDirective,
},
props: {
initialAuthorizationKey: {
type: String,
required: false,
default: '',
},
changeKeyUrl: {
type: String,
required: true,
},
notifyUrl: {
type: String,
required: true,
},
learnMoreUrl: {
type: String,
required: true,
},
},
data() {
return {
authorizationKey: this.initialAuthorizationKey,
sectionDescription: sprintf(
__(
'To receive alerts from manually configured Prometheus services, add the following URL and Authorization key to your Prometheus webhook config file. Learn more about %{linkStart}configuring Prometheus%{linkEnd} to send alerts to GitLab.',
),
{
linkStart: `<a href="${this.learnMoreUrl}" target="_blank" rel="noopener noreferrer">`,
linkEnd: '</a>',
},
false,
),
};
},
methods: {
resetKey() {
axios
.post(this.changeKeyUrl)
.then(res => {
this.authorizationKey = res.data.token;
})
.catch(() => {
createFlash(__('Failed to reset key. Please try again.'));
});
},
},
};
</script>
<template>
<div class="row py-4 border-top js-prometheus-alerts">
<div class="col-lg-3">
<h4 class="mt-0">
{{ __('Alerts') }}
</h4>
<p>
{{ __('Receive alerts from manually configured Prometheus servers.') }}
</p>
</div>
<div class="col-lg-9">
<p v-html="sectionDescription"></p>
<gl-form-group :label="__('URL')" label-for="notify-url" label-class="label-bold">
<div class="input-group">
<gl-form-input id="notify-url" :readonly="true" :value="notifyUrl" />
<span class="input-group-append">
<clipboard-button :text="notifyUrl" :title="$options.copyToClipboard" />
</span>
</div>
</gl-form-group>
<gl-form-group
:label="__('Authorization key')"
label-for="authorization-key"
label-class="label-bold"
>
<div class="input-group">
<gl-form-input id="authorization-key" :readonly="true" :value="authorizationKey" />
<span class="input-group-append">
<clipboard-button :text="authorizationKey" :title="$options.copyToClipboard" />
</span>
</div>
</gl-form-group>
<template v-if="authorizationKey.length > 0">
<gl-modal
modal-id="authKeyModal"
:title="__('Reset authorization key?')"
:ok-title="__('Reset authorization key')"
ok-variant="danger"
@ok="resetKey"
>
{{
__(
'Resetting the authorization key will invalidate the previous key. Existing alert configurations will need to be updated with the new key.',
)
}}
</gl-modal>
<gl-button v-gl-modal.authKeyModal class="js-reset-auth-key">{{
__('Reset key')
}}</gl-button>
</template>
<gl-button v-else class="js-reset-auth-key" @click="resetKey">{{
__('Generate key')
}}</gl-button>
</div>
</div>
</template>
import Vue from 'vue';
import ResetKey from './components/reset_key.vue';
export default () => {
const el = document.querySelector('#js-settings-prometheus-alerts');
if (!el) {
return;
}
const { authorizationKey, changeKeyUrl, notifyUrl, learnMoreUrl } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
el,
render(createElement) {
return createElement(ResetKey, {
props: {
initialAuthorizationKey: authorizationKey,
changeKeyUrl,
notifyUrl,
learnMoreUrl,
},
});
},
});
};
......@@ -1583,13 +1583,6 @@ class User < ApplicationRecord
end
def read_only_attribute?(attribute)
if Feature.enabled?(:ldap_readonly_attributes, default_enabled: true)
enabled = Gitlab::Auth::Ldap::Config.enabled?
read_only = attribute.to_sym.in?(UserSyncedAttributesMetadata::SYNCABLE_ATTRIBUTES)
return true if enabled && read_only
end
user_synced_attributes_metadata&.read_only?(attribute)
end
......
......@@ -60,11 +60,7 @@ module Users
end
def discard_read_only_attributes
if Feature.enabled?(:ldap_readonly_attributes, default_enabled: true)
params.reject! { |key, _| @user.read_only_attribute?(key.to_sym) }
else
discard_synced_attributes
end
discard_synced_attributes
end
def discard_synced_attributes
......
......@@ -162,4 +162,6 @@
= render_if_exists "groups/ee/settings_nav"
= render_if_exists "groups/ee/administration_nav"
= render 'shared/sidebar_toggle_button'
- return unless can?(current_user, :read_prometheus_alerts, @project)
- return unless @service.manual_configuration?
- notify_url = notify_project_prometheus_alerts_url(@project, format: :json)
- authorization_key = @project.alerting_setting.try(:token)
- learn_more_url = help_page_path('user/project/integrations/prometheus', anchor: 'external-prometheus-instances')
#js-settings-prometheus-alerts{ data: { notify_url: notify_url, authorization_key: authorization_key, change_key_url: reset_alerting_token_project_settings_operations_path(@project), learn_more_url: learn_more_url } }
......@@ -6,4 +6,4 @@
.row.append-bottom-default.prometheus-metrics-monitoring.js-prometheus-metrics-monitoring
= render 'projects/services/prometheus/metrics', project: @project
= render_if_exists 'projects/services/prometheus/external_alerts', project: @project
= render 'projects/services/prometheus/external_alerts', project: @project
---
title: Revert LDAP readonly attributes feature
merge_request: 28541
author:
type: removed
---
title: Move Alerting feature to Core
merge_request: 28196
author:
type: changed
# frozen_string_literal: true
class RemoveHealthStatusFromEpics < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
with_lock_retries do
remove_column :epics, :health_status
end
end
def down
with_lock_retries do
add_column :epics, :health_status, :integer, limit: 2
end
end
end
......@@ -2271,7 +2271,6 @@ CREATE TABLE public.epics (
state_id smallint DEFAULT 1 NOT NULL,
start_date_sourcing_epic_id integer,
due_date_sourcing_epic_id integer,
health_status smallint,
external_key character varying(255)
);
......@@ -12819,6 +12818,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200226100614
20200226100624
20200226100634
20200226124757
20200226162156
20200226162239
20200226162634
......
......@@ -38,6 +38,24 @@ SCIM mapping:
![Azure AD SCIM](img/AzureAD-scim_attribute_mapping.png)
## Okta
Basic SAML app configuration:
![Okta basic SAML](img/Okta-SAMLsetup.png)
User claims and attributes:
![Okta Attributes](img/Okta-attributes.png)
Advanced SAML app settings (defaults):
![Okta Advanced Settings](img/Okta-advancedsettings.png)
IdP Links and Certificate:
![Okta Links and Certificate](img/Okta-linkscert.png)
## OneLogin
Application details:
......
......@@ -173,7 +173,7 @@ To see the status of your GitLab.com subscription, log into GitLab.com and go to
1. Go to **User Avatar > Settings**.
1. Click **Billing**.
- For groups:
1. From the group page (*not* from a project within the group), go to **Settings > Billing**.
1. From the group page (*not* from a project within the group), go to **Administration > Billing**.
The following table describes details of your subscription for groups:
......@@ -427,7 +427,7 @@ CI pipeline minutes are the execution time for your [pipelines](../ci/pipelines/
Quotas apply to:
- Groups, where the minutes are shared across all members of the group, its subgroups, and nested projects. To view the group's usage, navigate to the group, then **{settings}** **Settings > Usage Quotas**.
- Groups, where the minutes are shared across all members of the group, its subgroups, and nested projects. To view the group's usage, navigate to the group, then **{settings}** **Administration > Usage Quotas**.
- Your personal account, where the minutes are available for your personal projects. To view and buy personal minutes, click your avatar, then **{settings}** **Settings > Pipeline quota**.
Only pipeline minutes for GitLab shared runners are restricted. If you have a specific runner set up for your projects, there is no limit to your build time on GitLab.com.
......@@ -448,10 +448,10 @@ main quota. Additional minutes:
To purchase additional minutes for your group on GitLab.com:
1. From your group, go to **{settings}** **Settings > Usage Quotas**.
1. From your group, go to **{settings}** **Administration > Usage Quotas**.
1. Locate the subscription card that's linked to your group on GitLab.com, click **Buy more CI minutes**, and complete the details about the transaction.
1. Once we have processed your payment, the extra CI minutes will be synced to your group.
1. To confirm the available CI minutes, go to your group, then **{settings}** **Settings > Usage Quotas**.
1. To confirm the available CI minutes, go to your group, then **{settings}** **Administration > Usage Quotas**.
The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
To purchase additional minutes for your personal namespace:
......
......@@ -255,6 +255,8 @@ configured to act as a remote proxy and add the `Gitlab-DAST-Permission` header.
### API scan
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10928) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
Using an API specification as a scan's target is a useful way to seed URLs for scanning an API.
Vulnerability rules in an API scan are different than those in a normal website scan.
......
......@@ -24,7 +24,7 @@ Note the following:
## Configuring your Identity Provider
1. Navigate to the group and click **Settings > SAML SSO**.
1. Navigate to the group and click **Administration > SAML SSO**.
1. Configure your SAML server using the **Assertion consumer service URL** and **Identifier**. Alternatively GitLab provides [metadata XML configuration](#metadata-configuration). See [your identity provider's documentation](#providers) for more details.
1. Configure the SAML response to include a NameID that uniquely identifies each user.
1. Configure required assertions using the [table below](#assertions).
......@@ -116,7 +116,7 @@ This feature is similar to the [Credentials inventory for self-managed instances
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/34648) in GitLab 12.9.
Groups with group-managed accounts can disallow forking of projects to destinations outside the group.
To do so, enable the "Prohibit outer forks" option in **Settings > SAML SSO**.
To do so, enable the "Prohibit outer forks" option in **Administration > SAML SSO**.
When enabled, projects within the group can only be forked to other destinations within the group (including its subgroups).
##### Other restrictions for Group-managed accounts
......@@ -146,7 +146,7 @@ assertions to be able to create a user.
GitLab provides metadata XML that can be used to configure your Identity Provider.
1. Navigate to the group and click **Settings > SAML SSO**.
1. Navigate to the group and click **Administration > SAML SSO**.
1. Copy the provided **GitLab metadata URL**.
1. Follow your Identity Provider's documentation and paste the metadata URL when it is requested.
......@@ -154,7 +154,7 @@ GitLab provides metadata XML that can be used to configure your Identity Provide
Once you've set up your identity provider to work with GitLab, you'll need to configure GitLab to use it for authentication:
1. Navigate to the group's **Settings > SAML SSO**.
1. Navigate to the group's **Administration > SAML SSO**.
1. Find the SSO URL from your Identity Provider and enter it the **Identity provider single sign on URL** field.
1. Find and enter the fingerprint for the SAML token signing certificate in the **Certificate** field.
1. Click the **Enable SAML authentication for this group** toggle switch.
......@@ -234,6 +234,13 @@ Set other user attributes and claims according to the [assertions table](#assert
Under Okta's **Single sign on URL** field, check the option **Use this for Recipient URL and Destination URL**.
Please note that Okta's generic SAML app does not have a **Login URL** field, where the **Identity provider single sign on URL** would normally go. The **Identity provider single sign on URL** may be required the first time a user is logging in if they are having any difficulties.
We recommend:
- **Application username** (NameID) set to **Custom** `user.getInternalProperty("id")`.
- **Name ID Format** set to **Persistent**.
Set attribute statements according to the [assertions table](#assertions).
### OneLogin setup notes
......@@ -281,14 +288,14 @@ If the information information you need isn't listed above you may wish to check
To link SAML to your existing GitLab.com account:
1. Sign in to your GitLab.com account.
1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on the group's **Settings > SAML SSO** page.
1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on the group's **Administration > SAML SSO** page.
1. Visit the SSO URL and click **Authorize**.
1. Enter your credentials on the Identity Provider if prompted.
1. You will be redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com.
## Signing in to GitLab.com with SAML
1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on a group's **Settings > SAML SSO** page. If configured, it might also be possible to sign in to GitLab starting from your Identity Provider.
1. Locate the SSO URL for the group you are signing in to. A group Admin can find this on a group's **Administration > SAML SSO** page. If configured, it might also be possible to sign in to GitLab starting from your Identity Provider.
1. Visit the SSO URL and click the **Sign in with Single Sign-On** button.
1. Enter your credentials on the Identity Provider if prompted.
1. You will be signed in to GitLab.com and redirected to the group.
......
......@@ -30,7 +30,7 @@ The following identity providers are supported:
Once [Single sign-on](index.md) has been configured, we can:
1. Navigate to the group and click **Settings > SAML SSO**.
1. Navigate to the group and click **Administration > SAML SSO**.
1. Click on the **Generate a SCIM token** button.
1. Save the token and URL so they can be used in the next step.
......
......@@ -671,7 +671,8 @@ To remove the alert, click back on the alert icon for the desired metric, and cl
#### External Prometheus instances
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
>- [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9258) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.8.
>- [Moved](https://gitlab.com/gitlab-org/gitlab/issues/42640) to [GitLab Core](https://about.gitlab.com/pricing/) in 12.10.
For manually configured Prometheus servers, a notify endpoint is provided to use with Prometheus webhooks. If you have manual configuration enabled, an **Alerts** section is added to **Settings > Integrations > Prometheus**. This contains the *URL* and *Authorization Key*. The **Reset Key** button will invalidate the key and generate a new one.
......
......@@ -99,6 +99,7 @@ module Gitlab
projects_with_repositories_enabled: count(ProjectFeature.where('repository_access_level > ?', ProjectFeature::DISABLED)),
projects_with_error_tracking_enabled: count(::ErrorTracking::ProjectErrorTrackingSetting.where(enabled: true)),
projects_with_alerts_service_enabled: count(AlertsService.active),
projects_with_prometheus_alerts: distinct_count(PrometheusAlert, :project_id),
protected_branches: count(ProtectedBranch),
releases: count(Release),
remote_mirrors: count(RemoteMirror),
......
......@@ -1584,6 +1584,9 @@ msgstr ""
msgid "AdminUsers|You are about to permanently delete the user %{username}. This will delete all of the issues, merge requests, and groups linked to them. To avoid data loss, consider using the %{strong_start}block user%{strong_end} feature instead. Once you %{strong_start}Delete user%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "Administration"
msgstr ""
msgid "Advanced"
msgstr ""
......@@ -7364,9 +7367,6 @@ msgstr ""
msgid "Email display name"
msgstr ""
msgid "Email domain is not editable in subgroups. Value inherited from top-level parent group."
msgstr ""
msgid "Email not verified. Please verify your email in Salesforce."
msgstr ""
......@@ -8675,6 +8675,9 @@ msgstr ""
msgid "FeatureFlags|Active"
msgstr ""
msgid "FeatureFlags|Add strategy"
msgstr ""
msgid "FeatureFlags|All users"
msgstr ""
......@@ -8699,6 +8702,9 @@ msgstr ""
msgid "FeatureFlags|Edit Feature Flag"
msgstr ""
msgid "FeatureFlags|Enable features for specific users and specific environments by defining feature flag strategies. By default, features are available to all users in all environments."
msgstr ""
msgid "FeatureFlags|Environment Spec"
msgstr ""
......@@ -8711,6 +8717,9 @@ msgstr ""
msgid "FeatureFlags|Feature Flag behavior is built up by creating a set of rules to define the status of target environments. A default wildcard rule %{codeStart}*%{codeEnd} for %{boldStart}All Environments%{boldEnd} is set, and you are able to add as many rules as you need by choosing environment specs below. You can toggle the behavior for each of your rules to set them %{boldStart}Active%{boldEnd} or %{boldStart}Inactive%{boldEnd}."
msgstr ""
msgid "FeatureFlags|Feature Flag has no strategies"
msgstr ""
msgid "FeatureFlags|Feature Flags"
msgstr ""
......@@ -8780,6 +8789,9 @@ msgstr ""
msgid "FeatureFlags|Status"
msgstr ""
msgid "FeatureFlags|Strategies"
msgstr ""
msgid "FeatureFlags|Target environments"
msgstr ""
......@@ -10683,9 +10695,6 @@ msgstr ""
msgid "IP Address"
msgstr ""
msgid "IP address restriction is not editable in subgroups. Value inherited from top-level parent group."
msgstr ""
msgid "IP subnet restriction only allowed for top-level groups"
msgstr ""
......@@ -13499,9 +13508,6 @@ msgstr ""
msgid "No thanks, don't show this again"
msgstr ""
msgid "No value set by top-level parent group."
msgstr ""
msgid "No vulnerabilities found for this group"
msgstr ""
......
......@@ -22,7 +22,7 @@ variables:
stages:
- production
# This job continuously deploys to production on every push to `master`.
# This job continuously deploys to staging/production on every push to `master`.
production:
stage: production
......
......@@ -11,6 +11,14 @@ module QA
view 'app/assets/javascripts/monitoring/components/dashboard.vue' do
element :prometheus_graphs
element :dashboards_filter_dropdown
element :environments_dropdown
element :edit_dashboard_button
element :show_last_dropdown
end
view 'app/assets/javascripts/monitoring/components/duplicate_dashboard_form.vue' do
element :duplicate_dashboard_filename_field
end
view 'app/assets/javascripts/monitoring/components/panel_type.vue' do
......@@ -35,6 +43,35 @@ module QA
end
end
def has_edit_dashboard_enabled?
within_element :prometheus_graphs do
has_element? :edit_dashboard_button
end
end
def duplicate_dashboard(save_as = 'test_duplication.yml', commit_option = 'Commit to master branch')
click_element :dashboards_filter_dropdown
click_on 'Duplicate dashboard'
fill_element :duplicate_dashboard_filename_field, save_as
choose commit_option
within('.modal-content') { click_button(class: 'btn-success') }
end
def filter_environment(environment = 'production')
click_element :environments_dropdown
within_element :environments_dropdown do
click_link_with_text environment
end
end
def show_last(range = '8 hours')
click_element :show_last_dropdown
within_element :show_last_dropdown do
click_on range
end
end
private
def wait_for_data
......
......@@ -25,7 +25,7 @@ module QA::Page
end
def wait_for_latest_pipeline_status
wait_until(reload: false, max_duration: 300) do
wait_until(reload: false, max_duration: 360) do
within_element_by_index(:pipeline_commit_status, 0) { yield }
end
end
......
# frozen_string_literal: true
module QA
# Git protocol v2 is temporarily disabled
context 'Create', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/issues/27828', type: :bug } do
context 'Create' do
describe 'Push over SSH using Git protocol version 2', :requires_git_protocol_v2 do
# Note: If you run this test against GDK make sure you've enabled sshd and
# enabled setting the Git protocol by adding `AcceptEnv GIT_PROTOCOL` to
......
# frozen_string_literal: true
module QA
context 'Monitor' do
describe 'Dashboards', :orchestrated, :kubernetes, quarantine: { type: :new } do
before(:all) do
@cluster = Service::KubernetesCluster.new.create!
Flow::Login.sign_in
create_project_to_monitor
wait_for_deployment
end
before do
Flow::Login.sign_in_unless_signed_in
@project.visit!
end
after(:all) do
@cluster&.remove!
end
it 'duplicates to create dashboard to custom' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |dashboard|
dashboard.duplicate_dashboard
expect(dashboard).to have_metrics
expect(dashboard).to have_edit_dashboard_enabled
end
end
it 'verifies data on filtered deployed environment' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |dashboard|
dashboard.filter_environment
expect(dashboard).to have_metrics
end
end
it 'filters using the quick range' do
Page::Project::Menu.perform(&:go_to_operations_metrics)
Page::Project::Operations::Metrics::Show.perform do |dashboard|
dashboard.show_last('30 minutes')
expect(dashboard).to have_metrics
dashboard.show_last('3 hours')
expect(dashboard).to have_metrics
dashboard.show_last('1 day')
expect(dashboard).to have_metrics
end
end
private
def wait_for_deployment
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
Page::Project::Pipeline::Index.perform(&:wait_for_latest_pipeline_success_or_retry)
Page::Project::Menu.perform(&:go_to_operations_metrics)
end
def create_project_to_monitor
@project = Resource::Project.fabricate_via_api! do |project|
project.name = 'cluster-with-prometheus'
project.description = 'Cluster with Prometheus'
end
@cluster_props = Resource::KubernetesCluster.fabricate_via_browser_ui! do |cluster_settings|
cluster_settings.project = @project
cluster_settings.cluster = @cluster
cluster_settings.install_helm_tiller = true
cluster_settings.install_ingress = true
cluster_settings.install_prometheus = true
end
Resource::CiVariable.fabricate_via_api! do |ci_variable|
ci_variable.project = @project
ci_variable.key = 'AUTO_DEVOPS_DOMAIN'
ci_variable.value = @cluster_props.ingress_ip
ci_variable.masked = false
end
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = @project
push.directory = Pathname
.new(__dir__)
.join('../../../../../fixtures/monitored_auto_devops')
push.commit_message = 'Create AutoDevOps compatible Project for Monitoring'
end
end
end
end
end
---
title: Remove health_status column from epics
merge_request: 26302
author:
type: other
......@@ -26,6 +26,9 @@ FactoryBot.define do
create_list(:issue, 2, project: projects[0], author: User.alert_bot)
create_list(:issue, 2, project: projects[1], author: User.alert_bot)
create_list(:issue, 4, project: projects[0])
create(:prometheus_alert, project: projects[0])
create(:prometheus_alert, project: projects[0])
create(:prometheus_alert, project: projects[1])
create(:zoom_meeting, project: projects[0], issue: projects[0].issues[0], issue_status: :added)
create_list(:zoom_meeting, 2, project: projects[0], issue: projects[0].issues[1], issue_status: :removed)
create(:zoom_meeting, project: projects[0], issue: projects[0].issues[2], issue_status: :added)
......
# frozen_string_literal: true
require 'spec_helper'
describe 'Prometheus external alerts', :js do
let(:project) { create(:project) }
let(:user) { create(:user) }
let(:alerts_section_selector) { '.js-prometheus-alerts' }
let(:alerts_section) { page.find(alerts_section_selector) }
before do
sign_in(user)
project.add_maintainer(user)
visit_edit_service
end
context 'with manual configuration' do
before do
create(:prometheus_service, project: project, api_url: 'http://prometheus.example.com', manual_configuration: '1', active: true)
end
it 'shows the Alerts section' do
visit_edit_service
expect(alerts_section).to have_content('Alerts')
expect(alerts_section).to have_content('Receive alerts from manually configured Prometheus servers.')
expect(alerts_section).to have_content('URL')
expect(alerts_section).to have_content('Authorization key')
end
end
context 'with no configuration' do
it 'does not show the Alerts section' do
wait_for_requests
expect(page).not_to have_css(alerts_section_selector)
end
end
private
def visit_edit_service
visit(project_settings_integrations_path(project))
click_link('Prometheus')
end
end
......@@ -19,6 +19,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
>
<dashboards-dropdown-stub
class="mb-0 d-flex"
data-qa-selector="dashboards_filter_dropdown"
defaultbranch="master"
id="monitor-dashboards-dropdown"
selecteddashboard="[object Object]"
......@@ -74,6 +75,7 @@ exports[`Dashboard template matches the default snapshot 1`] = `
<gl-form-group-stub
class="col-sm-auto col-md-auto col-lg-auto"
data-qa-selector="show_last_dropdown"
label="Show last"
label-for="monitor-time-window-dropdown"
label-size="sm"
......
import { shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import ResetKey from '~/prometheus_alerts/components/reset_key.vue';
import { GlModal } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import axios from '~/lib/utils/axios_utils';
describe('ResetKey', () => {
let mock;
let vm;
const propsData = {
initialAuthorizationKey: 'abcd1234',
changeKeyUrl: '/updateKeyUrl',
notifyUrl: '/root/autodevops-deploy/prometheus/alerts/notify.json',
learnMoreUrl: '/learnMore',
};
beforeEach(() => {
mock = new MockAdapter(axios);
setFixtures('<div class="flash-container"></div><div id="reset-key"></div>');
});
afterEach(() => {
mock.restore();
vm.destroy();
});
describe('authorization key exists', () => {
beforeEach(() => {
propsData.initialAuthorizationKey = 'abcd1234';
vm = shallowMount(ResetKey, {
propsData,
});
});
it('shows fields and buttons', () => {
expect(vm.find('#notify-url').attributes('value')).toEqual(propsData.notifyUrl);
expect(vm.find('#authorization-key').attributes('value')).toEqual(
propsData.initialAuthorizationKey,
);
expect(vm.findAll(ClipboardButton).length).toBe(2);
expect(vm.find('.js-reset-auth-key').text()).toEqual('Reset key');
});
it('reset updates key', () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find(GlModal).vm.$emit('ok');
return vm.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(vm.vm.authorizationKey).toEqual('newToken');
expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
});
it('reset key failure shows error', () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(500);
vm.find(GlModal).vm.$emit('ok');
return vm.vm
.$nextTick()
.then(waitForPromises)
.then(() => {
expect(vm.find('#authorization-key').attributes('value')).toEqual(
propsData.initialAuthorizationKey,
);
expect(document.querySelector('.flash-container').innerText.trim()).toEqual(
'Failed to reset key. Please try again.',
);
});
});
});
describe('authorization key has not been set', () => {
beforeEach(() => {
propsData.initialAuthorizationKey = '';
vm = shallowMount(ResetKey, {
propsData,
});
});
it('shows Generate Key button', () => {
expect(vm.find('.js-reset-auth-key').text()).toEqual('Generate key');
expect(vm.find('#authorization-key').attributes('value')).toEqual('');
});
it('Generate key button triggers key change', () => {
mock.onPost(propsData.changeKeyUrl).replyOnce(200, { token: 'newToken' });
vm.find('.js-reset-auth-key').vm.$emit('click');
return waitForPromises().then(() => {
expect(vm.find('#authorization-key').attributes('value')).toEqual('newToken');
});
});
});
});
......@@ -51,6 +51,7 @@ describe Gitlab::UsageData, :aggregate_failures do
expect(count_data[:projects_with_repositories_enabled]).to eq(3)
expect(count_data[:projects_with_error_tracking_enabled]).to eq(1)
expect(count_data[:projects_with_alerts_service_enabled]).to eq(1)
expect(count_data[:projects_with_prometheus_alerts]).to eq(2)
expect(count_data[:issues_created_from_gitlab_error_tracking_ui]).to eq(1)
expect(count_data[:issues_with_associated_zoom_link]).to eq(2)
expect(count_data[:issues_using_zoom_quick_actions]).to eq(3)
......
......@@ -4263,30 +4263,6 @@ describe User, :do_not_mock_admin_mode do
end
describe '#read_only_attribute?' do
context 'when LDAP server is enabled' do
before do
allow(Gitlab::Auth::Ldap::Config).to receive(:enabled?).and_return(true)
end
%i[name email location].each do |attribute|
it "is true for #{attribute}" do
expect(subject.read_only_attribute?(attribute)).to be_truthy
end
end
context 'and ldap_readonly_attributes feature is disabled' do
before do
stub_feature_flags(ldap_readonly_attributes: false)
end
%i[name email location].each do |attribute|
it "is false" do
expect(subject.read_only_attribute?(attribute)).to be_falsey
end
end
end
end
context 'when synced attributes metadata is present' do
it 'delegates to synced_attributes_metadata' do
subject.build_user_synced_attributes_metadata
......@@ -4297,7 +4273,7 @@ describe User, :do_not_mock_admin_mode do
end
end
context 'when synced attributes metadata is present' do
context 'when synced attributes metadata is not present' do
it 'is false for any attribute' do
expect(subject.read_only_attribute?(:email)).to be_falsey
end
......
......@@ -3,11 +3,15 @@
require 'spec_helper'
describe API::Pipelines do
let(:user) { create(:user) }
let(:non_member) { create(:user) }
let(:project) { create(:project, :repository, creator: user) }
let_it_be(:user) { create(:user) }
let_it_be(:non_member) { create(:user) }
let!(:pipeline) do
# We need to reload as the shared example 'pipelines visibility table' is changing project
let_it_be(:project, reload: true) do
create(:project, :repository, creator: user)
end
let_it_be(:pipeline) do
create(:ci_empty_pipeline, project: project, sha: project.commit.id,
ref: project.default_branch, user: user)
end
......@@ -26,7 +30,7 @@ describe API::Pipelines do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
expect(json_response.first['sha']).to match /\A\h{40}\z/
expect(json_response.first['sha']).to match(/\A\h{40}\z/)
expect(json_response.first['id']).to eq pipeline.id
expect(json_response.first['web_url']).to be_present
expect(json_response.first.keys).to contain_exactly(*%w[id sha ref status web_url created_at updated_at])
......@@ -438,7 +442,7 @@ describe API::Pipelines do
get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['sha']).to match /\A\h{40}\z/
expect(json_response['sha']).to match(/\A\h{40}\z/)
end
it 'returns 404 when it does not exist' do
......
......@@ -13,7 +13,6 @@ describe PrometheusAlertEntity do
context 'when user can read prometheus alerts' do
before do
prometheus_alert.project.add_maintainer(user)
stub_licensed_features(prometheus_alerts: true)
end
it 'exposes prometheus_alert attributes' do
......
......@@ -55,15 +55,6 @@ describe Users::UpdateService do
expect(result[:message]).to eq("Emoji is not included in the list")
end
it 'ignores read-only attributes' do
allow(user).to receive(:read_only_attribute?).with(:name).and_return(true)
expect do
update_user(user, name: 'changed' + user.name)
user.reload
end.not_to change { user.name }
end
it 'updates user detail with provided attributes' do
result = update_user(user, job_title: 'Backend Engineer')
......
......@@ -92,6 +92,7 @@ module UsageDataHelpers
projects_with_repositories_enabled
projects_with_error_tracking_enabled
projects_with_alerts_service_enabled
projects_with_prometheus_alerts
pages_domains
protected_branches
releases
......
......@@ -121,8 +121,16 @@ RSpec.shared_context 'group navbar structure' do
_('Projects'),
_('CI / CD'),
_('Webhooks'),
_('Audit Events'),
_('Usage Quotas')
_('Audit Events')
]
}
end
let(:administration_nav_item) do
{
nav_item: _('Administration'),
nav_sub_items: [
s_('UsageQuota|Usage Quotas')
]
}
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