From ebe92e84a92d7d00710a6c5017ef2bb160268471 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Fri, 26 Jun 2020 18:09:03 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- .../javascripts/monitoring/stores/utils.js | 23 +++++- .../javascripts/pages/projects/show/index.js | 25 +----- .../pages/projects/tree/show/index.js | 45 +---------- .../repository/components/table/index.vue | 2 +- app/controllers/projects/tree_controller.rb | 10 +-- app/controllers/projects_controller.rb | 5 -- app/helpers/projects_helper.rb | 4 - app/models/alert_management/alert.rb | 2 + app/models/ci/pipeline.rb | 12 +-- app/models/commit_collection.rb | 31 ++++--- app/models/concerns/issuable.rb | 6 +- app/models/environment.rb | 1 + app/models/project.rb | 4 - app/models/prometheus_alert.rb | 1 + app/views/projects/_files.html.haml | 20 ++--- app/views/projects/_home_panel.html.haml | 2 +- .../projects/buttons/_download.html.haml | 8 +- app/views/projects/show.html.haml | 4 - app/views/projects/tree/_readme.html.haml | 2 +- .../projects/tree/_tree_header.html.haml | 81 +------------------ app/views/projects/tree/show.html.haml | 4 - ...heus-columns-to-alert-management-alert.yml | 5 ++ ...payload-when-old-associations-is-empty.yml | 5 ++ ...eus_alert_id_to_alert_management_alerts.rb | 16 ++++ ..._environment_to_alert_management_alerts.rb | 25 ++++++ db/structure.sql | 14 ++++ doc/administration/pages/index.md | 8 +- doc/development/geo/framework.md | 4 +- doc/topics/autodevops/index.md | 6 +- lib/api/entities/commit_detail.rb | 5 +- lib/api/search.rb | 6 +- locale/gitlab.pot | 3 - package.json | 4 +- qa/qa/page/project/show.rb | 5 +- .../projects/tree_controller_spec.rb | 28 ------- spec/controllers/projects_controller_spec.rb | 30 ------- spec/frontend/monitoring/store/utils_spec.js | 16 ++-- spec/models/alert_management/alert_spec.rb | 4 +- spec/models/ci/pipeline_spec.rb | 31 ------- spec/models/concerns/issuable_spec.rb | 21 +++++ spec/models/environment_spec.rb | 1 + spec/models/prometheus_alert_spec.rb | 4 + .../projects/alerting/notify_service_spec.rb | 8 +- spec/views/projects/show.html.haml_spec.rb | 41 ---------- .../tree/_tree_header.html.haml_spec.rb | 55 ------------- .../projects/tree/show.html.haml_spec.rb | 22 ----- yarn.lock | 16 ++-- 47 files changed, 199 insertions(+), 476 deletions(-) create mode 100644 changelogs/unreleased/222253-add-prometheus-columns-to-alert-management-alert.yml create mode 100644 changelogs/unreleased/dont-include-changes-in-webhook-payload-when-old-associations-is-empty.yml create mode 100644 db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb create mode 100644 db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb delete mode 100644 spec/views/projects/show.html.haml_spec.rb delete mode 100644 spec/views/projects/tree/_tree_header.html.haml_spec.rb diff --git a/app/assets/javascripts/monitoring/stores/utils.js b/app/assets/javascripts/monitoring/stores/utils.js index b2b959fdda2..d7cb6abb563 100644 --- a/app/assets/javascripts/monitoring/stores/utils.js +++ b/app/assets/javascripts/monitoring/stores/utils.js @@ -352,11 +352,16 @@ const normalizeStringResult = result => [ * [ * { * "metric": { "": "", ... }, - * "value": [ , "" ] + * "value": [ , "" ], + * "values": [ [ , "" ] ] * }, * ... * ] * + * `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": { "": "", ... }, + * "value": [ , "" ], * "values": [ [ , "" ], ... ] * }, * + * `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 diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js index 3c44053e2b2..42c7a6835ed 100644 --- a/app/assets/javascripts/pages/projects/show/index.js +++ b/app/assets/javascripts/pages/projects/show/index.js @@ -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(); }); diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js index 0d1d32317fe..78a4ea23f1a 100644 --- a/app/assets/javascripts/pages/projects/tree/show/index.js +++ b/app/assets/javascripts/pages/projects/tree/show/index.js @@ -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(); }); diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue index c8549180a25..c1f350dccd6 100644 --- a/app/assets/javascripts/repository/components/table/index.vue +++ b/app/assets/javascripts/repository/components/table/index.vue @@ -80,7 +80,7 @@ export default { { 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 # diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index b004eb30684..8df3b8356e7 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -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 diff --git a/app/models/alert_management/alert.rb b/app/models/alert_management/alert.rb index 306f7f4996b..905245cda60 100644 --- a/app/models/alert_management/alert.rb +++ b/app/models/alert_management/alert.rb @@ -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 diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 0eb37242b79..e2411e3828b 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -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 diff --git a/app/models/commit_collection.rb b/app/models/commit_collection.rb index 6eeba204774..456d32bf403 100644 --- a/app/models/commit_collection.rb +++ b/app/models/commit_collection.rb @@ -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 diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb index 220af8ab7c7..715cbd15d93 100644 --- a/app/models/concerns/issuable.rb +++ b/app/models/concerns/issuable.rb @@ -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] diff --git a/app/models/environment.rb b/app/models/environment.rb index 55c2e4173f6..494b166f80a 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -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' diff --git a/app/models/project.rb b/app/models/project.rb index 546d8c2d0ef..3410c5c9a25 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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, diff --git a/app/models/prometheus_alert.rb b/app/models/prometheus_alert.rb index fbc0281296f..32f9809e538 100644 --- a/app/models/prometheus_alert.rb +++ b/app/models/prometheus_alert.rb @@ -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! diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml index 47f91f719bc..1562cc065f1 100644 --- a/app/views/projects/_files.html.haml +++ b/app/views/projects/_files.html.haml @@ -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' diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 9e387404893..0efe870b3e0 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -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 diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 445752d0a15..1d0ad6dcde6 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -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') diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 732b0d6c9e1..4a521f2f46e 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -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" diff --git a/app/views/projects/tree/_readme.html.haml b/app/views/projects/tree/_readme.html.haml index 3e3804ae204..6d2bdda8254 100644 --- a/app/views/projects/tree/_readme.html.haml +++ b/app/views/projects/tree/_readme.html.haml @@ -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 diff --git a/app/views/projects/tree/_tree_header.html.haml b/app/views/projects/tree/_tree_header.html.haml index d5f7673488f..eab6d750a02 100644 --- a/app/views/projects/tree/_tree_header.html.haml +++ b/app/views/projects/tree/_tree_header.html.haml @@ -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') diff --git a/app/views/projects/tree/show.html.haml b/app/views/projects/tree/show.html.haml index 65f5bc31d2e..3dd12a7b641 100644 --- a/app/views/projects/tree/show.html.haml +++ b/app/views/projects/tree/show.html.haml @@ -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) diff --git a/changelogs/unreleased/222253-add-prometheus-columns-to-alert-management-alert.yml b/changelogs/unreleased/222253-add-prometheus-columns-to-alert-management-alert.yml new file mode 100644 index 00000000000..3ffa0bc63a1 --- /dev/null +++ b/changelogs/unreleased/222253-add-prometheus-columns-to-alert-management-alert.yml @@ -0,0 +1,5 @@ +--- +title: Add prometheus_alert_id and environment_id to Alert management alerts +merge_request: 34995 +author: +type: added diff --git a/changelogs/unreleased/dont-include-changes-in-webhook-payload-when-old-associations-is-empty.yml b/changelogs/unreleased/dont-include-changes-in-webhook-payload-when-old-associations-is-empty.yml new file mode 100644 index 00000000000..37d512f5d56 --- /dev/null +++ b/changelogs/unreleased/dont-include-changes-in-webhook-payload-when-old-associations-is-empty.yml @@ -0,0 +1,5 @@ +--- +title: Don't include changes in webhook payload when old associations are empty +merge_request: 35158 +author: +type: fixed diff --git a/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb b/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb new file mode 100644 index 00000000000..e7669db0a28 --- /dev/null +++ b/db/migrate/20200622040750_add_prometheus_alert_id_to_alert_management_alerts.rb @@ -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 diff --git a/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb b/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb new file mode 100644 index 00000000000..f4869b15735 --- /dev/null +++ b/db/migrate/20200625045442_add_idx_and_fk_for_prometheus_and_environment_to_alert_management_alerts.rb @@ -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 diff --git a/db/structure.sql b/db/structure.sql index ff179531ee6..480fb3323e7 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -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 \. diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index 18c17fc06b7..71a661d326c 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -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). --- diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index 3b40c43b122..614c0f8c0d8 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -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 + and as examples to add the new event type. Please also remove this notice when you've added it. #### Admin UI diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 178fd474104..e9b59b8c222 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -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 diff --git a/lib/api/entities/commit_detail.rb b/lib/api/entities/commit_detail.rb index d9efc53eeb4..22424b38bb9 100644 --- a/lib/api/entities/commit_detail.rb +++ b/lib/api/entities/commit_detail.rb @@ -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 diff --git a/lib/api/search.rb b/lib/api/search.rb index 8e5d1daad6b..ac00d3682a0 100644 --- a/lib/api/search.rb +++ b/lib/api/search.rb @@ -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) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 68c9cdd47db..c8125fabb4a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/package.json b/package.json index ca2a8a81c11..1a4b3674d43 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 00298ff9fb5..d9d310d9c8c 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -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 diff --git a/spec/controllers/projects/tree_controller_spec.rb b/spec/controllers/projects/tree_controller_spec.rb index f6ec04d4dd7..8e4e275bdbe 100644 --- a/spec/controllers/projects/tree_controller_spec.rb +++ b/spec/controllers/projects/tree_controller_spec.rb @@ -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 diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 56baa09b4bd..d88a1e3666b 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -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 } diff --git a/spec/frontend/monitoring/store/utils_spec.js b/spec/frontend/monitoring/store/utils_spec.js index d32d10ba0fb..61b97bb8020 100644 --- a/spec/frontend/monitoring/store/utils_spec.js +++ b/spec/frontend/monitoring/store/utils_spec.js @@ -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], ], }, ]); diff --git a/spec/models/alert_management/alert_spec.rb b/spec/models/alert_management/alert_spec.rb index f76acd0f91d..7ee3bc35388 100644 --- a/spec/models/alert_management/alert_spec.rb +++ b/spec/models/alert_management/alert_spec.rb @@ -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) } diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index a72cda03755..62b189dd7d4 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -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') diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index 51da6ee0bbd..96d3e2b7b1b 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -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) } diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 6cbb8a0a1c8..c449a3c3c47 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -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) } diff --git a/spec/models/prometheus_alert_spec.rb b/spec/models/prometheus_alert_spec.rb index 357ddbf63f5..7169a34d96f 100644 --- a/spec/models/prometheus_alert_spec.rb +++ b/spec/models/prometheus_alert_spec.rb @@ -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 diff --git a/spec/services/projects/alerting/notify_service_spec.rb b/spec/services/projects/alerting/notify_service_spec.rb index 9fec1fa6913..045075daf63 100644 --- a/spec/services/projects/alerting/notify_service_spec.rb +++ b/spec/services/projects/alerting/notify_service_spec.rb @@ -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 diff --git a/spec/views/projects/show.html.haml_spec.rb b/spec/views/projects/show.html.haml_spec.rb deleted file mode 100644 index 89a6085ff10..00000000000 --- a/spec/views/projects/show.html.haml_spec.rb +++ /dev/null @@ -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 diff --git a/spec/views/projects/tree/_tree_header.html.haml_spec.rb b/spec/views/projects/tree/_tree_header.html.haml_spec.rb deleted file mode 100644 index 4012d68acd0..00000000000 --- a/spec/views/projects/tree/_tree_header.html.haml_spec.rb +++ /dev/null @@ -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 diff --git a/spec/views/projects/tree/show.html.haml_spec.rb b/spec/views/projects/tree/show.html.haml_spec.rb index 6337546e489..bdf9b08d8f5 100644 --- a/spec/views/projects/tree/show.html.haml_spec.rb +++ b/spec/views/projects/tree/show.html.haml_spec.rb @@ -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 diff --git a/yarn.lock b/yarn.lock index 77af9aeb24c..f5ca6a8ea29 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"