BigW Consortium Gitlab

Commit b3edcfeb by Clement Ho

Merge branch '9-3-stable-rc7' into '9-3-stable'

Prepare 9.3 RC7 See merge request !12348
parents 31573d98 261e4fe8
...@@ -487,6 +487,7 @@ class FilteredSearchManager { ...@@ -487,6 +487,7 @@ class FilteredSearchManager {
} }
searchState(e) { searchState(e) {
e.preventDefault();
const target = e.currentTarget; const target = e.currentTarget;
// remove focus outline after click // remove focus outline after click
target.blur(); target.blur();
......
...@@ -22,6 +22,7 @@ export default class IssuableBulkUpdateSidebar { ...@@ -22,6 +22,7 @@ export default class IssuableBulkUpdateSidebar {
initDomElements() { initDomElements() {
this.$page = $('.page-with-sidebar'); this.$page = $('.page-with-sidebar');
this.$sidebar = $('.right-sidebar'); this.$sidebar = $('.right-sidebar');
this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide'); this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
this.$bulkEditSubmitBtn = $('.update-selected-issues'); this.$bulkEditSubmitBtn = $('.update-selected-issues');
this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle'); this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
...@@ -113,6 +114,7 @@ export default class IssuableBulkUpdateSidebar { ...@@ -113,6 +114,7 @@ export default class IssuableBulkUpdateSidebar {
toggleSidebarDisplay(show) { toggleSidebarDisplay(show) {
this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show); this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show); this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
this.$sidebarInnerContainer.toggleClass(HIDDEN_CLASS, !show);
this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show); this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show); this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
} }
......
...@@ -7,6 +7,13 @@ import Cookies from 'js-cookie'; ...@@ -7,6 +7,13 @@ import Cookies from 'js-cookie';
function Sidebar(currentUser) { function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this); this.toggleTodo = this.toggleTodo.bind(this);
this.sidebar = $('aside'); this.sidebar = $('aside');
this.$sidebarInner = this.sidebar.find('.issuable-sidebar');
this.$navGitlab = $('.navbar-gitlab');
this.$layoutNav = $('.layout-nav');
this.$subScroll = $('.sub-nav-scroll');
this.$rightSidebar = $('.js-right-sidebar');
this.removeListeners(); this.removeListeners();
this.addEventListeners(); this.addEventListeners();
} }
...@@ -21,14 +28,15 @@ import Cookies from 'js-cookie'; ...@@ -21,14 +28,15 @@ import Cookies from 'js-cookie';
Sidebar.prototype.addEventListeners = function() { Sidebar.prototype.addEventListeners = function() {
const $document = $(document); const $document = $(document);
const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight, 10); const throttledSetSidebarHeight = _.throttle(this.setSidebarHeight.bind(this), 20);
const debouncedSetSidebarHeight = _.debounce(this.setSidebarHeight.bind(this), 200);
this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked); this.sidebar.on('click', '.sidebar-collapsed-icon', this, this.sidebarCollapseClicked);
$('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden); $('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden);
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading); $('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded); $('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
$(window).on('resize', () => throttledSetSidebarHeight()); $(window).on('resize', () => throttledSetSidebarHeight());
$document.on('scroll', () => throttledSetSidebarHeight()); $document.on('scroll', () => debouncedSetSidebarHeight());
$document.on('click', '.js-sidebar-toggle', function(e, triggered) { $document.on('click', '.js-sidebar-toggle', function(e, triggered) {
var $allGutterToggleIcons, $this, $thisIcon; var $allGutterToggleIcons, $this, $thisIcon;
e.preventDefault(); e.preventDefault();
...@@ -207,13 +215,14 @@ import Cookies from 'js-cookie'; ...@@ -207,13 +215,14 @@ import Cookies from 'js-cookie';
}; };
Sidebar.prototype.setSidebarHeight = function() { Sidebar.prototype.setSidebarHeight = function() {
const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + $('.sub-nav-scroll').outerHeight(); const $navHeight = this.$navGitlab.outerHeight() + this.$layoutNav.outerHeight() + (this.$subScroll ? this.$subScroll.outerHeight() : 0);
const $rightSidebar = $('.js-right-sidebar');
const diff = $navHeight - $(window).scrollTop(); const diff = $navHeight - $(window).scrollTop();
if (diff > 0) { if (diff > 0) {
$rightSidebar.outerHeight($(window).height() - diff); this.$rightSidebar.outerHeight($(window).height() - diff);
this.$sidebarInner.height('100%');
} else { } else {
$rightSidebar.outerHeight('100%'); this.$rightSidebar.outerHeight('100%');
this.$sidebarInner.height('');
} }
}; };
......
function expandSectionParent($section, $content) {
$section.addClass('expanded');
$content.off('animationend.expandSectionParent');
}
function expandSection($section) { function expandSection($section) {
$section.find('.js-settings-toggle').text('Close'); $section.find('.js-settings-toggle').text('Close');
$section.find('.settings-content').addClass('expanded').off('scroll').scrollTop(0);
const $content = $section.find('.settings-content');
$content.addClass('expanded').off('scroll.expandSection').scrollTop(0);
if ($content.hasClass('no-animate')) {
expandSectionParent($section, $content);
} else {
$content.on('animationend.expandSectionParent', () => expandSectionParent($section, $content));
}
} }
function closeSection($section) { function closeSection($section) {
$section.find('.js-settings-toggle').text('Expand'); $section.find('.js-settings-toggle').text('Expand');
$section.find('.settings-content').removeClass('expanded').on('scroll', () => expandSection($section));
const $content = $section.find('.settings-content');
$content.removeClass('expanded').on('scroll.expandSection', () => expandSection($section));
$section.removeClass('expanded');
} }
function toggleSection($section) { function toggleSection($section) {
...@@ -21,7 +38,7 @@ function toggleSection($section) { ...@@ -21,7 +38,7 @@ function toggleSection($section) {
export default function initSettingsPanels() { export default function initSettingsPanels() {
$('.settings').each((i, elm) => { $('.settings').each((i, elm) => {
const $section = $(elm); const $section = $(elm);
$section.on('click', '.js-settings-toggle', () => toggleSection($section)); $section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
$section.find('.settings-content:not(.expanded)').on('scroll', () => expandSection($section)); $section.find('.settings-content:not(.expanded)').on('scroll.expandSection', () => expandSection($section));
}); });
} }
...@@ -45,8 +45,7 @@ ...@@ -45,8 +45,7 @@
li { li {
display: flex; display: flex;
a, a {
.btn-link {
padding: $gl-btn-padding; padding: $gl-btn-padding;
padding-bottom: 11px; padding-bottom: 11px;
font-size: 14px; font-size: 14px;
...@@ -68,29 +67,7 @@ ...@@ -68,29 +67,7 @@
} }
} }
.btn-link { &.active a {
padding-top: 16px;
padding-left: 15px;
padding-right: 15px;
border-left: none;
border-right: none;
border-top: none;
border-radius: 0;
&:hover,
&:active,
&:focus {
background-color: transparent;
}
&:active {
outline: 0;
box-shadow: none;
}
}
&.active a,
&.active .btn-link {
border-bottom: 2px solid $link-underline-blue; border-bottom: 2px solid $link-underline-blue;
color: $black; color: $black;
font-weight: 600; font-weight: 600;
......
...@@ -97,17 +97,19 @@ ...@@ -97,17 +97,19 @@
.issues-bulk-update.right-sidebar { .issues-bulk-update.right-sidebar {
@include maintain-sidebar-dimensions; @include maintain-sidebar-dimensions;
transition: right $sidebar-transition-duration; width: 0;
right: -$gutter-width; padding: 0;
transition: width $sidebar-transition-duration;
&.right-sidebar-expanded { &.right-sidebar-expanded {
@include maintain-sidebar-dimensions; @include maintain-sidebar-dimensions;
right: 0; width: $gutter-width;
} }
&.right-sidebar-collapsed { &.right-sidebar-collapsed {
@include maintain-sidebar-dimensions; @include maintain-sidebar-dimensions;
right: -$gutter-width; width: 0;
padding: 0;
.block { .block {
padding: 16px 0; padding: 16px 0;
...@@ -118,5 +120,6 @@ ...@@ -118,5 +120,6 @@
.issuable-sidebar { .issuable-sidebar {
padding: 0 3px; padding: 0 3px;
width: calc(100% + 35px);
} }
} }
...@@ -44,6 +44,10 @@ ...@@ -44,6 +44,10 @@
&:target, &:target,
&.target { &.target {
background: $line-target-blue; background: $line-target-blue;
&.system-note .note-body .note-text.system-note-commit-list::after {
background: linear-gradient(rgba($line-target-blue, 0.1) -100px, $line-target-blue 100%);
}
} }
.avatar { .avatar {
......
...@@ -322,6 +322,7 @@ $note-disabled-comment-color: #b2b2b2; ...@@ -322,6 +322,7 @@ $note-disabled-comment-color: #b2b2b2;
$note-targe3-outside: #fffff0; $note-targe3-outside: #fffff0;
$note-targe3-inside: #ffffd3; $note-targe3-inside: #ffffd3;
$note-line2-border: #ddd; $note-line2-border: #ddd;
$note-icon-gutter-width: 55px;
/* /*
......
...@@ -204,7 +204,7 @@ ...@@ -204,7 +204,7 @@
.issuable-sidebar { .issuable-sidebar {
width: calc(100% + 100px); width: calc(100% + 100px);
height: 100%; height: calc(100% - #{$header-height});
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
......
...@@ -148,8 +148,20 @@ ...@@ -148,8 +148,20 @@
padding: 6px 0; padding: 6px 0;
} }
.notes-form > li { .notes.notes-form > li.timeline-entry {
@include notes-media('max', $screen-sm-max) {
padding: 0;
}
.timeline-content {
@include notes-media('max', $screen-sm-max) {
margin: 0;
}
}
.timeline-entry-inner {
border: 0; border: 0;
}
} }
.note-edit-form { .note-edit-form {
......
...@@ -14,16 +14,6 @@ ul.notes { ...@@ -14,16 +14,6 @@ ul.notes {
margin: 0; margin: 0;
padding: 0; padding: 0;
.timeline-content {
margin-left: 55px;
&.timeline-content-form {
@include notes-media('max', $screen-sm-max) {
margin-left: 0;
}
}
}
.note-created-ago, .note-created-ago,
.note-updated-at { .note-updated-at {
white-space: nowrap; white-space: nowrap;
...@@ -46,15 +36,47 @@ ul.notes { ...@@ -46,15 +36,47 @@ ul.notes {
} }
} }
> li { > li { // .timeline-entry
padding: $gl-padding $gl-btn-padding; padding: 0;
display: block; display: block;
position: relative; position: relative;
border-bottom: 0;
@include notes-media('min', $screen-sm-min) {
padding-left: $note-icon-gutter-width;
}
.timeline-entry-inner {
padding: $gl-padding $gl-btn-padding;
border-bottom: 1px solid $white-normal; border-bottom: 1px solid $white-normal;
}
&:last-child { &:target,
// Override `.timeline > li:last-child { border-bottom: none; }` &.target {
border-bottom: 1px solid $white-normal; border-bottom: 1px solid $white-normal;
&:not(:first-child) {
border-top: 1px solid $white-normal;
margin-top: -1px;
}
.timeline-entry-inner {
border-bottom: 0;
}
}
.timeline-icon {
@include notes-media('min', $screen-sm-min) {
margin-left: -$note-icon-gutter-width;
}
}
.timeline-content {
margin-left: $note-icon-gutter-width;
@include notes-media('min', $screen-sm-min) {
margin-left: 0;
}
} }
&.being-posted { &.being-posted {
...@@ -73,7 +95,7 @@ ul.notes { ...@@ -73,7 +95,7 @@ ul.notes {
} }
&.note-discussion { &.note-discussion {
&.timeline-entry { .timeline-entry-inner {
padding: $gl-padding 10px; padding: $gl-padding 10px;
} }
} }
...@@ -152,13 +174,8 @@ ul.notes { ...@@ -152,13 +174,8 @@ ul.notes {
.system-note { .system-note {
font-size: 14px; font-size: 14px;
padding-left: 0;
clear: both; clear: both;
@include notes-media('min', $screen-sm-min) {
margin-left: 65px;
}
.note-header-info { .note-header-info {
padding-bottom: 0; padding-bottom: 0;
} }
...@@ -192,13 +209,16 @@ ul.notes { ...@@ -192,13 +209,16 @@ ul.notes {
.timeline-icon { .timeline-icon {
float: left; float: left;
@include notes-media('min', $screen-sm-min) {
margin-left: 0;
width: auto;
}
svg { svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
fill: $gray-darkest; fill: $gray-darkest;
position: absolute; margin-top: 2px;
left: 0;
top: 2px;
} }
} }
...@@ -250,7 +270,7 @@ ul.notes { ...@@ -250,7 +270,7 @@ ul.notes {
&::after { &::after {
content: ''; content: '';
width: 100%; width: 100%;
height: 67px; height: 70px;
position: absolute; position: absolute;
left: 0; left: 0;
bottom: 0; bottom: 0;
...@@ -639,15 +659,12 @@ ul.notes { ...@@ -639,15 +659,12 @@ ul.notes {
.discussion-body, .discussion-body,
.diff-file { .diff-file {
.notes .note { .notes .note {
border-bottom: 1px solid $white-normal;
.timeline-entry-inner {
padding-left: $gl-padding; padding-left: $gl-padding;
padding-right: $gl-padding; padding-right: $gl-padding;
border-bottom: none;
&.system-note {
padding-left: 0;
@media (min-width: $screen-sm-min) {
margin-left: 70px;
}
} }
} }
} }
......
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
&:first-of-type { &:first-of-type {
margin-top: 10px; margin-top: 10px;
} }
&.expanded {
overflow: visible;
}
} }
.settings-header { .settings-header {
......
...@@ -6,7 +6,7 @@ class Projects::DeployKeysController < Projects::ApplicationController ...@@ -6,7 +6,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
before_action :authorize_admin_project! before_action :authorize_admin_project!
before_action :authorize_update_deploy_key!, only: [:edit, :update] before_action :authorize_update_deploy_key!, only: [:edit, :update]
layout "project_settings" layout 'project_settings'
def index def index
respond_to do |format| respond_to do |format|
...@@ -66,7 +66,7 @@ class Projects::DeployKeysController < Projects::ApplicationController ...@@ -66,7 +66,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
protected protected
def deploy_key def deploy_key
@deploy_key ||= @project.deploy_keys.find(params[:id]) @deploy_key ||= DeployKey.find(params[:id])
end end
def create_params def create_params
......
...@@ -15,8 +15,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController ...@@ -15,8 +15,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html format.html
format.json do format.json do
Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: { render json: {
environments: EnvironmentSerializer environments: EnvironmentSerializer
.new(project: @project, current_user: @current_user) .new(project: @project, current_user: @current_user)
......
...@@ -138,17 +138,6 @@ module Ci ...@@ -138,17 +138,6 @@ module Ci
ExpandVariables.expand(environment, simple_variables) if environment ExpandVariables.expand(environment, simple_variables) if environment
end end
def environment_url
return @environment_url if defined?(@environment_url)
@environment_url =
if unexpanded_url = options&.dig(:environment, :url)
ExpandVariables.expand(unexpanded_url, simple_variables)
else
persisted_environment&.external_url
end
end
def has_environment? def has_environment?
environment.present? environment.present?
end end
...@@ -192,7 +181,7 @@ module Ci ...@@ -192,7 +181,7 @@ module Ci
slugified.gsub(/[^a-z0-9]/, '-')[0..62] slugified.gsub(/[^a-z0-9]/, '-')[0..62]
end end
# Variables whose value does not depend on other variables # Variables whose value does not depend on environment
def simple_variables def simple_variables
variables = predefined_variables variables = predefined_variables
variables += project.predefined_variables variables += project.predefined_variables
...@@ -207,7 +196,8 @@ module Ci ...@@ -207,7 +196,8 @@ module Ci
variables variables
end end
# All variables, including those dependent on other variables # All variables, including those dependent on environment, which could
# contain unexpanded variables.
def variables def variables
simple_variables.concat(persisted_environment_variables) simple_variables.concat(persisted_environment_variables)
end end
...@@ -481,9 +471,10 @@ module Ci ...@@ -481,9 +471,10 @@ module Ci
variables = persisted_environment.predefined_variables variables = persisted_environment.predefined_variables
if url = environment_url # Here we're passing unexpanded environment_url for runner to expand,
variables << { key: 'CI_ENVIRONMENT_URL', value: url, public: true } # and we need to make sure that CI_ENVIRONMENT_NAME and
end # CI_ENVIRONMENT_SLUG so on are available for the URL be expanded.
variables << { key: 'CI_ENVIRONMENT_URL', value: environment_url, public: true } if environment_url
variables variables
end end
...@@ -506,6 +497,10 @@ module Ci ...@@ -506,6 +497,10 @@ module Ci
variables variables
end end
def environment_url
options&.dig(:environment, :url) || persisted_environment&.external_url
end
def build_attributes_from_config def build_attributes_from_config
return {} unless pipeline.config_processor return {} unless pipeline.config_processor
......
...@@ -2,7 +2,7 @@ class CreateDeploymentService ...@@ -2,7 +2,7 @@ class CreateDeploymentService
attr_reader :job attr_reader :job
delegate :expanded_environment_name, delegate :expanded_environment_name,
:environment_url, :variables,
:project, :project,
to: :job to: :job
...@@ -14,7 +14,8 @@ class CreateDeploymentService ...@@ -14,7 +14,8 @@ class CreateDeploymentService
return unless executable? return unless executable?
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
environment.external_url = environment_url if environment_url environment.external_url = expanded_environment_url if
expanded_environment_url
environment.fire_state_event(action) environment.fire_state_event(action)
return unless environment.save return unless environment.save
...@@ -49,6 +50,17 @@ class CreateDeploymentService ...@@ -49,6 +50,17 @@ class CreateDeploymentService
@environment_options ||= job.options&.dig(:environment) || {} @environment_options ||= job.options&.dig(:environment) || {}
end end
def expanded_environment_url
return @expanded_environment_url if defined?(@expanded_environment_url)
@expanded_environment_url =
ExpandVariables.expand(environment_url, variables) if environment_url
end
def environment_url
environment_options[:url]
end
def on_stop def on_stop
environment_options[:on_stop] environment_options[:on_stop]
end end
......
- type = local_assigns.fetch(:type) - type = local_assigns.fetch(:type)
%aside.issues-bulk-update.js-right-sidebar.right-sidebar.affix-top{ data: { "offset-top" => "50", "spy" => "affix" }, "aria-live" => "polite" } %aside.issues-bulk-update.js-right-sidebar.right-sidebar.affix-top{ data: { "offset-top" => "50", "spy" => "affix" }, "aria-live" => "polite" }
.issuable-sidebar .issuable-sidebar.hidden
= form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do = form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
.block .block
.filter-item.inline.update-issues-btn.pull-left .filter-item.inline.update-issues-btn.pull-left
......
- type = local_assigns.fetch(:type, :issues) - type = local_assigns.fetch(:type, :issues)
- page_context_word = type.to_s.humanize(capitalize: false) - page_context_word = type.to_s.humanize(capitalize: false)
- issuables = @issues || @merge_requests - issuables = @issues || @merge_requests
- closed_title = 'Filter by issues that are currently closed.'
%ul.nav-links.issues-state-filters %ul.nav-links.issues-state-filters
%li{ class: active_when(params[:state] == 'opened') }> %li{ class: active_when(params[:state] == 'opened') }>
%button.btn.btn-link{ id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", type: 'button', data: { state: 'opened' } } = link_to page_filter_path(state: 'opened', label: true), id: 'state-opened', title: "Filter by #{page_context_word} that are currently opened.", data: { state: 'opened' } do
#{issuables_state_counter_text(type, :opened)} #{issuables_state_counter_text(type, :opened)}
- if type == :merge_requests - if type == :merge_requests
%li{ class: active_when(params[:state] == 'merged') }> %li{ class: active_when(params[:state] == 'merged') }>
%button.btn.btn-link{ id: 'state-merged', title: 'Filter by merge requests that are currently merged.', type: 'button', data: { state: 'merged' } } = link_to page_filter_path(state: 'merged', label: true), id: 'state-merged', title: 'Filter by merge requests that are currently merged.', data: { state: 'merged' } do
#{issuables_state_counter_text(type, :merged)} #{issuables_state_counter_text(type, :merged)}
- closed_title = 'Filter by merge requests that are currently closed and unmerged.'
%li{ class: active_when(params[:state] == 'closed') }> %li{ class: active_when(params[:state] == 'closed') }>
%button.btn.btn-link{ id: 'state-closed', title: closed_title, type: 'button', data: { state: 'closed' } } = link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by merge requests that are currently closed and unmerged.', data: { state: 'closed' } do
#{issuables_state_counter_text(type, :closed)}
- else
%li{ class: active_when(params[:state] == 'closed') }>
= link_to page_filter_path(state: 'closed', label: true), id: 'state-closed', title: 'Filter by issues that are currently closed.', data: { state: 'closed' } do
#{issuables_state_counter_text(type, :closed)} #{issuables_state_counter_text(type, :closed)}
%li{ class: active_when(params[:state] == 'all') }> %li{ class: active_when(params[:state] == 'all') }>
%button.btn.btn-link{ id: 'state-all', title: "Show all #{page_context_word}.", type: 'button', data: { state: 'all' } } = link_to page_filter_path(state: 'all', label: true), id: 'state-all', title: "Show all #{page_context_word}.", data: { state: 'all' } do
#{issuables_state_counter_text(type, :all)} #{issuables_state_counter_text(type, :all)}
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
- if can_create_note? - if can_create_note?
%ul.notes.notes-form.timeline %ul.notes.notes-form.timeline
%li.timeline-entry %li.timeline-entry
.timeline-entry-inner
.flash-container.timeline-content .flash-container.timeline-content
.timeline-icon.hidden-xs.hidden-sm .timeline-icon.hidden-xs.hidden-sm
......
---
title: Fix edit button for deploy keys available from other projects
merge_request: 12301
author: Alexander Randa
---
title: Standardize timeline note margins across different viewport sizes
merge_request: 12364
author:
---
title: Fix passing CI_ENVIRONMENT_NAME and CI_ENVIRONMENT_SLUG for CI_ENVIRONMENT_URL
merge_request: 12344
author:
---
title: Disable environment list refresh due to bug https://gitlab.com/gitlab-org/gitlab-ee/issues/2677
merge_request: 12347
author:
---
title: Fix GitHub importer performance on branch existence check
merge_request:
author:
...@@ -3,19 +3,11 @@ class AddStageIdToCiBuilds < ActiveRecord::Migration ...@@ -3,19 +3,11 @@ class AddStageIdToCiBuilds < ActiveRecord::Migration
DOWNTIME = false DOWNTIME = false
disable_ddl_transaction!
def up def up
add_column :ci_builds, :stage_id, :integer add_column :ci_builds, :stage_id, :integer
add_concurrent_foreign_key :ci_builds, :ci_stages, column: :stage_id, on_delete: :cascade
add_concurrent_index :ci_builds, :stage_id
end end
def down def down
remove_foreign_key :ci_builds, column: :stage_id
remove_concurrent_index :ci_builds, :stage_id
remove_column :ci_builds, :stage_id, :integer remove_column :ci_builds, :stage_id, :integer
end end
end end
class AddIndexForHeadPipelineMergeRequest < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :merge_requests, :head_pipeline_id
end
def down
remove_concurrent_index :merge_requests, :head_pipeline_id if index_exists?(:merge_requests, :head_pipeline_id)
end
end
...@@ -7,6 +7,8 @@ class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration ...@@ -7,6 +7,8 @@ class EnableAutoCancelPendingPipelinesForAll < ActiveRecord::Migration
DOWNTIME = false DOWNTIME = false
def up def up
disable_statement_timeout
update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1) update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1)
end end
......
class RemoveStageIdIndexFromBuilds < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
if index_exists?(:ci_builds, :stage_id)
remove_foreign_key(:ci_builds, column: :stage_id)
remove_concurrent_index(:ci_builds, :stage_id)
end
end
def down
# noop
end
end
...@@ -3,23 +3,17 @@ class MigrateBuildStageReference < ActiveRecord::Migration ...@@ -3,23 +3,17 @@ class MigrateBuildStageReference < ActiveRecord::Migration
DOWNTIME = false DOWNTIME = false
def up ##
disable_statement_timeout # This is an empty migration, content has been moved to a new one:
# post migrate 20170526190000 MigrateBuildStageReferenceAgain
stage_id = Arel.sql <<-SQL.strip_heredoc #
(SELECT id FROM ci_stages # See gitlab-org/gitlab-ce!12337 for more details.
WHERE ci_stages.pipeline_id = ci_builds.commit_id
AND ci_stages.name = ci_builds.stage)
SQL
update_column_in_batches(:ci_builds, :stage_id, stage_id) do |table, query| def up
query.where(table[:stage_id].eq(nil)) # noop
end
end end
def down def down
disable_statement_timeout # noop
update_column_in_batches(:ci_builds, :stage_id, nil)
end end
end end
class MigrateBuildStageReferenceAgain < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
disable_statement_timeout
stage_id = Arel.sql <<-SQL.strip_heredoc
(SELECT id FROM ci_stages
WHERE ci_stages.pipeline_id = ci_builds.commit_id
AND ci_stages.name = ci_builds.stage)
SQL
update_column_in_batches(:ci_builds, :stage_id, stage_id) do |table, query|
query.where(table[:stage_id].eq(nil))
end
end
def down
disable_statement_timeout
update_column_in_batches(:ci_builds, :stage_id, nil)
end
end
class AddStageIdIndexToBuilds < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
unless index_exists?(:ci_builds, :stage_id)
add_concurrent_foreign_key(:ci_builds, :ci_stages, column: :stage_id, on_delete: :cascade)
add_concurrent_index(:ci_builds, :stage_id)
end
end
def down
if index_exists?(:ci_builds, :stage_id)
remove_foreign_key(:ci_builds, column: :stage_id)
remove_concurrent_index(:ci_builds, :stage_id)
end
end
end
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170606202615) do ActiveRecord::Schema.define(version: 20170621102400) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
enable_extension "pg_trgm" enable_extension "pg_trgm"
...@@ -760,6 +761,7 @@ ActiveRecord::Schema.define(version: 20170606202615) do ...@@ -760,6 +761,7 @@ ActiveRecord::Schema.define(version: 20170606202615) do
add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree add_index "merge_requests", ["created_at"], name: "index_merge_requests_on_created_at", using: :btree
add_index "merge_requests", ["deleted_at"], name: "index_merge_requests_on_deleted_at", using: :btree add_index "merge_requests", ["deleted_at"], name: "index_merge_requests_on_deleted_at", using: :btree
add_index "merge_requests", ["description"], name: "index_merge_requests_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"} add_index "merge_requests", ["description"], name: "index_merge_requests_on_description_trigram", using: :gin, opclasses: {"description"=>"gin_trgm_ops"}
add_index "merge_requests", ["head_pipeline_id"], name: "index_merge_requests_on_head_pipeline_id", using: :btree
add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
add_index "merge_requests", ["source_project_id"], name: "index_merge_requests_on_source_project_id", using: :btree add_index "merge_requests", ["source_project_id"], name: "index_merge_requests_on_source_project_id", using: :btree
......
...@@ -127,6 +127,14 @@ New translations will be added with their default content and will be marked ...@@ -127,6 +127,14 @@ New translations will be added with their default content and will be marked
fuzzy. To use the translation, look for the `#, fuzzy` mention in `gitlab.edit.po` fuzzy. To use the translation, look for the `#, fuzzy` mention in `gitlab.edit.po`
and remove it. and remove it.
We need to make sure we remove the `fuzzy` translations before generating the
`locale/**/gitlab.po` file. When they aren't removed, the resulting `.po` will
be treated as a binary file which could overwrite translations that were merged
before the new translations.
When we are just preparing a page to be translated, but not actually adding any
translations. There's no need to generate `.po` files.
Translations that aren't used in the source code anymore will be marked with Translations that aren't used in the source code anymore will be marked with
`~#`; these can be removed to keep our translation files clutter-free. `~#`; these can be removed to keep our translation files clutter-free.
......
...@@ -167,15 +167,15 @@ environment which has had a successful deployment. ...@@ -167,15 +167,15 @@ environment which has had a successful deployment.
## Determining the performance impact of a merge ## Determining the performance impact of a merge
> [Introduced][ce-10408] in GitLab 9.2. > [Introduced][ce-10408] in GitLab 9.2.
> GitLab 9.3 added the [numeric comparison](https://gitlab.com/gitlab-org/gitlab-ce/issues/27439) of the 30 minute averages.
Developers can view the performance impact of their changes within the merge Developers can view the performance impact of their changes within the merge
request workflow. When a source branch has been deployed to an environment, a request workflow. When a source branch has been deployed to an environment, a sparkline and numeric comparison of the average memory consumption will appear. On the sparkline, a dot
sparkline will appear showing the average memory consumption of the app. The dot
indicates when the current changes were deployed, with up to 30 minutes of indicates when the current changes were deployed, with up to 30 minutes of
performance data displayed before and after. The sparkline will be updated after performance data displayed before and after. The comparison shows the difference between the 30 minute average before and after the deployment. This information is updated after
each commit has been deployed. each commit has been deployed.
Once merged and the target branch has been redeployed, the sparkline will switch Once merged and the target branch has been redeployed, the metrics will switch
to show the new environments this revision has been deployed to. to show the new environments this revision has been deployed to.
Performance data will be available for the duration it is persisted on the Performance data will be available for the duration it is persisted on the
......
...@@ -86,7 +86,7 @@ module API ...@@ -86,7 +86,7 @@ module API
at_least_one_of :title, :can_push at_least_one_of :title, :can_push
end end
put ":id/deploy_keys/:key_id" do put ":id/deploy_keys/:key_id" do
key = user_project.deploy_keys.find(params.delete(:key_id)) key = DeployKey.find(params.delete(:key_id))
authorize!(:update_deploy_key, key) authorize!(:update_deploy_key, key)
......
...@@ -172,7 +172,7 @@ module Github ...@@ -172,7 +172,7 @@ module Github
next unless merge_request.new_record? && pull_request.valid? next unless merge_request.new_record? && pull_request.valid?
begin begin
restore_branches(pull_request) pull_request.restore_branches!
author_id = user_id(pull_request.author, project.creator_id) author_id = user_id(pull_request.author, project.creator_id)
description = format_description(pull_request.description, pull_request.author) description = format_description(pull_request.description, pull_request.author)
...@@ -208,7 +208,7 @@ module Github ...@@ -208,7 +208,7 @@ module Github
rescue => e rescue => e
error(:pull_request, pull_request.url, e.message) error(:pull_request, pull_request.url, e.message)
ensure ensure
clean_up_restored_branches(pull_request) pull_request.remove_restored_branches!
end end
end end
...@@ -325,32 +325,6 @@ module Github ...@@ -325,32 +325,6 @@ module Github
end end
end end
def restore_branches(pull_request)
restore_source_branch(pull_request) unless pull_request.source_branch_exists?
restore_target_branch(pull_request) unless pull_request.target_branch_exists?
end
def restore_source_branch(pull_request)
repository.create_branch(pull_request.source_branch_name, pull_request.source_branch_sha)
end
def restore_target_branch(pull_request)
repository.create_branch(pull_request.target_branch_name, pull_request.target_branch_sha)
end
def remove_branch(name)
repository.delete_branch(name)
rescue Rugged::ReferenceError
errors << { type: :branch, url: nil, error: "Could not clean up restored branch: #{name}" }
end
def clean_up_restored_branches(pull_request)
return if pull_request.opened?
remove_branch(pull_request.source_branch_name) unless pull_request.source_branch_exists?
remove_branch(pull_request.target_branch_name) unless pull_request.target_branch_exists?
end
def label_ids(labels) def label_ids(labels)
labels.map { |attrs| cached[:label_ids][attrs.fetch('name')] }.compact labels.map { |attrs| cached[:label_ids][attrs.fetch('name')] }.compact
end end
......
...@@ -26,13 +26,25 @@ module Github ...@@ -26,13 +26,25 @@ module Github
end end
def exists? def exists?
branch_exists? && commit_exists? @exists ||= branch_exists? && commit_exists?
end end
def valid? def valid?
sha.present? && ref.present? sha.present? && ref.present?
end end
def restore!(name)
repository.create_branch(name, sha)
rescue Gitlab::Git::Repository::InvalidRef => e
Rails.logger.error("#{self.class.name}: Could not restore branch #{name}: #{e}")
end
def remove!(name)
repository.delete_branch(name)
rescue Rugged::ReferenceError => e
Rails.logger.error("#{self.class.name}: Could not remove branch #{name}: #{e}")
end
private private
def branch_exists? def branch_exists?
......
module Github module Github
module Representation module Representation
class PullRequest < Representation::Issuable class PullRequest < Representation::Issuable
attr_reader :project
delegate :user, :repo, :ref, :sha, to: :source_branch, prefix: true delegate :user, :repo, :ref, :sha, to: :source_branch, prefix: true
delegate :user, :exists?, :repo, :ref, :sha, :short_sha, to: :target_branch, prefix: true delegate :user, :exists?, :repo, :ref, :sha, :short_sha, to: :target_branch, prefix: true
...@@ -10,10 +8,6 @@ module Github ...@@ -10,10 +8,6 @@ module Github
project project
end end
def source_branch_exists?
!cross_project? && source_branch.exists?
end
def source_branch_name def source_branch_name
@source_branch_name ||= @source_branch_name ||=
if cross_project? || !source_branch_exists? if cross_project? || !source_branch_exists?
...@@ -23,6 +17,12 @@ module Github ...@@ -23,6 +17,12 @@ module Github
end end
end end
def source_branch_exists?
return @source_branch_exists if defined?(@source_branch_exists)
@source_branch_exists = !cross_project? && source_branch.exists?
end
def target_project def target_project
project project
end end
...@@ -31,6 +31,10 @@ module Github ...@@ -31,6 +31,10 @@ module Github
@target_branch_name ||= target_branch_exists? ? target_branch_ref : target_branch_name_prefixed @target_branch_name ||= target_branch_exists? ? target_branch_ref : target_branch_name_prefixed
end end
def target_branch_exists?
@target_branch_exists ||= target_branch.exists?
end
def state def state
return 'merged' if raw['state'] == 'closed' && raw['merged_at'].present? return 'merged' if raw['state'] == 'closed' && raw['merged_at'].present?
return 'closed' if raw['state'] == 'closed' return 'closed' if raw['state'] == 'closed'
...@@ -46,6 +50,18 @@ module Github ...@@ -46,6 +50,18 @@ module Github
source_branch.valid? && target_branch.valid? source_branch.valid? && target_branch.valid?
end end
def restore_branches!
restore_source_branch!
restore_target_branch!
end
def remove_restored_branches!
return if opened?
remove_source_branch!
remove_target_branch!
end
private private
def project def project
...@@ -73,6 +89,32 @@ module Github ...@@ -73,6 +89,32 @@ module Github
source_branch_repo.id != target_branch_repo.id source_branch_repo.id != target_branch_repo.id
end end
def restore_source_branch!
return if source_branch_exists?
source_branch.restore!(source_branch_name)
end
def restore_target_branch!
return if target_branch_exists?
target_branch.restore!(target_branch_name)
end
def remove_source_branch!
# We should remove the source/target branches only if they were
# restored. Otherwise, we'll remove branches like 'master' that
# target_branch_exists? returns true. In other words, we need
# to clean up only the restored branches that (source|target)_branch_exists?
# returns false for the first time it has been called, because of
# this that is important to memoize these values.
source_branch.remove!(source_branch_name) unless source_branch_exists?
end
def remove_target_branch!
target_branch.remove!(target_branch_name) unless target_branch_exists?
end
end end
end end
end end
No preview for this file type
...@@ -70,9 +70,6 @@ msgstr "" ...@@ -70,9 +70,6 @@ msgstr ""
msgid "ByAuthor|by" msgid "ByAuthor|by"
msgstr "" msgstr ""
msgid "CI configuration"
msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
...@@ -349,33 +346,12 @@ msgstr "" ...@@ -349,33 +346,12 @@ msgstr ""
msgid "From merge request merge until deploy to production" msgid "From merge request merge until deploy to production"
msgstr "" msgstr ""
msgid "Go to your fork"
msgstr ""
msgid "GoToYourFork|Fork"
msgstr ""
msgid "Home"
msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
msgid "Import repository"
msgstr ""
msgid "Interval Pattern" msgid "Interval Pattern"
msgstr "" msgstr ""
msgid "Introducing Cycle Analytics" msgid "Introducing Cycle Analytics"
msgstr "" msgstr ""
msgid "LFSStatus|Disabled"
msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
msgid "Last %d day" msgid "Last %d day"
msgid_plural "Last %d days" msgid_plural "Last %d days"
msgstr[0] "" msgstr[0] ""
...@@ -410,9 +386,6 @@ msgstr[1] "" ...@@ -410,9 +386,6 @@ msgstr[1] ""
msgid "Median" msgid "Median"
msgstr "" msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "New Issue" msgid "New Issue"
msgid_plural "New Issues" msgid_plural "New Issues"
msgstr[0] "" msgstr[0] ""
...@@ -619,21 +592,9 @@ msgstr "" ...@@ -619,21 +592,9 @@ msgstr ""
msgid "ProjectLifecycle|Stage" msgid "ProjectLifecycle|Stage"
msgstr "" msgstr ""
msgid "ProjectNetworkGraph|Graph"
msgstr ""
msgid "Read more" msgid "Read more"
msgstr "" msgstr ""
msgid "Readme"
msgstr ""
msgid "RefSwitcher|Branches"
msgstr ""
msgid "RefSwitcher|Tags"
msgstr ""
msgid "Related Commits" msgid "Related Commits"
msgstr "" msgstr ""
...@@ -688,21 +649,6 @@ msgstr "" ...@@ -688,21 +649,6 @@ msgstr ""
msgid "Select target branch" msgid "Select target branch"
msgstr "" msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}"
msgstr ""
msgid "Set up CI"
msgstr ""
msgid "Set up Koding"
msgstr ""
msgid "Set up auto deploy"
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
msgid "Showing %d event" msgid "Showing %d event"
msgid_plural "Showing %d events" msgid_plural "Showing %d events"
msgstr[0] "" msgstr[0] ""
...@@ -737,9 +683,6 @@ msgstr "" ...@@ -737,9 +683,6 @@ msgstr ""
msgid "The collection of events added to the data gathered for that stage." msgid "The collection of events added to the data gathered for that stage."
msgstr "" msgstr ""
msgid "The fork relationship has been removed."
msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "" msgstr ""
...@@ -755,15 +698,6 @@ msgstr "" ...@@ -755,15 +698,6 @@ msgstr ""
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "" msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
msgid "The repository for this project does not exist."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request." msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "" msgstr ""
...@@ -779,9 +713,6 @@ msgstr "" ...@@ -779,9 +713,6 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "" msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
msgid "Time before an issue gets scheduled" msgid "Time before an issue gets scheduled"
msgstr "" msgstr ""
...@@ -794,129 +725,6 @@ msgstr "" ...@@ -794,129 +725,6 @@ msgstr ""
msgid "Time until first merge request" msgid "Time until first merge request"
msgstr "" msgstr ""
msgid "Timeago|%s days ago"
msgstr ""
msgid "Timeago|%s days remaining"
msgstr ""
msgid "Timeago|%s hours remaining"
msgstr ""
msgid "Timeago|%s minutes ago"
msgstr ""
msgid "Timeago|%s minutes remaining"
msgstr ""
msgid "Timeago|%s months ago"
msgstr ""
msgid "Timeago|%s months remaining"
msgstr ""
msgid "Timeago|%s seconds remaining"
msgstr ""
msgid "Timeago|%s weeks ago"
msgstr ""
msgid "Timeago|%s weeks remaining"
msgstr ""
msgid "Timeago|%s years ago"
msgstr ""
msgid "Timeago|%s years remaining"
msgstr ""
msgid "Timeago|1 day remaining"
msgstr ""
msgid "Timeago|1 hour remaining"
msgstr ""
msgid "Timeago|1 minute remaining"
msgstr ""
msgid "Timeago|1 month remaining"
msgstr ""
msgid "Timeago|1 week remaining"
msgstr ""
msgid "Timeago|1 year remaining"
msgstr ""
msgid "Timeago|Past due"
msgstr ""
msgid "Timeago|a day ago"
msgstr ""
msgid "Timeago|a month ago"
msgstr ""
msgid "Timeago|a week ago"
msgstr ""
msgid "Timeago|a while"
msgstr ""
msgid "Timeago|a year ago"
msgstr ""
msgid "Timeago|about %s hours ago"
msgstr ""
msgid "Timeago|about a minute ago"
msgstr ""
msgid "Timeago|about an hour ago"
msgstr ""
msgid "Timeago|in %s days"
msgstr ""
msgid "Timeago|in %s hours"
msgstr ""
msgid "Timeago|in %s minutes"
msgstr ""
msgid "Timeago|in %s months"
msgstr ""
msgid "Timeago|in %s seconds"
msgstr ""
msgid "Timeago|in %s weeks"
msgstr ""
msgid "Timeago|in %s years"
msgstr ""
msgid "Timeago|in 1 day"
msgstr ""
msgid "Timeago|in 1 hour"
msgstr ""
msgid "Timeago|in 1 minute"
msgstr ""
msgid "Timeago|in 1 month"
msgstr ""
msgid "Timeago|in 1 week"
msgstr ""
msgid "Timeago|in 1 year"
msgstr ""
msgid "Timeago|less than a minute ago"
msgstr ""
msgid "Time|hr" msgid "Time|hr"
msgid_plural "Time|hrs" msgid_plural "Time|hrs"
msgstr[0] "" msgstr[0] ""
...@@ -936,27 +744,6 @@ msgstr "" ...@@ -936,27 +744,6 @@ msgstr ""
msgid "Total test time for all commits/merges" msgid "Total test time for all commits/merges"
msgstr "" msgstr ""
msgid "Unstar"
msgstr ""
msgid "Upload New File"
msgstr ""
msgid "Upload file"
msgstr ""
msgid "Use your global notification setting"
msgstr ""
msgid "VisibilityLevel|Internal"
msgstr ""
msgid "VisibilityLevel|Private"
msgstr ""
msgid "VisibilityLevel|Public"
msgstr ""
msgid "Want to see the data? Please ask an administrator for access." msgid "Want to see the data? Please ask an administrator for access."
msgstr "" msgstr ""
......
...@@ -77,9 +77,6 @@ msgstr "" ...@@ -77,9 +77,6 @@ msgstr ""
msgid "ByAuthor|by" msgid "ByAuthor|by"
msgstr "" msgstr ""
msgid "CI configuration"
msgstr ""
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
...@@ -356,33 +353,12 @@ msgstr "" ...@@ -356,33 +353,12 @@ msgstr ""
msgid "From merge request merge until deploy to production" msgid "From merge request merge until deploy to production"
msgstr "" msgstr ""
msgid "Go to your fork"
msgstr ""
msgid "GoToYourFork|Fork"
msgstr ""
msgid "Home"
msgstr ""
msgid "Housekeeping successfully started"
msgstr ""
msgid "Import repository"
msgstr ""
msgid "Interval Pattern" msgid "Interval Pattern"
msgstr "" msgstr ""
msgid "Introducing Cycle Analytics" msgid "Introducing Cycle Analytics"
msgstr "" msgstr ""
msgid "LFSStatus|Disabled"
msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
msgid "Last %d day" msgid "Last %d day"
msgid_plural "Last %d days" msgid_plural "Last %d days"
msgstr[0] "" msgstr[0] ""
...@@ -417,9 +393,6 @@ msgstr[1] "" ...@@ -417,9 +393,6 @@ msgstr[1] ""
msgid "Median" msgid "Median"
msgstr "" msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "New Issue" msgid "New Issue"
msgid_plural "New Issues" msgid_plural "New Issues"
msgstr[0] "" msgstr[0] ""
...@@ -626,21 +599,9 @@ msgstr "" ...@@ -626,21 +599,9 @@ msgstr ""
msgid "ProjectLifecycle|Stage" msgid "ProjectLifecycle|Stage"
msgstr "" msgstr ""
msgid "ProjectNetworkGraph|Graph"
msgstr ""
msgid "Read more" msgid "Read more"
msgstr "" msgstr ""
msgid "Readme"
msgstr ""
msgid "RefSwitcher|Branches"
msgstr ""
msgid "RefSwitcher|Tags"
msgstr ""
msgid "Related Commits" msgid "Related Commits"
msgstr "" msgstr ""
...@@ -695,21 +656,6 @@ msgstr "" ...@@ -695,21 +656,6 @@ msgstr ""
msgid "Select target branch" msgid "Select target branch"
msgstr "" msgstr ""
msgid "Set a password on your account to pull or push via %{protocol}"
msgstr ""
msgid "Set up CI"
msgstr ""
msgid "Set up Koding"
msgstr ""
msgid "Set up auto deploy"
msgstr ""
msgid "SetPasswordToCloneLink|set a password"
msgstr ""
msgid "Showing %d event" msgid "Showing %d event"
msgid_plural "Showing %d events" msgid_plural "Showing %d events"
msgstr[0] "" msgstr[0] ""
...@@ -744,9 +690,6 @@ msgstr "" ...@@ -744,9 +690,6 @@ msgstr ""
msgid "The collection of events added to the data gathered for that stage." msgid "The collection of events added to the data gathered for that stage."
msgstr "" msgstr ""
msgid "The fork relationship has been removed."
msgstr ""
msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage." msgid "The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage."
msgstr "" msgstr ""
...@@ -762,15 +705,6 @@ msgstr "" ...@@ -762,15 +705,6 @@ msgstr ""
msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle." msgid "The production stage shows the total time it takes between creating an issue and deploying the code to production. The data will be automatically added once you have completed the full idea to production cycle."
msgstr "" msgstr ""
msgid "The project can be accessed by any logged in user."
msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
msgid "The repository for this project does not exist."
msgstr ""
msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request." msgid "The review stage shows the time from creating the merge request to merging it. The data will automatically be added after you merge your first merge request."
msgstr "" msgstr ""
...@@ -786,9 +720,6 @@ msgstr "" ...@@ -786,9 +720,6 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6." msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr "" msgstr ""
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
msgid "Time before an issue gets scheduled" msgid "Time before an issue gets scheduled"
msgstr "" msgstr ""
...@@ -801,129 +732,6 @@ msgstr "" ...@@ -801,129 +732,6 @@ msgstr ""
msgid "Time until first merge request" msgid "Time until first merge request"
msgstr "" msgstr ""
msgid "Timeago|%s days ago"
msgstr ""
msgid "Timeago|%s days remaining"
msgstr ""
msgid "Timeago|%s hours remaining"
msgstr ""
msgid "Timeago|%s minutes ago"
msgstr ""
msgid "Timeago|%s minutes remaining"
msgstr ""
msgid "Timeago|%s months ago"
msgstr ""
msgid "Timeago|%s months remaining"
msgstr ""
msgid "Timeago|%s seconds remaining"
msgstr ""
msgid "Timeago|%s weeks ago"
msgstr ""
msgid "Timeago|%s weeks remaining"
msgstr ""
msgid "Timeago|%s years ago"
msgstr ""
msgid "Timeago|%s years remaining"
msgstr ""
msgid "Timeago|1 day remaining"
msgstr ""
msgid "Timeago|1 hour remaining"
msgstr ""
msgid "Timeago|1 minute remaining"
msgstr ""
msgid "Timeago|1 month remaining"
msgstr ""
msgid "Timeago|1 week remaining"
msgstr ""
msgid "Timeago|1 year remaining"
msgstr ""
msgid "Timeago|Past due"
msgstr ""
msgid "Timeago|a day ago"
msgstr ""
msgid "Timeago|a month ago"
msgstr ""
msgid "Timeago|a week ago"
msgstr ""
msgid "Timeago|a while"
msgstr ""
msgid "Timeago|a year ago"
msgstr ""
msgid "Timeago|about %s hours ago"
msgstr ""
msgid "Timeago|about a minute ago"
msgstr ""
msgid "Timeago|about an hour ago"
msgstr ""
msgid "Timeago|in %s days"
msgstr ""
msgid "Timeago|in %s hours"
msgstr ""
msgid "Timeago|in %s minutes"
msgstr ""
msgid "Timeago|in %s months"
msgstr ""
msgid "Timeago|in %s seconds"
msgstr ""
msgid "Timeago|in %s weeks"
msgstr ""
msgid "Timeago|in %s years"
msgstr ""
msgid "Timeago|in 1 day"
msgstr ""
msgid "Timeago|in 1 hour"
msgstr ""
msgid "Timeago|in 1 minute"
msgstr ""
msgid "Timeago|in 1 month"
msgstr ""
msgid "Timeago|in 1 week"
msgstr ""
msgid "Timeago|in 1 year"
msgstr ""
msgid "Timeago|less than a minute ago"
msgstr ""
msgid "Time|hr" msgid "Time|hr"
msgid_plural "Time|hrs" msgid_plural "Time|hrs"
msgstr[0] "" msgstr[0] ""
......
...@@ -58,9 +58,11 @@ describe Projects::EnvironmentsController do ...@@ -58,9 +58,11 @@ describe Projects::EnvironmentsController do
expect(json_response['stopped_count']).to eq 1 expect(json_response['stopped_count']).to eq 1
end end
it 'sets the polling interval header' do it 'does not set the polling interval header' do
# TODO, this is a temporary fix, see follow up issue:
# https://gitlab.com/gitlab-org/gitlab-ee/issues/2677
expect(response).to have_http_status(:ok) expect(response).to have_http_status(:ok)
expect(response.headers['Poll-Interval']).to eq("3000") expect(response.headers['Poll-Interval']).to be_nil
end end
end end
......
...@@ -59,6 +59,11 @@ RSpec.describe 'Dashboard Issues', feature: true do ...@@ -59,6 +59,11 @@ RSpec.describe 'Dashboard Issues', feature: true do
expect(page).to have_content(other_issue.title) expect(page).to have_content(other_issue.title)
end end
it 'state filter tabs work' do
find('#state-closed').click
expect(page).to have_current_path(issues_dashboard_url(assignee_id: current_user.id, scope: 'all', state: 'closed'), url: true)
end
it_behaves_like "it has an RSS button with current_user's RSS token" it_behaves_like "it has an RSS button with current_user's RSS token"
it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token" it_behaves_like "an autodiscoverable RSS feed with current_user's RSS token"
end end
......
...@@ -16,6 +16,21 @@ feature 'Issues > Labels bulk assignment', feature: true do ...@@ -16,6 +16,21 @@ feature 'Issues > Labels bulk assignment', feature: true do
login_as user login_as user
end end
context 'sidebar' do
before do
enable_bulk_update
end
it 'is present when bulk edit is enabled' do
expect(page).to have_css('.issuable-sidebar')
end
it 'is not present when bulk edit is disabled' do
disable_bulk_update
expect(page).not_to have_css('.issuable-sidebar')
end
end
context 'can bulk assign' do context 'can bulk assign' do
before do before do
enable_bulk_update enable_bulk_update
...@@ -398,4 +413,8 @@ feature 'Issues > Labels bulk assignment', feature: true do ...@@ -398,4 +413,8 @@ feature 'Issues > Labels bulk assignment', feature: true do
visit namespace_project_issues_path(project.namespace, project) visit namespace_project_issues_path(project.namespace, project)
click_button 'Edit Issues' click_button 'Edit Issues'
end end
def disable_bulk_update
click_button 'Cancel'
end
end end
...@@ -65,6 +65,23 @@ feature 'Repository settings', feature: true do ...@@ -65,6 +65,23 @@ feature 'Repository settings', feature: true do
expect(page).to have_content('Write access allowed') expect(page).to have_content('Write access allowed')
end end
scenario 'edit a deploy key from projects user has access to' do
project2 = create(:project_empty_repo)
project2.team << [user, role]
project2.deploy_keys << private_deploy_key
visit namespace_project_settings_repository_path(project.namespace, project)
find('li', text: private_deploy_key.title).click_link('Edit')
fill_in 'deploy_key_title', with: 'updated_deploy_key'
check 'deploy_key_can_push'
click_button 'Save changes'
expect(page).to have_content('updated_deploy_key')
expect(page).to have_content('Write access allowed')
end
scenario 'remove an existing deploy key' do scenario 'remove an existing deploy key' do
project.deploy_keys << private_deploy_key project.deploy_keys << private_deploy_key
visit namespace_project_settings_repository_path(project.namespace, project) visit namespace_project_settings_repository_path(project.namespace, project)
......
...@@ -104,6 +104,7 @@ describe('Filtered Search Manager', () => { ...@@ -104,6 +104,7 @@ describe('Filtered Search Manager', () => {
it('should blur button', () => { it('should blur button', () => {
const e = { const e = {
preventDefault: () => {},
currentTarget: { currentTarget: {
blur: () => {}, blur: () => {},
}, },
...@@ -116,6 +117,7 @@ describe('Filtered Search Manager', () => { ...@@ -116,6 +117,7 @@ describe('Filtered Search Manager', () => {
it('should not call search if there is no state', () => { it('should not call search if there is no state', () => {
const e = { const e = {
preventDefault: () => {},
currentTarget: { currentTarget: {
blur: () => {}, blur: () => {},
}, },
...@@ -127,6 +129,7 @@ describe('Filtered Search Manager', () => { ...@@ -127,6 +129,7 @@ describe('Filtered Search Manager', () => {
it('should call search when there is state', () => { it('should call search when there is state', () => {
const e = { const e = {
preventDefault: () => {},
currentTarget: { currentTarget: {
blur: () => {}, blur: () => {},
dataset: { dataset: {
......
require 'spec_helper' require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170526185921_migrate_build_stage_reference.rb') require Rails.root.join('db', 'post_migrate', '20170526190000_migrate_build_stage_reference_again.rb')
describe MigrateBuildStageReference, :migration do describe MigrateBuildStageReferenceAgain, :migration do
## ##
# Create test data - pipeline and CI/CD jobs. # Create test data - pipeline and CI/CD jobs.
# #
......
...@@ -439,42 +439,6 @@ describe Ci::Build, :models do ...@@ -439,42 +439,6 @@ describe Ci::Build, :models do
end end
end end
describe '#environment_url' do
subject { job.environment_url }
context 'when yaml environment uses $CI_COMMIT_REF_NAME' do
let(:job) do
create(:ci_build,
ref: 'master',
options: { environment: { url: 'http://review/$CI_COMMIT_REF_NAME' } })
end
it { is_expected.to eq('http://review/master') }
end
context 'when yaml environment uses yaml_variables containing symbol keys' do
let(:job) do
create(:ci_build,
yaml_variables: [{ key: :APP_HOST, value: 'host' }],
options: { environment: { url: 'http://review/$APP_HOST' } })
end
it { is_expected.to eq('http://review/host') }
end
context 'when yaml environment does not have url' do
let(:job) { create(:ci_build, environment: 'staging') }
let!(:environment) do
create(:environment, project: job.project, name: job.environment)
end
it 'returns the external_url from persisted environment' do
is_expected.to eq(environment.external_url)
end
end
end
describe '#starts_environment?' do describe '#starts_environment?' do
subject { build.starts_environment? } subject { build.starts_environment? }
...@@ -1276,10 +1240,20 @@ describe Ci::Build, :models do ...@@ -1276,10 +1240,20 @@ describe Ci::Build, :models do
context 'when the URL was set from the job' do context 'when the URL was set from the job' do
before do before do
build.update(options: { environment: { url: 'http://host/$CI_JOB_NAME' } }) build.update(options: { environment: { url: url } })
end end
it_behaves_like 'containing environment variables' it_behaves_like 'containing environment variables'
context 'when variables are used in the URL, it does not expand' do
let(:url) { 'http://$CI_PROJECT_NAME-$CI_ENVIRONMENT_SLUG' }
it_behaves_like 'containing environment variables'
it 'puts $CI_ENVIRONMENT_URL in the last so all other variables are available to be used when runners are trying to expand it' do
expect(subject.last).to eq(environment_variables.last)
end
end
end end
context 'when the URL was not set from the job, but environment' do context 'when the URL was not set from the job, but environment' do
......
...@@ -158,6 +158,16 @@ describe API::DeployKeys do ...@@ -158,6 +158,16 @@ describe API::DeployKeys do
expect(json_response['title']).to eq('new title') expect(json_response['title']).to eq('new title')
expect(json_response['can_push']).to eq(true) expect(json_response['can_push']).to eq(true)
end end
it 'updates a private ssh key from projects user has access with correct attributes' do
create(:deploy_keys_project, project: project2, deploy_key: private_deploy_key)
put api("/projects/#{project.id}/deploy_keys/#{private_deploy_key.id}", admin), { title: 'new title', can_push: true }
expect(json_response['id']).to eq(private_deploy_key.id)
expect(json_response['title']).to eq('new title')
expect(json_response['can_push']).to eq(true)
end
end end
describe 'DELETE /projects/:id/deploy_keys/:key_id' do describe 'DELETE /projects/:id/deploy_keys/:key_id' do
......
...@@ -122,6 +122,61 @@ describe CreateDeploymentService, services: true do ...@@ -122,6 +122,61 @@ describe CreateDeploymentService, services: true do
end end
end end
describe '#expanded_environment_url' do
subject { service.send(:expanded_environment_url) }
context 'when yaml environment uses $CI_COMMIT_REF_NAME' do
let(:job) do
create(:ci_build,
ref: 'master',
options: { environment: { url: 'http://review/$CI_COMMIT_REF_NAME' } })
end
it { is_expected.to eq('http://review/master') }
end
context 'when yaml environment uses $CI_ENVIRONMENT_SLUG' do
let(:job) do
create(:ci_build,
ref: 'master',
environment: 'production',
options: { environment: { url: 'http://review/$CI_ENVIRONMENT_SLUG' } })
end
let!(:environment) do
create(:environment,
project: job.project,
name: 'production',
slug: 'prod-slug',
external_url: 'http://review/old')
end
it { is_expected.to eq('http://review/prod-slug') }
end
context 'when yaml environment uses yaml_variables containing symbol keys' do
let(:job) do
create(:ci_build,
yaml_variables: [{ key: :APP_HOST, value: 'host' }],
options: { environment: { url: 'http://review/$APP_HOST' } })
end
it { is_expected.to eq('http://review/host') }
end
context 'when yaml environment does not have url' do
let(:job) { create(:ci_build, environment: 'staging') }
let!(:environment) do
create(:environment, project: job.project, name: job.environment)
end
it 'returns the external_url from persisted environment' do
is_expected.to be_nil
end
end
end
describe 'processing of builds' do describe 'processing of builds' do
shared_examples 'does not create deployment' do shared_examples 'does not create deployment' do
it 'does not create a new deployment' do it 'does not create a new deployment' do
......
...@@ -36,12 +36,13 @@ RSpec.configure do |config| ...@@ -36,12 +36,13 @@ RSpec.configure do |config|
$capybara_server_already_started = true $capybara_server_already_started = true
end end
config.after(:each, :js) do config.after(:each, :js) do |example|
# capybara/rspec already calls Capybara.reset_sessions! in an `after` hook, # capybara/rspec already calls Capybara.reset_sessions! in an `after` hook,
# but `block_and_wait_for_requests_complete` is called before it so by # but `block_and_wait_for_requests_complete` is called before it so by
# calling it explicitely here, we prevent any new requests from being fired # calling it explicitely here, we prevent any new requests from being fired
# See https://github.com/teamcapybara/capybara/blob/ffb41cfad620de1961bb49b1562a9fa9b28c0903/lib/capybara/rspec.rb#L20-L25 # See https://github.com/teamcapybara/capybara/blob/ffb41cfad620de1961bb49b1562a9fa9b28c0903/lib/capybara/rspec.rb#L20-L25
Capybara.reset_sessions! # We don't reset the session when the example failed, because we need capybara-screenshot to have access to it.
Capybara.reset_sessions! unless example.exception
block_and_wait_for_requests_complete block_and_wait_for_requests_complete
end end
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