Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
heptapod
heptapod
Commits
903efabd2014
Commit
903efabd
authored
Feb 11, 2020
by
GitLab Bot
Browse files
Add latest changes from gitlab-org/gitlab@master
parent
46209aef7c2c
Changes
24
Hide whitespace changes
Inline
Side-by-side
app/assets/javascripts/blob/file_template_mediator.js
View file @
903efabd
...
...
@@ -117,11 +117,7 @@
selector
.
hide
();
}
});
if
(
this
.
editor
.
getValue
()
!==
''
)
{
this
.
setTypeSelectorToggleText
(
item
.
name
);
}
this
.
setTypeSelectorToggleText
(
item
.
name
);
this
.
cacheToggleText
();
}
...
...
app/assets/javascripts/code_navigation/store/actions.js
View file @
903efabd
...
...
@@ -16,7 +16,7 @@
commit
(
types
.
REQUEST_DATA
);
api
.
lsifData
(
state
.
projectPath
,
state
.
commitId
,
state
.
p
ath
)
.
lsifData
(
state
.
projectPath
,
state
.
commitId
,
state
.
blobP
ath
)
.
then
(({
data
})
=>
{
const
normalizedData
=
data
.
reduce
((
acc
,
d
)
=>
{
if
(
d
.
hover
)
{
...
...
app/models/container_expiration_policy.rb
View file @
903efabd
...
...
@@ -14,7 +14,7 @@
validates
:keep_n
,
inclusion:
{
in:
->
(
_
)
{
self
.
keep_n_options
.
keys
}
},
allow_nil:
true
scope
:active
,
->
{
where
(
enabled:
true
)
}
scope
:preloaded
,
->
{
preload
(
:
project
)
}
scope
:preloaded
,
->
{
preload
(
project
:
[
:route
]
)
}
def
self
.
keep_n_options
{
...
...
app/models/incident_management/project_incident_management_setting.rb
0 → 100644
View file @
903efabd
# frozen_string_literal: true
module
IncidentManagement
class
ProjectIncidentManagementSetting
<
ApplicationRecord
include
Gitlab
::
Utils
::
StrongMemoize
belongs_to
:project
validate
:issue_template_exists
,
if: :create_issue?
def
available_issue_templates
Gitlab
::
Template
::
IssueTemplate
.
all
(
project
)
end
def
issue_template_content
strong_memoize
(
:issue_template_content
)
do
issue_template
&
.
content
if
issue_template_key
.
present?
end
end
private
def
issue_template_exists
return
unless
issue_template_key
.
present?
errors
.
add
(
:issue_template_key
,
'not found'
)
unless
issue_template
end
def
issue_template
Gitlab
::
Template
::
IssueTemplate
.
find
(
issue_template_key
,
project
)
rescue
Gitlab
::
Template
::
Finders
::
RepoTemplateFinder
::
FileNotFoundError
end
end
end
app/models/project.rb
View file @
903efabd
...
...
@@ -187,6 +187,7 @@
has_one
:import_state
,
autosave:
true
,
class_name:
'ProjectImportState'
,
inverse_of: :project
has_one
:import_export_upload
,
dependent: :destroy
# rubocop:disable Cop/ActiveRecordDependent
has_one
:project_repository
,
inverse_of: :project
has_one
:incident_management_setting
,
inverse_of: :project
,
class_name:
'IncidentManagement::ProjectIncidentManagementSetting'
has_one
:error_tracking_setting
,
inverse_of: :project
,
class_name:
'ErrorTracking::ProjectErrorTrackingSetting'
has_one
:metrics_setting
,
inverse_of: :project
,
class_name:
'ProjectMetricsSetting'
has_one
:grafana_integration
,
inverse_of: :project
...
...
@@ -316,6 +317,7 @@
allow_destroy:
true
,
reject_if:
->
(
attrs
)
{
attrs
[
:id
].
blank?
&&
attrs
[
:url
].
blank?
}
accepts_nested_attributes_for
:incident_management_setting
,
update_only:
true
accepts_nested_attributes_for
:error_tracking_setting
,
update_only:
true
accepts_nested_attributes_for
:metrics_setting
,
update_only:
true
,
allow_destroy:
true
accepts_nested_attributes_for
:grafana_integration
,
update_only:
true
,
allow_destroy:
true
...
...
app/services/incident_management/create_issue_service.rb
0 → 100644
View file @
903efabd
# frozen_string_literal: true
module
IncidentManagement
class
CreateIssueService
<
BaseService
include
Gitlab
::
Utils
::
StrongMemoize
INCIDENT_LABEL
=
{
title:
'incident'
,
color:
'#CC0033'
,
description:
<<~
DESCRIPTION
.
chomp
Denotes a disruption to IT services and \
the associated issues require immediate attention
DESCRIPTION
}.
freeze
def
initialize
(
project
,
params
)
super
(
project
,
User
.
alert_bot
,
params
)
end
def
execute
return
error_with
(
'setting disabled'
)
unless
incident_management_setting
.
create_issue?
return
error_with
(
'invalid alert'
)
unless
alert
.
valid?
issue
=
create_issue
return
error_with
(
issue_errors
(
issue
))
unless
issue
.
valid?
success
(
issue:
issue
)
end
private
def
create_issue
issue
=
do_create_issue
(
label_ids:
issue_label_ids
)
# Create an unlabelled issue if we couldn't create the issue
# due to labels errors.
# See https://gitlab.com/gitlab-org/gitlab-foss/issues/65042
if
issue
.
errors
.
include?
(
:labels
)
log_label_error
(
issue
)
issue
=
do_create_issue
end
issue
end
def
do_create_issue
(
**
params
)
Issues
::
CreateService
.
new
(
project
,
current_user
,
title:
issue_title
,
description:
issue_description
,
**
params
).
execute
end
def
issue_title
alert
.
full_title
end
def
issue_description
horizontal_line
=
"
\n
---
\n\n
"
[
alert_summary
,
alert_markdown
,
issue_template_content
].
compact
.
join
(
horizontal_line
)
end
def
issue_label_ids
[
find_or_create_label
(
**
INCIDENT_LABEL
)
].
compact
.
map
(
&
:id
)
end
def
find_or_create_label
(
**
params
)
Labels
::
FindOrCreateService
.
new
(
current_user
,
project
,
**
params
)
.
execute
end
def
alert_summary
alert
.
issue_summary_markdown
end
def
alert_markdown
alert
.
alert_markdown
end
def
alert
strong_memoize
(
:alert
)
do
Gitlab
::
Alerting
::
Alert
.
new
(
project:
project
,
payload:
params
).
present
end
end
def
issue_template_content
incident_management_setting
.
issue_template_content
end
def
incident_management_setting
strong_memoize
(
:incident_management_setting
)
do
project
.
incident_management_setting
||
project
.
build_incident_management_setting
end
end
def
issue_errors
(
issue
)
issue
.
errors
.
full_messages
.
to_sentence
end
def
log_label_error
(
issue
)
log_info
<<~
TEXT
.
chomp
Cannot create incident issue with labels \
#{
issue
.
labels
.
map
(
&
:title
).
inspect
}
\
for "
#{
project
.
full_name
}
":
#{
issue
.
errors
.
full_messages
.
to_sentence
}
.
Retrying without labels.
TEXT
end
def
error_with
(
message
)
log_error
(
%{Cannot create incident issue for "#{project.full_name}": #{message}}
)
error
(
message
)
end
end
end
app/views/projects/blob/_blob.html.haml
View file @
903efabd
...
...
@@ -10,7 +10,7 @@
#blob-content-holder
.blob-content-holder
-
if
native_code_navigation_enabled?
(
@project
)
#js-code-navigation
{
data:
{
commit_id:
blob
.
commit_id
,
path:
blob
.
path
,
project_path:
@project
.
full_path
}
}
#js-code-navigation
{
data:
{
commit_id:
blob
.
commit_id
,
blob_
path:
blob
.
path
,
project_path:
@project
.
full_path
}
}
%article
.file-holder
=
render
'projects/blob/header'
,
blob:
blob
=
render
'projects/blob/content'
,
blob:
blob
app/workers/all_queues.yml
View file @
903efabd
...
...
@@ -429,6 +429,12 @@
:latency_sensitive:
:resource_boundary: :unknown
:weight:
1
-
:name: incident_management:incident_management_process_alert
:feature_category: :incident_management
:has_external_dependencies:
:latency_sensitive:
:resource_boundary: :unknown
:weight:
2
-
:name: mail_scheduler:mail_scheduler_issue_due
:feature_category: :issue_tracking
:has_external_dependencies:
...
...
app/workers/concerns/worker_context.rb
View file @
903efabd
...
...
@@ -60,6 +60,6 @@
end
def
with_context
(
context
,
&
block
)
Gitlab
::
ApplicationContext
.
new
(
context
).
use
(
&
block
)
Gitlab
::
ApplicationContext
.
new
(
context
).
use
{
yield
(
**
context
)
}
end
end
app/workers/container_expiration_policy_worker.rb
View file @
903efabd
...
...
@@ -2,9 +2,9 @@
class
ContainerExpirationPolicyWorker
include
ApplicationWorker
include
CronjobQueue
# rubocop:disable Scalability/CronWorkerContext
include
CronjobQueue
feature_category
:container_registry
def
perform
ContainerExpirationPolicy
.
runnable_schedules
.
preloaded
.
find_each
do
|
container_expiration_policy
|
...
...
@@ -6,11 +6,13 @@
feature_category
:container_registry
def
perform
ContainerExpirationPolicy
.
runnable_schedules
.
preloaded
.
find_each
do
|
container_expiration_policy
|
ContainerExpirationPolicyService
.
new
(
container_expiration_policy
.
project
,
container_expiration_policy
.
project
.
owner
).
execute
(
container_expiration_policy
)
with_context
(
project:
container_expiration_policy
.
project
,
user:
container_expiration_policy
.
project
.
owner
)
do
|
project
:,
user
:|
ContainerExpirationPolicyService
.
new
(
project
,
user
)
.
execute
(
container_expiration_policy
)
end
end
end
end
app/workers/incident_management/process_alert_worker.rb
0 → 100644
View file @
903efabd
# frozen_string_literal: true
module
IncidentManagement
class
ProcessAlertWorker
include
ApplicationWorker
queue_namespace
:incident_management
feature_category
:incident_management
def
perform
(
project_id
,
alert
)
project
=
find_project
(
project_id
)
return
unless
project
create_issue
(
project
,
alert
)
end
private
def
find_project
(
project_id
)
Project
.
find_by_id
(
project_id
)
end
def
create_issue
(
project
,
alert
)
IncidentManagement
::
CreateIssueService
.
new
(
project
,
alert
)
.
execute
end
end
end
changelogs/unreleased/show_selected_template_type.yml
0 → 100644
View file @
903efabd
---
title
:
Show selected template type when clicked
merge_request
:
24596
author
:
type
:
fixed
config/prometheus/self_monitoring_default.yml
0 → 100644
View file @
903efabd
dashboard
:
'
Default
dashboard'
priority
:
1
panel_groups
:
-
group
:
Web Service
panels
:
-
title
:
Web Service - Error Ratio
type
:
line-chart
y_label
:
"
Unhandled
Exceptions
(%)"
metrics
:
-
id
:
wser_web_service
query_range
:
'
max(max_over_time(gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="web",
stage="main"}[1m]))
by
(type)
*
100'
unit
:
"
%"
label
:
"
Error
Ratio"
-
id
:
wser_degradation_slo
query_range
:
'
avg(slo:max:gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="web",
stage="main"})
or
avg(slo:max:gitlab_service_errors:ratio{type="web"})
*
100'
unit
:
"
%"
label
:
"
Degradation
SLO"
-
id
:
wser_outage_slo
query_range
:
'
2
*
(avg(slo:max:gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="web",
stage="main"})
or
avg(slo:max:gitlab_service_errors:ratio{type="web"}))
*
100'
unit
:
"
%"
label
:
"
Outage
SLO"
-
group
:
API Service
panels
:
-
title
:
API Service - Error Ratio
type
:
line-chart
y_label
:
"
Unhandled
Exceptions
(%)"
metrics
:
-
id
:
aser_web_service
query_range
:
'
max(max_over_time(gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="api",
stage="main"}[1m]))
by
(type)
*
100'
unit
:
"
%"
label
:
"
Error
Ratio"
-
id
:
aser_degradation_slo
query_range
:
'
avg(slo:max:gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="api",
stage="main"})
or
avg(slo:max:gitlab_service_errors:ratio{type="web"})
*
100'
unit
:
"
%"
label
:
"
Degradation
SLO"
-
id
:
aser_outage_slo
query_range
:
'
2
*
(avg(slo:max:gitlab_service_errors:ratio{environment="{{ci_environment_slug}}",
type="api",
stage="main"})
or
avg(slo:max:gitlab_service_errors:ratio{type="web"}))
*
100'
unit
:
"
%"
label
:
"
Outage
SLO"
doc/ci/environments.md
View file @
903efabd
...
...
@@ -115,11 +115,14 @@
-
Lastly we deploy to the staging server.
NOTE:
**Note:**
The
`environment`
keyword is just a hint for GitLab that this job actually
deploys to the
`name`
environment. It can also have a
`url`
that is
exposed in various places within GitLab. Each time a job that
has an environment specified succeeds, a deployment is recorded, storing
the Git SHA and environment name.
The
`environment`
keyword defines where the app is deployed.
The environment
`name`
and
`url`
is exposed in various places
within GitLab. Each time a job that has an environment specified
succeeds, a deployment is recorded, along with the Git SHA and environment name.
CAUTION:
**Caution**
:
Some characters are not allowed in environment names. Use only letters,
numbers, spaces, and
`-`
,
`_`
,
`/`
,
`{`
,
`}`
, or
`.`
. Also, it must not start nor end with
`/`
.
In summary, with the above
`.gitlab-ci.yml`
we have achieved the following:
...
...
doc/user/project/deploy_boards.md
View file @
903efabd
...
...
@@ -27,7 +27,7 @@
to the latest release.
Since Deploy Boards are tightly coupled with Kubernetes, there is some required
knowledge. In particular you should be familiar with:
knowledge. In particular
,
you should be familiar with:
-
[
Kubernetes pods
](
https://kubernetes.io/docs/concepts/workloads/pods/pod/
)
-
[
Kubernetes labels
](
https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
)
...
...
@@ -37,7 +37,7 @@
## Use cases
Since the Deploy Board is a visual representation of the Kubernetes pods for a
specific environment, there are lot of use
s
cases. To name a few:
specific environment, there are
a
lot of use cases. To name a few:
-
You want to promote what's running in staging, to production. You go to the
environments list, verify that what's running in staging is what you think is
...
...
@@ -65,7 +65,7 @@
NOTE:
**Running on OpenShift:**
If you are using OpenShift, ensure that you're using the
`Deployment`
resource
instead of
`DeploymentConfiguration`
, o
therwise the Deploy Boards won't render
instead of
`DeploymentConfiguration`
. O
therwise
,
the Deploy Boards won't render
correctly. For more information, read the
[
OpenShift docs
](
https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations
)
and
[
GitLab issue #4584
](
https://gitlab.com/gitlab-org/gitlab/issues/4584
)
.
...
...
spec/factories/incident_management/project_incident_management_settings.rb
0 → 100644
View file @
903efabd
# frozen_string_literal: true
FactoryBot
.
define
do
factory
:project_incident_management_setting
,
class:
'IncidentManagement::ProjectIncidentManagementSetting'
do
project
create_issue
{
false
}
issue_template_key
{
nil
}
send_email
{
false
}
end
end
spec/features/issues/issue_detail_spec.rb
View file @
903efabd
...
...
@@ -23,5 +23,6 @@
context
'when issue description has xss snippet'
do
before
do
issue
.
update!
(
description:
''
)
sign_in
(
user
)
visit
project_issue_path
(
project
,
issue
)
...
...
@@ -26,7 +27,6 @@
sign_in
(
user
)
visit
project_issue_path
(
project
,
issue
)
wait_for_requests
end
it
'encodes the description to prevent xss issues'
do
page
.
within
(
'.issuable-details .detail-page-description'
)
do
...
...
@@ -29,5 +29,7 @@
end
it
'encodes the description to prevent xss issues'
do
page
.
within
(
'.issuable-details .detail-page-description'
)
do
image
=
find
(
'img.js-lazy-loaded'
)
expect
(
page
).
to
have_selector
(
'img'
,
count:
1
)
...
...
@@ -33,6 +35,6 @@
expect
(
page
).
to
have_selector
(
'img'
,
count:
1
)
expect
(
find
(
'img'
)
[
'onerror'
]).
to
be_nil
expect
(
find
(
'img'
)
[
'src'
]).
to
end_with
(
'/a'
)
expect
(
image
[
'onerror'
]).
to
be_nil
expect
(
image
[
'src'
]).
to
end_with
(
'/a'
)
end
end
end
...
...
spec/features/projects/files/template_type_dropdown_spec.rb
View file @
903efabd
...
...
@@ -75,6 +75,11 @@
check_type_selector_toggle_text
(
'.gitignore'
)
end
it
'sets the toggle text when selecting the template type'
do
select_template_type
(
'.gitignore'
)
check_type_selector_toggle_text
(
'.gitignore'
)
end
it
'selects every template type correctly'
do
try_selecting_all_types
end
...
...
spec/lib/gitlab/graphql/connections/keyset/connection_spec.rb
View file @
903efabd
...
...
@@ -103,7 +103,75 @@
end
end
context
'when multiple orders are defined'
do
shared_examples
'nodes are in ascending order'
do
context
'when no cursor is passed'
do
let
(
:arguments
)
{
{}
}
it
'returns projects in ascending order'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
ascending_nodes
)
end
end
context
'when before cursor value is not NULL'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
ascending_nodes
[
2
])
}
}
it
'returns all projects before the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
ascending_nodes
.
first
(
2
))
end
end
context
'when after cursor value is not NULL'
do
let
(
:arguments
)
{
{
after:
encoded_cursor
(
ascending_nodes
[
1
])
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
ascending_nodes
.
last
(
3
))
end
end
context
'when before and after cursor'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
ascending_nodes
.
last
),
after:
encoded_cursor
(
ascending_nodes
.
first
)
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
ascending_nodes
[
1
..
3
])
end
end
end
shared_examples
'nodes are in descending order'
do
context
'when no cursor is passed'
do
let
(
:arguments
)
{
{}
}
it
'only returns projects in descending order'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
descending_nodes
)
end
end
context
'when before cursor value is not NULL'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
descending_nodes
[
2
])
}
}
it
'returns all projects before the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
descending_nodes
.
first
(
2
))
end
end
context
'when after cursor value is not NULL'
do
let
(
:arguments
)
{
{
after:
encoded_cursor
(
descending_nodes
[
1
])
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
descending_nodes
.
last
(
3
))
end
end
context
'when before and after cursor'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
descending_nodes
.
last
),
after:
encoded_cursor
(
descending_nodes
.
first
)
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
(
descending_nodes
[
1
..
3
])
end
end
end
context
'when multiple orders with nil values are defined'
do
let!
(
:project1
)
{
create
(
:project
,
last_repository_check_at:
10
.
days
.
ago
)
}
# Asc: project5 Desc: project3
let!
(
:project2
)
{
create
(
:project
,
last_repository_check_at:
nil
)
}
# Asc: project1 Desc: project1
let!
(
:project3
)
{
create
(
:project
,
last_repository_check_at:
5
.
days
.
ago
)
}
# Asc: project3 Desc: project5
...
...
@@ -114,7 +182,5 @@
let
(
:nodes
)
do
Project
.
order
(
Arel
.
sql
(
'projects.last_repository_check_at IS NULL'
)).
order
(
last_repository_check_at: :asc
).
order
(
id: :asc
)
end
context
'when no cursor is passed'
do
let
(
:arguments
)
{
{}
}
let
(
:ascending_nodes
)
{
[
project5
,
project1
,
project3
,
project2
,
project4
]
}
...
...
@@ -120,8 +186,5 @@
it
'returns projects in ascending order'
do
expect
(
subject
.
sliced_nodes
).
to
eq
([
project5
,
project1
,
project3
,
project2
,
project4
])
end
end
it_behaves_like
'nodes are in ascending order'
context
'when before cursor value is NULL'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
project4
)
}
}
...
...
@@ -131,14 +194,6 @@
end
end
context
'when before cursor value is not NULL'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
project3
)
}
}
it
'returns all projects before the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
([
project5
,
project1
])
end
end
context
'when after cursor value is NULL'
do
let
(
:arguments
)
{
{
after:
encoded_cursor
(
project2
)
}
}
...
...
@@ -146,25 +201,9 @@
expect
(
subject
.
sliced_nodes
).
to
eq
([
project4
])
end
end
context
'when after cursor value is not NULL'
do
let
(
:arguments
)
{
{
after:
encoded_cursor
(
project1
)
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
([
project3
,
project2
,
project4
])
end
end
context
'when before and after cursor'
do
let
(
:arguments
)
{
{
before:
encoded_cursor
(
project4
),
after:
encoded_cursor
(
project5
)
}
}
it
'returns all projects after the cursor'
do
expect
(
subject
.
sliced_nodes
).
to
eq
([
project1
,
project3
,
project2
])
end
end
end
context
'when descending'
do
let
(
:nodes
)
do
Project
.
order
(
Arel
.
sql
(
'projects.last_repository_check_at IS NULL'
)).
order
(
last_repository_check_at: :desc
).
order
(
id: :asc
)
end
...
...
@@ -165,10 +204,8 @@
end
context
'when descending'
do
let
(
:nodes
)
do
Project
.
order
(
Arel
.
sql
(
'projects.last_repository_check_at IS NULL'
)).
order
(
last_repository_check_at: :desc
).
order
(
id: :asc
)