Commit 3495951d authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'dj-dependency-path-tooltip' into 'master'

Add a tooltip for Dependency Path

See merge request gitlab-org/gitlab!44557
parents 3101bc43 12c9839c
...@@ -24,10 +24,10 @@ export default { ...@@ -24,10 +24,10 @@ export default {
}, },
inject: { inject: {
autoDevopsHelpPath: { autoDevopsHelpPath: {
type: String, default: '',
}, },
externalEndpointHelpPath: { externalEndpointHelpPath: {
type: String, default: '',
}, },
}, },
data() { data() {
......
...@@ -122,67 +122,20 @@ export default { ...@@ -122,67 +122,20 @@ export default {
</script> </script>
<template> <template>
<li :class="{ 'js-toggle-container': collapsible }" class="commit flex-row"> <li :class="{ 'js-toggle-container': collapsible }" class="commit">
<div class="d-flex align-items-center align-self-start"> <div
<input class="d-block d-sm-flex flex-row-reverse justify-content-between align-items-start flex-lg-row-reverse"
v-if="isSelectable" >
class="mr-2" <div
type="checkbox" class="commit-actions flex-row d-none d-sm-flex align-items-start flex-wrap justify-content-end"
:checked="checked" >
@change="$emit('handleCheckboxChange', $event.target.checked)"
/>
<user-avatar-link
:link-href="authorUrl"
:img-src="authorAvatar"
:img-alt="authorName"
:img-size="40"
class="avatar-cell d-none d-sm-block"
/>
</div>
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<a
:href="commit.commit_url"
class="commit-row-message item-title"
v-html="commit.title_html"
></a>
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
<gl-button
v-if="commit.description_html && collapsible"
class="js-toggle-button"
size="small"
icon="ellipsis_h"
:aria-label="__('Toggle commit description')"
/>
<div class="committer">
<a
:href="authorUrl"
:class="authorClass"
:data-user-id="authorId"
v-text="authorName"
></a>
{{ s__('CommitWidget|authored') }}
<time-ago-tooltip :time="commit.authored_date" />
</div>
<pre
v-if="commit.description_html"
:class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
class="commit-row-description gl-mb-3 text-dark"
v-html="commitDescription"
></pre>
</div>
<div class="commit-actions flex-row d-none d-sm-flex">
<div v-if="commit.signature_html" v-html="commit.signature_html"></div> <div v-if="commit.signature_html" v-html="commit.signature_html"></div>
<commit-pipeline-status <commit-pipeline-status
v-if="commit.pipeline_status_path" v-if="commit.pipeline_status_path"
:endpoint="commit.pipeline_status_path" :endpoint="commit.pipeline_status_path"
class="d-inline-flex" class="d-inline-flex mb-2"
/> />
<gl-button-group class="gl-ml-4" data-testid="commit-sha-group"> <gl-button-group class="gl-ml-4 gl-mb-4" data-testid="commit-sha-group">
<gl-button label class="gl-font-monospace" v-text="commit.short_id" /> <gl-button label class="gl-font-monospace" v-text="commit.short_id" />
<clipboard-button <clipboard-button
:text="commit.id" :text="commit.id"
...@@ -226,6 +179,62 @@ export default { ...@@ -226,6 +179,62 @@ export default {
</gl-button-group> </gl-button-group>
</div> </div>
</div> </div>
<div>
<div class="d-flex float-left align-items-center align-self-start">
<input
v-if="isSelectable"
class="mr-2"
type="checkbox"
:checked="checked"
@change="$emit('handleCheckboxChange', $event.target.checked)"
/>
<user-avatar-link
:link-href="authorUrl"
:img-src="authorAvatar"
:img-alt="authorName"
:img-size="40"
class="avatar-cell d-none d-sm-block"
/>
</div>
<div class="commit-detail flex-list">
<div class="commit-content qa-commit-content">
<a
:href="commit.commit_url"
class="commit-row-message item-title"
v-html="commit.title_html"
></a>
<span class="commit-row-message d-block d-sm-none">&middot; {{ commit.short_id }}</span>
<gl-button
v-if="commit.description_html && collapsible"
class="js-toggle-button"
size="small"
icon="ellipsis_h"
:aria-label="__('Toggle commit description')"
/>
<div class="committer">
<a
:href="authorUrl"
:class="authorClass"
:data-user-id="authorId"
v-text="authorName"
></a>
{{ s__('CommitWidget|authored') }}
<time-ago-tooltip :time="commit.authored_date" />
</div>
</div>
</div>
</div>
</div>
<div>
<pre
v-if="commit.description_html"
:class="{ 'js-toggle-content': collapsible, 'd-block': !collapsible }"
class="commit-row-description gl-mb-3 text-dark"
v-html="commitDescription"
></pre>
</div> </div>
</li> </li>
</template> </template>
<script> <script>
import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui'; import { GlButton, GlFormSelect, GlToggle, GlLoadingIcon, GlSprintf } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import tooltip from '~/vue_shared/directives/tooltip';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
export default { export default {
name: 'ServiceDeskSetting', name: 'ServiceDeskSetting',
directives: {
tooltip,
},
components: { components: {
ClipboardButton, ClipboardButton,
GlButton, GlButton,
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* eslint-disable vue/no-v-html */ /* eslint-disable vue/no-v-html */
import { GlTooltipDirective, GlLink, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui'; import { GlTooltipDirective, GlLink, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
import defaultAvatarUrl from 'images/no_avatar.png'; import defaultAvatarUrl from 'images/no_avatar.png';
import pathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql';
import { sprintf, s__ } from '~/locale'; import { sprintf, s__ } from '~/locale';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue'; import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue'; import TimeagoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
...@@ -9,7 +10,6 @@ import CiIcon from '../../vue_shared/components/ci_icon.vue'; ...@@ -9,7 +10,6 @@ import CiIcon from '../../vue_shared/components/ci_icon.vue';
import ClipboardButton from '../../vue_shared/components/clipboard_button.vue'; import ClipboardButton from '../../vue_shared/components/clipboard_button.vue';
import getRefMixin from '../mixins/get_ref'; import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql'; import projectPathQuery from '../queries/project_path.query.graphql';
import pathLastCommitQuery from '../queries/path_last_commit.query.graphql';
export default { export default {
components: { components: {
......
import Vue from 'vue'; import Vue from 'vue';
import PathLastCommitQuery from 'shared_queries/repository/path_last_commit.query.graphql';
import { escapeFileUrl, joinPaths, webIDEUrl } from '../lib/utils/url_utility'; import { escapeFileUrl, joinPaths, webIDEUrl } from '../lib/utils/url_utility';
import createRouter from './router'; import createRouter from './router';
import App from './components/app.vue'; import App from './components/app.vue';
...@@ -18,6 +19,10 @@ export default function setupVueRepositoryList() { ...@@ -18,6 +19,10 @@ export default function setupVueRepositoryList() {
const { dataset } = el; const { dataset } = el;
const { projectPath, projectShortPath, ref, escapedRef, fullName } = dataset; const { projectPath, projectShortPath, ref, escapedRef, fullName } = dataset;
const router = createRouter(projectPath, escapedRef); const router = createRouter(projectPath, escapedRef);
const pathRegex = /-\/tree\/[^/]+\/(.+$)/;
const matches = window.location.href.match(pathRegex);
const currentRoutePath = matches ? matches[1] : '';
apolloProvider.clients.defaultClient.cache.writeData({ apolloProvider.clients.defaultClient.cache.writeData({
data: { data: {
...@@ -29,6 +34,43 @@ export default function setupVueRepositoryList() { ...@@ -29,6 +34,43 @@ export default function setupVueRepositoryList() {
}, },
}); });
const initLastCommitApp = () =>
new Vue({
el: document.getElementById('js-last-commit'),
router,
apolloProvider,
render(h) {
return h(LastCommit, {
props: {
currentPath: this.$route.params.path,
},
});
},
});
if (window.gl.startup_graphql_calls) {
const query = window.gl.startup_graphql_calls.find(
call => call.operationName === 'pathLastCommit',
);
query.fetchCall
.then(res => res.json())
.then(res => {
apolloProvider.clients.defaultClient.writeQuery({
query: PathLastCommitQuery,
data: res.data,
variables: {
projectPath,
ref,
path: currentRoutePath,
},
});
})
.catch(() => {})
.finally(() => initLastCommitApp());
} else {
initLastCommitApp();
}
router.afterEach(({ params: { path } }) => { router.afterEach(({ params: { path } }) => {
setTitle(path, ref, fullName); setTitle(path, ref, fullName);
}); });
...@@ -77,20 +119,6 @@ export default function setupVueRepositoryList() { ...@@ -77,20 +119,6 @@ export default function setupVueRepositoryList() {
}); });
} }
// eslint-disable-next-line no-new
new Vue({
el: document.getElementById('js-last-commit'),
router,
apolloProvider,
render(h) {
return h(LastCommit, {
props: {
currentPath: this.$route.params.path,
},
});
},
});
const treeHistoryLinkEl = document.getElementById('js-tree-history-link'); const treeHistoryLinkEl = document.getElementById('js-tree-history-link');
const { historyLink } = treeHistoryLinkEl.dataset; const { historyLink } = treeHistoryLinkEl.dataset;
......
...@@ -8,11 +8,8 @@ ...@@ -8,11 +8,8 @@
@import './pages/commits'; @import './pages/commits';
@import './pages/deploy_keys'; @import './pages/deploy_keys';
@import './pages/detail_page'; @import './pages/detail_page';
@import './pages/diff';
@import './pages/editor'; @import './pages/editor';
@import './pages/environment_logs'; @import './pages/environment_logs';
@import './pages/error_list';
@import './pages/error_tracking_list';
@import './pages/events'; @import './pages/events';
@import './pages/experience_level'; @import './pages/experience_level';
@import './pages/experimental_separate_sign_up'; @import './pages/experimental_separate_sign_up';
......
...@@ -70,3 +70,4 @@ ...@@ -70,3 +70,4 @@
@import 'framework/spinner'; @import 'framework/spinner';
@import 'framework/card'; @import 'framework/card';
@import 'framework/editor-lite'; @import 'framework/editor-lite';
@import 'framework/diffs';
...@@ -267,6 +267,7 @@ ...@@ -267,6 +267,7 @@
} }
} }
} }
//.view.swipe //.view.swipe
.view.onion-skin { .view.onion-skin {
.onion-skin-frame { .onion-skin-frame {
...@@ -335,6 +336,7 @@ ...@@ -335,6 +336,7 @@
} }
} }
} }
//.view.onion-skin //.view.onion-skin
} }
...@@ -961,15 +963,13 @@ table.code { ...@@ -961,15 +963,13 @@ table.code {
.frame.click-to-comment, .frame.click-to-comment,
.btn-transparent.image-diff-overlay-add-comment { .btn-transparent.image-diff-overlay-add-comment {
position: relative; position: relative;
cursor: image-url('illustrations/image_comment_light_cursor.svg') cursor: image-url('illustrations/image_comment_light_cursor.svg') $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
$image-comment-cursor-left-offset $image-comment-cursor-top-offset,
auto; auto;
// Retina cursor // Retina cursor
// scss-lint:disable DuplicateProperty // scss-lint:disable DuplicateProperty
cursor: image-set(image-url('illustrations/image_comment_light_cursor.svg') 1x, cursor: image-set(image-url('illustrations/image_comment_light_cursor.svg') 1x,
image-url('illustrations/image_comment_light_cursor@2x.svg') 2x) image-url('illustrations/image_comment_light_cursor@2x.svg') 2x) $image-comment-cursor-left-offset $image-comment-cursor-top-offset,
$image-comment-cursor-left-offset $image-comment-cursor-top-offset,
auto; auto;
.comment-indicator { .comment-indicator {
...@@ -1078,85 +1078,6 @@ table.code { ...@@ -1078,85 +1078,6 @@ table.code {
position: relative; position: relative;
} }
.diff-tree-list {
position: -webkit-sticky;
position: sticky;
$top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 15px;
top: $top-pos;
max-height: calc(100vh - #{$top-pos});
z-index: 202;
.with-system-header & {
top: $top-pos + $system-header-height;
}
.with-system-header.with-performance-bar & {
top: $top-pos + $system-header-height + $performance-bar-height;
}
.with-performance-bar & {
$performance-bar-top-pos: $performance-bar-height + $top-pos;
top: $performance-bar-top-pos;
max-height: calc(100vh - #{$performance-bar-top-pos});
}
.drag-handle {
bottom: 16px;
transform: translateX(10px);
}
}
.diff-files-holder {
flex: 1;
min-width: 0;
z-index: 201;
}
.compare-versions-container {
min-width: 0;
}
.tree-list-holder {
height: 100%;
.file-row {
margin-left: 0;
margin-right: 0;
}
}
.tree-list-scroll {
max-height: 100%;
padding-bottom: $grid-size;
overflow-y: scroll;
overflow-x: auto;
}
.tree-list-search {
flex: 0 0 34px;
.form-control {
padding-left: 30px;
}
}
.tree-list-icon {
top: 50%;
left: 10px;
transform: translateY(-50%);
&,
svg {
fill: $gl-text-color-tertiary;
}
}
.tree-list-clear-icon {
right: 10px;
left: auto;
line-height: 0;
}
.discussion-collapsible { .discussion-collapsible {
margin: 0 $gl-padding $gl-padding 71px; margin: 0 $gl-padding $gl-padding 71px;
...@@ -1172,30 +1093,6 @@ table.code { ...@@ -1172,30 +1093,6 @@ table.code {
} }
} }
@media (max-width: map-get($grid-breakpoints, md)-1) {
.diffs .files {
@include fixed-width-container;
flex-direction: column;
.diff-tree-list {
position: relative;
top: 0;
// !important is required to override inline styles of resizable sidebar
width: 100% !important;
}
.tree-list-holder {
max-height: calc(50px + 50vh);
padding-right: 0;
}
}
.discussion-collapsible {
margin: $gl-padding;
margin-top: 0;
}
}
.image-diff-overlay, .image-diff-overlay,
.image-diff-overlay-add-comment { .image-diff-overlay-add-comment {
top: 0; top: 0;
...@@ -1218,3 +1115,15 @@ table.code { ...@@ -1218,3 +1115,15 @@ table.code {
display: none; display: none;
} }
} }
@media (max-width: map-get($grid-breakpoints, md)-1) {
.diffs .files {
@include fixed-width-container;
flex-direction: column;
}
.discussion-collapsible {
margin: $gl-padding;
margin-top: 0;
}
}
@import 'page_bundles/mixins_and_variables_and_functions';
.error-list { .error-list {
.dropdown {
min-width: auto;
}
.sort-control { .sort-control {
.btn { .btn {
padding-right: 2rem; padding-right: 2rem;
...@@ -17,7 +23,7 @@ ...@@ -17,7 +23,7 @@
min-height: 68px; min-height: 68px;
&:last-child { &:last-child {
background-color: $gray-10; background-color: var(--gray-10, $gray-10);
&::before { &::before {
content: none !important; content: none !important;
......
@import 'mixins_and_variables_and_functions';
.compare-versions-container {
min-width: 0;
}
.diff-files-holder {
flex: 1;
min-width: 0;
z-index: 201;
}
.diff-tree-list {
position: -webkit-sticky;
position: sticky;
$top-pos: $header-height + $mr-tabs-height + $mr-version-controls-height + 15px;
top: $top-pos;
max-height: calc(100vh - #{$top-pos});
z-index: 202;
.with-system-header & {
top: $top-pos + $system-header-height;
}
.with-system-header.with-performance-bar & {
top: $top-pos + $system-header-height + $performance-bar-height;
}
.with-performance-bar & {
$performance-bar-top-pos: $performance-bar-height + $top-pos;
top: $performance-bar-top-pos;
max-height: calc(100vh - #{$performance-bar-top-pos});
}
.drag-handle {
bottom: 16px;
transform: translateX(10px);
}
}
.tree-list-holder {
height: 100%;
.file-row {
margin-left: 0;
margin-right: 0;
}
}
.tree-list-scroll {
max-height: 100%;
padding-bottom: $grid-size;
overflow-y: scroll;
overflow-x: auto;
}
.tree-list-search {
flex: 0 0 34px;
.form-control {
padding-left: 30px;
}
}
.tree-list-icon {
top: 50%;
left: 10px;
transform: translateY(-50%);
&,
svg {
fill: var(--gray-400, $gray-400);
}
}
.tree-list-clear-icon {
right: 10px;
left: auto;
line-height: 0;
}
@media (max-width: map-get($grid-breakpoints, md)-1) {
.diffs .files {
.diff-tree-list {
position: relative;
top: 0;
// !important is required to override inline styles of resizable sidebar
width: 100% !important;
}
.tree-list-holder {
max-height: calc(50px + 50vh);
padding-right: 0;
}
}
}
.error-list {
.dropdown {
min-width: auto;
}
}
query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) { query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
project(fullPath: $projectPath) { project(fullPath: $projectPath) {
__typename
repository { repository {
__typename
tree(path: $path, ref: $ref) { tree(path: $path, ref: $ref) {
__typename
lastCommit { lastCommit {
__typename
sha sha
title title
titleHtml titleHtml
...@@ -13,15 +17,20 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) { ...@@ -13,15 +17,20 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
authorName authorName
authorGravatar authorGravatar
author { author {
__typename
name name
avatarUrl avatarUrl
webPath webPath
} }
signatureHtml signatureHtml
pipelines(ref: $ref, first: 1) { pipelines(ref: $ref, first: 1) {
__typename
edges { edges {
__typename
node { node {
__typename
detailedStatus { detailedStatus {
__typename
detailsPath detailsPath
icon icon
tooltip tooltip
......
# frozen_string_literal: true
module StartupjsHelper
def page_startup_graphql_calls
@graphql_startup_calls
end
def add_page_startup_graphql_call(query, variables = {})
@graphql_startup_calls ||= []
file_location = File.join(Rails.root, "app/graphql/queries/#{query}.query.graphql")
return unless File.exist?(file_location)
query_str = File.read(file_location)
@graphql_startup_calls << { query: query_str, variables: variables }
end
end
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
- @metric.cards.each do |card| - @metric.cards.each do |card|
= render 'card', card: card = render 'card', card: card
.devops-steps.d-none.d-lg-block.d-xl-block .devops-steps.d-none.d-lg-block
- @metric.idea_to_production_steps.each_with_index do |step, index| - @metric.idea_to_production_steps.each_with_index do |step, index|
.devops-step{ class: "devops-#{score_level(step.percentage_score)}-score" } .devops-step{ class: "devops-#{score_level(step.percentage_score)}-score" }
= custom_icon("i2p_step_#{index + 1}") = custom_icon("i2p_step_#{index + 1}")
......
- return unless page_startup_api_calls.present? - return unless page_startup_api_calls.present? || page_startup_graphql_calls.present?
= javascript_tag nonce: true do = javascript_tag nonce: true do
:plain :plain
var gl = window.gl || {}; var gl = window.gl || {};
gl.startup_calls = #{page_startup_api_calls.to_json}; gl.startup_calls = #{page_startup_api_calls.to_json};
gl.startup_graphql_calls = #{page_startup_graphql_calls.to_json};
if (gl.startup_calls && window.fetch) { if (gl.startup_calls && window.fetch) {
Object.keys(gl.startup_calls).forEach(apiCall => { Object.keys(gl.startup_calls).forEach(apiCall => {
// fetch won’t send cookies in older browsers, unless you set the credentials init option. // fetch won’t send cookies in older browsers, unless you set the credentials init option.
...@@ -14,3 +16,21 @@ ...@@ -14,3 +16,21 @@
}; };
}); });
} }
if (gl.startup_graphql_calls && window.fetch) {
const url = `#{api_graphql_url}`
const opts = {
method: "POST",
headers: { "Content-Type": "application/json", 'X-CSRF-Token': "#{form_authenticity_token}" },
};
gl.startup_graphql_calls = gl.startup_graphql_calls.map(call => ({
operationName: call.query.match(/^query (.+)\(/)[1],
fetchCall: fetch(url, {
...opts,
credentials: 'same-origin',
body: JSON.stringify(call)
})
}))
}
- page_title _('Errors') - page_title _('Errors')
- add_page_specific_style 'page_bundles/error_tracking_index'
#js-error_tracking{ data: error_tracking_data(@current_user, @project) } #js-error_tracking{ data: error_tracking_data(@current_user, @project) }
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
- suggest_changes_help_path = help_page_path('user/discussions/index.md', anchor: 'suggest-changes') - suggest_changes_help_path = help_page_path('user/discussions/index.md', anchor: 'suggest-changes')
- number_of_pipelines = @pipelines.size - number_of_pipelines = @pipelines.size
- mr_action = j(params[:tab].presence || 'show') - mr_action = j(params[:tab].presence || 'show')
- add_page_specific_style 'page_bundles/merge_requests'
- add_page_specific_style 'page_bundles/pipelines' - add_page_specific_style 'page_bundles/pipelines'
- add_page_specific_style 'page_bundles/reports' - add_page_specific_style 'page_bundles/reports'
......
- current_route_path = request.fullpath.match(/-\/tree\/[^\/]+\/(.+$)/).to_a[1]
- add_page_startup_graphql_call('repository/path_last_commit', { projectPath: @project.full_path, ref: current_ref, currentRoutePath: current_route_path })
- breadcrumb_title _("Repository") - breadcrumb_title _("Repository")
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
......
---
title: Improve the Commit box on the Merge Request Changs tab when browsing per commit
merge_request: 43613
author:
type: fixed
---
title: Remove duplicated BS display properties from Admin DevOps report' HAML
merge_request: 44846
author: Takuya Noguchi
type: other
...@@ -178,10 +178,12 @@ module Gitlab ...@@ -178,10 +178,12 @@ module Gitlab
config.assets.precompile << "page_bundles/dev_ops_report.css" config.assets.precompile << "page_bundles/dev_ops_report.css"
config.assets.precompile << "page_bundles/environments.css" config.assets.precompile << "page_bundles/environments.css"
config.assets.precompile << "page_bundles/error_tracking_details.css" config.assets.precompile << "page_bundles/error_tracking_details.css"
config.assets.precompile << "page_bundles/error_tracking_index.css"
config.assets.precompile << "page_bundles/ide.css" config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/issues_list.css" config.assets.precompile << "page_bundles/issues_list.css"
config.assets.precompile << "page_bundles/jira_connect.css" config.assets.precompile << "page_bundles/jira_connect.css"
config.assets.precompile << "page_bundles/merge_conflicts.css" config.assets.precompile << "page_bundles/merge_conflicts.css"
config.assets.precompile << "page_bundles/merge_requests.css"
config.assets.precompile << "page_bundles/milestone.css" config.assets.precompile << "page_bundles/milestone.css"
config.assets.precompile << "page_bundles/pipeline.css" config.assets.precompile << "page_bundles/pipeline.css"
config.assets.precompile << "page_bundles/pipelines.css" config.assets.precompile << "page_bundles/pipelines.css"
......
...@@ -97,6 +97,7 @@ const alias = { ...@@ -97,6 +97,7 @@ const alias = {
vue$: 'vue/dist/vue.esm.js', vue$: 'vue/dist/vue.esm.js',
spec: path.join(ROOT_PATH, 'spec/javascripts'), spec: path.join(ROOT_PATH, 'spec/javascripts'),
jest: path.join(ROOT_PATH, 'spec/frontend'), jest: path.join(ROOT_PATH, 'spec/frontend'),
shared_queries: path.join(ROOT_PATH, 'app/graphql/queries'),
// the following resolves files which are different between CE and EE // the following resolves files which are different between CE and EE
ee_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'), ee_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
......
# frozen_string_literal: true
gitlab_danger = GitlabDanger.new(helper.gitlab_helper)
TEMPLATE_MESSAGE = <<~MSG
This merge request requires a CI/CD Template review. To make sure these
changes are reviewed, take the following steps:
1. Ensure the merge request has the ~"ci::templates" label.
If the merge request modifies CI/CD Template files, Danger will do this for you.
1. Prepare your MR for a CI/CD Template review according to the
[template development guide](https://docs.gitlab.com/ee/development/cicd/templates.html).
1. Assign and `@` mention the CI/CD Template reviewer suggested by Reviewer Roulette.
MSG
TEMPLATE_FILES_MESSAGE = <<~MSG
The following files require a review from the CI/CD Templates maintainers:
MSG
return unless gitlab_danger.ci?
template_paths_to_review = helper.changes_by_category[:ci_template]
if gitlab.mr_labels.include?('ci::templates') || template_paths_to_review.any?
message 'This merge request adds or changes files that require a ' \
'review from the CI/CD Templates maintainers.'
markdown(TEMPLATE_MESSAGE)
markdown(TEMPLATE_FILES_MESSAGE + helper.markdown_list(template_paths_to_review)) if template_paths_to_review.any?
end
...@@ -10,7 +10,8 @@ SPECIALIZATIONS = { ...@@ -10,7 +10,8 @@ SPECIALIZATIONS = {
frontend: 'frontend', frontend: 'frontend',
docs: 'documentation', docs: 'documentation',
qa: 'QA', qa: 'QA',
engineering_productivity: 'Engineering Productivity' engineering_productivity: 'Engineering Productivity',
ci_template: 'ci::templates'
}.freeze }.freeze
labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _changes), memo| labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
......
.approvals-body {
@include media-breakpoint-up(md) {
display: flex;
align-items: center;
}
.approve-btn {
vertical-align: baseline;
}
.approvals-required-text {
svg {
position: relative;
top: 3px;
}
}
}
.approvals-footer {
display: flex;
.approvers-prefix {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.approvers-list {
display: flex;
align-items: center;
margin-left: 7px;
}
.avatar-placeholder {
color: $gray-darkest;
}
.unapprove-btn {
border: 0;
background: transparent;
cursor: pointer;
&:hover {
color: $gl-text-color-secondary;
text-decoration: none;
}
&:focus {
outline: none;
}
}
}
...@@ -33,6 +33,7 @@ module.exports = path => { ...@@ -33,6 +33,7 @@ module.exports = path => {
'^~(/.*)$': '<rootDir>/app/assets/javascripts$1', '^~(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^ee_component(/.*)$': '^ee_component(/.*)$':
'<rootDir>/app/assets/javascripts/vue_shared/components/empty_component.js', '<rootDir>/app/assets/javascripts/vue_shared/components/empty_component.js',
'^shared_queries(/.*)$': '<rootDir>/app/graphql/queries$1',
'^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1', '^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1', '^helpers(/.*)$': '<rootDir>/spec/frontend/helpers$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1', '^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
......
...@@ -123,7 +123,8 @@ module Gitlab ...@@ -123,7 +123,8 @@ module Gitlab
none: "", none: "",
qa: "~QA", qa: "~QA",
test: "~test ~Quality for `spec/features/*`", test: "~test ~Quality for `spec/features/*`",
engineering_productivity: '~"Engineering Productivity" for CI, Danger' engineering_productivity: '~"Engineering Productivity" for CI, Danger',
ci_template: '~"ci::templates"'
}.freeze }.freeze
# First-match win, so be sure to put more specific regex at the top... # First-match win, so be sure to put more specific regex at the top...
CATEGORIES = { CATEGORIES = {
...@@ -176,6 +177,8 @@ module Gitlab ...@@ -176,6 +177,8 @@ module Gitlab
%r{(CODEOWNERS)} => :engineering_productivity, %r{(CODEOWNERS)} => :engineering_productivity,
%r{(tests.yml)} => :engineering_productivity, %r{(tests.yml)} => :engineering_productivity,
%r{\Alib/gitlab/ci/templates} => :ci_template,
%r{\A(ee/)?spec/features/} => :test, %r{\A(ee/)?spec/features/} => :test,
%r{\A(ee/)?spec/support/shared_examples/features/} => :test, %r{\A(ee/)?spec/support/shared_examples/features/} => :test,
%r{\A(ee/)?spec/support/shared_contexts/features/} => :test, %r{\A(ee/)?spec/support/shared_contexts/features/} => :test,
......
...@@ -52,6 +52,11 @@ module Gitlab ...@@ -52,6 +52,11 @@ module Gitlab
# Fetch an already picked backend maintainer, or pick one otherwise # Fetch an already picked backend maintainer, or pick one otherwise
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
end end
when :ci_template
if spin.maintainer.nil?
# Fetch an already picked backend maintainer, or pick one otherwise
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
end
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe StartupjsHelper do
describe '#page_startup_graphql_calls' do
let(:query_location) { 'repository/path_last_commit' }
let(:query_content) do
File.read(File.join(Rails.root, 'app/graphql/queries', "#{query_location}.query.graphql"))
end
it 'returns an array containing GraphQL Page Startup Calls' do
helper.add_page_startup_graphql_call(query_location, { ref: 'foo' })
startup_graphql_calls = helper.page_startup_graphql_calls
expect(startup_graphql_calls).to include({ query: query_content, variables: { ref: 'foo' } })
end
end
end
...@@ -284,7 +284,8 @@ RSpec.describe Gitlab::Danger::Helper do ...@@ -284,7 +284,8 @@ RSpec.describe Gitlab::Danger::Helper do
'.codeclimate.yml' | [:engineering_productivity] '.codeclimate.yml' | [:engineering_productivity]
'.gitlab/CODEOWNERS' | [:engineering_productivity] '.gitlab/CODEOWNERS' | [:engineering_productivity]
'lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' | [:backend] 'lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml' | [:ci_template]
'lib/gitlab/ci/templates/dotNET-Core.yml' | [:ci_template]
'ee/FOO_VERSION' | [:unknown] 'ee/FOO_VERSION' | [:unknown]
...@@ -376,6 +377,7 @@ RSpec.describe Gitlab::Danger::Helper do ...@@ -376,6 +377,7 @@ RSpec.describe Gitlab::Danger::Helper do
:none | '' :none | ''
:qa | '~QA' :qa | '~QA'
:engineering_productivity | '~"Engineering Productivity" for CI, Danger' :engineering_productivity | '~"Engineering Productivity" for CI, Danger'
:ci_template | '~"ci::templates"'
end end
with_them do with_them do
......
...@@ -4,8 +4,11 @@ require 'webmock/rspec' ...@@ -4,8 +4,11 @@ require 'webmock/rspec'
require 'timecop' require 'timecop'
require 'gitlab/danger/roulette' require 'gitlab/danger/roulette'
require 'active_support/testing/time_helpers'
RSpec.describe Gitlab::Danger::Roulette do RSpec.describe Gitlab::Danger::Roulette do
include ActiveSupport::Testing::TimeHelpers
around do |example| around do |example|
travel_to(Time.utc(2020, 06, 22, 10)) { example.run } travel_to(Time.utc(2020, 06, 22, 10)) { example.run }
end end
...@@ -67,13 +70,25 @@ RSpec.describe Gitlab::Danger::Roulette do ...@@ -67,13 +70,25 @@ RSpec.describe Gitlab::Danger::Roulette do
) )
end end
let(:ci_template_reviewer) do
Gitlab::Danger::Teammate.new(
'username' => 'ci-template-maintainer',
'name' => 'CI Template engineer',
'role' => '~"ci::templates"',
'projects' => { 'gitlab' => 'reviewer ci_template' },
'available' => true,
'tz_offset_hours' => 2.0
)
end
let(:teammates) do let(:teammates) do
[ [
backend_maintainer.to_h, backend_maintainer.to_h,
frontend_maintainer.to_h, frontend_maintainer.to_h,
frontend_reviewer.to_h, frontend_reviewer.to_h,
software_engineer_in_test.to_h, software_engineer_in_test.to_h,
engineering_productivity_reviewer.to_h engineering_productivity_reviewer.to_h,
ci_template_reviewer.to_h
] ]
end end
...@@ -166,6 +181,14 @@ RSpec.describe Gitlab::Danger::Roulette do ...@@ -166,6 +181,14 @@ RSpec.describe Gitlab::Danger::Roulette do
end end
end end
context 'when change contains CI/CD Template category' do
let(:categories) { [:ci_template] }
it 'assigns CI/CD Template reviewer and fallback to backend maintainer' do
expect(spins).to eq([described_class::Spin.new(:ci_template, ci_template_reviewer, backend_maintainer, false, false)])
end
end
context 'when change contains test category' do context 'when change contains test category' do
let(:categories) { [:test] } let(:categories) { [:test] }
...@@ -332,7 +355,8 @@ RSpec.describe Gitlab::Danger::Roulette do ...@@ -332,7 +355,8 @@ RSpec.describe Gitlab::Danger::Roulette do
frontend_reviewer, frontend_reviewer,
frontend_maintainer, frontend_maintainer,
software_engineer_in_test, software_engineer_in_test,
engineering_productivity_reviewer engineering_productivity_reviewer,
ci_template_reviewer
]) ])
end end
......
...@@ -4,6 +4,7 @@ require 'timecop' ...@@ -4,6 +4,7 @@ require 'timecop'
require 'rspec-parameterized' require 'rspec-parameterized'
require 'gitlab/danger/teammate' require 'gitlab/danger/teammate'
require 'active_support/testing/time_helpers'
RSpec.describe Gitlab::Danger::Teammate do RSpec.describe Gitlab::Danger::Teammate do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
...@@ -148,6 +149,8 @@ RSpec.describe Gitlab::Danger::Teammate do ...@@ -148,6 +149,8 @@ RSpec.describe Gitlab::Danger::Teammate do
end end
describe '#local_hour' do describe '#local_hour' do
include ActiveSupport::Testing::TimeHelpers
around do |example| around do |example|
travel_to(Time.utc(2020, 6, 23, 10)) { example.run } travel_to(Time.utc(2020, 6, 23, 10)) { example.run }
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment