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 {
}
searchState(e) {
e.preventDefault();
const target = e.currentTarget;
// remove focus outline after click
target.blur();
......
......@@ -22,6 +22,7 @@ export default class IssuableBulkUpdateSidebar {
initDomElements() {
this.$page = $('.page-with-sidebar');
this.$sidebar = $('.right-sidebar');
this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
this.$bulkEditSubmitBtn = $('.update-selected-issues');
this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
......@@ -113,6 +114,7 @@ export default class IssuableBulkUpdateSidebar {
toggleSidebarDisplay(show) {
this.$page.toggleClass(SIDEBAR_EXPANDED_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_COLLAPSED_CLASS, !show);
}
......
......@@ -7,6 +7,13 @@ import Cookies from 'js-cookie';
function Sidebar(currentUser) {
this.toggleTodo = this.toggleTodo.bind(this);
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.addEventListeners();
}
......@@ -21,14 +28,15 @@ import Cookies from 'js-cookie';
Sidebar.prototype.addEventListeners = function() {
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);
$('.dropdown').on('hidden.gl.dropdown', this, this.onSidebarDropdownHidden);
$('.dropdown').on('loading.gl.dropdown', this.sidebarDropdownLoading);
$('.dropdown').on('loaded.gl.dropdown', this.sidebarDropdownLoaded);
$(window).on('resize', () => throttledSetSidebarHeight());
$document.on('scroll', () => throttledSetSidebarHeight());
$document.on('scroll', () => debouncedSetSidebarHeight());
$document.on('click', '.js-sidebar-toggle', function(e, triggered) {
var $allGutterToggleIcons, $this, $thisIcon;
e.preventDefault();
......@@ -207,13 +215,14 @@ import Cookies from 'js-cookie';
};
Sidebar.prototype.setSidebarHeight = function() {
const $navHeight = $('.navbar-gitlab').outerHeight() + $('.layout-nav').outerHeight() + $('.sub-nav-scroll').outerHeight();
const $rightSidebar = $('.js-right-sidebar');
const $navHeight = this.$navGitlab.outerHeight() + this.$layoutNav.outerHeight() + (this.$subScroll ? this.$subScroll.outerHeight() : 0);
const diff = $navHeight - $(window).scrollTop();
if (diff > 0) {
$rightSidebar.outerHeight($(window).height() - diff);
this.$rightSidebar.outerHeight($(window).height() - diff);
this.$sidebarInner.height('100%');
} 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) {
$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) {
$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) {
......@@ -21,7 +38,7 @@ function toggleSection($section) {
export default function initSettingsPanels() {
$('.settings').each((i, elm) => {
const $section = $(elm);
$section.on('click', '.js-settings-toggle', () => toggleSection($section));
$section.find('.settings-content:not(.expanded)').on('scroll', () => expandSection($section));
$section.on('click.toggleSection', '.js-settings-toggle', () => toggleSection($section));
$section.find('.settings-content:not(.expanded)').on('scroll.expandSection', () => expandSection($section));
});
}
......@@ -45,8 +45,7 @@
li {
display: flex;
a,
.btn-link {
a {
padding: $gl-btn-padding;
padding-bottom: 11px;
font-size: 14px;
......@@ -68,29 +67,7 @@
}
}
.btn-link {
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 {
&.active a {
border-bottom: 2px solid $link-underline-blue;
color: $black;
font-weight: 600;
......
......@@ -97,17 +97,19 @@
.issues-bulk-update.right-sidebar {
@include maintain-sidebar-dimensions;
transition: right $sidebar-transition-duration;
right: -$gutter-width;
width: 0;
padding: 0;
transition: width $sidebar-transition-duration;
&.right-sidebar-expanded {
@include maintain-sidebar-dimensions;
right: 0;
width: $gutter-width;
}
&.right-sidebar-collapsed {
@include maintain-sidebar-dimensions;
right: -$gutter-width;
width: 0;
padding: 0;
.block {
padding: 16px 0;
......@@ -118,5 +120,6 @@
.issuable-sidebar {
padding: 0 3px;
width: calc(100% + 35px);
}
}
......@@ -44,6 +44,10 @@
&:target,
&.target {
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 {
......
......@@ -322,6 +322,7 @@ $note-disabled-comment-color: #b2b2b2;
$note-targe3-outside: #fffff0;
$note-targe3-inside: #ffffd3;
$note-line2-border: #ddd;
$note-icon-gutter-width: 55px;
/*
......
......@@ -204,7 +204,7 @@
.issuable-sidebar {
width: calc(100% + 100px);
height: 100%;
height: calc(100% - #{$header-height});
overflow-y: scroll;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
......
......@@ -148,8 +148,20 @@
padding: 6px 0;
}
.notes-form > li {
border: 0;
.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;
}
}
.note-edit-form {
......
......@@ -14,16 +14,6 @@ ul.notes {
margin: 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-updated-at {
white-space: nowrap;
......@@ -46,17 +36,49 @@ ul.notes {
}
}
> li {
padding: $gl-padding $gl-btn-padding;
> li { // .timeline-entry
padding: 0;
display: block;
position: relative;
border-bottom: 1px solid $white-normal;
border-bottom: 0;
@include notes-media('min', $screen-sm-min) {
padding-left: $note-icon-gutter-width;
}
&:last-child {
// Override `.timeline > li:last-child { border-bottom: none; }`
.timeline-entry-inner {
padding: $gl-padding $gl-btn-padding;
border-bottom: 1px solid $white-normal;
}
&:target,
&.target {
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 {
pointer-events: none;
opacity: 0.5;
......@@ -73,7 +95,7 @@ ul.notes {
}
&.note-discussion {
&.timeline-entry {
.timeline-entry-inner {
padding: $gl-padding 10px;
}
}
......@@ -152,13 +174,8 @@ ul.notes {
.system-note {
font-size: 14px;
padding-left: 0;
clear: both;
@include notes-media('min', $screen-sm-min) {
margin-left: 65px;
}
.note-header-info {
padding-bottom: 0;
}
......@@ -192,13 +209,16 @@ ul.notes {
.timeline-icon {
float: left;
@include notes-media('min', $screen-sm-min) {
margin-left: 0;
width: auto;
}
svg {
width: 16px;
height: 16px;
fill: $gray-darkest;
position: absolute;
left: 0;
top: 2px;
margin-top: 2px;
}
}
......@@ -250,7 +270,7 @@ ul.notes {
&::after {
content: '';
width: 100%;
height: 67px;
height: 70px;
position: absolute;
left: 0;
bottom: 0;
......@@ -639,15 +659,12 @@ ul.notes {
.discussion-body,
.diff-file {
.notes .note {
padding-left: $gl-padding;
padding-right: $gl-padding;
&.system-note {
padding-left: 0;
border-bottom: 1px solid $white-normal;
@media (min-width: $screen-sm-min) {
margin-left: 70px;
}
.timeline-entry-inner {
padding-left: $gl-padding;
padding-right: $gl-padding;
border-bottom: none;
}
}
}
......
......@@ -29,6 +29,10 @@
&:first-of-type {
margin-top: 10px;
}
&.expanded {
overflow: visible;
}
}
.settings-header {
......
......@@ -6,7 +6,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
before_action :authorize_admin_project!
before_action :authorize_update_deploy_key!, only: [:edit, :update]
layout "project_settings"
layout 'project_settings'
def index
respond_to do |format|
......@@ -66,7 +66,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
protected
def deploy_key
@deploy_key ||= @project.deploy_keys.find(params[:id])
@deploy_key ||= DeployKey.find(params[:id])
end
def create_params
......
......@@ -15,8 +15,6 @@ class Projects::EnvironmentsController < Projects::ApplicationController
respond_to do |format|
format.html
format.json do
Gitlab::PollingInterval.set_header(response, interval: 3_000)
render json: {
environments: EnvironmentSerializer
.new(project: @project, current_user: @current_user)
......
......@@ -138,17 +138,6 @@ module Ci
ExpandVariables.expand(environment, simple_variables) if environment
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?
environment.present?
end
......@@ -192,7 +181,7 @@ module Ci
slugified.gsub(/[^a-z0-9]/, '-')[0..62]
end
# Variables whose value does not depend on other variables
# Variables whose value does not depend on environment
def simple_variables
variables = predefined_variables
variables += project.predefined_variables
......@@ -207,7 +196,8 @@ module Ci
variables
end
# All variables, including those dependent on other variables
# All variables, including those dependent on environment, which could
# contain unexpanded variables.
def variables
simple_variables.concat(persisted_environment_variables)
end
......@@ -481,9 +471,10 @@ module Ci
variables = persisted_environment.predefined_variables
if url = environment_url
variables << { key: 'CI_ENVIRONMENT_URL', value: url, public: true }
end
# Here we're passing unexpanded environment_url for runner to expand,
# and we need to make sure that CI_ENVIRONMENT_NAME and
# 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
end
......@@ -506,6 +497,10 @@ module Ci
variables
end
def environment_url
options&.dig(:environment, :url) || persisted_environment&.external_url
end
def build_attributes_from_config
return {} unless pipeline.config_processor
......
......@@ -2,7 +2,7 @@ class CreateDeploymentService
attr_reader :job
delegate :expanded_environment_name,
:environment_url,
:variables,
:project,
to: :job
......@@ -14,7 +14,8 @@ class CreateDeploymentService
return unless executable?
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)
return unless environment.save
......@@ -49,6 +50,17 @@ class CreateDeploymentService
@environment_options ||= job.options&.dig(:environment) || {}
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
environment_options[:on_stop]
end
......
- 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" }
.issuable-sidebar
.issuable-sidebar.hidden
= form_tag [:bulk_update, @project.namespace.becomes(Namespace), @project, type], method: :post, class: "bulk-update" do
.block
.filter-item.inline.update-issues-btn.pull-left
......
- type = local_assigns.fetch(:type, :issues)
- page_context_word = type.to_s.humanize(capitalize: false)
- issuables = @issues || @merge_requests
- closed_title = 'Filter by issues that are currently closed.'
%ul.nav-links.issues-state-filters
%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)}
- if type == :merge_requests
%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)}
- closed_title = 'Filter by merge requests that are currently closed and unmerged.'
%li{ class: active_when(params[:state] == 'closed') }>
%button.btn.btn-link{ id: 'state-closed', title: closed_title, type: 'button', data: { state: 'closed' } }
#{issuables_state_counter_text(type, :closed)}
%li{ class: active_when(params[: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)}
%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)}
......@@ -6,13 +6,14 @@
- if can_create_note?
%ul.notes.notes-form.timeline
%li.timeline-entry
.flash-container.timeline-content
.timeline-entry-inner
.flash-container.timeline-content
.timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) }
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
.timeline-icon.hidden-xs.hidden-sm
%a.author_link{ href: user_path(current_user) }
= image_tag avatar_icon(current_user), alt: current_user.to_reference, class: 'avatar s40'
.timeline-content.timeline-content-form
= render "shared/notes/form", view: diff_view, supports_autocomplete: autocomplete
- elsif !current_user
.disabled-comment.text-center.prepend-top-default
Please
......
---
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
DOWNTIME = false
disable_ddl_transaction!
def up
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
def down
remove_foreign_key :ci_builds, column: :stage_id
remove_concurrent_index :ci_builds, :stage_id
remove_column :ci_builds, :stage_id, :integer
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
DOWNTIME = false
def up
disable_statement_timeout
update_column_in_batches(:projects, :auto_cancel_pending_pipelines, 1)
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
DOWNTIME = false
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
##
# This is an empty migration, content has been moved to a new one:
# post migrate 20170526190000 MigrateBuildStageReferenceAgain
#
# See gitlab-org/gitlab-ce!12337 for more details.
update_column_in_batches(:ci_builds, :stage_id, stage_id) do |table, query|
query.where(table[:stage_id].eq(nil))
end
def up
# noop
end
def down
disable_statement_timeout
update_column_in_batches(:ci_builds, :stage_id, nil)
# noop
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 @@
#
# 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
enable_extension "plpgsql"
enable_extension "pg_trgm"
......@@ -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", ["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", ["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", ["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
......
......@@ -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`
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
`~#`; these can be removed to keep our translation files clutter-free.
......
......@@ -167,15 +167,15 @@ environment which has had a successful deployment.
## Determining the performance impact of a merge
> [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
request workflow. When a source branch has been deployed to an environment, a
sparkline will appear showing the average memory consumption of the app. The dot
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
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.
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.
Performance data will be available for the duration it is persisted on the
......
......@@ -86,7 +86,7 @@ module API
at_least_one_of :title, :can_push
end
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)
......
......@@ -172,7 +172,7 @@ module Github
next unless merge_request.new_record? && pull_request.valid?
begin
restore_branches(pull_request)
pull_request.restore_branches!
author_id = user_id(pull_request.author, project.creator_id)
description = format_description(pull_request.description, pull_request.author)
......@@ -208,7 +208,7 @@ module Github
rescue => e
error(:pull_request, pull_request.url, e.message)
ensure
clean_up_restored_branches(pull_request)
pull_request.remove_restored_branches!
end
end
......@@ -325,32 +325,6 @@ module Github
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)
labels.map { |attrs| cached[:label_ids][attrs.fetch('name')] }.compact
end
......
......@@ -26,13 +26,25 @@ module Github
end
def exists?
branch_exists? && commit_exists?
@exists ||= branch_exists? && commit_exists?
end
def valid?
sha.present? && ref.present?
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
def branch_exists?
......
module Github
module Representation
class PullRequest < Representation::Issuable
attr_reader :project
delegate :user, :repo, :ref, :sha, to: :source_branch, prefix: true
delegate :user, :exists?, :repo, :ref, :sha, :short_sha, to: :target_branch, prefix: true
......@@ -10,10 +8,6 @@ module Github
project
end
def source_branch_exists?
!cross_project? && source_branch.exists?
end
def source_branch_name
@source_branch_name ||=
if cross_project? || !source_branch_exists?
......@@ -23,6 +17,12 @@ module Github
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
project
end
......@@ -31,6 +31,10 @@ module Github
@target_branch_name ||= target_branch_exists? ? target_branch_ref : target_branch_name_prefixed
end
def target_branch_exists?
@target_branch_exists ||= target_branch.exists?
end
def state
return 'merged' if raw['state'] == 'closed' && raw['merged_at'].present?
return 'closed' if raw['state'] == 'closed'
......@@ -46,6 +50,18 @@ module Github
source_branch.valid? && target_branch.valid?
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
def project
......@@ -73,6 +89,32 @@ module Github
source_branch_repo.id != target_branch_repo.id
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
No preview for this file type
......@@ -70,9 +70,6 @@ msgstr ""
msgid "ByAuthor|by"
msgstr ""
msgid "CI configuration"
msgstr ""
msgid "Cancel"
msgstr ""
......@@ -349,33 +346,12 @@ msgstr ""
msgid "From merge request merge until deploy to production"
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"
msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
msgid "LFSStatus|Disabled"
msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
......@@ -410,9 +386,6 @@ msgstr[1] ""
msgid "Median"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] ""
......@@ -619,21 +592,9 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
msgid "ProjectNetworkGraph|Graph"
msgstr ""
msgid "Read more"
msgstr ""
msgid "Readme"
msgstr ""
msgid "RefSwitcher|Branches"
msgstr ""
msgid "RefSwitcher|Tags"
msgstr ""
msgid "Related Commits"
msgstr ""
......@@ -688,21 +649,6 @@ msgstr ""
msgid "Select target branch"
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_plural "Showing %d events"
msgstr[0] ""
......@@ -737,9 +683,6 @@ msgstr ""
msgid "The collection of events added to the data gathered for that stage."
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."
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."
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."
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."
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"
msgstr ""
......@@ -794,129 +725,6 @@ msgstr ""
msgid "Time until first merge request"
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_plural "Time|hrs"
msgstr[0] ""
......@@ -936,27 +744,6 @@ msgstr ""
msgid "Total test time for all commits/merges"
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."
msgstr ""
......
......@@ -77,9 +77,6 @@ msgstr ""
msgid "ByAuthor|by"
msgstr ""
msgid "CI configuration"
msgstr ""
msgid "Cancel"
msgstr ""
......@@ -356,33 +353,12 @@ msgstr ""
msgid "From merge request merge until deploy to production"
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"
msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
msgid "LFSStatus|Disabled"
msgstr ""
msgid "LFSStatus|Enabled"
msgstr ""
msgid "Last %d day"
msgid_plural "Last %d days"
msgstr[0] ""
......@@ -417,9 +393,6 @@ msgstr[1] ""
msgid "Median"
msgstr ""
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] ""
......@@ -626,21 +599,9 @@ msgstr ""
msgid "ProjectLifecycle|Stage"
msgstr ""
msgid "ProjectNetworkGraph|Graph"
msgstr ""
msgid "Read more"
msgstr ""
msgid "Readme"
msgstr ""
msgid "RefSwitcher|Branches"
msgstr ""
msgid "RefSwitcher|Tags"
msgstr ""
msgid "Related Commits"
msgstr ""
......@@ -695,21 +656,6 @@ msgstr ""
msgid "Select target branch"
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_plural "Showing %d events"
msgstr[0] ""
......@@ -744,9 +690,6 @@ msgstr ""
msgid "The collection of events added to the data gathered for that stage."
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."
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."
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."
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."
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"
msgstr ""
......@@ -801,129 +732,6 @@ msgstr ""
msgid "Time until first merge request"
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_plural "Time|hrs"
msgstr[0] ""
......
......@@ -58,9 +58,11 @@ describe Projects::EnvironmentsController do
expect(json_response['stopped_count']).to eq 1
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.headers['Poll-Interval']).to eq("3000")
expect(response.headers['Poll-Interval']).to be_nil
end
end
......
......@@ -59,6 +59,11 @@ RSpec.describe 'Dashboard Issues', feature: true do
expect(page).to have_content(other_issue.title)
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 "an autodiscoverable RSS feed with current_user's RSS token"
end
......
......@@ -16,6 +16,21 @@ feature 'Issues > Labels bulk assignment', feature: true do
login_as user
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
before do
enable_bulk_update
......@@ -398,4 +413,8 @@ feature 'Issues > Labels bulk assignment', feature: true do
visit namespace_project_issues_path(project.namespace, project)
click_button 'Edit Issues'
end
def disable_bulk_update
click_button 'Cancel'
end
end
......@@ -65,6 +65,23 @@ feature 'Repository settings', feature: true do
expect(page).to have_content('Write access allowed')
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
project.deploy_keys << private_deploy_key
visit namespace_project_settings_repository_path(project.namespace, project)
......
......@@ -104,6 +104,7 @@ describe('Filtered Search Manager', () => {
it('should blur button', () => {
const e = {
preventDefault: () => {},
currentTarget: {
blur: () => {},
},
......@@ -116,6 +117,7 @@ describe('Filtered Search Manager', () => {
it('should not call search if there is no state', () => {
const e = {
preventDefault: () => {},
currentTarget: {
blur: () => {},
},
......@@ -127,6 +129,7 @@ describe('Filtered Search Manager', () => {
it('should call search when there is state', () => {
const e = {
preventDefault: () => {},
currentTarget: {
blur: () => {},
dataset: {
......
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.
#
......
......@@ -439,42 +439,6 @@ describe Ci::Build, :models do
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
subject { build.starts_environment? }
......@@ -1276,10 +1240,20 @@ describe Ci::Build, :models do
context 'when the URL was set from the job' do
before do
build.update(options: { environment: { url: 'http://host/$CI_JOB_NAME' } })
build.update(options: { environment: { url: url } })
end
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
context 'when the URL was not set from the job, but environment' do
......
......@@ -158,6 +158,16 @@ describe API::DeployKeys do
expect(json_response['title']).to eq('new title')
expect(json_response['can_push']).to eq(true)
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
describe 'DELETE /projects/:id/deploy_keys/:key_id' do
......
......@@ -122,6 +122,61 @@ describe CreateDeploymentService, services: true do
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
shared_examples 'does not create deployment' do
it 'does not create a new deployment' do
......
......@@ -36,12 +36,13 @@ RSpec.configure do |config|
$capybara_server_already_started = true
end
config.after(:each, :js) do
config.after(:each, :js) do |example|
# capybara/rspec already calls Capybara.reset_sessions! in an `after` hook,
# 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
# 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
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