...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
"number-leading-zero":"always", "number-leading-zero":"always",
"number-no-trailing-zeros":true, "number-no-trailing-zeros":true,
"property-no-unknown":true, "property-no-unknown":true,
"property-no-vendor-prefix":true, "property-no-vendor-prefix": [true, { "ignoreProperties": ["user-select"] }],
"rule-empty-line-before":[ "rule-empty-line-before":[
"always-multi-line", "always-multi-line",
{ {
... ...
......
8.5.1 8.5.2
...@@ -221,6 +221,7 @@ export default { ...@@ -221,6 +221,7 @@ export default {
<gl-dropdown-item <gl-dropdown-item
v-for="environment in store.environmentsData" v-for="environment in store.environmentsData"
:key="environment.id" :key="environment.id"
:href="environment.metrics_path"
:active="environment.name === currentEnvironmentName" :active="environment.name === currentEnvironmentName"
active-class="is-active" active-class="is-active"
>{{ environment.name }}</gl-dropdown-item >{{ environment.name }}</gl-dropdown-item
... ...
......
import Vue from 'vue'; import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import Dashboard from './components/dashboard.vue'; import Dashboard from 'ee_else_ce/monitoring/components/dashboard.vue';
export default (props = {}) => { export default (props = {}) => {
const el = document.getElementById('prometheus-graphs'); const el = document.getElementById('prometheus-graphs');
... ...
......
...@@ -22,13 +22,10 @@ const handleUserPopoverMouseOut = ({ target }) => { ...@@ -22,13 +22,10 @@ const handleUserPopoverMouseOut = ({ target }) => {
* Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes. * Adds a MergeRequestPopover component to the body, hands over as much data as the target element has in data attributes.
* loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover * loads based on data-project-path and data-iid more data about an MR from the API and sets it on the popover
*/ */
const handleMRPopoverMount = apolloProvider => ({ target }) => { const handleMRPopoverMount = ({ apolloProvider, projectPath, mrTitle, iid }) => ({ target }) => {
// Add listener to actually remove it again // Add listener to actually remove it again
target.addEventListener('mouseleave', handleUserPopoverMouseOut); target.addEventListener('mouseleave', handleUserPopoverMouseOut);
const { projectPath, mrTitle, iid } = target.dataset;
const mergeRequest = {};
renderFn = setTimeout(() => { renderFn = setTimeout(() => {
const MRPopoverComponent = Vue.extend(MRPopover); const MRPopoverComponent = Vue.extend(MRPopover);
renderedPopover = new MRPopoverComponent({ renderedPopover = new MRPopoverComponent({
...@@ -36,7 +33,6 @@ const handleMRPopoverMount = apolloProvider => ({ target }) => { ...@@ -36,7 +33,6 @@ const handleMRPopoverMount = apolloProvider => ({ target }) => {
target, target,
projectPath, projectPath,
mergeRequestIID: iid, mergeRequestIID: iid,
mergeRequest,
mergeRequestTitle: mrTitle, mergeRequestTitle: mrTitle,
}, },
apolloProvider, apolloProvider,
...@@ -57,8 +53,13 @@ export default elements => { ...@@ -57,8 +53,13 @@ export default elements => {
const listenerAddedAttr = 'data-mr-listener-added'; const listenerAddedAttr = 'data-mr-listener-added';
mrLinks.forEach(el => { mrLinks.forEach(el => {
if (!el.getAttribute(listenerAddedAttr)) { const { projectPath, mrTitle, iid } = el.dataset;
el.addEventListener('mouseenter', handleMRPopoverMount(apolloProvider));
if (!el.getAttribute(listenerAddedAttr) && projectPath && mrTitle && iid) {
el.addEventListener(
'mouseenter',
handleMRPopoverMount({ apolloProvider, projectPath, mrTitle, iid }),
);
el.setAttribute(listenerAddedAttr, true); el.setAttribute(listenerAddedAttr, true);
} }
}); });
... ...
......
...@@ -34,6 +34,7 @@ export default () => { ...@@ -34,6 +34,7 @@ export default () => {
props: { props: {
isLoading: this.mediator.state.isLoading, isLoading: this.mediator.state.isLoading,
pipeline: this.mediator.store.state.pipeline, pipeline: this.mediator.store.state.pipeline,
mediator: this.mediator,
}, },
on: { on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph, refreshPipelineGraph: this.requestRefreshPipelineGraph,
... ...
......
...@@ -22,6 +22,7 @@ import noteHeader from '~/notes/components/note_header.vue'; ...@@ -22,6 +22,7 @@ import noteHeader from '~/notes/components/note_header.vue';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import TimelineEntryItem from './timeline_entry_item.vue'; import TimelineEntryItem from './timeline_entry_item.vue';
import { spriteIcon } from '../../../lib/utils/common_utils'; import { spriteIcon } from '../../../lib/utils/common_utils';
import initMRPopovers from '~/mr_popover/';
const MAX_VISIBLE_COMMIT_LIST_COUNT = 3; const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
...@@ -71,6 +72,9 @@ export default { ...@@ -71,6 +72,9 @@ export default {
); );
}, },
}, },
mounted() {
initMRPopovers(this.$el.querySelectorAll('.gfm-merge_request'));
},
}; };
</script> </script>
... ...
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
opacity: 1 !important; opacity: 1 !important;
* { * {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; user-select: none;
// !important to make sure no style can override this when dragging // !important to make sure no style can override this when dragging
cursor: grabbing !important; cursor: grabbing !important;
... ...
......
...@@ -84,6 +84,9 @@ input[type='checkbox']:hover { ...@@ -84,6 +84,9 @@ input[type='checkbox']:hover {
.search-icon { .search-icon {
transition: color $default-transition-duration; transition: color $default-transition-duration;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; user-select: none;
} }
... ...
......
...@@ -19,7 +19,7 @@ module Projects ...@@ -19,7 +19,7 @@ module Projects
redirect_to project_settings_ci_cd_path(@project) redirect_to project_settings_ci_cd_path(@project)
else else
render 'show' redirect_to project_settings_ci_cd_path(@project), alert: result[:message]
end end
end end
end end
... ...
......
...@@ -4,7 +4,7 @@ require 'nokogiri' ...@@ -4,7 +4,7 @@ require 'nokogiri'
module MarkupHelper module MarkupHelper
include ActionView::Helpers::TagHelper include ActionView::Helpers::TagHelper
include ActionView::Context include ::Gitlab::ActionViewOutput::Context
def plain?(filename) def plain?(filename)
Gitlab::MarkupHelper.plain?(filename) Gitlab::MarkupHelper.plain?(filename)
...@@ -83,7 +83,8 @@ module MarkupHelper ...@@ -83,7 +83,8 @@ module MarkupHelper
text = sanitize( text = sanitize(
text, text,
tags: tags, tags: tags,
attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version'] attributes: Rails::Html::WhiteListSanitizer.allowed_attributes +
%w(style data-src data-name data-unicode-version data-iid data-project-path data-mr-title)
) )
# since <img> tags are stripped, this can leave empty <a> tags hanging around # since <img> tags are stripped, this can leave empty <a> tags hanging around
... ...
......
...@@ -4,6 +4,7 @@ module Ci ...@@ -4,6 +4,7 @@ module Ci
class Bridge < CommitStatus class Bridge < CommitStatus
include Ci::Processable include Ci::Processable
include Ci::Contextable include Ci::Contextable
include Ci::PipelineDelegator
include Importable include Importable
include AfterCommitQueue include AfterCommitQueue
include HasRef include HasRef
...@@ -13,8 +14,6 @@ module Ci ...@@ -13,8 +14,6 @@ module Ci
belongs_to :trigger_request belongs_to :trigger_request
validates :ref, presence: true validates :ref, presence: true
delegate :merge_request_event?, to: :pipeline
def self.retry(bridge, current_user) def self.retry(bridge, current_user)
raise NotImplementedError raise NotImplementedError
end end
... ...
......
...@@ -6,6 +6,7 @@ module Ci ...@@ -6,6 +6,7 @@ module Ci
include Ci::Processable include Ci::Processable
include Ci::Metadatable include Ci::Metadatable
include Ci::Contextable include Ci::Contextable
include Ci::PipelineDelegator
include TokenAuthenticatable include TokenAuthenticatable
include AfterCommitQueue include AfterCommitQueue
include ObjectStorage::BackgroundMove include ObjectStorage::BackgroundMove
...@@ -48,8 +49,6 @@ module Ci ...@@ -48,8 +49,6 @@ module Ci
delegate :terminal_specification, to: :runner_session, allow_nil: true delegate :terminal_specification, to: :runner_session, allow_nil: true
delegate :gitlab_deploy_token, to: :project delegate :gitlab_deploy_token, to: :project
delegate :trigger_short_token, to: :trigger_request, allow_nil: true delegate :trigger_short_token, to: :trigger_request, allow_nil: true
delegate :merge_request_event?, :merge_request_ref?,
:legacy_detached_merge_request_pipeline?, to: :pipeline
## ##
# Since Gitlab 11.5, deployments records started being created right after # Since Gitlab 11.5, deployments records started being created right after
... ...
......
...@@ -754,6 +754,22 @@ module Ci ...@@ -754,6 +754,22 @@ module Ci
self.sha == sha || self.source_sha == sha self.sha == sha || self.source_sha == sha
end end
def triggered_by?(current_user)
user == current_user
end
def source_ref
if triggered_by_merge_request?
merge_request.source_branch
else
ref
end
end
def source_ref_slug
Gitlab::Utils.slugify(source_ref.to_s)
end
private private
def ci_yaml_from_repo def ci_yaml_from_repo
... ...
......
...@@ -70,8 +70,8 @@ module Ci ...@@ -70,8 +70,8 @@ module Ci
variables.append(key: 'CI_COMMIT_SHA', value: sha) variables.append(key: 'CI_COMMIT_SHA', value: sha)
variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha) variables.append(key: 'CI_COMMIT_SHORT_SHA', value: short_sha)
variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha) variables.append(key: 'CI_COMMIT_BEFORE_SHA', value: before_sha)
variables.append(key: 'CI_COMMIT_REF_NAME', value: ref) variables.append(key: 'CI_COMMIT_REF_NAME', value: source_ref)
variables.append(key: 'CI_COMMIT_REF_SLUG', value: ref_slug) variables.append(key: 'CI_COMMIT_REF_SLUG', value: source_ref_slug)
variables.append(key: "CI_COMMIT_TAG", value: ref) if tag? variables.append(key: "CI_COMMIT_TAG", value: ref) if tag?
variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request variables.append(key: "CI_PIPELINE_TRIGGERED", value: 'true') if trigger_request
variables.append(key: "CI_JOB_MANUAL", value: 'true') if action? variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
...@@ -85,8 +85,8 @@ module Ci ...@@ -85,8 +85,8 @@ module Ci
Gitlab::Ci::Variables::Collection.new.tap do |variables| Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_BUILD_REF', value: sha) variables.append(key: 'CI_BUILD_REF', value: sha)
variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha) variables.append(key: 'CI_BUILD_BEFORE_SHA', value: before_sha)
variables.append(key: 'CI_BUILD_REF_NAME', value: ref) variables.append(key: 'CI_BUILD_REF_NAME', value: source_ref)
variables.append(key: 'CI_BUILD_REF_SLUG', value: ref_slug) variables.append(key: 'CI_BUILD_REF_SLUG', value: source_ref_slug)
variables.append(key: 'CI_BUILD_NAME', value: name) variables.append(key: 'CI_BUILD_NAME', value: name)
variables.append(key: 'CI_BUILD_STAGE', value: stage) variables.append(key: 'CI_BUILD_STAGE', value: stage)
variables.append(key: "CI_BUILD_TAG", value: ref) if tag? variables.append(key: "CI_BUILD_TAG", value: ref) if tag?
... ...
......
# frozen_string_literal: true
##
# This module is mainly used by child associations of `Ci::Pipeline` that needs to look up
# single source of truth. For example, `Ci::Build` has `git_ref` method, which behaves
# slightly different from `Ci::Pipeline`'s `git_ref`. This is very confusing as
# the system could behave differently time to time.
# We should have a single interface in `Ci::Pipeline` and access the method always.
module Ci
module PipelineDelegator
extend ActiveSupport::Concern
included do
delegate :merge_request_event?,
:merge_request_ref?,
:source_ref,
:source_ref_slug,
:legacy_detached_merge_request_pipeline?, to: :pipeline
end
end
end
# frozen_string_literal: true # frozen_string_literal: true
##
# We will disable `ref` and `sha` attributes in `Ci::Build` in the future
# and remove this module in favor of Ci::PipelineDelegator.
module HasRef module HasRef
extend ActiveSupport::Concern extend ActiveSupport::Concern
... ...
......
...@@ -79,7 +79,11 @@ class Deployment < ApplicationRecord ...@@ -79,7 +79,11 @@ class Deployment < ApplicationRecord
end end
def cluster def cluster
project.deployment_platform(environment: environment.name)&.cluster platform = project.deployment_platform(environment: environment.name)
if platform.present? && platform.respond_to?(:cluster)
platform.cluster
end
end end
def last? def last?
... ...
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module UserStatusTooltip module UserStatusTooltip
extend ActiveSupport::Concern extend ActiveSupport::Concern
include ActionView::Helpers::TagHelper include ActionView::Helpers::TagHelper
include ActionView::Context include ::Gitlab::ActionViewOutput::Context
include EmojiHelper include EmojiHelper
include UsersHelper include UsersHelper
... ...
......
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
- if @scope == 'projects' - if @scope == 'projects'
.term .term
= render 'shared/projects/list', projects: @search_objects, pipeline_status: false = render 'shared/projects/list', projects: @search_objects, pipeline_status: false
- elsif %w[blobs wiki_blobs].include?(@scope)
= render partial: 'search/results/blob', collection: @search_objects, locals: { projects: blob_projects(@search_objects) }
- else - else
= render partial: "search/results/#{@scope.singularize}", collection: @search_objects - locals = { projects: blob_projects(@search_objects) } if %w[blobs wiki_blobs].include?(@scope)
= render partial: "search/results/#{@scope.singularize}", collection: @search_objects, locals: locals
- if @scope != 'projects' - if @scope != 'projects'
= paginate_collection(@search_objects) = paginate_collection(@search_objects)