Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-06-26 18:09:03 +00:00
parent 2a53c24c51
commit ebe92e84a9
47 changed files with 199 additions and 476 deletions

View File

@ -352,11 +352,16 @@ const normalizeStringResult = result => [
* [
* {
* "metric": { "<label_name>": "<label_value>", ... },
* "value": [ <unix_time>, "<sample_value>" ]
* "value": [ <unix_time>, "<sample_value>" ],
* "values": [ [ <unix_time>, "<sample_value>" ] ]
* },
* ...
* ]
*
* `metric` - Key-value pairs object representing metric measured
* `value` - The vector result
* `values` - An array with a single value representing the result
*
* This method also adds the matrix version of the vector
* by introducing a `values` array with a single element. This
* allows charts to default to `values` if needed.
@ -379,16 +384,28 @@ const normalizeVectorResult = result =>
*
* {
* "metric": { "<label_name>": "<label_value>", ... },
* "value": [ <unix_time>, "<sample_value>" ],
* "values": [ [ <unix_time>, "<sample_value>" ], ... ]
* },
*
* `metric` - Key-value pairs object representing metric measured
* `value` - The last (more recent) result
* `values` - A range of results for the metric
*
* See https://prometheus.io/docs/prometheus/latest/querying/api/#range-vectors
*
* @param {array} result
* @returns {array}
* @returns {object} Normalized result.
*/
const normalizeResultMatrix = result =>
result.map(({ metric, values }) => ({ metric, values: values.map(mapScalarValue) }));
result.map(({ metric, values }) => {
const mappedValues = values.map(mapScalarValue);
return {
metric,
value: mappedValues[mappedValues.length - 1],
values: mappedValues,
};
});
/**
* Parse response data from a Prometheus Query that comes

View File

@ -1,21 +1,16 @@
import $ from 'jquery';
import 'jquery.waitforimages';
import initBlob from '~/blob_edit/blob_bundle';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import NotificationsForm from '~/notifications_form';
import UserCallout from '~/user_callout';
import TreeView from '~/tree';
import BlobViewer from '~/blob/viewer/index';
import Activities from '~/activities';
import { ajaxGet } from '~/lib/utils/common_utils';
import GpgBadges from '~/gpg_badges';
import initReadMore from '~/read_more';
import leaveByUrl from '~/namespaces/leave_by_url';
import Star from '../../../star';
import notificationsDropdown from '../../../notifications_dropdown';
import initNamespaceStorageLimitAlert from '~/namespace_storage_limit_alert';
import { showLearnGitLabProjectPopover } from '~/onboarding_issues';
import initTree from 'ee_else_ce/repository';
document.addEventListener('DOMContentLoaded', () => {
initReadMore();
@ -31,10 +26,10 @@ document.addEventListener('DOMContentLoaded', () => {
});
// Project show page loads different overview content based on user preferences
const treeSlider = document.querySelector('#tree-slider');
const treeSlider = document.getElementById('js-tree-list');
if (treeSlider) {
new TreeView(); // eslint-disable-line no-new
initBlob();
initTree();
}
if (document.querySelector('.blob-viewer')) {
@ -45,21 +40,7 @@ document.addEventListener('DOMContentLoaded', () => {
new Activities(); // eslint-disable-line no-new
}
$(treeSlider).waitForImages(() => {
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
});
GpgBadges.fetch();
leaveByUrl('project');
if (document.getElementById('js-tree-list')) {
initBlob();
import('ee_else_ce/repository')
.then(m => m.default())
.catch(e => {
throw e;
});
}
showLearnGitLabProjectPopover();
});

View File

@ -1,53 +1,12 @@
import $ from 'jquery';
import 'jquery.waitforimages';
import Vue from 'vue';
import initBlob from '~/blob_edit/blob_bundle';
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import GpgBadges from '~/gpg_badges';
import TreeView from '../../../../tree';
import ShortcutsNavigation from '../../../../behaviors/shortcuts/shortcuts_navigation';
import BlobViewer from '../../../../blob/viewer';
import NewCommitForm from '../../../../new_commit_form';
import { ajaxGet } from '../../../../lib/utils/common_utils';
import initTree from 'ee_else_ce/repository';
document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
new TreeView(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new
$('#tree-slider').waitForImages(() =>
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath),
);
initBlob();
const commitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status');
const statusLink = document.querySelector('.commit-actions .ci-status-link');
if (statusLink != null) {
statusLink.remove();
// eslint-disable-next-line no-new
new Vue({
el: commitPipelineStatusEl,
components: {
commitPipelineStatus,
},
render(createElement) {
return createElement('commit-pipeline-status', {
props: {
endpoint: commitPipelineStatusEl.dataset.endpoint,
},
});
},
});
}
GpgBadges.fetch();
if (document.getElementById('js-tree-list')) {
import('ee_else_ce/repository')
.then(m => m.default())
.catch(e => {
throw e;
});
}
initTree();
});

View File

@ -80,7 +80,7 @@ export default {
<table-header v-once />
<tbody>
<parent-row
v-show="showParentRow"
v-if="showParentRow"
:commit-ref="escapedRef"
:path="path"
:loading-path="loadingPath"

View File

@ -20,7 +20,7 @@ class Projects::TreeController < Projects::ApplicationController
end
def show
return render_404 unless @repository.commit(@ref)
return render_404 unless @commit
if tree.entries.empty?
if @repository.blob_at(@commit.id, @path)
@ -29,14 +29,6 @@ class Projects::TreeController < Projects::ApplicationController
return redirect_to_tree_root_for_missing_path(@project, @ref, @path)
end
end
respond_to do |format|
format.html do
lfs_blob_ids if Feature.disabled?(:vue_file_list, @project, default_enabled: true)
@last_commit = @repository.last_commit_for_path(@commit.id, @tree.path, literal_pathspec: true) || @commit
end
end
end
def create_dir

View File

@ -22,7 +22,6 @@ class ProjectsController < Projects::ApplicationController
before_action :assign_ref_vars, if: -> { action_name == 'show' && repo_exists? }
before_action :tree,
if: -> { action_name == 'show' && repo_exists? && project_view_files? }
before_action :lfs_blob_ids, if: :show_blob_ids?, only: :show
before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export]
before_action :present_project, only: [:edit]
before_action :authorize_download_code!, only: [:refs]
@ -302,10 +301,6 @@ class ProjectsController < Projects::ApplicationController
private
def show_blob_ids?
repo_exists? && project_view_files? && Feature.disabled?(:vue_file_list, @project, default_enabled: true)
end
# Render project landing depending of which features are available
# So if page is not available in the list it renders the next page
#

View File

@ -732,10 +732,6 @@ module ProjectsHelper
!project.repository.gitlab_ci_yml
end
def vue_file_list_enabled?
Feature.enabled?(:vue_file_list, @project, default_enabled: true)
end
def native_code_navigation_enabled?(project)
Feature.enabled?(:code_navigation, project, default_enabled: true)
end

View File

@ -30,6 +30,8 @@ module AlertManagement
belongs_to :project
belongs_to :issue, optional: true
belongs_to :prometheus_alert, optional: true
belongs_to :environment, optional: true
has_many :alert_assignees, inverse_of: :alert
has_many :assignees, through: :alert_assignees

View File

@ -320,9 +320,7 @@ module Ci
# ref - The ref to scope the data to (e.g. "master"). If the ref is not
# given we simply get the latest pipelines for the commits, regardless
# of what refs the pipelines belong to.
# project_key - Support `commits` from different projects, returns results
# keyed by `hash[project_id][commit_id]`
def self.latest_pipeline_per_commit(commits, ref = nil, project_key: false)
def self.latest_pipeline_per_commit(commits, ref = nil)
p1 = arel_table
p2 = arel_table.alias
@ -343,13 +341,7 @@ module Ci
relation = relation.where(ref: ref) if ref
relation.each_with_object({}) do |pipeline, hash|
commits = if project_key
hash[pipeline.project_id] ||= {}
else
hash
end
commits[pipeline.sha] = pipeline
hash[pipeline.sha] = pipeline
end
end

View File

@ -1,13 +1,16 @@
# frozen_string_literal: true
# A collection of Commit instances for a specific Git reference.
# A collection of Commit instances for a specific container and Git reference.
class CommitCollection
include Enumerable
include Gitlab::Utils::StrongMemoize
attr_reader :container, :ref, :commits
# container - The object the commits belong to (each commit project will be used if not provided).
delegate :repository, to: :container, allow_nil: true
delegate :project, to: :repository, allow_nil: true
# container - The object the commits belong to.
# commits - The Commit instances to store.
# ref - The name of the ref (e.g. "master").
def initialize(container, commits, ref = nil)
@ -39,13 +42,12 @@ class CommitCollection
# Setting the pipeline for each commit ahead of time removes the need for running
# a query for every commit we're displaying.
def with_latest_pipeline(ref = nil)
# since commit ids are not unique across all projects, use project_key = true to get commits by project
pipelines = ::Ci::Pipeline.ci_sources.latest_pipeline_per_commit(map(&:id), ref, project_key: true)
return self unless project
pipelines = project.ci_pipelines.latest_pipeline_per_commit(map(&:id), ref)
# set the pipeline for each commit by project_id and commit for the latest pipeline for ref
each do |commit|
project_id = container&.id || commit.project_id
commit.set_latest_pipeline_for_ref(ref, pipelines.dig(project_id, commit.id))
commit.set_latest_pipeline_for_ref(ref, pipelines[commit.id])
end
self
@ -62,19 +64,16 @@ class CommitCollection
# Batch load any commits that are not backed by full gitaly data, and
# replace them in the collection.
def enrich!
return self if fully_enriched?
# Batch load full Commits from the repository
# and map to a Hash of id => Commit
# A container is needed in order to fetch data from gitaly. Containers
# can be absent from commits in certain rare situations (like when
# viewing a MR of a deleted fork). In these cases, assume that the
# enriched data is not needed.
commits_to_enrich = unenriched.select { |c| container.present? || c.container.present? }
replacements = Hash[commits_to_enrich.map do |c|
commit_container = container || c.container
[c.id, Commit.lazy(commit_container, c.id)]
return self if container.blank? || fully_enriched?
# Batch load full Commits from the repository
# and map to a Hash of id => Commit
replacements = Hash[unenriched.map do |c|
[c.id, Commit.lazy(container, c.id)]
end.compact]
# Replace the commits, keeping the same order

View File

@ -411,8 +411,8 @@ module Issuable
changes = previous_changes
if old_associations
old_labels = old_associations.fetch(:labels, [])
old_assignees = old_associations.fetch(:assignees, [])
old_labels = old_associations.fetch(:labels, labels)
old_assignees = old_associations.fetch(:assignees, assignees)
if old_labels != labels
changes[:labels] = [old_labels.map(&:hook_attrs), labels.map(&:hook_attrs)]
@ -423,7 +423,7 @@ module Issuable
end
if self.respond_to?(:total_time_spent)
old_total_time_spent = old_associations.fetch(:total_time_spent, nil)
old_total_time_spent = old_associations.fetch(:total_time_spent, total_time_spent)
if old_total_time_spent != total_time_spent
changes[:total_time_spent] = [old_total_time_spent, total_time_spent]

View File

@ -21,6 +21,7 @@ class Environment < ApplicationRecord
has_many :prometheus_alerts, inverse_of: :environment
has_many :metrics_dashboard_annotations, class_name: 'Metrics::Dashboard::Annotation', inverse_of: :environment
has_many :self_managed_prometheus_alert_events, inverse_of: :environment
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
has_one :last_deployment, -> { success.order('deployments.id DESC') }, class_name: 'Deployment'
has_one :last_deployable, through: :last_deployment, source: 'deployable', source_type: 'CommitStatus'

View File

@ -520,10 +520,6 @@ class Project < ApplicationRecord
group: :ip_restrictions, namespace: [:route, :owner])
}
scope :with_api_commit_entity_associations, -> {
preload(:project_feature, :route, namespace: [:route, :owner])
}
enum auto_cancel_pending_pipelines: { disabled: 0, enabled: 1 }
chronic_duration_attr :build_timeout_human_readable, :build_timeout,

View File

@ -16,6 +16,7 @@ class PrometheusAlert < ApplicationRecord
has_many :prometheus_alert_events, inverse_of: :prometheus_alert
has_many :related_issues, through: :prometheus_alert_events
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :prometheus_alert
after_save :clear_prometheus_adapter_cache!
after_destroy :clear_prometheus_adapter_cache!

View File

@ -1,8 +1,6 @@
- is_project_overview = local_assigns.fetch(:is_project_overview, false)
- commit = local_assigns.fetch(:commit) { @repository.commit }
- ref = local_assigns.fetch(:ref) { current_ref }
- project = local_assigns.fetch(:project) { @project }
- content_url = local_assigns.fetch(:content_url) { @tree.readme ? project_blob_path(@project, tree_join(@ref, @tree.readme.path)) : project_tree_path(@project, @ref) }
- show_auto_devops_callout = show_auto_devops_callout?(@project)
- add_page_startup_api_call logs_file_project_ref_path(@project, ref, @path, format: "json", offset: 0)
- if @tree.readme
@ -12,19 +10,13 @@
.nav-block
= render 'projects/tree/tree_header', tree: @tree
- if vue_file_list_enabled?
#js-last-commit
- elsif commit
= render 'shared/commit_well', commit: commit, ref: ref, project: project
#js-last-commit
- if is_project_overview
.project-buttons.gl-mb-3{ class: ("js-show-on-project-root" if vue_file_list_enabled?) }
.project-buttons.gl-mb-3.js-show-on-project-root
= render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
- if vue_file_list_enabled?
#js-tree-list{ data: vue_file_list_data(project, ref) }
- if can_edit_tree?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'
- else
= render 'projects/tree/tree_content', tree: @tree, content_url: content_url
#js-tree-list{ data: vue_file_list_data(project, ref) }
- if can_edit_tree?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'

View File

@ -3,7 +3,7 @@
- max_project_topic_length = 15
- emails_disabled = @project.emails_disabled?
.project-home-panel{ class: [("empty-project" if empty_repo), ("js-show-on-project-root" if vue_file_list_enabled?)] }
.project-home-panel.js-show-on-project-root{ class: [("empty-project" if empty_repo)] }
.row.gl-mb-3
.home-panel-title-row.col-md-12.col-lg-6.d-flex
.avatar-container.rect-avatar.s64.home-panel-avatar.append-right-default.float-none

View File

@ -12,13 +12,7 @@
%h5.m-0.dropdown-bold-header= _('Download source code')
.dropdown-menu-content
= render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: nil
- if vue_file_list_enabled?
#js-directory-downloads{ data: { links: directory_download_links(project, ref, archive_prefix).to_json } }
- elsif directory?
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download this directory')
.dropdown-menu-content
= render 'projects/buttons/download_links', project: project, ref: ref, archive_prefix: archive_prefix, path: @path
#js-directory-downloads{ data: { links: directory_download_links(project, ref, archive_prefix).to_json } }
- if pipeline && pipeline.latest_builds_with_artifacts.any?
%section.border-top.pt-1.mt-1
%h5.m-0.dropdown-bold-header= _('Download artifacts')

View File

@ -7,10 +7,6 @@
= render partial: 'flash_messages', locals: { project: @project }
- if !@project.empty_repo? && can?(current_user, :download_code, @project) && !vue_file_list_enabled?
- signatures_path = project_signatures_path(@project, @project.default_branch)
.js-signature-container{ data: { 'signatures-path': signatures_path } }
%div{ class: [("limit-container-width" unless fluid_layout)] }
= render "projects/last_push"

View File

@ -1,5 +1,5 @@
- if readme.rich_viewer
%article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout), ("js-show-on-root" if vue_file_list_enabled?)] }
%article.file-holder.readme-holder{ id: 'readme', class: [("limited-width-container" unless fluid_layout)] }
.js-file-title.file-title-flex-parent
.file-header-content
= blob_icon readme.mode, readme.name

View File

@ -5,92 +5,17 @@
.tree-ref-holder
= render 'shared/ref_switcher', destination: 'tree', path: @path, show_create: true
- if on_top_of_branch?
- addtotree_toggle_attributes = { 'data-toggle': 'dropdown', 'data-target': '.add-to-tree-dropdown', 'data-boundary': 'window' }
- else
- addtotree_toggle_attributes = { title: _("You can only add files when you are on a branch"), data: { container: 'body' }, class: 'disabled has-tooltip' }
- if vue_file_list_enabled?
#js-repo-breadcrumb{ data: breadcrumb_data_attributes }
- else
%ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item
= link_to project_tree_path(@project, @ref) do
= @project.path
- path_breadcrumbs do |title, path|
%li.breadcrumb-item
= link_to truncate(title, length: 40), project_tree_path(@project, tree_join(@ref, path))
- if can_collaborate || can_create_mr_from_fork
%li.breadcrumb-item
%button.btn.add-to-tree.qa-add-to-tree{ addtotree_toggle_attributes, type: 'button' }
= sprite_icon('plus', size: 16, css_class: 'float-left')
= sprite_icon('chevron-down', size: 16, css_class: 'float-left')
- if on_top_of_branch?
.add-to-tree-dropdown
%ul.dropdown-menu
- if can_edit_tree?
%li.dropdown-header
#{ _('This directory') }
%li
= link_to project_new_blob_path(@project, @id), class: 'qa-new-file-option' do
#{ _('New file') }
%li
= link_to '#modal-upload-blob', { 'data-target' => '#modal-upload-blob', 'data-toggle' => 'modal' } do
#{ _('Upload file') }
%li
= link_to '#modal-create-new-dir', { 'data-target' => '#modal-create-new-dir', 'data-toggle' => 'modal' } do
#{ _('New directory') }
- elsif can_create_mr_from_fork
%li
- continue_params = { to: project_new_blob_path(@project, @id),
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now }
- fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('New file') }
%li
- continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to upload a file again.",
notice_now: edit_in_new_fork_notice_now }
- fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('Upload file') }
%li
- continue_params = { to: request.fullpath,
notice: edit_in_new_fork_notice + " Try to create a new directory again.",
notice_now: edit_in_new_fork_notice_now }
- fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
= link_to fork_path, method: :post do
#{ _('New directory') }
- if can?(current_user, :push_code, @project)
%li.divider
%li.dropdown-header
#{ _('This repository') }
%li
= link_to new_project_branch_path(@project) do
#{ _('New branch') }
%li
= link_to new_project_tag_path(@project) do
#{ _('New tag') }
#js-repo-breadcrumb{ data: breadcrumb_data_attributes }
.tree-controls
.d-block.d-sm-flex.flex-wrap.align-items-start.gl-children-ml-sm-3<
= render_if_exists 'projects/tree/lock_link'
- if vue_file_list_enabled?
#js-tree-history-link.d-inline-block{ data: { history_link: project_commits_path(@project, @ref) } }
- else
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
#js-tree-history-link.d-inline-block{ data: { history_link: project_commits_path(@project, @ref) } }
= render 'projects/find_file_link'
- if can_collaborate || current_user&.already_forked?(@project)
- if vue_file_list_enabled?
#js-tree-web-ide-link.d-inline-block
- else
= link_to ide_edit_path(@project, @ref, @path), class: 'btn btn-default qa-web-ide-button' do
= _('Web IDE')
#js-tree-web-ide-link.d-inline-block
- elsif can_create_mr_from_fork
= link_to '#modal-confirm-fork', class: 'btn btn-default qa-web-ide-button', data: { target: '#modal-confirm-fork', toggle: 'modal'} do
= _('Web IDE')

View File

@ -1,13 +1,9 @@
- breadcrumb_title _("Repository")
- @content_class = "limit-container-width" unless fluid_layout
- signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit)
- page_title @path.presence || _("Files"), @ref
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
- unless vue_file_list_enabled?
.js-signature-container{ data: { 'signatures-path': signatures_path } }
= render 'projects/last_push'
= render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id)

View File

@ -0,0 +1,5 @@
---
title: Add prometheus_alert_id and environment_id to Alert management alerts
merge_request: 34995
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Don't include changes in webhook payload when old associations are empty
merge_request: 35158
author:
type: fixed

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class AddPrometheusAlertIdToAlertManagementAlerts < ActiveRecord::Migration[6.0]
DOWNTIME = false
def up
add_column :alert_management_alerts, :prometheus_alert_id, :integer
add_column :alert_management_alerts, :environment_id, :integer
end
def down
remove_column :alert_management_alerts, :prometheus_alert_id
remove_column :alert_management_alerts, :environment_id
end
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
class AddIdxAndFkForPrometheusAndEnvironmentToAlertManagementAlerts < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :alert_management_alerts, :prometheus_alert_id, where: 'prometheus_alert_id is not null'
add_concurrent_foreign_key :alert_management_alerts, :prometheus_alerts, column: :prometheus_alert_id, on_delete: :cascade
add_concurrent_index :alert_management_alerts, :environment_id, where: 'environment_id is not null'
add_concurrent_foreign_key :alert_management_alerts, :environments, column: :environment_id, on_delete: :nullify
end
def down
remove_concurrent_index :alert_management_alerts, :prometheus_alert_id
remove_foreign_key_without_error :alert_management_alerts, column: :prometheus_alert_id
remove_concurrent_index :alert_management_alerts, :environment_id
remove_foreign_key_without_error :alert_management_alerts, column: :environment_id
end
end

View File

@ -8736,6 +8736,8 @@ CREATE TABLE public.alert_management_alerts (
monitoring_tool text,
hosts text[] DEFAULT '{}'::text[] NOT NULL,
payload jsonb DEFAULT '{}'::jsonb NOT NULL,
prometheus_alert_id integer,
environment_id integer,
CONSTRAINT check_2df3e2fdc1 CHECK ((char_length(monitoring_tool) <= 100)),
CONSTRAINT check_5e9e57cadb CHECK ((char_length(description) <= 1000)),
CONSTRAINT check_bac14dddde CHECK ((char_length(service) <= 100)),
@ -18337,12 +18339,16 @@ CREATE INDEX index_alert_assignees_on_alert_id ON public.alert_management_alert_
CREATE UNIQUE INDEX index_alert_assignees_on_user_id_and_alert_id ON public.alert_management_alert_assignees USING btree (user_id, alert_id);
CREATE INDEX index_alert_management_alerts_on_environment_id ON public.alert_management_alerts USING btree (environment_id) WHERE (environment_id IS NOT NULL);
CREATE INDEX index_alert_management_alerts_on_issue_id ON public.alert_management_alerts USING btree (issue_id);
CREATE UNIQUE INDEX index_alert_management_alerts_on_project_id_and_fingerprint ON public.alert_management_alerts USING btree (project_id, fingerprint);
CREATE UNIQUE INDEX index_alert_management_alerts_on_project_id_and_iid ON public.alert_management_alerts USING btree (project_id, iid);
CREATE INDEX index_alert_management_alerts_on_prometheus_alert_id ON public.alert_management_alerts USING btree (prometheus_alert_id) WHERE (prometheus_alert_id IS NOT NULL);
CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id ON public.alert_management_alert_user_mentions USING btree (alert_management_alert_id) WHERE (note_id IS NULL);
CREATE UNIQUE INDEX index_alert_user_mentions_on_alert_id_and_note_id ON public.alert_management_alert_user_mentions USING btree (alert_management_alert_id, note_id);
@ -20779,6 +20785,9 @@ ALTER TABLE ONLY public.geo_event_log
ALTER TABLE ONLY public.ci_build_trace_sections
ADD CONSTRAINT fk_4ebe41f502 FOREIGN KEY (build_id) REFERENCES public.ci_builds(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.alert_management_alerts
ADD CONSTRAINT fk_51ab4b6089 FOREIGN KEY (prometheus_alert_id) REFERENCES public.prometheus_alerts(id) ON DELETE CASCADE;
ALTER TABLE ONLY public.path_locks
ADD CONSTRAINT fk_5265c98f24 FOREIGN KEY (project_id) REFERENCES public.projects(id) ON DELETE CASCADE;
@ -20986,6 +20995,9 @@ ALTER TABLE ONLY public.merge_requests
ALTER TABLE ONLY public.epics
ADD CONSTRAINT fk_aa5798e761 FOREIGN KEY (closed_by_id) REFERENCES public.users(id) ON DELETE SET NULL;
ALTER TABLE ONLY public.alert_management_alerts
ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES public.environments(id) ON DELETE SET NULL;
ALTER TABLE ONLY public.identities
ADD CONSTRAINT fk_aade90f0fc FOREIGN KEY (saml_provider_id) REFERENCES public.saml_providers(id) ON DELETE CASCADE;
@ -23400,6 +23412,7 @@ COPY "schema_migrations" (version) FROM STDIN;
20200618134723
20200619154527
20200619154528
20200622040750
20200622070606
20200622070620
20200622095419
@ -23411,5 +23424,6 @@ COPY "schema_migrations" (version) FROM STDIN;
20200623170000
20200623185440
20200624075411
20200625045442
\.

View File

@ -190,7 +190,7 @@ control over how the Pages daemon runs and serves content in your environment.
| Setting | Description |
| ------- | ----------- |
| `pages_external_url` | The URL where GitLab Pages is accessible, including protocol (HTTP / HTTPS). If `https://` is used, you must also set `gitlab_pages['ssl_certificate']` and `gitlab_pages['ssl_certificate_key']`.
| **gitlab_pages[]** | |
| `gitlab_pages[]` | |
| `access_control` | Whether to enable [access control](index.md#access-control).
| `api_secret_key` | Full path to file with secret key used to authenticate with the GitLab API. Auto-generated when left unset.
| `artifacts_server` | Enable viewing [artifacts](../job_artifacts.md) in GitLab Pages.
@ -225,14 +225,14 @@ control over how the Pages daemon runs and serves content in your environment.
| `tls_max_version` | Specifies the maximum SSL/TLS version ("ssl3", "tls1.0", "tls1.1" or "tls1.2").
| `tls_min_version` | Specifies the minimum SSL/TLS version ("ssl3", "tls1.0", "tls1.1" or "tls1.2").
| `use_http2` | Enable HTTP2 support.
| **gitlab_pages['env'][]** | |
| `gitlab_pages['env'][]` | |
| `http_proxy` | Configure GitLab Pages to use an HTTP Proxy to mediate traffic between Pages and GitLab. Sets an environment variable `http_proxy` when starting Pages daemon.
| **gitlab_rails[]** | |
| `gitlab_rails[]` | |
| `pages_domain_verification_cron_worker` | Schedule for verifying custom GitLab Pages domains.
| `pages_domain_ssl_renewal_cron_worker` | Schedule for obtaining and renewing SSL certificates through Let's Encrypt for GitLab Pages domains.
| `pages_domain_removal_cron_worker` | Schedule for removing unverified custom GitLab Pages domains.
| `pages_path` | The directory on disk where pages are stored, defaults to `GITLAB-RAILS/shared/pages`.
| **pages_nginx[]** | |
| `pages_nginx[]` | |
| `enable` | Include a virtual host `server{}` block for Pages inside NGINX. Needed for NGINX to proxy traffic back to the Pages daemon. Set to `false` if the Pages daemon should directly receive all requests, for example, when using [custom domains](index.md#custom-domains).
---

View File

@ -533,8 +533,8 @@ via the GraphQL API!
1. Take care of replicating "update" events. Geo Framework does not currently support
replicating "update" events because all entities added to the framework, by this time,
are immutable. If this is the case
for the entity you're going to add, please follow [https://gitlab.com/gitlab-org/gitlab/-/issues/118743]
and [https://gitlab.com/gitlab-org/gitlab/-/issues/118745] as examples to add the new event type.
for the entity you're going to add, please follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
Please also remove this notice when you've added it.
#### Admin UI

View File

@ -363,10 +363,12 @@ service account for your project. For help debugging this issue, see
After upgrading to GitLab 13.0, you may encounter this message when deploying
with Auto DevOps:
> Detected an existing PostgreSQL database installed on the
```plaintext
Detected an existing PostgreSQL database installed on the
deprecated channel 1, but the current channel is set to 2. The default
channel changed to 2 in of GitLab 13.0.
> [...]
[...]
```
Auto DevOps, by default, installs an in-cluster PostgreSQL database alongside
your application. The default installation method changed in GitLab 13.0, and

View File

@ -8,15 +8,14 @@ module API
expose :project_id
expose :last_pipeline do |commit, options|
pipeline = commit.latest_pipeline if can_read_pipeline?
pipeline = commit.last_pipeline if can_read_pipeline?
::API::Entities::PipelineBasic.represent(pipeline, options)
end
private
def can_read_pipeline?
Ability.allowed?(options[:current_user], :read_pipeline, object.latest_pipeline)
Ability.allowed?(options[:current_user], :read_pipeline, object.last_pipeline)
end
end
end

View File

@ -24,8 +24,7 @@ module API
merge_requests: :with_api_entity_associations,
projects: :with_api_entity_associations,
issues: :with_api_entity_associations,
milestones: :with_api_entity_associations,
commits: :with_api_commit_entity_associations
milestones: :with_api_entity_associations
}.freeze
def search(additional_params = {})
@ -39,9 +38,6 @@ module API
results = SearchService.new(current_user, search_params).search_objects(preload_method)
# preload commit data
results = CommitCollection.new(nil, results).with_latest_pipeline if params[:scope].to_sym == :commits
Gitlab::UsageDataCounters::SearchCounter.count(:all_searches)
paginate(results)

View File

@ -26156,9 +26156,6 @@ msgstr ""
msgid "You can now submit a merge request to get this change into the original project."
msgstr ""
msgid "You can only add files when you are on a branch"
msgstr ""
msgid "You can only edit files when you are on a branch"
msgstr ""

View File

@ -40,8 +40,8 @@
"@babel/plugin-syntax-import-meta": "^7.10.1",
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
"@gitlab/svgs": "1.143.0",
"@gitlab/ui": "17.6.1",
"@gitlab/svgs": "1.144.0",
"@gitlab/ui": "17.8.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-1",
"@sentry/browser": "^5.10.2",

View File

@ -51,9 +51,12 @@ module QA
element :quick_actions
end
view 'app/views/projects/tree/_tree_header.html.haml' do
view 'app/assets/javascripts/repository/components/breadcrumbs.vue' do
element :add_to_tree
element :new_file_option
end
view 'app/assets/javascripts/repository/index.js' do
element :web_ide_button
end

View File

@ -89,34 +89,6 @@ RSpec.describe Projects::TreeController do
end
end
describe "GET show" do
context 'lfs_blob_ids instance variable' do
let(:id) { 'master' }
context 'with vue tree view enabled' do
before do
get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
end
it 'is not set' do
expect(assigns[:lfs_blob_ids]).to be_nil
end
end
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
end
it 'is set' do
expect(assigns[:lfs_blob_ids]).not_to be_nil
end
end
end
end
describe 'GET show with whitespace in ref' do
render_views

View File

@ -386,36 +386,6 @@ RSpec.describe ProjectsController do
end
end
context 'lfs_blob_ids instance variable' do
let(:project) { create(:project, :public, :repository) }
before do
sign_in(user)
end
context 'with vue tree view enabled' do
before do
get :show, params: { namespace_id: project.namespace, id: project }
end
it 'is not set' do
expect(assigns[:lfs_blob_ids]).to be_nil
end
end
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
get :show, params: { namespace_id: project.namespace, id: project }
end
it 'is set' do
expect(assigns[:lfs_blob_ids]).not_to be_nil
end
end
end
context 'namespace storage limit' do
let_it_be(:project) { create(:project, :public, :repository ) }
let(:namespace) { project.namespace }

View File

@ -781,7 +781,7 @@ describe('normalizeQueryResponseData', () => {
job: 'prometheus',
instance: 'localhost:9090',
},
values: [[1435781430.781, '1'], [1435781445.781, '1'], [1435781460.781, '1']],
values: [[1435781430.781, '1'], [1435781445.781, '2'], [1435781460.781, '3']],
},
{
metric: {
@ -789,7 +789,7 @@ describe('normalizeQueryResponseData', () => {
job: 'node',
instance: 'localhost:9091',
},
values: [[1435781430.781, '0'], [1435781445.781, '0'], [1435781460.781, '1']],
values: [[1435781430.781, '4'], [1435781445.781, '5'], [1435781460.781, '6']],
},
],
};
@ -797,18 +797,20 @@ describe('normalizeQueryResponseData', () => {
expect(normalizeQueryResponseData(mockMatrix)).toEqual([
{
metric: { __name__: 'up', instance: 'localhost:9090', job: 'prometheus' },
value: ['2015-07-01T20:11:00.781Z', 3],
values: [
['2015-07-01T20:10:30.781Z', 1],
['2015-07-01T20:10:45.781Z', 1],
['2015-07-01T20:11:00.781Z', 1],
['2015-07-01T20:10:45.781Z', 2],
['2015-07-01T20:11:00.781Z', 3],
],
},
{
metric: { __name__: 'up', instance: 'localhost:9091', job: 'node' },
value: ['2015-07-01T20:11:00.781Z', 6],
values: [
['2015-07-01T20:10:30.781Z', 0],
['2015-07-01T20:10:45.781Z', 0],
['2015-07-01T20:11:00.781Z', 1],
['2015-07-01T20:10:30.781Z', 4],
['2015-07-01T20:10:45.781Z', 5],
['2015-07-01T20:11:00.781Z', 6],
],
},
]);

View File

@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe AlertManagement::Alert do
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:issue) }
it { is_expected.to belong_to(:issue).optional }
it { is_expected.to belong_to(:prometheus_alert).optional }
it { is_expected.to belong_to(:environment).optional }
it { is_expected.to have_many(:assignees).through(:alert_assignees) }
it { is_expected.to have_many(:notes) }
it { is_expected.to have_many(:ordered_notes) }

View File

@ -1923,37 +1923,6 @@ RSpec.describe Ci::Pipeline, :mailer do
end
end
context 'when there are two pipelines for a ref, sha across multiple projects' do
let(:project_2) { create(:project) }
let!(:commit_456_project_2_ref_test) do
create(
:ci_empty_pipeline,
status: 'success',
ref: 'test',
sha: '456',
project: project_2
)
end
context 'when project_key is false' do
it 'returns the latest pipeline' do
result = described_class.latest_pipeline_per_commit(%w[456])
expect(result).to match('456' => commit_456_project_2_ref_test)
end
end
context 'when project_key is true' do
it 'returns the latest pipeline per project' do
result = described_class.latest_pipeline_per_commit(%w[456], project_key: true)
expect(result[project.id]).to match('456' => commit_456_ref_test)
expect(result[project_2.id]).to match('456' => commit_456_project_2_ref_test)
end
end
end
context 'with a ref' do
it 'only includes the pipelines for the given ref' do
result = described_class.latest_pipeline_per_commit(%w[123 456], 'master')

View File

@ -416,6 +416,27 @@ RSpec.describe Issuable do
describe '#to_hook_data' do
let(:builder) { double }
context 'when old_associations is empty' do
let(:label) { create(:label) }
before do
issue.update!(labels: [label])
issue.assignees << user
issue.spend_time(duration: 2, user_id: user.id, spent_at: Time.current)
expect(Gitlab::HookData::IssuableBuilder)
.to receive(:new).with(issue).and_return(builder)
end
it 'delegates to Gitlab::HookData::IssuableBuilder#build and does not set labels, assignees, nor total_time_spent' do
expect(builder).to receive(:build).with(
user: user,
changes: {})
# In some cases, old_associations is empty, e.g. on a close event
issue.to_hook_data(user)
end
end
context 'labels are updated' do
let(:labels) { create_list(:label, 2) }

View File

@ -18,6 +18,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
it { is_expected.to belong_to(:project).required }
it { is_expected.to have_many(:deployments) }
it { is_expected.to have_many(:metrics_dashboard_annotations) }
it { is_expected.to have_many(:alert_management_alerts) }
it { is_expected.to delegate_method(:stop_action).to(:last_deployment) }
it { is_expected.to delegate_method(:manual_actions).to(:last_deployment) }

View File

@ -33,6 +33,10 @@ RSpec.describe PrometheusAlert do
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to belong_to(:environment) }
it { is_expected.to belong_to(:prometheus_metric) }
it { is_expected.to have_many(:prometheus_alert_events) }
it { is_expected.to have_many(:related_issues) }
it { is_expected.to have_many(:alert_management_alerts) }
end
describe 'project validations' do

View File

@ -134,7 +134,9 @@ RSpec.describe Projects::Alerting::NotifyService do
monitoring_tool: payload_raw.fetch(:monitoring_tool),
service: payload_raw.fetch(:service),
fingerprint: Digest::SHA1.hexdigest(fingerprint),
ended_at: nil
ended_at: nil,
prometheus_alert_id: nil,
environment_id: nil
)
end
@ -193,7 +195,9 @@ RSpec.describe Projects::Alerting::NotifyService do
monitoring_tool: nil,
service: nil,
fingerprint: nil,
ended_at: nil
ended_at: nil,
prometheus_alert_id: nil,
environment_id: nil
)
end
end

View File

@ -1,41 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/show.html.haml' do
include Devise::Test::ControllerHelpers
let(:user) { create(:admin) }
let(:project) { create(:project, :repository) }
before do
presented_project = project.present(current_user: user)
allow(presented_project).to receive(:default_view).and_return('customize_workflow')
allow(controller).to receive(:current_user).and_return(user)
assign(:project, presented_project)
end
context 'commit signatures' do
context 'with vue tree view enabled' do
it 'are not rendered via js-signature-container' do
render
expect(rendered).not_to have_css('.js-signature-container')
end
end
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
end
it 'rendered via js-signature-container' do
render
expect(rendered).to have_css('.js-signature-container')
end
end
end
end

View File

@ -1,55 +0,0 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'projects/tree/_tree_header' do
let(:project) { create(:project, :repository) }
let(:current_user) { create(:user) }
let(:repository) { project.repository }
before do
stub_feature_flags(vue_file_list: false)
assign(:project, project)
assign(:repository, repository)
assign(:id, File.join('master', ''))
assign(:ref, 'master')
allow(view).to receive(:current_user).and_return(current_user)
allow(view).to receive(:can_collaborate_with_project?) { true }
end
it 'renders the WebIDE button when user can collaborate but not create fork or MR' do
allow(view).to receive(:can?) { false }
render
expect(rendered).to have_link('Web IDE')
end
it 'renders the WebIDE button when user can create fork and can open MR in project' do
allow(view).to receive(:can?) { true }
render
expect(rendered).to have_link('Web IDE')
end
it 'opens a popup confirming a fork if the user can create fork/MR but cannot collaborate with the project' do
allow(view).to receive(:can?) { true }
allow(view).to receive(:can_collaborate_with_project?) { false }
render
expect(rendered).to have_link('Web IDE', href: '#modal-confirm-fork')
end
it 'does not render the WebIDE button when user cannot collaborate or create mr' do
allow(view).to receive(:can?) { false }
allow(view).to receive(:can_collaborate_with_project?) { false }
render
expect(rendered).not_to have_link('Web IDE')
end
end

View File

@ -39,26 +39,4 @@ RSpec.describe 'projects/tree/show' do
expect(rendered).to have_css('.js-project-refs-dropdown .dropdown-toggle-text', text: ref)
end
end
context 'commit signatures' do
context 'with vue tree view disabled' do
before do
stub_feature_flags(vue_file_list: false)
end
it 'rendered via js-signature-container' do
render
expect(rendered).to have_css('.js-signature-container')
end
end
context 'with vue tree view enabled' do
it 'are not rendered via js-signature-container' do
render
expect(rendered).not_to have_css('.js-signature-container')
end
end
end
end

View File

@ -843,15 +843,15 @@
eslint-plugin-vue "^6.2.1"
vue-eslint-parser "^7.0.0"
"@gitlab/svgs@1.143.0":
version "1.143.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.143.0.tgz#94bb9c09dd328ea7c125b21349f7237e9d6786b8"
integrity sha512-KZSMfR2DWT4EeEMGopbFOpqK1F2X9BXdUpUaLp8ovOmFJ1mtiMxNk9QYkejhx91IQrc8wwYp/XPPSeGOZjjCnA==
"@gitlab/svgs@1.144.0":
version "1.144.0"
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.144.0.tgz#ee0ec58516405391cbaef00f5a660da6edf27538"
integrity sha512-ejcsxoyfYwXyG8naOnn7QnY0oxrRNcWRBuH9VHrGL9/FXBJWq2NLXENi+v0TjcWvSsc2fBx/nk5V8Au96g0yEg==
"@gitlab/ui@17.6.1":
version "17.6.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.6.1.tgz#3c7cd6463a0d38c7c5037b5ca861af99680df9ae"
integrity sha512-iCgcKn8hxn2k/763t77CRf07Dnw7wycl+rCUN8UIzBKe4yNswaNVrvjcdfM/TXe46EUVkQ2LfrwPuBShXAeHCA==
"@gitlab/ui@17.8.0":
version "17.8.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-17.8.0.tgz#187b92634d3b034f036d96238a7c39a5e7f1606b"
integrity sha512-BwZY5D6zUilCj9Uh1nhB3VQMHsSwYxMHpz/t4qu1URIwWLeyDuEMxx6CEMT4p1Cir2eWxwxh9AauduPcmRTJPw==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"