Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-07-13 21:09:24 +00:00
parent d9aac35d79
commit 0698388e65
60 changed files with 596 additions and 219 deletions

View File

@ -1,12 +1,12 @@
<script>
import { mapGetters } from 'vuex';
import { escape } from 'lodash';
import { GlDeprecatedButton } from '@gitlab/ui';
import { GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
export default {
components: {
GlDeprecatedButton,
GlButton,
},
props: {
changesEmptyStateIllustration: {
@ -43,9 +43,9 @@ export default {
<div class="text-content text-center">
<span v-html="emptyStateText"></span>
<div class="text-center">
<gl-deprecated-button :href="getNoteableData.new_blob_path" variant="success">{{
<gl-button :href="getNoteableData.new_blob_path" variant="success" category="primary">{{
__('Create commit')
}}</gl-deprecated-button>
}}</gl-button>
</div>
</div>
</div>

View File

@ -1,8 +1,15 @@
import Vue from 'vue';
import MrWidgetOptions from 'ee_else_ce/vue_merge_request_widget/mr_widget_options.vue';
import Translate from '../vue_shared/translate';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
Vue.use(Translate);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default () => {
if (gl.mrWidget) return;
@ -10,7 +17,7 @@ export default () => {
gl.mrWidgetData.gitlabLogo = gon.gitlab_logo;
gl.mrWidgetData.defaultAvatarUrl = gon.default_avatar_url;
const vm = new Vue(MrWidgetOptions);
const vm = new Vue({ ...MrWidgetOptions, apolloProvider });
window.gl.mrWidget = {
checkStatus: vm.checkStatus,

View File

@ -360,14 +360,6 @@ table {
}
}
.toolbar-button-icon {
position: relative;
top: 1px;
margin-right: $gl-padding-4;
color: inherit;
font-size: 16px;
}
.toolbar-text {
font-size: 14px;
line-height: 16px;

View File

@ -9,7 +9,7 @@ module Groups
def show
respond_to do |format|
format.json do
render status: :ok, json: { variables: GroupVariableSerializer.new.represent(@group.variables) }
render status: :ok, json: { variables: ::Ci::GroupVariableSerializer.new.represent(@group.variables) }
end
end
end
@ -29,7 +29,7 @@ module Groups
private
def render_group_variables
render status: :ok, json: { variables: GroupVariableSerializer.new.represent(@group.variables) }
render status: :ok, json: { variables: ::Ci::GroupVariableSerializer.new.represent(@group.variables) }
end
def render_error

View File

@ -0,0 +1,31 @@
# frozen_string_literal: true
module Projects
module IncidentManagement
class PagerDutyIncidentsController < Projects::ApplicationController
respond_to :json
skip_before_action :verify_authenticity_token
skip_before_action :project
prepend_before_action :project_without_auth
def create
result = ServiceResponse.success(http_status: :accepted)
unless Feature.enabled?(:pagerduty_webhook, @project)
result = ServiceResponse.error(message: 'Unauthorized', http_status: :unauthorized)
end
head result.http_status
end
private
def project_without_auth
@project ||= Project
.find_by_full_path("#{params[:namespace_id]}/#{params[:project_id]}")
end
end
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
module Projects
module Pipelines
class StagesController < Projects::Pipelines::ApplicationController
before_action :authorize_update_pipeline!
def play_manual
::Ci::PlayManualStageService
.new(@project, current_user, pipeline: pipeline)
.execute(stage)
respond_to do |format|
format.json do
render json: StageSerializer
.new(project: @project, current_user: @current_user)
.represent(stage)
end
end
end
private
def stage
@pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name])
end
end
end
end

View File

@ -1,25 +0,0 @@
# frozen_string_literal: true
class Projects::StagesController < Projects::PipelinesController
before_action :authorize_update_pipeline!
def play_manual
::Ci::PlayManualStageService
.new(@project, current_user, pipeline: pipeline)
.execute(stage)
respond_to do |format|
format.json do
render json: StageSerializer
.new(project: @project, current_user: @current_user)
.represent(stage)
end
end
end
private
def stage
@pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name])
end
end

View File

@ -6,7 +6,7 @@ class Projects::VariablesController < Projects::ApplicationController
def show
respond_to do |format|
format.json do
render status: :ok, json: { variables: VariableSerializer.new.represent(@project.variables) }
render status: :ok, json: { variables: ::Ci::VariableSerializer.new.represent(@project.variables) }
end
end
end
@ -26,7 +26,7 @@ class Projects::VariablesController < Projects::ApplicationController
private
def render_variables
render status: :ok, json: { variables: VariableSerializer.new.represent(@project.variables) }
render status: :ok, json: { variables: ::Ci::VariableSerializer.new.represent(@project.variables) }
end
def render_error

View File

@ -53,6 +53,15 @@ module IconsHelper
content_tag(:svg, content_tag(:use, "", { "xlink:href" => "#{sprite_icon_path}##{icon_name}" } ), class: css_classes.empty? ? nil : css_classes.join(' '))
end
def loading_icon(container: false, color: 'orange', size: 'sm', css_class: nil)
css_classes = ['gl-spinner', "gl-spinner-#{color}", "gl-spinner-#{size}"]
css_classes << "#{css_class}" unless css_class.blank?
spinner = content_tag(:span, "", { class: css_classes.join(' '), aria: { label: _('Loading') } })
container == true ? content_tag(:div, spinner, { class: 'gl-spinner-container' }) : spinner
end
def external_snippet_icon(name)
content_tag(:span, "", class: "gl-snippet-icon gl-snippet-icon-#{name}")
end

View File

@ -57,7 +57,7 @@ module AlertManagement
validates :started_at, presence: true
validates :fingerprint, allow_blank: true, uniqueness: {
scope: :project,
conditions: -> { where.not(status: STATUSES[:resolved]) },
conditions: -> { not_resolved },
message: -> (object, data) { _('Cannot have multiple unresolved alerts') }
}, unless: :resolved?
validate :hosts_length
@ -120,6 +120,7 @@ module AlertManagement
scope :for_environment, -> (environment) { where(environment: environment) }
scope :search, -> (query) { fuzzy_search(query, [:title, :description, :monitoring_tool, :service]) }
scope :open, -> { with_status(:triggered, :acknowledged) }
scope :not_resolved, -> { where.not(status: STATUSES[:resolved]) }
scope :with_prometheus_alert, -> { includes(:prometheus_alert) }
scope :order_start_time, -> (sort_order) { order(started_at: sort_order) }

View File

@ -6,7 +6,7 @@ module Projects
RESERVED_ANNOTATIONS = %w(gitlab_incident_markdown gitlab_y_label title).freeze
GENERIC_ALERT_SUMMARY_ANNOTATIONS = %w(monitoring_tool service hosts).freeze
MARKDOWN_LINE_BREAK = " \n".freeze
INCIDENT_LABEL_NAME = IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES[:title].freeze
INCIDENT_LABEL_NAME = ::IncidentManagement::CreateIncidentLabelService::LABEL_PROPERTIES[:title].freeze
METRIC_TIME_WINDOW = 30.minutes
def full_title

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
module Ci
class GroupVariableEntity < Ci::BasicVariableEntity
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module Ci
class GroupVariableSerializer < BaseSerializer
entity ::Ci::GroupVariableEntity
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module Ci
class VariableEntity < Ci::BasicVariableEntity
expose :environment_scope
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
module Ci
class VariableSerializer < BaseSerializer
entity ::Ci::VariableEntity
end
end

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
class GroupVariableEntity < Ci::BasicVariableEntity
end

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
class GroupVariableSerializer < BaseSerializer
entity GroupVariableEntity
end

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
class VariableEntity < Ci::BasicVariableEntity
expose :environment_scope
end

View File

@ -1,5 +0,0 @@
# frozen_string_literal: true
class VariableSerializer < BaseSerializer
entity VariableEntity
end

View File

@ -94,7 +94,7 @@ module AlertManagement
end
def am_alert
@am_alert ||= AlertManagement::Alert.for_fingerprint(project, gitlab_fingerprint).first
@am_alert ||= AlertManagement::Alert.not_resolved.for_fingerprint(project, gitlab_fingerprint).first
end
def bad_request

View File

@ -4,7 +4,7 @@ module Projects
module Alerting
class NotifyService < BaseService
include Gitlab::Utils::StrongMemoize
include IncidentManagement::Settings
include ::IncidentManagement::Settings
def execute(token)
return forbidden unless alerts_service_activated?
@ -55,7 +55,7 @@ module Projects
def find_alert_by_fingerprint(fingerprint)
return unless fingerprint
AlertManagement::Alert.for_fingerprint(project, fingerprint).first
AlertManagement::Alert.not_resolved.for_fingerprint(project, fingerprint).first
end
def send_email?
@ -65,7 +65,7 @@ module Projects
def process_incident_issues(alert)
return if alert.issue
IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
::IncidentManagement::ProcessAlertWorker.perform_async(nil, nil, alert.id)
end
def send_alert_email

View File

@ -5,7 +5,7 @@ module Projects
module Alerts
class NotifyService < BaseService
include Gitlab::Utils::StrongMemoize
include IncidentManagement::Settings
include ::IncidentManagement::Settings
# This set of keys identifies a payload as a valid Prometheus
# payload and thus processable by this service. See also

View File

@ -16,8 +16,7 @@
%span.attaching-file-message
-# Populated by app/assets/javascripts/dropzone_input.js
%span.uploading-progress 0%
%span.uploading-spinner
.toolbar-button-icon.spinner.align-text-top
= loading_icon(css_class: 'align-text-bottom gl-mr-2')
%span.uploading-error-container.hide
%span.uploading-error-icon

View File

@ -0,0 +1,5 @@
---
title: Support fenced code blocks in Atlassian Document Format converter
merge_request: 35065
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Open new alert when existing alert is resolved
merge_request: 36261
author:
type: added

View File

@ -22,10 +22,8 @@ resources :pipelines, only: [:index, :new, :create, :show, :destroy] do
get :test_reports_count
end
member do
resources :stages, only: [], param: :name do
post :play_manual
end
resources :stages, only: [], param: :name, controller: 'pipelines/stages' do
post :play_manual
end
resources :tests, only: [:show], param: :suite_name, controller: 'pipelines/tests' do

View File

@ -406,6 +406,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post 'alerts/notify', to: 'alerting/notifications#create'
post 'incident_management/pager_duty', to: 'incident_management/pager_duty_incidents#create'
draw :legacy_builds
resources :hooks, only: [:index, :create, :edit, :update, :destroy], constraints: { id: /\d+/ } do # rubocop: disable Cop/PutProjectRoutesUnderScope

View File

@ -21,6 +21,7 @@ exceptions:
- CLI
- CNAME
- CPU
- CORE
- CSS
- CSV
- DNS

View File

@ -11,11 +11,11 @@ level: warning
nonword: true
ignorecase: true
tokens:
- "GitLab 2."
- "GitLab 3."
- "GitLab 4."
- "GitLab 5."
- "GitLab 6."
- "GitLab 7."
- "GitLab 8."
- "GitLab 9."
- "GitLab (v)?2."
- "GitLab (v)?3."
- "GitLab (v)?4."
- "GitLab (v)?5."
- "GitLab (v)?6."
- "GitLab (v)?7."
- "GitLab (v)?8."
- "GitLab (v)?9."

View File

@ -140,7 +140,7 @@ The following API resources are available outside of project and group contexts
| [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) |
| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
| [Projects](projects.md) | `/users/:id/projects` (also available for projects) |
| [Project Repository Storage Moves](project_repository_storage_moves.md) | `/project_repository_storage_moves` |
| [Project repository storage moves](project_repository_storage_moves.md) **(CORE ONLY)** | `/project_repository_storage_moves` |
| [Runners](runners.md) | `/runners` (also available for projects) |
| [Search](search.md) | `/search` (also available for groups and projects) |
| [Settings](settings.md) **(CORE ONLY)** | `/application/settings` |

View File

@ -1,3 +1,10 @@
---
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# Deployments API
## List project deployments

View File

@ -1,3 +1,10 @@
---
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# Environments API
## List environments

View File

@ -1,3 +1,9 @@
---
stage: Monitor
group: Health
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Error Tracking settings API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/34940) in GitLab 12.7.

View File

@ -1,3 +1,10 @@
---
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# Freeze Periods API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29382) in GitLab 13.0.

View File

@ -1,3 +1,9 @@
---
stage: Configure
group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Group clusters API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30213) in GitLab 12.1.

View File

@ -1,3 +1,10 @@
---
stage: Monitor
group: APM
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# Dashboard annotations API
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29089) in GitLab 12.10 behind a disabled feature flag.

View File

@ -1,3 +1,10 @@
---
stage: Monitor
group: APM
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# User-starred metrics dashboards API
The starred dashboard feature makes navigating to frequently-used dashboards easier

View File

@ -1,3 +1,9 @@
---
stage: Configure
group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Project clusters API
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23922) in GitLab 11.7.

View File

@ -5,11 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
# Project repository storage move API
# Project repository storage moves API **(CORE ONLY)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
Project repository storage can be moved. To retrieve project repository storage moves using the API, you must [authenticate yourself](README.md#authentication) as an administrator.
Project repository storage can be moved. To retrieve project repository storage moves using the API,
you must [authenticate yourself](README.md#authentication) as an administrator.
## Retrieve all project repository storage moves
@ -23,7 +24,7 @@ are [paginated](README.md#pagination).
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/project_repository_storage_moves'
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_repository_storage_moves"
```
Example response:
@ -66,7 +67,7 @@ Parameters:
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/1/repository_storage_moves'
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves"
```
Example response:
@ -106,7 +107,7 @@ Parameters:
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/project_repository_storage_moves/1'
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/project_repository_storage_moves/1"
```
Example response:
@ -145,7 +146,7 @@ Parameters:
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" 'https://gitlab.example.com/api/v4/projects/1/repository_storage_moves/1'
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves/1"
```
Example response:
@ -185,7 +186,7 @@ Example request:
```shell
curl --request POST --header "PRIVATE_TOKEN: <your_access_token>" --header "Content-Type: application/json" \
--data '{"destination_storage_name":"storage2"}' 'https://gitlab.example.com/api/v4/projects/1/repository_storage_moves'
--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/projects/1/repository_storage_moves"
```
Example response:

View File

@ -1,3 +1,10 @@
---
stage: Release
group: Release Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: concepts, howto
---
# Protected environments API **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30595) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.8.

View File

@ -963,8 +963,8 @@ a corresponding cluster type. The default value is blank. You can
check the recommended variables for each cluster type in the official
documentation:
- [Google GKE](https://cilium.readthedocs.io/en/stable/gettingstarted/k8s-install-gke/#prepare-deploy-cilium)
- [AWS EKS](https://cilium.readthedocs.io/en/stable/gettingstarted/k8s-install-eks/#prepare-deploy-cilium)
- [Google GKE](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#deploy-cilium)
- [AWS EKS](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-eks/#deploy-cilium)
You can customize Cilium's Helm variables by defining the
`.gitlab/managed-apps/cilium/values.yaml` file in your cluster
@ -974,9 +974,9 @@ for the available configuration options.
CAUTION: **Caution:**
Installation and removal of the Cilium requires a **manual**
[restart](https://cilium.readthedocs.io/en/stable/gettingstarted/k8s-install-gke/#restart-remaining-pods)
[restart](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods)
of all affected pods in all namespaces to ensure that they are
[managed](https://cilium.readthedocs.io/en/stable/troubleshooting/#ensure-pod-is-managed-by-cilium)
[managed](https://docs.cilium.io/en/stable/troubleshooting/#ensure-pod-is-managed-by-cilium)
by the correct networking plugin.
NOTE: **Note:**

View File

@ -101,4 +101,6 @@ displays a counter on the
[Alert Management List](../operations/alert_management.md#alert-management-list)
and details pages.
If the existing alert is already `resolved`, then a new alert will be created instead.
![Alert Management List](../operations/img/alert_list_v13_1.png)

View File

@ -18,7 +18,7 @@ module Gitlab
def action_path
pipeline = subject.pipeline
project_stage_play_manual_path(pipeline.project, pipeline, subject.name)
project_pipeline_stage_play_manual_path(pipeline.project, pipeline, subject.name)
end
def action_method

View File

@ -12,6 +12,46 @@ module Kramdown
# Note: this is only an initial implementation. Currently don't
# strip out IALs or other specific kramdown syntax.
class Commonmark < ::Kramdown::Converter::Kramdown
# replaces the ^ used in kramdown. This forces the current
# block to end, so that a different list or codeblock can be
# started. https://kramdown.gettalong.org/syntax.html#eob-marker
END_OF_BLOCK = '<!-- -->'
def convert(el, opts = { indent: 0 })
res = super
if [:ul, :dl, :ol, :codeblock].include?(el.type) && opts[:next] &&
([el.type, :codeblock].include?(opts[:next].type) ||
(opts[:next].type == :blank && opts[:nnext] &&
[el.type, :codeblock].include?(opts[:nnext].type)))
# replace the end of block character
res.sub!(/\^\n\n\z/m, "#{END_OF_BLOCK}\n\n")
end
res
end
def convert_codeblock(el, _opts)
# Although tildes are supported in CommonMark, backticks are more common
"```#{el.options[:lang]}\n" +
el.value.split(/\n/).map {|l| l.empty? ? "" : "#{l}" }.join("\n") +
"\n```\n\n"
end
def convert_li(el, opts)
res = super
if el.children.first && el.children.first.type == :p && !el.children.first.options[:transparent]
if el.children.size == 1 && @stack.last.children.last == el &&
(@stack.last.children.any? {|c| c.children.first.type != :p } || @stack.last.children.size == 1)
# replace the end of block character
res.sub!(/\^\n\z/m, "#{END_OF_BLOCK}\n")
end
end
res
end
def convert_table(el, opts)
return super unless @options[:html_tables]

View File

@ -71,6 +71,11 @@ msgstr ""
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr ""
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
msgstr[0] ""
msgstr[1] ""
msgid "%d URL scanned"
msgid_plural "%d URLs scanned"
msgstr[0] ""
@ -8305,6 +8310,9 @@ msgstr ""
msgid "Download as"
msgstr ""
msgid "Download as CSV"
msgstr ""
msgid "Download asset"
msgstr ""
@ -24515,6 +24523,9 @@ msgstr ""
msgid "To this GitLab instance"
msgstr ""
msgid "To view all %{scannedResourcesCount} scanned URLs, please download the CSV file"
msgstr ""
msgid "To view the roadmap, add a start or due date to one of your epics in this group or its subgroups. In the months view, only epics in the past month, current month, and next 5 months are shown."
msgstr ""

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::IncidentManagement::PagerDutyIncidentsController do
let_it_be(:project) { create(:project) }
describe 'POST #create' do
let(:payload) { { messages: [] } }
def make_request
post :create, params: project_params, body: payload.to_json, as: :json
end
context 'when pagerduty_webhook feature enabled' do
before do
stub_feature_flags(pagerduty_webhook: project)
end
it 'responds with 202 Accepted' do
make_request
expect(response).to have_gitlab_http_status(:accepted)
end
end
context 'when pagerduty_webhook feature disabled' do
before do
stub_feature_flags(pagerduty_webhook: false)
end
it 'responds with 401 Unauthorized' do
make_request
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
end
private
def project_params(opts = {})
opts.reverse_merge(namespace_id: project.namespace, project_id: project)
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Projects::StagesController do
RSpec.describe Projects::Pipelines::StagesController do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
@ -60,7 +60,7 @@ RSpec.describe Projects::StagesController do
post :play_manual, params: {
namespace_id: project.namespace,
project_id: project,
id: pipeline.id,
pipeline_id: pipeline.id,
stage_name: stage_name
}, format: :json
end

View File

@ -14,6 +14,18 @@
}
]
},
{
"type": "codeBlock",
"attrs": {
"language": "css"
},
"content": [
{
"type": "text",
"text": ".overflow { overflow: hidden; }"
}
]
},
{
"type": "bulletList",
"content": [
@ -37,6 +49,37 @@
"text": "public DemoClass()\n{\n // assign default value\n x = 0;\n}"
}
]
},
{
"type": "orderedList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list Item 1"
}
]
},
{
"type": "codeBlock",
"attrs": {
"language": "ruby"
},
"content": [
{
"type": "text",
"text": "def test\n # assign default value\n x = 0\nend"
}
]
}
]
}
]
}
]
}

View File

@ -1,17 +1,38 @@
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
console.log(data)
return data
}
```javascript
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
console.log(data)
return data
}
```
<!-- -->
```css
.overflow { overflow: hidden; }
```
* Item 1
public DemoClass()
{
// assign default value
x = 0;
}
```java
public DemoClass()
{
// assign default value
x = 0;
}
```
1. Number list Item 1
```ruby
def test
# assign default value
x = 0
end
```

View File

@ -165,37 +165,40 @@ Col 3 Row 3
<del>Strikethrough</del>
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
let data = {
fields: {
summary: faker.lorem.sentence(),
issuetype: {
id: issueType.id
},
project: {
id: project.id
},
reporter: {
id: pickRandom(users)
}
}
```javascript
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
let data = {
fields: {
summary: faker.lorem.sentence(),
issuetype: {
id: issueType.id
},
project: {
id: project.id
},
reporter: {
id: pickRandom(users)
}
if (issueType.subtask) {
data = {
parent: {
key: parentIssue
}
}
}
console.log(data)
return data
}
}
if (issueType.subtask) {
data = {
parent: {
key: parentIssue
}
}
}
console.log(data)
return data
}
```
![jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c)

View File

@ -146,6 +146,25 @@
]
}
]
},
{
"type": "orderedList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Another list"
}
]
}
]
}
]
}
]
}

View File

@ -17,4 +17,9 @@
9. Number list item 9
10. Number list item 10
<!-- -->
1. Another list
<!-- -->

View File

@ -2,6 +2,7 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { createStore } from '~/mr_notes/stores';
import NoChanges from '~/diffs/components/no_changes.vue';
import { GlButton } from '@gitlab/ui';
describe('Diff no changes empty state', () => {
let vm;
@ -37,4 +38,11 @@ describe('Diff no changes empty state', () => {
expect(vm.contains('script')).toBe(false);
});
describe('Renders', () => {
it('Show create commit button', () => {
createComponent();
expect(vm.find(GlButton).exists()).toBe(true);
});
});
});

View File

@ -235,4 +235,25 @@ RSpec.describe IconsHelper do
.to eq("<span class=\"gl-snippet-icon gl-snippet-icon-download\"></span>")
end
end
describe 'loading_icon' do
it 'returns span with gl-spinner class and default configuration' do
expect(loading_icon.to_s)
.to eq '<span class="gl-spinner gl-spinner-orange gl-spinner-sm" aria-label="Loading"></span>'
end
context 'when css_class is provided' do
it 'appends css_class to gl-spinner element' do
expect(loading_icon(css_class: 'gl-mr-2').to_s)
.to eq '<span class="gl-spinner gl-spinner-orange gl-spinner-sm gl-mr-2" aria-label="Loading"></span>'
end
end
context 'when container is true' do
it 'creates a container that has the gl-spinner-container class selector' do
expect(loading_icon(container: true).to_s)
.to eq '<div class="gl-spinner-container"><span class="gl-spinner gl-spinner-orange gl-spinner-sm" aria-label="Loading"></span></div>'
end
end
end
end

View File

@ -235,6 +235,14 @@ RSpec.describe AlertManagement::Alert do
it { is_expected.to contain_exactly(acknowledged_alert, triggered_alert) }
end
describe '.not_resolved' do
subject { described_class.not_resolved }
let!(:acknowledged_alert) { create(:alert_management_alert, :acknowledged, project: project) }
it { is_expected.to contain_exactly(acknowledged_alert, triggered_alert, ignored_alert) }
end
end
describe '.last_prometheus_alert_by_project_id' do

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe GroupVariableEntity do
RSpec.describe Ci::GroupVariableEntity do
let(:variable) { create(:ci_group_variable) }
let(:entity) { described_class.new(variable) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe VariableEntity do
RSpec.describe Ci::VariableEntity do
let(:variable) { create(:ci_variable) }
let(:entity) { described_class.new(variable) }

View File

@ -39,22 +39,27 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
context 'when Prometheus alert status is firing' do
context 'when alert with the same fingerprint already exists' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
it 'increases alert events count' do
expect { execute }.to change { alert.reload.events }.by(1)
it_behaves_like 'adds an alert management alert event'
context 'existing alert is resolved' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
it_behaves_like 'creates an alert management alert'
end
context 'when status can be changed' do
it 'changes status to triggered' do
expect { execute }.to change { alert.reload.triggered? }.to(true)
end
context 'existing alert is ignored' do
let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
it_behaves_like 'adds an alert management alert event'
end
it 'does not executes the alert service hooks' do
expect(alert).not_to receive(:execute_services)
context 'two existing alerts, one resolved one open' do
let!(:resolved_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: parsed_alert.gitlab_fingerprint) }
subject
it_behaves_like 'adds an alert management alert event'
end
context 'when status change did not succeed' do
@ -73,23 +78,11 @@ RSpec.describe AlertManagement::ProcessPrometheusAlertService do
execute
end
end
it { is_expected.to be_success }
end
context 'when alert does not exist' do
context 'when alert can be created' do
it 'creates a new alert' do
expect { execute }.to change { AlertManagement::Alert.where(project: project).count }.by(1)
end
it 'executes the alert service hooks' do
slack_service = create(:service, type: 'SlackService', project: project, alert_events: true, active: true)
subject
expect(ProjectServiceWorker).to have_received(:perform_async).with(slack_service.id, an_instance_of(Hash))
end
it_behaves_like 'creates an alert management alert'
end
context 'when alert cannot be created' do

View File

@ -64,12 +64,6 @@ RSpec.describe Projects::Alerting::NotifyService do
end
end
shared_examples 'NotifyService does not create alert' do
it 'does not create alert' do
expect { subject }.not_to change(AlertManagement::Alert, :count)
end
end
describe '#execute' do
let(:token) { 'invalid-token' }
let(:starts_at) { Time.current.change(usec: 0) }
@ -107,62 +101,64 @@ RSpec.describe Projects::Alerting::NotifyService do
end
context 'with valid payload' do
shared_examples 'assigns the alert properties' do
it 'ensure that created alert has all data properly assigned' do
subject
expect(last_alert_attributes).to match(
project_id: project.id,
title: payload_raw.fetch(:title),
started_at: Time.zone.parse(payload_raw.fetch(:start_time)),
severity: payload_raw.fetch(:severity),
status: AlertManagement::Alert::STATUSES[:triggered],
events: 1,
hosts: payload_raw.fetch(:hosts),
payload: payload_raw.with_indifferent_access,
issue_id: nil,
description: payload_raw.fetch(:description),
monitoring_tool: payload_raw.fetch(:monitoring_tool),
service: payload_raw.fetch(:service),
fingerprint: Digest::SHA1.hexdigest(fingerprint),
ended_at: nil,
prometheus_alert_id: nil,
environment_id: nil
)
end
end
let(:last_alert_attributes) do
AlertManagement::Alert.last.attributes
.except('id', 'iid', 'created_at', 'updated_at')
.with_indifferent_access
end
it 'creates AlertManagement::Alert' do
expect { subject }.to change(AlertManagement::Alert, :count).by(1)
end
it 'created alert has all data properly assigned' do
subject
expect(last_alert_attributes).to match(
project_id: project.id,
title: payload_raw.fetch(:title),
started_at: Time.zone.parse(payload_raw.fetch(:start_time)),
severity: payload_raw.fetch(:severity),
status: AlertManagement::Alert::STATUSES[:triggered],
events: 1,
hosts: payload_raw.fetch(:hosts),
payload: payload_raw.with_indifferent_access,
issue_id: nil,
description: payload_raw.fetch(:description),
monitoring_tool: payload_raw.fetch(:monitoring_tool),
service: payload_raw.fetch(:service),
fingerprint: Digest::SHA1.hexdigest(fingerprint),
ended_at: nil,
prometheus_alert_id: nil,
environment_id: nil
)
end
it 'executes the alert service hooks' do
slack_service = create(:service, type: 'SlackService', project: project, alert_events: true, active: true)
subject
expect(ProjectServiceWorker).to have_received(:perform_async).with(slack_service.id, an_instance_of(Hash))
end
it_behaves_like 'creates an alert management alert'
it_behaves_like 'assigns the alert properties'
context 'existing alert with same fingerprint' do
let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) }
let!(:existing_alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
it 'does not create AlertManagement::Alert' do
expect { subject }.not_to change(AlertManagement::Alert, :count)
it_behaves_like 'adds an alert management alert event'
context 'existing alert is resolved' do
let!(:alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) }
it_behaves_like 'creates an alert management alert'
it_behaves_like 'assigns the alert properties'
end
it 'increments the existing alert count' do
expect { subject }.to change { existing_alert.reload.events }.from(1).to(2)
context 'existing alert is ignored' do
let!(:alert) { create(:alert_management_alert, :ignored, project: project, fingerprint: fingerprint_sha) }
it_behaves_like 'adds an alert management alert event'
end
it 'does not executes the alert service hooks' do
subject
context 'two existing alerts, one resolved one open' do
let!(:resolved_existing_alert) { create(:alert_management_alert, :resolved, project: project, fingerprint: fingerprint_sha) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
expect(ProjectServiceWorker).not_to have_received(:perform_async)
it_behaves_like 'adds an alert management alert event'
end
end
@ -174,9 +170,7 @@ RSpec.describe Projects::Alerting::NotifyService do
}
end
it 'creates AlertManagement::Alert' do
expect { subject }.to change(AlertManagement::Alert, :count).by(1)
end
it_behaves_like 'creates an alert management alert'
it 'created alert has all data properly assigned' do
subject
@ -218,19 +212,19 @@ RSpec.describe Projects::Alerting::NotifyService do
end
it_behaves_like 'does not process incident issues due to error', http_status: :bad_request
it_behaves_like 'NotifyService does not create alert'
it_behaves_like 'does not an create alert management alert'
end
context 'when alert already exists' do
let(:fingerprint_sha) { Digest::SHA1.hexdigest(fingerprint) }
let!(:existing_alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
let!(:alert) { create(:alert_management_alert, project: project, fingerprint: fingerprint_sha) }
context 'when existing alert does not have an associated issue' do
it_behaves_like 'processes incident issues'
end
context 'when existing alert has an associated issue' do
let!(:existing_alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) }
let!(:alert) { create(:alert_management_alert, :with_issue, project: project, fingerprint: fingerprint_sha) }
it_behaves_like 'does not process incident issues'
end
@ -246,14 +240,14 @@ RSpec.describe Projects::Alerting::NotifyService do
context 'with invalid token' do
it_behaves_like 'does not process incident issues due to error', http_status: :unauthorized
it_behaves_like 'NotifyService does not create alert'
it_behaves_like 'does not an create alert management alert'
end
context 'with deactivated Alerts Service' do
let!(:alerts_service) { create(:alerts_service, :inactive, project: project) }
it_behaves_like 'does not process incident issues due to error', http_status: :forbidden
it_behaves_like 'NotifyService does not create alert'
it_behaves_like 'does not an create alert management alert'
end
end
end

View File

@ -0,0 +1,41 @@
# frozen_string_literal: true
RSpec.shared_examples 'creates an alert management alert' do
it { is_expected.to be_success }
it 'creates AlertManagement::Alert' do
expect { subject }.to change(AlertManagement::Alert, :count).by(1)
end
it 'executes the alert service hooks' do
slack_service = create(:service, type: 'SlackService', project: project, alert_events: true, active: true)
subject
expect(ProjectServiceWorker).to have_received(:perform_async).with(slack_service.id, an_instance_of(Hash))
end
end
RSpec.shared_examples 'does not an create alert management alert' do
it 'does not create alert' do
expect { subject }.not_to change(AlertManagement::Alert, :count)
end
end
RSpec.shared_examples 'adds an alert management alert event' do
it { is_expected.to be_success }
it 'does not create an alert' do
expect { subject }.not_to change(AlertManagement::Alert, :count)
end
it 'increases alert events count' do
expect { subject }.to change { alert.reload.events }.by(1)
end
it 'does not executes the alert service hooks' do
expect(alert).not_to receive(:execute_services)
subject
end
end