This instance will be upgraded to Heptapod 0.27.1 on 2021-12-02 at 15:00 UTC+1 (a few minutes of down time)

Commit 5e752496 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent af296eb4e807
......@@ -98,6 +98,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Remove IIFEs from jira_connect.js file. !19248 (nuwe1)
## 12.4.5
- No changes.
## 12.4.3
### Fixed (2 changes)
......@@ -370,6 +370,10 @@ entry.
- Change selects from default browser style to custom style.
## 12.4.5
- No changes.
## 12.4.3
### Fixed (2 changes)
......@@ -9,7 +9,12 @@ export default {
computed: {
...mapState(['traceEndpoint', 'trace', 'isTraceComplete']),
updated() {
this.$nextTick(() => {
title: Fixes job log not scrolling to the bottom
type: fixed
......@@ -29,6 +29,10 @@ def ce_port_changelog?(changelog_path) && !ee_changelog?(changelog_path)
def docs_only_change?
helper.changes_by_category.keys == [:docs]
def check_changelog(path)
yaml = YAML.safe_load(
......@@ -55,7 +59,7 @@ def sanitized_mr_title
gitlab.mr_json["title"].gsub(/^WIP: */, '').gsub(/`/, '\\\`')
changelog_needed = (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
changelog_needed = !docs_only_change? && (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
changelog_found = git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
if git.modified_files.include?("")
......@@ -8,10 +8,13 @@ class RemoveIndexOnSnippetsProjectId < ActiveRecord::Migration[5.2]
def up
remove_concurrent_index :snippets, [:project_id]
remove_concurrent_index_by_name :snippets, 'index_snippets_on_project_id'
# This is an extra index that is not present in db/schema.rb but known to exist on some installs
remove_concurrent_index_by_name :snippets, :snippets_project_id_idx if index_exists_by_name? :snippets, :snippets_project_id_idx
def down
add_concurrent_index :snippets, [:project_id]
add_concurrent_index :snippets, [:project_id], name: 'index_snippets_on_project_id'
......@@ -19,7 +19,7 @@ NOTE: **Note:**
- Group sync: Once an hour, GitLab will update group membership
based on LDAP group members.
## Multiple LDAP servers **(STARTER ONLY)**
## Multiple LDAP servers
With GitLab Enterprise Edition Starter, you can configure multiple LDAP servers
that your GitLab instance will connect to.
......@@ -58,30 +58,30 @@ This section is for links to information elsewhere in the GitLab documentation.
- required extension pg_trgm
- required extension postgres_fdw for Geo
- Errors like this in the `production / Sidekiq` log; see: [Set default_transaction_isolation into read committed](
- Errors like this in the `production/sidekiq` log; see: [Set default_transaction_isolation into read committed](
ActiveRecord::StatementInvalid PG::TRSerializationFailure: ERROR: could not serialize access due to concurrent update
ActiveRecord::StatementInvalid PG::TRSerializationFailure: ERROR: could not serialize access due to concurrent update
- PostgreSQL HA - [replication slot errors](
- PostgreSQL HA - [replication slot errors](
pg_basebackup: could not create temporary replication slot "pg_basebackup_12345": ERROR: all replication slots are in use
HINT: Free one or increase max_replication_slots.
pg_basebackup: could not create temporary replication slot "pg_basebackup_12345": ERROR: all replication slots are in use
HINT: Free one or increase max_replication_slots.
- GEO [replication errors](../geo/replication/ including:
ERROR: replication slots can only be used if max_replication_slots > 0
ERROR: replication slots can only be used if max_replication_slots > 0
FATAL: could not start WAL streaming: ERROR: replication slot “geo_secondary_my_domain_com” does not exist
FATAL: could not start WAL streaming: ERROR: replication slot “geo_secondary_my_domain_com” does not exist
Command exceeded allowed execution time
Command exceeded allowed execution time
PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device
PANIC: could not write to file ‘pg_xlog/xlogtemp.123’: No space left on device
- [Checking GEO configuration](../geo/replication/ including
- reconfiguring hosts/ports
......@@ -69,6 +69,7 @@ description: 'Learn how to contribute to GitLab.'
- [Developing against interacting components or features](
- [File uploads](
- [Auto DevOps development guide](
- [Cycle Analytics development guide](
## Performance guides
# Cycle Analytics development guide
Cycle analytics calculates the time between two arbitrary events recorded on domain objects and provides aggregated statistics about the duration.
## Stage
During development, events occur that move issues and merge requests through different stages of progress until they are considered finished. These stages can be expressed with the `Stage` model.
Example stage:
- Name: Development
- Start event: Issue created
- End event: Issue first mentioned in commit
- Parent: `Group: gitlab-org`
### Events
Events are the smallest building blocks of the cycle analytics feature. A stage consists of two events:
- Start
- End
These events play a key role in the duration calculation.
Formula: `duration = end_event_time - start_event_time`
To make the duration calculation flexible, each `Event` is implemented as a separate class. They're responsible for defining a timestamp expression that will be used in the calculation query.
#### Implementing an `Event` class
There are a few methods that are required to be implemented, the `StageEvent` base class describes them in great detail. The most important ones are:
- `object_type`
- `timestamp_projection`
The `object_type` method defines which domain object will be queried for the calculation. Currently two models are allowed:
- `Issue`
- `MergeRequest`
For the duration calculation the `timestamp_projection` method will be used.
def timestamp_projection
# your timestamp expression comes here
# event will use the issue creation time in the duration calculation
def timestamp_projection
NOTE: **Note:**
More complex expressions are also possible (e.g. using `COALESCE`). Look at the existing event classes for examples.
In some cases, defining the `timestamp_projection` method is not enough. The calculation query should know which table contains the timestamp expression. Each `Event` class is responsible for making modifications to the calculation query to make the `timestamp_projection` work. This usually means joining an additional table.
Example for joining the `issue_metrics` table and using the `first_mentioned_in_commit_at` column as the timestamp expression:
def object_type
def timestamp_projection
def apply_query_customization(query)
# in this case the query attribute will be based on the Issue model: `Issue.where(...)`
### Validating start and end events
Some start/end event pairs are not "compatible" with each other. For example:
- "Issue created" to "Merge Request created": The event classes are defined on different domain models, the `object_type` method is different.
- "Issue closed" to "Issue created": Issue must be created first before it can be closed.
- "Issue closed" to "Issue closed": Duration is always 0.
The `StageEvents` module describes the allowed `start_event` and `end_event` pairings (`PAIRING_RULES` constant). If a new event is added, it needs to be registered in this module.
​To add a new event:​
1. Add an entry in `ENUM_MAPPING` with a unique number, it'll be used in the `Stage` model as `enum`.
1. Define which events are compatible with the event in the `PAIRING_RULES` hash.
Supported start/end event pairings:
graph LR;
IssueCreated --> IssueClosed;
IssueCreated --> IssueFirstAddedToBoard;
IssueCreated --> IssueFirstAssociatedWithMilestone;
IssueCreated --> IssueFirstMentionedInCommit;
IssueCreated --> IssueLastEdited;
IssueCreated --> IssueLabelAdded;
IssueCreated --> IssueLabelRemoved;
MergeRequestCreated --> MergeRequestMerged;
MergeRequestCreated --> MergeRequestClosed;
MergeRequestCreated --> MergeRequestFirstDeployedToProduction;
MergeRequestCreated --> MergeRequestLastBuildStarted;
MergeRequestCreated --> MergeRequestLastBuildFinished;
MergeRequestCreated --> MergeRequestLastEdited;
MergeRequestCreated --> MergeRequestLabelAdded;
MergeRequestCreated --> MergeRequestLabelRemoved;
MergeRequestLastBuildStarted --> MergeRequestLastBuildFinished;
MergeRequestLastBuildStarted --> MergeRequestClosed;
MergeRequestLastBuildStarted --> MergeRequestFirstDeployedToProduction;
MergeRequestLastBuildStarted --> MergeRequestLastEdited;
MergeRequestLastBuildStarted --> MergeRequestMerged;
MergeRequestLastBuildStarted --> MergeRequestLabelAdded;
MergeRequestLastBuildStarted --> MergeRequestLabelRemoved;
MergeRequestMerged --> MergeRequestFirstDeployedToProduction;
MergeRequestMerged --> MergeRequestClosed;
MergeRequestMerged --> MergeRequestFirstDeployedToProduction;
MergeRequestMerged --> MergeRequestLastEdited;
MergeRequestMerged --> MergeRequestLabelAdded;
MergeRequestMerged --> MergeRequestLabelRemoved;
IssueLabelAdded --> IssueLabelAdded;
IssueLabelAdded --> IssueLabelRemoved;
IssueLabelAdded --> IssueClosed;
IssueLabelRemoved --> IssueClosed;
IssueFirstAddedToBoard --> IssueClosed;
IssueFirstAddedToBoard --> IssueFirstAssociatedWithMilestone;
IssueFirstAddedToBoard --> IssueFirstMentionedInCommit;
IssueFirstAddedToBoard --> IssueLastEdited;
IssueFirstAddedToBoard --> IssueLabelAdded;
IssueFirstAddedToBoard --> IssueLabelRemoved;
IssueFirstAssociatedWithMilestone --> IssueClosed;
IssueFirstAssociatedWithMilestone --> IssueFirstAddedToBoard;
IssueFirstAssociatedWithMilestone --> IssueFirstMentionedInCommit;
IssueFirstAssociatedWithMilestone --> IssueLastEdited;
IssueFirstAssociatedWithMilestone --> IssueLabelAdded;
IssueFirstAssociatedWithMilestone --> IssueLabelRemoved;
IssueFirstMentionedInCommit --> IssueClosed;
IssueFirstMentionedInCommit --> IssueFirstAssociatedWithMilestone;
IssueFirstMentionedInCommit --> IssueFirstAddedToBoard;
IssueFirstMentionedInCommit --> IssueLastEdited;
IssueFirstMentionedInCommit --> IssueLabelAdded;
IssueFirstMentionedInCommit --> IssueLabelRemoved;
IssueClosed --> IssueLastEdited;
IssueClosed --> IssueLabelAdded;
IssueClosed --> IssueLabelRemoved;
MergeRequestClosed --> MergeRequestFirstDeployedToProduction;
MergeRequestClosed --> MergeRequestLastEdited;
MergeRequestClosed --> MergeRequestLabelAdded;
MergeRequestClosed --> MergeRequestLabelRemoved;
MergeRequestFirstDeployedToProduction --> MergeRequestLastEdited;
MergeRequestFirstDeployedToProduction --> MergeRequestLabelAdded;
MergeRequestFirstDeployedToProduction --> MergeRequestLabelRemoved;
MergeRequestLastBuildFinished --> MergeRequestClosed;
MergeRequestLastBuildFinished --> MergeRequestFirstDeployedToProduction;
MergeRequestLastBuildFinished --> MergeRequestLastEdited;
MergeRequestLastBuildFinished --> MergeRequestMerged;
MergeRequestLastBuildFinished --> MergeRequestLabelAdded;
MergeRequestLastBuildFinished --> MergeRequestLabelRemoved;
MergeRequestLabelAdded --> MergeRequestLabelAdded;
MergeRequestLabelAdded --> MergeRequestLabelRemoved;
MergeRequestLabelRemoved --> MergeRequestLabelAdded;
MergeRequestLabelRemoved --> MergeRequestLabelRemoved;
### Parent
Teams and organizations might define their own way of building software, thus stages can be completely different. For each stage, a parent object needs to be defined.
Currently supported parents:
- `Project`
- `Group`
#### How parent relationship it work
1. User navigates to the cycle analytics page.
1. User selects a group.
1. Backend loads the defined stages for the selected group.
1. Additions and modifications to the stages will be persisted within the selected group only.
### Default stages
The [original implementation]( of cycle analytics defined 7 stages. These stages are always available for each parent, however altering these stages is not possible.
To make things efficient and reduce the number of records created, the default stages are expressed as in-memory objects (not persisted). When the user creates a custom stage for the first time, all the stages will be persisted. This behaviour is implemented in the cycle analytics service objects.
The reason for this was that we'd like to add the abilities to hide and order stages later on.
## Data Collector
`DataCollector` is the central point where the data will be queried from the database. The class always operates on a single stage and consists of the following components:
- `BaseQueryBuilder`:
- Responsible for composing the initial query.
- Deals with `Stage` specific configuration: events and their query customizations.
- Parameters coming from the UI: date ranges.
- `Median`: Calculates the median duration for a stage using the query from `BaseQueryBuilder`.
- `RecordsFetcher`: Loads relevant records for a stage using the query from `BaseQueryBuilder` and specific `Finder` classes to apply visibility rules.
- `DataForDurationChart`: Loads calculated durations with the finish time (end event timestamp) for the scatterplot chart.
For a new calculation or a query, implement it as a new method call in the `DataCollector` class.
## Database query
Structure of the database query:
SELECT (customized by: Median or RecordsFetcher or DataForDurationChart)
FROM OBJECT_TYPE (Issue or MergeRequest)
INNER JOIN (several JOIN statements, depending on the events)
(Filter by the PARENT model, example: filter Issues from Project A)
(Date range filter based on the OBJECT_TYPE.created_at)
(Check if the START_EVENT is earlier than END_EVENT, preventing negative duration)
Structure of the `SELECT` statement for `Median`:
Structure of the `SELECT` statement for `DataForDurationChart`:
## High-level overview
- Rails Controller (`Analytics::CycleAnalytics` module): Cycle analytics exposes its data via JSON endpoints, implemented within the `analytics` workspace. Configuring the stages are also implements JSON endpoints (CRUD).
- Services (`Analytics::CycleAnalytics` module): All `Stage` related actions will be delegated to respective service objects.
- Models (`Analytics::CycleAnalytics` module): Models are used to persist the `Stage` objects `ProjectStage` and `GroupStage`.
- Feature classes (`Gitlab::Analytics::CycleAnalytics` module):
- Responsible for composing queries and define feature specific busines logic.
- `DataCollector`, `Event`, `StageEvents`, etc.
## Testing
Since we have a lots of events and possible pairings, testing each pairing is not possible. The rule is to have at least one test case using an `Event` class.
Writing a test case for a stage using a new `Event` can be challenging since data must be created for both events. To make this a bit simpler, each test case must be implemented in the `data_collector_spec.rb` where the stage is tested through the `DataCollector`. Each test case will be turned into multiple tests, covering the following cases:
- Different parents: `Group` or `Project`
- Different calculations: `Median`, `RecordsFetcher` or `DataForDurationChart`
......@@ -4,7 +4,7 @@
NOTE: **Note:** NGINX Ingress versions prior to 0.16.0 offer an included [VTS Prometheus metrics exporter](, which exports metrics different than the built-in metrics.
GitLab has support for automatically detecting and monitoring the Kubernetes NGINX Ingress controller. This is provided by leveraging the built-in Prometheus metrics included with Kubernetes NGINX Ingress Controller [version 0.16.0]( onward.
GitLab has support for automatically detecting and monitoring the Kubernetes NGINX Ingress controller. This is provided by leveraging the built-in Prometheus metrics included with Kubernetes NGINX Ingress controller [version 0.16.0]( onward.
## Requirements
......@@ -8,6 +8,7 @@ module Common
def self.included(base)
base.view 'app/assets/javascripts/issue_show/components/title.vue' do
element :edit_button
element :title, required: true
base.view 'app/assets/javascripts/issue_show/components/fields/title.vue' do
......@@ -157,7 +157,7 @@ def toggle_more_assignees_link
def select_filter_with_text(text)
retry_on_exception do
click_element :discussion_filter
find_element(:filter_options, text: text).click
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