Commit d8dcd0c2 authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-11-06' into 'master'

CE upstream - 2018-11-06 17:26 UTC

Closes gitaly#1336

See merge request gitlab-org/gitlab-ee!8258
parents 8d4a2411 88e829c1
......@@ -65,6 +65,14 @@ export default {
deployedText() {
return this.$options.deployedTextMap[this.deployment.status];
},
isDeployInProgress() {
return this.deployment.status === 'running';
},
deployInProgressTooltip() {
return this.isDeployInProgress
? __('Stopping this environment is currently not possible as a deployment is in progress')
: '';
},
shouldRenderDropdown() {
return (
this.enableCiEnvironmentsStatusChanges &&
......@@ -183,15 +191,23 @@ export default {
css-class="js-deploy-url js-deploy-url-feature-flag deploy-link btn btn-default btn-sm inlin"
/>
</template>
<loading-button
<span
v-if="deployment.stop_url"
:loading="isStopping"
container-class="btn btn-default btn-sm inline prepend-left-4"
title="Stop environment"
@click="stopEnvironment"
v-tooltip
:title="deployInProgressTooltip"
class="d-inline-block"
tabindex="0"
>
<icon name="stop" />
</loading-button>
<loading-button
:loading="isStopping"
:disabled="isDeployInProgress"
:title="__('Stop environment')"
container-class="js-stop-env btn btn-default btn-sm inline prepend-left-4"
@click="stopEnvironment"
>
<icon name="stop" />
</loading-button>
</span>
</div>
</div>
</div>
......
......@@ -39,7 +39,7 @@
svg {
fill: currentColor;
$svg-sizes: 8 10 12 16 18 24 32 48 72;
$svg-sizes: 8 10 12 14 16 18 24 32 48 72;
@each $svg-size in $svg-sizes {
&.s#{$svg-size} {
@include svg-size(#{$svg-size}px);
......
......@@ -271,6 +271,7 @@ $flash-height: 52px;
$context-header-height: 60px;
$breadcrumb-min-height: 48px;
$project-title-row-height: 24px;
$gl-line-height: 16px;
// EE-only CSS variables START
$system-header-height: 35px;
......
......@@ -4,41 +4,29 @@
*/
.event-item {
font-size: $gl-font-size;
padding: $gl-padding-top 0 $gl-padding-top 40px;
padding: $gl-padding 0 $gl-padding 56px;
border-bottom: 1px solid $white-normal;
color: $gl-text-color;
color: $gl-text-color-secondary;
position: relative;
&.event-inline {
.system-note-image {
top: 20px;
}
.user-avatar {
top: 14px;
}
.event-title,
.event-item-timestamp {
line-height: 40px;
}
}
a {
color: $gl-text-color;
}
line-height: $gl-line-height;
.system-note-image {
position: absolute;
left: 0;
top: 14px;
svg {
width: 20px;
height: 20px;
fill: $gl-text-color-secondary;
}
}
.system-note-image-inline {
svg {
fill: $gl-text-color-secondary;
}
}
.system-note-image,
.system-note-image-inline {
&.opened-icon,
&.created-icon {
svg {
......@@ -53,16 +41,35 @@
&.accepted-icon svg {
fill: $blue-300;
}
&.commented-on-icon svg {
fill: $blue-600;
}
}
.event-user-info {
margin-bottom: $gl-padding-8;
.author_name {
a {
color: $gl-text-color;
font-weight: $gl-font-weight-bold;
}
}
}
.event-title {
@include str-truncated(calc(100% - 174px));
font-weight: $gl-font-weight-bold;
color: $gl-text-color;
.event-type {
&::first-letter {
text-transform: capitalize;
}
}
}
.event-body {
margin-top: $gl-padding-8;
margin-right: 174px;
color: $gl-text-color;
.event-note {
word-wrap: break-word;
......@@ -92,7 +99,7 @@
}
.note-image-attach {
margin-top: 4px;
margin-top: $gl-padding-4;
margin-left: 0;
max-width: 200px;
float: none;
......@@ -107,7 +114,6 @@
color: $gl-gray-500;
float: left;
font-size: $gl-font-size;
line-height: 16px;
margin-right: 5px;
}
}
......@@ -127,7 +133,9 @@
}
}
&:last-child { border: 0; }
&:last-child {
border: 0;
}
.event_commits {
li {
......@@ -154,7 +162,6 @@
.event-item-timestamp {
float: right;
line-height: 22px;
}
}
......@@ -177,10 +184,8 @@
.event-item {
padding-left: 0;
&.event-inline {
.event-title {
line-height: 20px;
}
.event-user-info {
margin-bottom: $gl-padding-4;
}
.event-title {
......@@ -194,7 +199,8 @@
}
.event-body {
margin: 0;
margin-top: $gl-padding-4;
margin-right: 0;
padding-left: 0;
}
......
......@@ -240,6 +240,12 @@
left: 0;
}
.activities-block {
.event-item {
padding-left: 40px;
}
}
@include media-breakpoint-down(xs) {
.cover-block {
padding-top: 20px;
......@@ -267,6 +273,12 @@
margin-right: 0;
}
}
.activities-block {
.event-item {
padding-left: 0;
}
}
}
}
......
......@@ -163,14 +163,10 @@ module EventsHelper
def event_note_title_html(event)
if event.note_target
text = raw("#{event.note_target_type} ") +
if event.commit_note?
content_tag(:span, event.note_target_reference, class: 'commit-sha')
else
event.note_target_reference
end
link_to(text, event_note_target_url(event), title: event.target_title, class: 'has-tooltip')
capture do
concat content_tag(:span, event.note_target_type, class: "event-target-type append-right-4")
concat link_to(event.note_target_reference, event_note_target_url(event), title: event.target_title, class: 'has-tooltip event-target-link append-right-4')
end
else
content_tag(:strong, '(deleted)')
end
......@@ -183,17 +179,9 @@ module EventsHelper
"--broken encoding"
end
def event_row_class(event)
if event.body?
"event-block"
else
"event-inline"
end
end
def icon_for_event(note)
def icon_for_event(note, size: 24)
icon_name = ICON_NAMES_BY_EVENT_TYPE[note]
sprite_icon(icon_name) if icon_name
sprite_icon(icon_name, size: size) if icon_name
end
def icon_for_profile_event(event)
......@@ -203,8 +191,24 @@ module EventsHelper
end
else
content_tag :div, class: 'system-note-image user-avatar' do
author_avatar(event, size: 32)
author_avatar(event, size: 40)
end
end
end
def inline_event_icon(event)
unless current_path?('users#show')
content_tag :span, class: "system-note-image-inline d-none d-sm-flex append-right-4 #{event.action_name.parameterize}-icon align-self-center" do
icon_for_event(event.action_name, size: 14)
end
end
end
def event_user_info(event)
content_tag(:div, class: "event-user-info") do
concat content_tag(:span, link_to_author(event), class: "author_name")
concat "&nbsp;".html_safe
concat content_tag(:span, event.author.to_reference, class: "username")
end
end
end
......@@ -3,7 +3,6 @@
module UserCalloutsHelper
GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'.freeze
GCP_SIGNUP_OFFER = 'gcp_signup_offer'.freeze
CLUSTER_SECURITY_WARNING = 'cluster_security_warning'.freeze
def show_gke_cluster_integration_callout?(project)
can?(current_user, :create_cluster, project) &&
......@@ -14,10 +13,6 @@ module UserCalloutsHelper
!user_dismissed?(GCP_SIGNUP_OFFER)
end
def show_cluster_security_warning?
!user_dismissed?(CLUSTER_SECURITY_WARNING)
end
private
def user_dismissed?(feature_name)
......
......@@ -10,7 +10,6 @@ module Ci
include Importable
include Gitlab::Utils::StrongMemoize
include Deployable
prepend EE::Ci::Build
belongs_to :project, inverse_of: :builds
......
......@@ -41,8 +41,8 @@ class Label < ActiveRecord::Base
scope :templates, -> { where(template: true) }
scope :with_title, ->(title) { where(title: title) }
scope :with_lists_and_board, -> { joins(lists: :board).merge(List.movable) }
scope :on_group_boards, ->(group_id) { with_lists_and_board.where(boards: { group_id: group_id }) }
scope :on_project_boards, ->(project_id) { with_lists_and_board.where(boards: { project_id: project_id }) }
scope :on_board, ->(board_id) { with_lists_and_board.where(boards: { id: board_id }) }
scope :order_name_asc, -> { reorder(title: :asc) }
scope :order_name_desc, -> { reorder(title: :desc) }
scope :subscribed_by, ->(user_id) { joins(:subscriptions).where(subscriptions: { user_id: user_id, subscribed: true }) }
......
......@@ -12,9 +12,9 @@ class IssueTrackerService < Service
# overridden patterns. See ReferenceRegexes::EXTERNAL_PATTERN
def self.reference_pattern(only_long: false)
if only_long
/(\b[A-Z][A-Z0-9_]+-)(?<issue>\d+)/
/(\b[A-Z][A-Z0-9_]*-)(?<issue>\d+)/
else
/(\b[A-Z][A-Z0-9_]+-|#{Issue.reference_prefix})(?<issue>\d+)/
/(\b[A-Z][A-Z0-9_]*-|#{Issue.reference_prefix})(?<issue>\d+)/
end
end
......
......@@ -917,10 +917,6 @@ class Repository
async_remove_remote(remote_name) if tmp_remote_name
end
def fetch_remote(remote, forced: false, ssh_auth: nil, no_tags: false, prune: true)
gitlab_shell.fetch_remote(raw_repository, remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, prune: prune)
end
def async_remove_remote(remote_name)
return unless remote_name
......
......@@ -70,10 +70,8 @@ module Boards
label_ids =
if moving_to_list.movable?
moving_from_list.label_id
elsif board.group_board?
::Label.on_group_boards(parent.id).pluck(:label_id)
else
::Label.on_project_boards(parent.id).pluck(:label_id)
::Label.on_board(board.id).pluck(:label_id)
end
Array(label_ids).compact
......
......@@ -7,9 +7,3 @@
.hidden.js-cluster-success.bs-callout.bs-callout-success{ role: 'alert' }
= s_("ClusterIntegration|Kubernetes cluster was successfully created on Google Kubernetes Engine. Refresh the page to see Kubernetes cluster's details")
- if show_cluster_security_warning?
.js-cluster-security-warning.alert.alert-block.alert-dismissable.bs-callout.bs-callout-warning
%button.close{ type: "button", data: { feature_id: UserCalloutsHelper::CLUSTER_SECURITY_WARNING, dismiss_endpoint: user_callouts_path } } &times;
= s_("ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application.")
= link_to s_("More information"), help_page_path('user/project/clusters/index.md', anchor: 'security-implications')
......@@ -64,7 +64,7 @@
.form-group
.form-check
= provider_gcp_field.check_box :legacy_abac, { class: 'form-check-input' }, false, true
= provider_gcp_field.label :legacy_abac, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
= provider_gcp_field.label :legacy_abac, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
.form-text.text-muted
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
......
......@@ -40,7 +40,7 @@
.form-group
.form-check
= platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
.form-text.text-muted
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
......
......@@ -28,7 +28,7 @@
.form-group
.form-check
= platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input qa-rbac-checkbox' }, 'rbac', 'abac'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
.form-text.text-muted
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
......
......@@ -29,7 +29,7 @@
.form-group
.form-check
= platform_kubernetes_field.check_box :authorization_type, { class: 'form-check-input', disabled: true }, 'rbac', 'abac'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster (experimental)'), class: 'form-check-label label-bold'
= platform_kubernetes_field.label :authorization_type, s_('ClusterIntegration|RBAC-enabled cluster'), class: 'form-check-label label-bold'
.form-text.text-muted
= s_('ClusterIntegration|Enable this setting if using role-based access control (RBAC).')
= s_('ClusterIntegration|This option will allow you to install applications on RBAC clusters.')
......
- if event.visible_to_user?(current_user)
.event-item{ class: event_row_class(event) }
.event-item
.event-item-timestamp
#{time_ago_with_tooltip(event.created_at)}
......
= icon_for_profile_event(event)
.event-title
%span.author_name= link_to_author(event)
%span{ class: event.action_name }
= event_user_info(event)
.event-title.d-flex.flex-wrap
= inline_event_icon(event)
- if event.target
= event.action_name
%strong
= link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip', title: event.target_title do
= event.target_type.titleize.downcase
= event.target.reference_link_text
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event.action_name
%span.event-target-type.append-right-4= event.target_type.titleize.downcase
= link_to [event.project.namespace.becomes(Namespace), event.project, event.target], class: 'has-tooltip event-target-link append-right-4', title: event.target_title do
= event.target.reference_link_text
- unless event.milestone?
%span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
- else
= event_action_name(event)
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event_action_name(event)
= render "events/event_scope", event: event
- if event.target.respond_to?(:title)
.event-body
.event-note
= event.target.title
= icon_for_profile_event(event)
.event-title
%span.author_name= link_to_author(event)
%span{ class: event.action_name }
= event_user_info(event)
.event-title.d-flex.flex-wrap
= inline_event_icon(event)
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event_action_name(event)
- if event.project
......
= icon_for_profile_event(event)
.event-title
%span.author_name= link_to_author(event)
= event.action_name
= event_user_info(event)
.event-title.d-flex.flex-wrap
= inline_event_icon(event)
%span.event-type.d-inline-block.append-right-4{ class: event.action_name }
= event.action_name
= event_note_title_html(event)
%span.event-target-title.append-right-4= "&quot;".html_safe + event.target.title + "&quot".html_safe
= render "events/event_scope", event: event
......
.event-inline.event-item
.event-item
.event-item-timestamp
= time_ago_with_tooltip(event.created_at)
.system-note-image= sprite_icon('eye-slash', size: 16, css_class: 'icon')
.system-note-image= sprite_icon('eye-slash', size: 24, css_class: 'icon')
.event-title
- author_name = capture do
%span.author_name= link_to_author(event)
= s_('Profiles|%{author_name} made a private contribution').html_safe % { author_name: author_name }
= event_user_info(event)
.event-title.d-flex.flex-wrap
= inline_event_icon(event)
= s_('Profiles|Made a private contribution')
......@@ -2,13 +2,15 @@
= icon_for_profile_event(event)
.event-title
%span.author_name= link_to_author(event)
%span.pushed #{event.action_name} #{event.ref_type}
%strong
= event_user_info(event)
.event-title.d-flex.flex-wrap
= inline_event_icon(event)
%span.event-type.d-inline-block.append-right-4.pushed #{event.action_name} #{event.ref_type}
%span
- commits_link = project_commits_path(project, event.ref_name)
- should_link = event.tag? ? project.repository.tag_exists?(event.ref_name) : project.repository.branch_exists?(event.ref_name)
= link_to_if should_link, event.ref_name, commits_link, class: 'ref-name'
= link_to_if should_link, event.ref_name, commits_link, class: 'ref-name append-right-4'
= render "events/event_scope", event: event
......
......@@ -11,8 +11,8 @@
- if can?(current_user, :read_cross_project)
.activities-block
.content-block
%h5.prepend-top-10
.border-bottom.prepend-top-16
%h5
= s_('UserProfile|Recent contributions')
.overview-content-list{ data: { href: user_path } }
.center.light.loading
......@@ -22,7 +22,7 @@
.col-md-12.col-lg-6
.projects-block
.content-block
.border-bottom.prepend-top-16
%h4
= s_('UserProfile|Personal projects')
.overview-content-list{ data: { href: user_projects_path } }
......
---
title: "Allowing issues with single letter identifiers to be linked to external issue tracker (f.ex T-123)"
merge_request: 22717
author: Dídac Rodríguez Arbonès
type: changed
\ No newline at end of file
---
title: Disables stop environment button while the deploy is in progress
merge_request:
author:
type: other
title: Redesign activity feed
merge_request: 22217
author:
type: other
---
title: Add background migration to populate Kubernetes namespaces
merge_request: 22433
author:
type: added
---
title: Fixed label removal from issue
merge_request: 22762
author:
type: fixed
---
title: Drop gcp_clusters table
merge_request: 22713
author:
type: other
---
title: Add gitlab:gitaly:check task for Gitaly health check
merge_request: 22063
author:
type: other
---
title: Removes experimental labels from cluster views
merge_request: 22550
author:
type: other
# frozen_string_literal: true
class DropGcpClustersTable < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
drop_table :gcp_clusters
end
def down
create_table :gcp_clusters do |t|
# Order columns by best align scheme
t.references :project, null: false, index: { unique: true }, foreign_key: { on_delete: :cascade }
t.references :user, foreign_key: { on_delete: :nullify }
t.references :service, foreign_key: { on_delete: :nullify }
t.integer :status
t.integer :gcp_cluster_size, null: false
# Timestamps
t.datetime_with_timezone :created_at, null: false
t.datetime_with_timezone :updated_at, null: false
# Enable/disable
t.boolean :enabled, default: true
# General
t.text :status_reason
# k8s integration specific
t.string :project_namespace
# Cluster details
t.string :endpoint
t.text :ca_cert
t.text :encrypted_kubernetes_token
t.string :encrypted_kubernetes_token_iv
t.string :username
t.text :encrypted_password
t.string :encrypted_password_iv
# GKE
t.string :gcp_project_id, null: false
t.string :gcp_cluster_zone, null: false
t.string :gcp_cluster_name, null: false
t.string :gcp_machine_type
t.string :gcp_operation_id
t.text :encrypted_gcp_token
t.string :encrypted_gcp_token_iv
end
end
end
# frozen_string_literal: true
class EnqueuePopulateClusterKubernetesNamespace < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
MIGRATION = 'PopulateClusterKubernetesNamespaceTable'.freeze
disable_ddl_transaction!
def up
BackgroundMigrationWorker.perform_async(MIGRATION)
end
def down
Clusters::KubernetesNamespace.delete_all
end
end
......@@ -1116,6 +1116,35 @@ ActiveRecord::Schema.define(version: 20181105201455) do
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
create_table "gcp_clusters", force: :cascade do |t|
t.integer "project_id", null: false
t.integer "user_id"
t.integer "service_id"
t.integer "status"
t.integer "gcp_cluster_size", null: false
t.datetime_with_timezone "created_at", null: false
t.datetime_with_timezone "updated_at", null: false
t.boolean "enabled", default: true
t.text "status_reason"
t.string "project_namespace"
t.string "endpoint"
t.text "ca_cert"
t.text "encrypted_kubernetes_token"
t.string "encrypted_kubernetes_token_iv"
t.string "username"
t.text "encrypted_password"
t.string "encrypted_password_iv"
t.string "gcp_project_id", null: false
t.string "gcp_cluster_zone", null: false
t.string "gcp_cluster_name", null: false
t.string "gcp_machine_type"
t.string "gcp_operation_id"
t.text "encrypted_gcp_token"
t.string "encrypted_gcp_token_iv"
end
add_index "gcp_clusters", ["project_id"], name: "index_gcp_clusters_on_project_id", unique: true, using: :btree
create_table "geo_cache_invalidation_events", id: :bigserial, force: :cascade do |t|
t.string "key", null: false
end
......@@ -3282,6 +3311,9 @@ ActiveRecord::Schema.define(version: 20181105201455) do
add_foreign_key "fork_network_members", "projects", on_delete: :cascade
add_foreign_key "fork_networks", "projects", column: "root_project_id", name: "fk_e7b436b2b5", on_delete: :nullify
add_foreign_key "forked_project_links", "projects", column: "forked_to_project_id", name: "fk_434510edb0", on_delete: :cascade
add_foreign_key "gcp_clusters", "projects", on_delete: :cascade
add_foreign_key "gcp_clusters", "services", on_delete: :nullify
add_foreign_key "gcp_clusters", "users", on_delete: :nullify
add_foreign_key "geo_event_log", "geo_cache_invalidation_events", column: "cache_invalidation_event_id", name: "fk_42c3b54bed", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_hashed_storage_migrated_events", column: "hashed_storage_migrated_event_id", name: "fk_27548c6db3", on_delete: :cascade
add_foreign_key "geo_event_log", "geo_job_artifact_deleted_events", column: "job_artifact_deleted_event_id", name: "fk_176d3fbb5d", on_delete: :cascade
......
......@@ -53,6 +53,7 @@ Git: /usr/bin/git
Runs the following rake tasks:
- `gitlab:gitlab_shell:check`
- `gitlab:gitaly:check`
- `gitlab:sidekiq:check`
- `gitlab:app:check`
......@@ -252,7 +253,7 @@ clear it.
To clear all exclusive leases:
DANGER: **DANGER**:
DANGER: **DANGER**:
Don't run it while GitLab or Sidekiq is running
```bash
......
export const hasFilters = state => Object.keys(state.filters).length > 0;
export const appliedFilters = state => state.filters;
\ No newline at end of file
export const appliedFilters = state => state.filters;
......@@ -8,7 +8,7 @@ module Geo
fetch_repository
update_root_ref
mark_sync_as_successful
rescue Gitlab::Shell::Error => e
rescue Gitlab::Shell::Error, Gitlab::Git::BaseError => e
# In some cases repository does not exist, the only way to know about this is to parse the error text.
# If it does not exist we should consider it as successfully downloaded.
if e.message.include? Gitlab::GitAccess::ERROR_MESSAGES[:no_repo]
......
......@@ -8,7 +8,7 @@ module Geo
fetch_repository
mark_sync_as_successful
rescue Gitlab::Shell::Error, ProjectWiki::CouldNotCreateWikiError => e
rescue Gitlab::Shell::Error, Gitlab::Git::BaseError, ProjectWiki::CouldNotCreateWikiError => e
# In some cases repository does not exist, the only way to know about this is to parse the error text.
# If it does not exist we should consider it as successfully downloaded.
if e.message.include? Gitlab::GitAccess::ERROR_MESSAGES[:no_repo]
......
......@@ -19,7 +19,7 @@ module Projects
update_branches
success
rescue Gitlab::Shell::Error, UpdateError => e
rescue Gitlab::Shell::Error, Gitlab::Git::BaseError, UpdateError => e
error(e.message)
end
......
# frozen_string_literal: true
#
# rubocop:disable Style/Documentation
module Gitlab
module BackgroundMigration
class PopulateClusterKubernetesNamespaceTable
include Gitlab::Database::MigrationHelpers
BATCH_SIZE = 1_000
module Migratable
class KubernetesNamespace < ActiveRecord::Base
self.table_name = 'clusters_kubernetes_namespaces'
end
class ClusterProject < ActiveRecord::Base
include EachBatch
self.table_name = 'cluster_projects'
belongs_to :project
def self.with_no_kubernetes_namespace
where.not(id: Migratable::KubernetesNamespace.select(:cluster_project_id))
end
def namespace
slug = "#{project.path}-#{project.id}".downcase
slug.gsub(/[^-a-z0-9]/, '-').gsub(/^-+/, '')
end
def service_account
"#{namespace}-service-account"
end
end
class Project < ActiveRecord::Base
self.table_name = 'projects'
end
end
def perform
cluster_projects_with_no_kubernetes_namespace.each_batch(of: BATCH_SIZE) do |cluster_projects_batch, index|
sql_values = sql_values_for(cluster_projects_batch)
insert_into_cluster_kubernetes_namespace(sql_values)
end
end
private
def cluster_projects_with_no_kubernetes_namespace
Migratable::ClusterProject.with_no_kubernetes_namespace
end
def sql_values_for(cluster_projects)
cluster_projects.map do |cluster_project|
values_for_cluster_project(cluster_project)
end
end
def values_for_cluster_project(cluster_project)
{
cluster_project_id: cluster_project.id,
cluster_id: cluster_project.cluster_id,
project_id: cluster_project.project_id,
namespace: cluster_project.namespace,
service_account_name: cluster_project.service_account,
created_at: 'NOW()',
updated_at: 'NOW()'
}
end
def insert_into_cluster_kubernetes_namespace(rows)
Gitlab::Database.bulk_insert(Migratable::KubernetesNamespace.table_name,
rows,
disable_quote: [:created_at, :updated_at])
end
end
end
end
......@@ -720,6 +720,26 @@ module Gitlab
end
end
# Fetch remote for repository
#
# remote - remote name
# ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
# prune - should we use --prune flag?
def fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, prune: true)
wrapped_gitaly_errors do
gitaly_repository_client.fetch_remote(
remote,
ssh_auth: ssh_auth,
forced: forced,
no_tags: no_tags,
prune: prune,
timeout: GITLAB_PROJECTS_TIMEOUT
)
end
end
def blob_at(sha, path)
Gitlab::Git::Blob.find(self, sha, path) unless Gitlab::Git.blank_ref?(sha)
end
......
......@@ -108,23 +108,6 @@ module Gitlab
success
end
# Fetch remote for repository
#
# repository - an instance of Git::Repository
# remote - remote name
# ssh_auth - SSH known_hosts data and a private key to use for public-key authentication
# forced - should we use --force flag?
# no_tags - should we use --no-tags flag?
#
# Ex.
# fetch_remote(my_repo, "upstream")
#
def fetch_remote(repository, remote, ssh_auth: nil, forced: false, no_tags: false, prune: true)
wrapped_gitaly_errors do
repository.gitaly_repository_client.fetch_remote(remote, ssh_auth: ssh_auth, forced: forced, no_tags: no_tags, timeout: git_timeout, prune: prune)
end
end
# Move repository reroutes to mv_directory which is an alias for
# mv_namespace. Given the underlying implementation is a move action,
# indescriminate of what the folders might be.
......
namespace :gitlab do
desc 'GitLab | Check the configuration of GitLab and its environment'
task check: %w{gitlab:gitlab_shell:check
gitlab:gitaly:check
gitlab:sidekiq:check
gitlab:incoming_email:check
gitlab:ldap:check
......@@ -47,13 +48,7 @@ namespace :gitlab do
start_checking "GitLab Shell"
check_gitlab_shell
Gitlab::GitalyClient::StorageSettings.allow_disk_access do
check_repo_base_exists
check_repo_base_is_not_symlink
check_repo_base_user_and_group
check_repo_base_permissions
check_repos_hooks_directory_is_link
end
check_repos_hooks_directory_is_link
check_gitlab_shell_self_test
finished_checking "GitLab Shell"
......@@ -62,116 +57,6 @@ namespace :gitlab do
# Checks
########################
def check_repo_base_exists
puts "Repo base directory exists?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
if File.exist?(repo_base_path)
puts "yes".color(:green)
else
puts "no".color(:red)
puts "#{repo_base_path} is missing".color(:red)
try_fixing_it(
"This should have been created when setting up GitLab Shell.",
"Make sure it's set correctly in config/gitlab.yml",
"Make sure GitLab Shell is installed correctly."
)
for_more_information(
see_installation_guide_section "GitLab Shell"
)
fix_and_rerun
end
end
end
def check_repo_base_is_not_symlink
puts "Repo storage directories are symlinks?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
puts "can't check because of previous errors".color(:magenta)
break
end
unless File.symlink?(repo_base_path)
puts "no".color(:green)
else
puts "yes".color(:red)
try_fixing_it(
"Make sure it's set to the real directory in config/gitlab.yml"
)
fix_and_rerun
end
end
end
def check_repo_base_permissions
puts "Repo paths access is drwxrws---?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
puts "can't check because of previous errors".color(:magenta)
break
end
if File.stat(repo_base_path).mode.to_s(8).ends_with?("2770")
puts "yes".color(:green)
else
puts "no".color(:red)
try_fixing_it(
"sudo chmod -R ug+rwX,o-rwx #{repo_base_path}",
"sudo chmod -R ug-s #{repo_base_path}",
"sudo find #{repo_base_path} -type d -print0 | sudo xargs -0 chmod g+s"
)
for_more_information(
see_installation_guide_section "GitLab Shell"
)
fix_and_rerun
end
end
end
def check_repo_base_user_and_group
gitlab_shell_ssh_user = Gitlab.config.gitlab_shell.ssh_user
puts "Repo paths owned by #{gitlab_shell_ssh_user}:root, or #{gitlab_shell_ssh_user}:#{Gitlab.config.gitlab_shell.owner_group}?"
Gitlab.config.repositories.storages.each do |name, repository_storage|
repo_base_path = repository_storage.legacy_disk_path
print "#{name}... "
unless File.exist?(repo_base_path)
puts "can't check because of previous errors".color(:magenta)
break
end
user_id = uid_for(gitlab_shell_ssh_user)
root_group_id = gid_for('root')
group_ids = [root_group_id, gid_for(Gitlab.config.gitlab_shell.owner_group)]
if File.stat(repo_base_path).uid == user_id && group_ids.include?(File.stat(repo_base_path).gid)
puts "yes".color(:green)
else
puts "no".color(:red)
puts " User id for #{gitlab_shell_ssh_user}: #{user_id}. Groupd id for root: #{root_group_id}".color(:blue)
try_fixing_it(
"sudo chown -R #{gitlab_shell_ssh_user}:root #{repo_base_path}"
)
for_more_information(
see_installation_guide_section "GitLab Shell"
)
fix_and_rerun
end
end
end
def check_repos_hooks_directory_is_link
print "hooks directories in repos are links: ... "
......@@ -250,6 +135,26 @@ namespace :gitlab do
end
end
namespace :gitaly do
desc 'GitLab | Check the health of Gitaly'
task check: :gitlab_environment do
warn_user_is_not_gitlab
start_checking 'Gitaly'
Gitlab::HealthChecks::GitalyCheck.readiness.each do |result|
print "#{result.labels[:shard]} ... "
if result.success
puts 'OK'.color(:green)
else
puts "FAIL: #{result.message}".color(:red)
end
end
finished_checking 'Gitaly'
end
end
namespace :sidekiq do
desc "GitLab | Check the configuration of Sidekiq"
task check: :gitlab_environment do
......
......@@ -1921,7 +1921,7 @@ msgstr ""
msgid "ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications."
msgstr ""
msgid "ClusterIntegration|RBAC-enabled cluster (experimental)"
msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr ""
msgid "ClusterIntegration|Read our %{link_to_help_page} on Kubernetes cluster integration."
......@@ -1993,9 +1993,6 @@ msgstr ""
msgid "ClusterIntegration|The IP address is in the process of being assigned. Please check your Kubernetes cluster or Quotas on Google Kubernetes Engine if it takes a long time."
msgstr ""
msgid "ClusterIntegration|The default cluster configuration grants access to many functionalities needed to successfully build and deploy a containerised application."
msgstr ""
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr ""
......@@ -6040,9 +6037,6 @@ msgstr ""
msgid "Profiles| You are going to change the username %{currentUsernameBold} to %{newUsernameBold}. Profile and projects will be redirected to the %{newUsername} namespace but this redirect will expire once the %{currentUsername} namespace is registered by another user or group. Please update your Git repository remotes as soon as possible."
msgstr ""
msgid "Profiles|%{author_name} made a private contribution"
msgstr ""
msgid "Profiles|Account scheduled for removal."
msgstr ""
......@@ -6106,6 +6100,9 @@ msgstr ""
msgid "Profiles|Learn more"
msgstr ""
msgid "Profiles|Made a private contribution"
msgstr ""
msgid "Profiles|Main settings"
msgstr ""
......@@ -7657,6 +7654,9 @@ msgstr ""
msgid "Status"
msgstr ""
msgid "Stop environment"
msgstr ""
msgid "Stop impersonation"
msgstr ""
......@@ -7666,6 +7666,9 @@ msgstr ""
msgid "Stopped"
msgstr ""
msgid "Stopping this environment is currently not possible as a deployment is in progress"
msgstr ""
msgid "Storage"
msgstr ""
......
......@@ -153,7 +153,7 @@ describe 'Contributions Calendar', :js do
include_context 'visit user page'
it 'displays calendar activity log' do
expect(find('.tab-pane#activity .content_list .event-note')).to have_content issue_title
expect(find('.tab-pane#activity .content_list .event-target-title')).to have_content issue_title
end
end
end
......
......@@ -14,14 +14,15 @@ describe 'Project member activity', :js do
wait_for_requests
end
subject { page.find(".event-title").text }
context 'when a user joins the project' do
before do
visit_activities_and_wait_with_event(Event::JOINED)
end
it { is_expected.to eq("#{user.name} joined project") }
it "presents the correct message" do
expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
expect(page.find('.event-title').text).to eq("joined project")
end
end
context 'when a user leaves the project' do
......@@ -29,7 +30,10 @@ describe 'Project member activity', :js do
visit_activities_and_wait_with_event(Event::LEFT)
end
it { is_expected.to eq("#{user.name} left project") }
it "presents the correct message" do
expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
expect(page.find('.event-title').text).to eq("left project")
end
end
context 'when a users membership expires for the project' do
......@@ -38,8 +42,8 @@ describe 'Project member activity', :js do
end
it "presents the correct message" do
message = "#{user.name} removed due to membership expiration from project"
is_expected.to eq(message)
expect(page.find('.event-user-info').text).to eq("#{user.name} #{user.to_reference}")
expect(page.find('.event-title').text).to eq("removed due to membership expiration from project")
end
end
end
......@@ -38,7 +38,7 @@ describe 'Merge request > User sees deployment widget', :js do
end
it 'does start build when stop button clicked' do
accept_confirm { click_button('Stop environment') }
accept_confirm { find('.js-stop-env').click }
expect(page).to have_content('close_app')
end
......@@ -47,7 +47,7 @@ describe 'Merge request > User sees deployment widget', :js do
let(:role) { :reporter }
it 'does not show stop button' do
expect(page).not_to have_button('Stop environment')
expect(page).not_to have_selector('.js-stop-env')
end
end
end
......
......@@ -24,6 +24,6 @@ describe "User creates milestone", :js do
visit(activity_project_path(project))
expect(page).to have_content("#{user.name} opened milestone")
expect(page).to have_content("#{user.name} #{user.to_reference} opened milestone")
end
end
......@@ -23,7 +23,7 @@ describe "User deletes milestone", :js do
visit(activity_project_path(project))
expect(page).to have_content("#{user.name} destroyed milestone")
expect(page).to have_content("#{user.name} #{user.to_reference} destroyed milestone")
end
end
......
......@@ -19,13 +19,13 @@ describe 'Projects > Activity > User sees activity' do
it 'shows the last push in the activity page', :js do
visit activity_project_path(project)
expect(page).to have_content "#{user.name} pushed new branch fix"
expect(page).to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
end
it 'allows to filter event with the "event_filter=issue" URL param', :js do
visit activity_project_path(project, event_filter: 'issue')
expect(page).not_to have_content "#{user.name} pushed new branch fix"
expect(page).to have_content "#{user.name} opened issue #{issue.to_reference}"
expect(page).not_to have_content "#{user.name} #{user.to_reference} pushed new branch fix"
expect(page).to have_content "#{user.name} #{user.to_reference} opened issue #{issue.to_reference}"
end
end
......@@ -5,7 +5,7 @@ describe 'Project > Activity > User sees private activity', :js do
let(:author) { create(:user) }
let(:user) { create(:user) }
let(:issue) { create(:issue, :confidential, project: project, author: author) }
let(:message) { "#{author.name} opened issue #{issue.to_reference}" }
let(:message) { "#{author.name} #{author.to_reference} opened issue #{issue.to_reference}" }
before do
project.add_developer(author)
......
......@@ -242,6 +242,10 @@ describe('Deployment component', () => {
it('renders information about running deployment', () => {
expect(vm.$el.querySelector('.js-deployment-info').textContent).toContain('Deploying to');
});
it('renders disabled stop button', () => {
expect(vm.$el.querySelector('.js-stop-env').getAttribute('disabled')).toBe('disabled');
});
});
describe('success', () => {
......
......@@ -101,15 +101,24 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
context "redmine project" do
let(:project) { create(:redmine_project) }
let(:issue) { ExternalIssue.new("#123", project) }
let(:reference) { issue.to_reference }
before do
project.issues_enabled = false
project.save!
project.update!(issues_enabled: false)
end
context "with a hash prefix" do
let(:issue) { ExternalIssue.new("#123", project) }
let(:reference) { issue.to_reference }
it_behaves_like "external issue tracker"
end
it_behaves_like "external issue tracker"
context "with a single-letter prefix" do
let(:issue) { ExternalIssue.new("T-123", project) }
let(:reference) { issue.to_reference }
it_behaves_like "external issue tracker"
end
end
context "jira project" do
......@@ -122,6 +131,15 @@ describe Banzai::Filter::ExternalIssueReferenceFilter do
it_behaves_like "external issue tracker"
end
context "with a single-letter prefix" do
let(:issue) { ExternalIssue.new("J-123", project) }
it "ignores reference" do
exp = act = "Issue #{reference}"
expect(filter(act).to_html).to eq exp
end
end
context "with wrong markdown" do
let(:issue) { ExternalIssue.new("#123", project) }
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::BackgroundMigration::PopulateClusterKubernetesNamespaceTable, :migration, schema: 20181022173835 do
let(:migration) { described_class.new }
let(:clusters) { create_list(:cluster, 10, :project, :provided_by_gcp) }
before do
clusters
end
shared_examples 'consistent kubernetes namespace attributes' do
it 'should populate namespace and service account information' do
subject
clusters_with_namespace.each do |cluster|
project = cluster.project
cluster_project = cluster.cluster_projects.first
namespace = "#{project.path}-#{project.id}"
kubernetes_namespace = cluster.reload.kubernetes_namespace
expect(kubernetes_namespace).to be_present
expect(kubernetes_namespace.cluster_project).to eq(cluster_project)
expect(kubernetes_namespace.project).to eq(cluster_project.project)
expect(kubernetes_namespace.cluster).to eq(cluster_project.cluster)
expect(kubernetes_namespace.namespace).to eq(namespace)
expect(kubernetes_namespace.service_account_name).to eq("#{namespace}-service-account")
end
end
end
subject { migration.perform }
context 'when no Clusters::Project has a Clusters::KubernetesNamespace' do
let(:cluster_projects) { Clusters::Project.all }
it 'should create a Clusters::KubernetesNamespace per Clusters::Project' do
expect do
subject
end.to change(Clusters::KubernetesNamespace, :count).by(cluster_projects.count)
end
it_behaves_like 'consistent kubernetes namespace attributes' do
let(:clusters_with_namespace) { clusters }
end
end
context 'when every Clusters::Project has Clusters::KubernetesNamespace' do
before do
clusters.each do |cluster|
create(:cluster_kubernetes_namespace,
cluster_project: cluster.cluster_projects.first,
cluster: cluster,
project: cluster.project)
end
end
it 'should not create any Clusters::KubernetesNamespace' do
expect do
subject
end.not_to change(Clusters::KubernetesNamespace, :count)
end
end
context 'when only some Clusters::Project have Clusters::KubernetesNamespace related' do
let(:with_kubernetes_namespace) { clusters.first(6) }
let(:with_no_kubernetes_namespace) { clusters.last(4) }
before do
with_kubernetes_namespace.each do |cluster|
create(:cluster_kubernetes_namespace,
cluster_project: cluster.cluster_projects.first,
cluster: cluster,
project: cluster.project)
end
end
it 'creates limited number of Clusters::KubernetesNamespace' do
expect do
subject
end.to change(Clusters::KubernetesNamespace, :count).by(with_no_kubernetes_namespace.count)
end
it 'should not modify clusters with Clusters::KubernetesNamespace' do
subject
with_kubernetes_namespace.each do |cluster|
expect(cluster.kubernetes_namespaces.count).to eq(1)
end
end
it_behaves_like 'consistent kubernetes namespace attributes' do
let(:clusters_with_namespace) { with_no_kubernetes_namespace }
end
end
end
......@@ -476,6 +476,27 @@ describe Gitlab::Git::Repository, :seed_helper do
end
end
describe '#fetch_remote' do
it 'delegates to the gitaly RepositoryService' do
ssh_auth = double(:ssh_auth)
expected_opts = {
ssh_auth: ssh_auth,
forced: true,
no_tags: true,
timeout: described_class::GITLAB_PROJECTS_TIMEOUT,
prune: false
}
expect(repository.gitaly_repository_client).to receive(:fetch_remote).with('remote-name', expected_opts)
repository.fetch_remote('remote-name', ssh_auth: ssh_auth, forced: true, no_tags: true, prune: false)
end
it_behaves_like 'wrapping gRPC errors', Gitlab::GitalyClient::RepositoryService, :fetch_remote do
subject { repository.fetch_remote('remote-name') }
end
end
describe '#find_remote_root_ref' do
it 'gets the remote root ref from GitalyClient' do
expect_any_instance_of(Gitlab::GitalyClient::RemoteService)
......
require 'spec_helper'
describe Gitlab::GitalyClient::RepositoryService do
using RSpec::Parameterized::TableSyntax
let(:project) { create(:project) }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
......@@ -107,16 +109,67 @@ describe Gitlab::GitalyClient::RepositoryService do
end
describe '#fetch_remote' do
let(:ssh_auth) { double(:ssh_auth, ssh_import?: true, ssh_key_auth?: false, ssh_known_hosts: nil) }
let(:import_url) { 'ssh://example.com' }
let(:remote) { 'remote-name' }
it 'sends a fetch_remote_request message' do
expected_request = gitaly_request_with_params(
remote: remote,
ssh_key: '',
known_hosts: '',
force: false,
no_tags: false,
no_prune: false
)
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
.with(gitaly_request_with_params(no_prune: false), kind_of(Hash))
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
client.fetch_remote(import_url, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 60)
client.fetch_remote(remote, ssh_auth: nil, forced: false, no_tags: false, timeout: 1)
end
context 'SSH auth' do
where(:ssh_import, :ssh_key_auth, :ssh_private_key, :ssh_known_hosts, :expected_params) do
false | false | 'key' | 'known_hosts' | {}
false | true | 'key' | 'known_hosts' | {}
true | false | 'key' | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | 'key' | 'known_hosts' | { ssh_key: 'key', known_hosts: 'known_hosts' }
true | true | 'key' | nil | { ssh_key: 'key' }
true | true | nil | 'known_hosts' | { known_hosts: 'known_hosts' }
true | true | nil | nil | {}
true | true | '' | '' | {}
end
with_them do
let(:ssh_auth) do
double(
:ssh_auth,
ssh_import?: ssh_import,
ssh_key_auth?: ssh_key_auth,
ssh_private_key: ssh_private_key,
ssh_known_hosts: ssh_known_hosts
)
end
it do
expected_request = gitaly_request_with_params({
remote: remote,
ssh_key: '',
known_hosts: '',
force: false,
no_tags: false,
no_prune: false
}.update(expected_params))
expect_any_instance_of(Gitaly::RepositoryService::Stub)
.to receive(:fetch_remote)
.with(expected_request, kind_of(Hash))
.and_return(double(value: true))
client.fetch_remote(remote, ssh_auth: ssh_auth, forced: false, no_tags: false, timeout: 1)
end
end
end
end
......
......@@ -498,126 +498,6 @@ describe Gitlab::Shell do
end
end
describe '#fetch_remote' do
def fetch_remote(ssh_auth = nil, prune = true)
gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', ssh_auth: ssh_auth, prune: prune)
end
def expect_call(fail, options = {})
receive_fetch_remote =
if fail
receive(:fetch_remote).and_raise(GRPC::NotFound)
else
receive(:fetch_remote).and_return(true)
end
expect_any_instance_of(Gitlab::GitalyClient::RepositoryService).to receive_fetch_remote
end
def build_ssh_auth(opts = {})
defaults = {
ssh_import?: true,
ssh_key_auth?: false,
ssh_known_hosts: nil,
ssh_private_key: nil
}
double(:ssh_auth, defaults.merge(opts))
end
it 'returns true when the command succeeds' do
expect_call(false, force: false, tags: true, prune: true)
expect(fetch_remote).to be_truthy
end
it 'returns true when the command succeeds' do
expect_call(false, force: false, tags: true, prune: false)
expect(fetch_remote(nil, false)).to be_truthy
end
it 'raises an exception when the command fails' do
expect_call(true, force: false, tags: true, prune: true)
expect { fetch_remote }.to raise_error(Gitlab::Shell::Error)
end
it 'allows forced and no_tags to be changed' do
expect_call(false, force: true, tags: false, prune: true)
result = gitlab_shell.fetch_remote(repository.raw_repository, 'remote-name', forced: true, no_tags: true, prune: true)
expect(result).to be_truthy
end
context 'SSH auth' do
it 'passes the SSH key if specified' do
expect_call(false, force: false, tags: true, prune: true, ssh_key: 'foo')
ssh_auth = build_ssh_auth(ssh_key_auth?: true, ssh_private_key: 'foo')
expect(fetch_remote(ssh_auth)).to be_truthy
end
it 'does not pass an empty SSH key' do
expect_call(false, force: false, tags: true, prune: true)
ssh_auth = build_ssh_auth(ssh_key_auth: true, ssh_private_key: '')
expect(fetch_remote(ssh_auth)).to be_truthy
end
it 'does not pass the key unless SSH key auth is to be used' do
expect_call(false, force: false, tags: true, prune: true)
ssh_auth = build_ssh_auth(ssh_key_auth: false, ssh_private_key: 'foo')
expect(fetch_remote(ssh_auth)).to be_truthy
end
it 'passes the known_hosts data if specified' do
expect_call(false, force: false, tags: true, prune: true, known_hosts: 'foo')
ssh_auth = build_ssh_auth(ssh_known_hosts: 'foo')
expect(fetch_remote(ssh_auth)).to be_truthy
end
it 'does not pass empty known_hosts data' do
expect_call(false, force: false, tags: true, prune: true)
ssh_auth = build_ssh_auth(ssh_known_hosts: '')
expect(fetch_remote(ssh_auth)).to be_truthy
end
it 'does not pass known_hosts data unless SSH is to be used' do
expect_call(false, force: false, tags: true, prune: true)
ssh_auth = build_ssh_auth(ssh_import?: false, ssh_known_hosts: 'foo')
expect(fetch_remote(ssh_auth)).to be_truthy
end
end
context 'gitaly call' do
let(:remote_name) { 'remote-name' }
let(:ssh_auth) { double(:ssh_auth) }
subject do
gitlab_shell.fetch_remote(repository.raw_repository, remote_name,
forced: true, no_tags: true, ssh_auth: ssh_auth)
end
it 'passes the correct params to the gitaly service' do
expect(repository.gitaly_repository_client).to receive(:fetch_remote)
.with(remote_name, ssh_auth: ssh_auth, forced: true, no_tags: true, prune: true, timeout: timeout)
subject
end
end
end
describe '#import_repository' do
let(:import_url) { 'https://gitlab.com/gitlab-org/gitlab-ce.git' }
......
......@@ -34,7 +34,7 @@ shared_examples 'issues move service' do |group|
described_class.new(parent, user, params).execute(issue)
issue.reload
expect(issue.labels).to contain_exactly(bug)
expect(issue.labels).to contain_exactly(bug, regression)
expect(issue).to be_closed
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