Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ba836d9859
commit
ade18c9d68
|
|
@ -402,7 +402,6 @@ RSpec/RepeatedExample:
|
|||
- 'spec/graphql/gitlab_schema_spec.rb'
|
||||
- 'spec/helpers/users_helper_spec.rb'
|
||||
- 'spec/lib/banzai/filter/autolink_filter_spec.rb'
|
||||
- 'spec/lib/banzai/filter/issuable_state_filter_spec.rb'
|
||||
- 'spec/lib/gitlab/closing_issue_extractor_spec.rb'
|
||||
- 'spec/lib/gitlab/danger/changelog_spec.rb'
|
||||
- 'spec/lib/gitlab/git/blob_spec.rb'
|
||||
|
|
|
|||
|
|
@ -208,24 +208,12 @@ class Projects::BlobController < Projects::ApplicationController
|
|||
.last_for_path(@repository, @ref, @path).sha
|
||||
end
|
||||
|
||||
def set_code_navigation_build
|
||||
return if Feature.disabled?(:code_navigation, @project)
|
||||
|
||||
artifact =
|
||||
Ci::JobArtifact
|
||||
.for_sha(@blob.commit_id, @project.id)
|
||||
.for_job_name(Ci::Build::CODE_NAVIGATION_JOB_NAME)
|
||||
.last
|
||||
|
||||
@code_navigation_build = artifact&.job
|
||||
end
|
||||
|
||||
def show_html
|
||||
environment_params = @repository.branch_exists?(@ref) ? { ref: @ref } : { commit: @commit }
|
||||
environment_params[:find_latest] = true
|
||||
@environment = EnvironmentsFinder.new(@project, current_user, environment_params).execute.last
|
||||
@last_commit = @repository.last_commit_for_path(@commit.id, @blob.path)
|
||||
set_code_navigation_build
|
||||
@code_navigation_path = Gitlab::CodeNavigationPath.new(@project, @blob.commit_id).full_json_path_for(@blob.path)
|
||||
|
||||
render 'show'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,8 +33,6 @@ module Ci
|
|||
scheduler_failure: 2
|
||||
}.freeze
|
||||
|
||||
CODE_NAVIGATION_JOB_NAME = 'code_navigation'
|
||||
|
||||
has_one :deployment, as: :deployable, class_name: 'Deployment'
|
||||
has_one :resource, class_name: 'Ci::Resource', inverse_of: :build
|
||||
has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
|
||||
|
|
|
|||
|
|
@ -64,6 +64,10 @@ class DiffFileEntity < DiffFileBaseEntity
|
|||
# Used for parallel diffs
|
||||
expose :parallel_diff_lines, using: DiffLineParallelEntity, if: -> (diff_file, options) { parallel_diff_view?(options, diff_file) && diff_file.text? }
|
||||
|
||||
expose :code_navigation_path, if: -> (diff_file) { options[:code_navigation_path] } do |diff_file|
|
||||
options[:code_navigation_path].full_json_path_for(diff_file.new_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parallel_diff_view?(options, diff_file)
|
||||
|
|
|
|||
|
|
@ -70,13 +70,21 @@ class DiffsEntity < Grape::Entity
|
|||
|
||||
expose :diff_files do |diffs, options|
|
||||
submodule_links = Gitlab::SubmoduleLinks.new(merge_request.project.repository)
|
||||
DiffFileEntity.represent(diffs.diff_files, options.merge(submodule_links: submodule_links))
|
||||
code_navigation_path =
|
||||
Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs.head_sha)
|
||||
|
||||
DiffFileEntity.represent(diffs.diff_files,
|
||||
options.merge(submodule_links: submodule_links, code_navigation_path: code_navigation_path))
|
||||
end
|
||||
|
||||
expose :merge_request_diffs, using: MergeRequestDiffEntity, if: -> (_, options) { options[:merge_request_diffs]&.any? } do |diffs|
|
||||
options[:merge_request_diffs]
|
||||
end
|
||||
|
||||
expose :definition_path_prefix, if: -> (diff_file) { Feature.enabled?(:code_navigation, merge_request.project) } do |diffs|
|
||||
project_blob_path(merge_request.project, diffs.diff_refs.head_sha)
|
||||
end
|
||||
|
||||
def merge_request
|
||||
options[:merge_request]
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,11 @@ class PaginatedDiffEntity < Grape::Entity
|
|||
|
||||
expose :diff_files do |diffs, options|
|
||||
submodule_links = Gitlab::SubmoduleLinks.new(merge_request.project.repository)
|
||||
DiffFileEntity.represent(diffs.diff_files, options.merge(submodule_links: submodule_links))
|
||||
code_navigation_path =
|
||||
Gitlab::CodeNavigationPath.new(merge_request.project, diffs.diff_refs.head_sha)
|
||||
|
||||
DiffFileEntity.represent(diffs.diff_files,
|
||||
options.merge(submodule_links: submodule_links, code_navigation_path: code_navigation_path))
|
||||
end
|
||||
|
||||
expose :pagination do
|
||||
|
|
|
|||
|
|
@ -45,9 +45,30 @@ module Metrics
|
|||
|
||||
# Returns a new dashboard Hash, supplemented with DB info
|
||||
def process_dashboard
|
||||
::Gitlab::Metrics::Dashboard::Processor
|
||||
.new(project, raw_dashboard, sequence, process_params)
|
||||
.process
|
||||
# Get the dashboard from cache/disk before beginning the benchmark.
|
||||
dashboard = raw_dashboard
|
||||
processed_dashboard = nil
|
||||
|
||||
benchmark_processing do
|
||||
processed_dashboard = ::Gitlab::Metrics::Dashboard::Processor
|
||||
.new(project, dashboard, sequence, process_params)
|
||||
.process
|
||||
end
|
||||
|
||||
processed_dashboard
|
||||
end
|
||||
|
||||
def benchmark_processing
|
||||
output = nil
|
||||
|
||||
processing_time_seconds = Benchmark.realtime { output = yield }
|
||||
|
||||
if output
|
||||
processing_time_metric.observe(
|
||||
processing_time_metric_labels,
|
||||
processing_time_seconds * 1_000
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def process_params
|
||||
|
|
@ -72,6 +93,26 @@ module Metrics
|
|||
def sequence
|
||||
SEQUENCE
|
||||
end
|
||||
|
||||
def processing_time_metric
|
||||
@processing_time_metric ||= ::Gitlab::Metrics.summary(
|
||||
:gitlab_metrics_dashboard_processing_time_ms,
|
||||
'Metrics dashboard processing time in milliseconds'
|
||||
)
|
||||
end
|
||||
|
||||
def processing_time_metric_labels
|
||||
{
|
||||
stages: sequence_string,
|
||||
service: self.class.name
|
||||
}
|
||||
end
|
||||
|
||||
# If @sequence is [STAGES::CommonMetricsInserter, STAGES::CustomMetricsInserter],
|
||||
# this function will output `CommonMetricsInserter-CustomMetricsInserter`.
|
||||
def sequence_string
|
||||
sequence.map { |stage_class| stage_class.to_s.split('::').last }.join('-')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@
|
|||
= render "projects/blob/auxiliary_viewer", blob: blob
|
||||
|
||||
#blob-content-holder.blob-content-holder
|
||||
- if @code_navigation_build
|
||||
- code_nav_url = raw_project_job_artifacts_url(@project, @code_navigation_build, path: "lsif/#{blob.path}")
|
||||
#js-code-navigation{ data: { code_nav_url: "#{code_nav_url}.json", definition_path_prefix: project_blob_path(@project, @ref) } }
|
||||
- if @code_navigation_path
|
||||
#js-code-navigation{ data: { code_nav_url: @code_navigation_path, definition_path_prefix: project_blob_path(@project, @ref) } }
|
||||
%article.file-holder
|
||||
= render 'projects/blob/header', blob: blob
|
||||
= render 'projects/blob/content', blob: blob
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Optimize suggestions counters
|
||||
merge_request: 26443
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -71,7 +71,6 @@
|
|||
- kubernetes_management
|
||||
- language_specific
|
||||
- license_compliance
|
||||
- live_coding
|
||||
- load_testing
|
||||
- logging
|
||||
- malware_scanning
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddIndexOnAuthorIdAndCreatedAtAndIdToNotes < ActiveRecord::Migration[6.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_index :notes, [:author_id, :created_at, :id]
|
||||
remove_concurrent_index :notes, [:author_id, :created_at]
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index :notes, [:author_id, :created_at]
|
||||
remove_concurrent_index :notes, [:author_id, :created_at, :id]
|
||||
end
|
||||
end
|
||||
|
|
@ -9519,7 +9519,7 @@ CREATE INDEX index_namespaces_on_type_partial ON public.namespaces USING btree (
|
|||
|
||||
CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON public.note_diff_files USING btree (diff_note_id);
|
||||
|
||||
CREATE INDEX index_notes_on_author_id_and_created_at ON public.notes USING btree (author_id, created_at);
|
||||
CREATE INDEX index_notes_on_author_id_and_created_at_and_id ON public.notes USING btree (author_id, created_at, id);
|
||||
|
||||
CREATE INDEX index_notes_on_commit_id ON public.notes USING btree (commit_id);
|
||||
|
||||
|
|
@ -12925,5 +12925,6 @@ COPY "schema_migrations" (version) FROM STDIN;
|
|||
20200326144443
|
||||
20200326145443
|
||||
20200330074719
|
||||
20200330132913
|
||||
\.
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
|
|
@ -256,9 +256,9 @@ application server, or a Gitaly node.
|
|||
|
||||
```ruby
|
||||
# Name of storage hash must match storage name in git_data_dirs on GitLab
|
||||
# server ('praefect') and in git_data_dirs on Gitaly nodes ('gitaly-1')
|
||||
# server ('storage_1') and in git_data_dirs on Gitaly nodes ('gitaly-1')
|
||||
praefect['virtual_storages'] = {
|
||||
'praefect' => {
|
||||
'storage_1' => {
|
||||
'gitaly-1' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN',
|
||||
|
|
@ -430,7 +430,7 @@ documentation](index.md#3-gitaly-server-configuration).
|
|||
gitlab-ctl restart gitaly
|
||||
```
|
||||
|
||||
**Complete these steps for each Gitaly node!**
|
||||
**The steps above must be completed for each Gitaly node!**
|
||||
|
||||
After all Gitaly nodes are configured, you can run the Praefect connection
|
||||
checker to verify Praefect can connect to all Gitaly servers in the Praefect
|
||||
|
|
@ -442,6 +442,34 @@ config.
|
|||
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dial-nodes
|
||||
```
|
||||
|
||||
1. Enable automatic failover by editing `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
praefect['failover_enabled'] = true
|
||||
```
|
||||
|
||||
When automatic failover is enabled, Praefect checks the health of internal
|
||||
Gitaly nodes. If the primary has a certain amount of health checks fail, it
|
||||
will promote one of the secondaries to be primary, and demote the primary to
|
||||
be a secondary.
|
||||
|
||||
Manual failover is possible by updating `praefect['virtual_storages']` and
|
||||
nominating a new primary node.
|
||||
|
||||
NOTE: **Note:**: Automatic failover is not yet supported for setups with
|
||||
multiple Praefect nodes. There is currently no coordination between Praefect
|
||||
nodes, which could result in two Praefect instances thinking two different
|
||||
Gitaly nodes are the primary. Follow issue
|
||||
[#2547](https://gitlab.com/gitlab-org/gitaly/-/issues/2547) for
|
||||
updates.
|
||||
|
||||
1. Save the changes to `/etc/gitlab/gitlab.rb` and [reconfigure
|
||||
Praefect](../restart_gitlab.md#omnibus-gitlab-reconfigure):
|
||||
|
||||
```shell
|
||||
gitlab-ctl reconfigure
|
||||
```
|
||||
|
||||
### GitLab
|
||||
|
||||
To complete this section you will need:
|
||||
|
|
@ -560,158 +588,14 @@ Particular attention should be shown to:
|
|||
- Deselect the **default** storage location
|
||||
- Select the **praefect** storage location
|
||||
|
||||

|
||||
|
||||
1. Verify everything is still working by creating a new project. Check the
|
||||
"Initialize repository with a README" box so that there is content in the
|
||||
repository that viewed. If the project is created, and you can see the
|
||||
README file, it works!
|
||||
|
||||
Congratulations! You have configured a highly available Praefect cluster.
|
||||
|
||||
### Failover
|
||||
|
||||
There are two ways to do a failover from one internal Gitaly node to another as the primary. Manually, or automatically.
|
||||
|
||||
As an example, in this `config.toml` we have one virtual storage named "default" with two internal Gitaly nodes behind it.
|
||||
One is deemed the "primary". This means that read and write traffic will go to `internal_storage_0`, and writes
|
||||
will get replicated to `internal_storage_1`:
|
||||
|
||||
```toml
|
||||
socket_path = "/path/to/Praefect.socket"
|
||||
|
||||
# failover_enabled will enable automatic failover
|
||||
failover_enabled = false
|
||||
|
||||
[logging]
|
||||
format = "json"
|
||||
level = "info"
|
||||
|
||||
[[virtual_storage]]
|
||||
name = "default"
|
||||
|
||||
[[virtual_storage.node]]
|
||||
name = "internal_storage_0"
|
||||
address = "tcp://localhost:9999"
|
||||
primary = true
|
||||
token = "supersecret"
|
||||
|
||||
[[virtual_storage.node]]
|
||||
name = "internal_storage_1"
|
||||
address = "tcp://localhost:9998"
|
||||
token = "supersecret"
|
||||
```
|
||||
|
||||
#### Manual failover
|
||||
|
||||
In order to failover from using one internal Gitaly node to using another, a manual failover step can be used. Unless `failover_enabled` is set to `true`
|
||||
in the `config.toml`, the only way to fail over from one primary to using another node as the primary is to do a manual failover.
|
||||
|
||||
1. Move `primary = true` from the current `[[virtual_storage.node]]` to another node in `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
praefect['virtual_storages'] = {
|
||||
'praefect' => {
|
||||
'gitaly-1' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN',
|
||||
# no longer the primary
|
||||
},
|
||||
'gitaly-2' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN',
|
||||
# this is the new primary
|
||||
'primary' => true
|
||||
},
|
||||
'gitaly-3' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
|
||||
|
||||
On a restart, Praefect will send write traffic to `internal_storage_1`. `internal_storage_0` is the new secondary now,
|
||||
and replication jobs will be created to replicate repository data to `internal_storage_0` **from** `internal_storage_1`
|
||||
|
||||
#### Automatic failover
|
||||
|
||||
When automatic failover is enabled, Praefect will do automatic detection of the health of internal Gitaly nodes. If the
|
||||
primary has a certain amount of health checks fail, it will decide to promote one of the secondaries to be primary, and
|
||||
demote the primary to be a secondary.
|
||||
|
||||
1. To enable automatic failover, edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
# failover_enabled turns on automatic failover
|
||||
praefect['failover_enabled'] = true
|
||||
praefect['virtual_storages'] = {
|
||||
'praefect' => {
|
||||
'gitaly-1' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN',
|
||||
'primary' => true
|
||||
},
|
||||
'gitaly-2' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN'
|
||||
},
|
||||
'gitaly-3' => {
|
||||
'address' => 'tcp://GITALY_HOST:8075',
|
||||
'token' => 'PRAEFECT_INTERNAL_TOKEN'
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
|
||||
|
||||
Below is the picture when Praefect starts up with the config.toml above:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Praefect] -->|Mutator RPC| B(internal_storage_0)
|
||||
B --> |Replication|C[internal_storage_1]
|
||||
```
|
||||
|
||||
Let's say suddenly `internal_storage_0` goes down. Praefect will detect this and
|
||||
automatically switch over to `internal_storage_1`, and `internal_storage_0` will serve as a secondary:
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Praefect] -->|Mutator RPC| B(internal_storage_1)
|
||||
B --> |Replication|C[internal_storage_0]
|
||||
```
|
||||
|
||||
NOTE: **Note:**: Currently this feature is supported for setups that only have 1 Praefect instance. Praefect instances running,
|
||||
for example behind a load balancer, `failover_enabled` should be disabled. The reason is The reason is because there
|
||||
is no coordination that currently happens across different Praefect instances, so there could be a situation where
|
||||
two Praefect instances think two different Gitaly nodes are the primary.
|
||||
|
||||
## Backend Node Recovery
|
||||
|
||||
When a Praefect backend node fails and is no longer able to
|
||||
replicate changes, the backend node will start to drift from the primary. If
|
||||
that node eventually recovers, it will need to be reconciled with the current
|
||||
primary. The primary node is considered the single source of truth for the
|
||||
state of a shard. The Praefect `reconcile` subcommand allows for the manual
|
||||
reconciliation between a backend node and the current primary.
|
||||
|
||||
Run the following command on the Praefect server after all placeholders
|
||||
(`<virtual-storage>` and `<target-storage>`) have been replaced:
|
||||
|
||||
```shell
|
||||
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -target <target-storage>
|
||||
```
|
||||
|
||||
- Replace the placeholder `<virtual-storage>` with the virtual storage containing the backend node storage to be checked.
|
||||
- Replace the placeholder `<target-storage>` with the backend storage name.
|
||||
|
||||
The command will return a list of repositories that were found to be
|
||||
inconsistent against the current primary. Each of these inconsistencies will
|
||||
also be logged with an accompanying replication job ID.
|
||||
|
||||
## Grafana
|
||||
### Grafana
|
||||
|
||||
Grafana is included with GitLab, and can be used to monitor your Praefect
|
||||
cluster. See [Grafana Dashboard
|
||||
|
|
@ -754,6 +638,54 @@ To get started quickly:
|
|||
1. Go to **Explore** and query `gitlab_build_info` to verify that you are
|
||||
getting metrics from all your machines.
|
||||
|
||||
Congratulations! You've configured an observable highly available Praefect
|
||||
cluster.
|
||||
|
||||
## Automatic failover and leader election
|
||||
|
||||
Praefect regularly checks the health of each backend Gitaly node. This
|
||||
information can be used to automatically failover to a new primary node if the
|
||||
current primary node is found to be unhealthy.
|
||||
|
||||
- **Manual:** Automatic failover is disabled. The primary node can be
|
||||
reconfigured in `/etc/gitlab/gitlab.rb` on the Praefect node. Modify the
|
||||
`praefect['virtual_storages']` field by moving the `primary = true` to promote
|
||||
a different Gitaly node to primary. In the steps above, `gitaly-1` was set to
|
||||
the primary.
|
||||
- **Memory:** Enabled by setting `praefect['failover_enabled'] = true` in
|
||||
`/etc/gitlab/gitlab.rb` on the Praefect node. If a sufficient number of health
|
||||
checks fail for the current primary backend Gitaly node, and new primary will
|
||||
be elected. **Do not use with multiple Praefect nodes!** Using with multiple
|
||||
Praefect nodes is likely to result in a split brain.
|
||||
- **PostgreSQL:** Coming soon. See isse
|
||||
[#2547](https://gitlab.com/gitlab-org/gitaly/-/issues/2547) for updates.
|
||||
|
||||
It is likely that we will implement support for Consul, and a cloud native
|
||||
strategy in the future.
|
||||
|
||||
## Backend Node Recovery
|
||||
|
||||
When a Praefect backend node fails and is no longer able to
|
||||
replicate changes, the backend node will start to drift from the primary. If
|
||||
that node eventually recovers, it will need to be reconciled with the current
|
||||
primary. The primary node is considered the single source of truth for the
|
||||
state of a shard. The Praefect `reconcile` subcommand allows for the manual
|
||||
reconciliation between a backend node and the current primary.
|
||||
|
||||
Run the following command on the Praefect server after all placeholders
|
||||
(`<virtual-storage>` and `<target-storage>`) have been replaced:
|
||||
|
||||
```shell
|
||||
sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -target <target-storage>
|
||||
```
|
||||
|
||||
- Replace the placeholder `<virtual-storage>` with the virtual storage containing the backend node storage to be checked.
|
||||
- Replace the placeholder `<target-storage>` with the backend storage name.
|
||||
|
||||
The command will return a list of repositories that were found to be
|
||||
inconsistent against the current primary. Each of these inconsistencies will
|
||||
also be logged with an accompanying replication job ID.
|
||||
|
||||
## Migrating existing repositories to Praefect
|
||||
|
||||
If your GitLab instance already has repositories, these won't be migrated
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ The following metrics are available:
|
|||
| `failed_login_captcha_total` | Gauge | 11.0 | Counter of failed CAPTCHA attempts during login | |
|
||||
| `successful_login_captcha_total` | Gauge | 11.0 | Counter of successful CAPTCHA attempts during login | |
|
||||
| `auto_devops_pipelines_completed_total` | Counter | 12.7 | Counter of completed Auto DevOps pipelines, labeled by status | |
|
||||
| `gitlab_metrics_dashboard_processing_time_ms` | Summary | 12.10 | Metrics dashboard processing time in milliseconds | service, stages |
|
||||
|
||||
## Metrics controlled by a feature flag
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
class CodeNavigationPath
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
include Gitlab::Routing
|
||||
|
||||
CODE_NAVIGATION_JOB_NAME = 'code_navigation'
|
||||
|
||||
def initialize(project, commit_sha)
|
||||
@project = project
|
||||
@commit_sha = commit_sha
|
||||
end
|
||||
|
||||
def full_json_path_for(path)
|
||||
return if Feature.disabled?(:code_navigation, project)
|
||||
return unless build
|
||||
|
||||
raw_project_job_artifacts_path(project, build, path: "lsif/#{path}.json")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :project, :commit_sha
|
||||
|
||||
def build
|
||||
strong_memoize(:build) do
|
||||
artifact = ::Ci::JobArtifact
|
||||
.for_sha(commit_sha, project.id)
|
||||
.for_job_name(CODE_NAVIGATION_JOB_NAME)
|
||||
.last
|
||||
|
||||
artifact&.job
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -118,32 +118,6 @@ describe Projects::BlobController do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when there is an artifact with code navigation data' do
|
||||
let!(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit.id) }
|
||||
let!(:job) { create(:ci_build, pipeline: pipeline, name: Ci::Build::CODE_NAVIGATION_JOB_NAME) }
|
||||
let!(:artifact) { create(:ci_job_artifact, :lsif, job: job) }
|
||||
|
||||
let(:id) { 'master/README.md' }
|
||||
|
||||
it 'assigns code_navigation_build variable' do
|
||||
request
|
||||
|
||||
expect(assigns[:code_navigation_build]).to eq(job)
|
||||
end
|
||||
|
||||
context 'when code_navigation feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(code_navigation: false)
|
||||
end
|
||||
|
||||
it 'does not assign code_navigation_build variable' do
|
||||
request
|
||||
|
||||
expect(assigns[:code_navigation_build]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET diff' do
|
||||
|
|
|
|||
|
|
@ -156,20 +156,6 @@ describe Banzai::Filter::IssuableStateFilter do
|
|||
expect(doc.css('a').last.text).to eq(merge_request.to_reference)
|
||||
end
|
||||
|
||||
it 'ignores reopened merge request references' do
|
||||
merge_request = create_merge_request(:opened)
|
||||
|
||||
link = create_link(
|
||||
merge_request.to_reference,
|
||||
merge_request: merge_request.id,
|
||||
reference_type: 'merge_request'
|
||||
)
|
||||
|
||||
doc = filter(link, context)
|
||||
|
||||
expect(doc.css('a').last.text).to eq(merge_request.to_reference)
|
||||
end
|
||||
|
||||
it 'ignores locked merge request references' do
|
||||
merge_request = create_merge_request(:locked)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::CodeNavigationPath do
|
||||
context 'when there is an artifact with code navigation data' do
|
||||
let(:project) { create(:project, :repository) }
|
||||
let(:sha) { project.commit.id }
|
||||
let(:build_name) { Gitlab::CodeNavigationPath::CODE_NAVIGATION_JOB_NAME }
|
||||
let(:path) { 'lib/app.rb' }
|
||||
let!(:pipeline) { create(:ci_pipeline, project: project, sha: sha) }
|
||||
let!(:job) { create(:ci_build, pipeline: pipeline, name: build_name) }
|
||||
let!(:artifact) { create(:ci_job_artifact, :lsif, job: job) }
|
||||
|
||||
subject { described_class.new(project, sha).full_json_path_for(path) }
|
||||
|
||||
it 'assigns code_navigation_build variable' do
|
||||
expect(subject).to eq("/#{project.full_path}/-/jobs/#{job.id}/artifacts/raw/lsif/#{path}.json")
|
||||
end
|
||||
|
||||
context 'when code_navigation feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(code_navigation: false)
|
||||
end
|
||||
|
||||
it 'does not assign code_navigation_build variable' do
|
||||
expect(subject).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,7 +5,7 @@ require 'spec_helper'
|
|||
describe DiffFileEntity do
|
||||
include RepoHelpers
|
||||
|
||||
let(:project) { create(:project, :repository) }
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let(:repository) { project.repository }
|
||||
let(:commit) { project.commit(sample_commit.id) }
|
||||
let(:diff_refs) { commit.diff_refs }
|
||||
|
|
@ -21,10 +21,11 @@ describe DiffFileEntity do
|
|||
end
|
||||
|
||||
context 'when there is a merge request' do
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
let(:user) { create(:user) }
|
||||
let(:code_navigation_path) { Gitlab::CodeNavigationPath.new(project, project.commit.sha) }
|
||||
let(:request) { EntityRequest.new(project: project, current_user: user) }
|
||||
let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
let(:entity) { described_class.new(diff_file, options.merge(request: request, merge_request: merge_request)) }
|
||||
let(:entity) { described_class.new(diff_file, options.merge(request: request, merge_request: merge_request, code_navigation_path: code_navigation_path)) }
|
||||
let(:exposed_urls) { %i(edit_path view_path context_lines_path) }
|
||||
|
||||
it_behaves_like 'diff file entity'
|
||||
|
|
@ -32,6 +33,7 @@ describe DiffFileEntity do
|
|||
it 'exposes additional attributes' do
|
||||
expect(subject).to include(*exposed_urls)
|
||||
expect(subject).to include(:replaced_view_path)
|
||||
expect(subject).to include(:code_navigation_path)
|
||||
end
|
||||
|
||||
it 'points all urls to merge request target project' do
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ describe DiffsEntity do
|
|||
:start_version, :latest_diff, :latest_version_path,
|
||||
:added_lines, :removed_lines, :render_overflow_warning,
|
||||
:email_patch_path, :plain_diff_path, :diff_files,
|
||||
:merge_request_diffs
|
||||
:merge_request_diffs, :definition_path_prefix
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ describe DiffsMetadataEntity do
|
|||
:start_version, :latest_diff, :latest_version_path,
|
||||
:added_lines, :removed_lines, :render_overflow_warning,
|
||||
:email_patch_path, :plain_diff_path,
|
||||
:merge_request_diffs,
|
||||
:context_commits,
|
||||
:merge_request_diffs, :context_commits,
|
||||
:definition_path_prefix,
|
||||
# Attributes
|
||||
:diff_files
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,10 +16,20 @@ describe Metrics::Dashboard::CustomDashboardService, :use_clean_rails_memory_sto
|
|||
describe '#get_dashboard' do
|
||||
let(:dashboard_path) { '.gitlab/dashboards/test.yml' }
|
||||
let(:service_params) { [project, user, { environment: environment, dashboard_path: dashboard_path }] }
|
||||
let(:service_call) { described_class.new(*service_params).get_dashboard }
|
||||
let(:service_call) { subject.get_dashboard }
|
||||
|
||||
subject { described_class.new(*service_params) }
|
||||
|
||||
context 'when the dashboard does not exist' do
|
||||
it_behaves_like 'misconfigured dashboard service response', :not_found
|
||||
|
||||
it 'does not update gitlab_metrics_dashboard_processing_time_ms metric', :prometheus do
|
||||
service_call
|
||||
metric = subject.send(:processing_time_metric)
|
||||
labels = subject.send(:processing_time_metric_labels)
|
||||
|
||||
expect(metric.get(labels)).to eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'raises error for users with insufficient permissions'
|
||||
|
|
@ -28,6 +38,7 @@ describe Metrics::Dashboard::CustomDashboardService, :use_clean_rails_memory_sto
|
|||
let(:project) { project_with_dashboard(dashboard_path) }
|
||||
|
||||
it_behaves_like 'valid dashboard service response'
|
||||
it_behaves_like 'updates gitlab_metrics_dashboard_processing_time_ms metric'
|
||||
|
||||
it 'caches the unprocessed dashboard for subsequent calls' do
|
||||
expect_any_instance_of(described_class)
|
||||
|
|
|
|||
|
|
@ -36,9 +36,12 @@ describe Metrics::Dashboard::PodDashboardService, :use_clean_rails_memory_store_
|
|||
describe '#get_dashboard' do
|
||||
let(:dashboard_path) { described_class::DASHBOARD_PATH }
|
||||
let(:service_params) { [project, user, { environment: environment, dashboard_path: dashboard_path }] }
|
||||
let(:service_call) { described_class.new(*service_params).get_dashboard }
|
||||
let(:service_call) { subject.get_dashboard }
|
||||
|
||||
subject { described_class.new(*service_params) }
|
||||
|
||||
it_behaves_like 'valid dashboard service response'
|
||||
it_behaves_like 'caches the unprocessed dashboard for subsequent calls'
|
||||
it_behaves_like 'updates gitlab_metrics_dashboard_processing_time_ms metric'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@ describe Metrics::Dashboard::SelfMonitoringDashboardService, :use_clean_rails_me
|
|||
|
||||
describe '#get_dashboard' do
|
||||
let(:service_params) { [project, user, { environment: environment }] }
|
||||
let(:service_call) { described_class.new(*service_params).get_dashboard }
|
||||
let(:service_call) { subject.get_dashboard }
|
||||
|
||||
subject { described_class.new(*service_params) }
|
||||
|
||||
it_behaves_like 'valid dashboard service response'
|
||||
it_behaves_like 'raises error for users with insufficient permissions'
|
||||
it_behaves_like 'caches the unprocessed dashboard for subsequent calls'
|
||||
it_behaves_like 'updates gitlab_metrics_dashboard_processing_time_ms metric'
|
||||
end
|
||||
|
||||
describe '.all_dashboard_paths' do
|
||||
|
|
|
|||
|
|
@ -16,11 +16,14 @@ describe Metrics::Dashboard::SystemDashboardService, :use_clean_rails_memory_sto
|
|||
describe '#get_dashboard' do
|
||||
let(:dashboard_path) { described_class::DASHBOARD_PATH }
|
||||
let(:service_params) { [project, user, { environment: environment, dashboard_path: dashboard_path }] }
|
||||
let(:service_call) { described_class.new(*service_params).get_dashboard }
|
||||
let(:service_call) { subject.get_dashboard }
|
||||
|
||||
subject { described_class.new(*service_params) }
|
||||
|
||||
it_behaves_like 'valid dashboard service response'
|
||||
it_behaves_like 'raises error for users with insufficient permissions'
|
||||
it_behaves_like 'caches the unprocessed dashboard for subsequent calls'
|
||||
it_behaves_like 'updates gitlab_metrics_dashboard_processing_time_ms metric'
|
||||
|
||||
context 'when called with a non-system dashboard' do
|
||||
let(:dashboard_path) { 'garbage/dashboard/path' }
|
||||
|
|
|
|||
|
|
@ -118,3 +118,13 @@ RSpec.shared_examples 'misconfigured dashboard service response with stepable' d
|
|||
expect(result[:message]).to eq(message) if message
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'updates gitlab_metrics_dashboard_processing_time_ms metric' do
|
||||
specify :prometheus do
|
||||
service_call
|
||||
metric = subject.send(:processing_time_metric)
|
||||
labels = subject.send(:processing_time_metric_labels)
|
||||
|
||||
expect(metric.get(labels)).to be > 0
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue