Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
2a53c24c51
commit
ebe92e84a9
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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
|
||||
|
||||
- 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
- if pipeline && pipeline.latest_builds_with_artifacts.any?
|
||||
%section.border-top.pt-1.mt-1
|
||||
%h5.m-0.dropdown-bold-header= _('Download artifacts')
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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') }
|
||||
|
||||
.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'
|
||||
|
||||
= 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')
|
||||
- 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')
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add prometheus_alert_id and environment_id to Alert management alerts
|
||||
merge_request: 34995
|
||||
author:
|
||||
type: added
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Don't include changes in webhook payload when old associations are empty
|
||||
merge_request: 35158
|
||||
author:
|
||||
type: fixed
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
\.
|
||||
|
||||
|
|
|
@ -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).
|
||||
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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],
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
|
@ -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) }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
16
yarn.lock
16
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"
|
||||
|
|
Loading…
Reference in New Issue