Commit e037854a authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '42431-add-auto-devops-and-clusters-button-to-projects' into 'master'

Add a button on the project page to set up a Kubernetes cluster and enable  Auto DevOps

Closes #42431

See merge request gitlab-org/gitlab-ce!16900
parents 20aaed90 44d33db1
...@@ -444,6 +444,19 @@ ...@@ -444,6 +444,19 @@
} }
} }
.btn-missing {
color: $notes-light-color;
border: 1px dashed $border-gray-normal-dashed;
border-radius: $border-radius-default;
&:hover,
&:active,
&:focus {
color: $notes-light-color;
background-color: $white-normal;
}
}
.btn-svg svg { .btn-svg svg {
@include btn-svg; @include btn-svg;
} }
......
...@@ -63,10 +63,6 @@ ...@@ -63,10 +63,6 @@
} }
} }
.project-stats {
display: none;
}
.group-buttons { .group-buttons {
display: none; display: none;
} }
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
transition: padding $sidebar-transition-duration; transition: padding $sidebar-transition-duration;
.container-fluid { .container-fluid {
background: $white-light;
padding: 0 $gl-padding; padding: 0 $gl-padding;
&.container-blank { &.container-blank {
......
...@@ -296,7 +296,7 @@ body { ...@@ -296,7 +296,7 @@ body {
line-height: 1.3; line-height: 1.3;
font-size: 1.25em; font-size: 1.25em;
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
margin: 12px 7px; margin: 12px 0;
} }
h1, h1,
......
...@@ -215,8 +215,8 @@ $tooltip-font-size: 12px; ...@@ -215,8 +215,8 @@ $tooltip-font-size: 12px;
*/ */
$gl-padding: 16px; $gl-padding: 16px;
$gl-padding-8: 8px; $gl-padding-8: 8px;
$gl-padding-4: 4px;
$gl-col-padding: 15px; $gl-col-padding: 15px;
$gl-btn-padding: 10px;
$gl-input-padding: 10px; $gl-input-padding: 10px;
$gl-vert-padding: 6px; $gl-vert-padding: 6px;
$gl-padding-top: 10px; $gl-padding-top: 10px;
...@@ -377,6 +377,10 @@ $inactive-badge-background: rgba(0, 0, 0, .08); ...@@ -377,6 +377,10 @@ $inactive-badge-background: rgba(0, 0, 0, .08);
$btn-active-gray: #ececec; $btn-active-gray: #ececec;
$btn-active-gray-light: e4e7ed; $btn-active-gray-light: e4e7ed;
$btn-white-active: #848484; $btn-white-active: #848484;
$gl-btn-padding: 10px;
$gl-btn-line-height: 16px;
$gl-btn-vert-padding: 8px;
$gl-btn-horz-padding: 12px;
/* /*
* Badges * Badges
......
...@@ -678,6 +678,9 @@ a.deploy-project-label { ...@@ -678,6 +678,9 @@ a.deploy-project-label {
} }
} }
.project-empty-note-panel {
border-bottom: 1px solid $border-color;
}
.project-stats { .project-stats {
font-size: 0; font-size: 0;
...@@ -686,11 +689,13 @@ a.deploy-project-label { ...@@ -686,11 +689,13 @@ a.deploy-project-label {
border-bottom: 1px solid $border-color; border-bottom: 1px solid $border-color;
.nav { .nav {
padding-top: 12px; margin-top: $gl-padding-8;
padding-bottom: 12px; margin-bottom: $gl-padding-8;
> li { > li {
display: inline-block; display: inline-block;
margin-top: $gl-padding-4;
margin-bottom: $gl-padding-4;
&:not(:last-child) { &:not(:last-child) {
margin-right: $gl-padding; margin-right: $gl-padding;
...@@ -704,36 +709,32 @@ a.deploy-project-label { ...@@ -704,36 +709,32 @@ a.deploy-project-label {
float: right; float: right;
} }
} }
}
> a { .stat-text,
padding: 0; .stat-link {
padding: $gl-btn-vert-padding 0;
background-color: transparent; background-color: transparent;
font-size: 14px; font-size: $gl-font-size;
line-height: 29px; line-height: $gl-btn-line-height;
color: $notes-light-color; color: $notes-light-color;
}
.stat-link {
&:hover, &:hover,
&:focus { &:focus {
color: $gl-text-color; color: $gl-text-color;
text-decoration: underline; text-decoration: underline;
} }
} }
}
}
li.missing { .btn {
border: 1px dashed $border-gray-normal-dashed; padding: $gl-btn-vert-padding $gl-btn-horz-padding;
border-radius: $border-radius-default; line-height: $gl-btn-line-height;
a {
padding-left: 10px;
padding-right: 10px;
color: $notes-light-color;
display: block;
} }
&:hover { .btn-missing {
background-color: $gray-normal; @extend .btn-missing;
} }
} }
} }
...@@ -743,7 +744,7 @@ pre.light-well { ...@@ -743,7 +744,7 @@ pre.light-well {
} }
.git-empty { .git-empty {
margin: 0 7px 7px; margin-bottom: 7px;
h5 { h5 {
color: $gl-text-color; color: $gl-text-color;
......
...@@ -114,6 +114,8 @@ class ProjectsController < Projects::ApplicationController ...@@ -114,6 +114,8 @@ class ProjectsController < Projects::ApplicationController
respond_to do |format| respond_to do |format|
format.html do format.html do
@notification_setting = current_user.notification_settings_for(@project) if current_user @notification_setting = current_user.notification_settings_for(@project) if current_user
@project = @project.present(current_user: current_user)
render_landing_page render_landing_page
end end
......
...@@ -34,7 +34,7 @@ module ApplicationHelper ...@@ -34,7 +34,7 @@ module ApplicationHelper
def project_icon(project_id, options = {}) def project_icon(project_id, options = {})
project = project =
if project_id.is_a?(Project) if project_id.respond_to?(:avatar_url)
project_id project_id
else else
Project.find_by_full_path(project_id) Project.find_by_full_path(project_id)
......
...@@ -10,12 +10,6 @@ module BranchesHelper ...@@ -10,12 +10,6 @@ module BranchesHelper
project_branches_path(@project, @id, options) project_branches_path(@project, @id, options)
end end
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name)
::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch_name)
end
def project_branches def project_branches
options_for_select(@project.repository.branch_names, @project.default_branch) options_for_select(@project.repository.branch_names, @project.default_branch)
end end
......
...@@ -48,30 +48,4 @@ module PreferencesHelper ...@@ -48,30 +48,4 @@ module PreferencesHelper
def user_color_scheme def user_color_scheme
Gitlab::ColorSchemes.for_user(current_user).css_class Gitlab::ColorSchemes.for_user(current_user).css_class
end end
def default_project_view
return anonymous_project_view unless current_user
user_view = current_user.project_view
if can?(current_user, :download_code, @project)
user_view
elsif user_view == "activity"
"activity"
elsif can?(current_user, :read_wiki, @project)
"wiki"
elsif @project.feature_available?(:issues, current_user)
"projects/issues/issues"
else
"customize_workflow"
end
end
def anonymous_project_view
if !@project.empty_repo? && can?(current_user, :download_code, @project)
'files'
else
'activity'
end
end
end end
...@@ -153,11 +153,6 @@ module ProjectsHelper ...@@ -153,11 +153,6 @@ module ProjectsHelper
end end
end end
def license_short_name(project)
license = project.repository.license
license&.nickname || license&.name || 'LICENSE'
end
def last_push_event def last_push_event
current_user&.recent_push(@project) current_user&.recent_push(@project)
end end
...@@ -390,55 +385,6 @@ module ProjectsHelper ...@@ -390,55 +385,6 @@ module ProjectsHelper
end end
end end
def add_special_file_path(project, file_name:, commit_message: nil, branch_name: nil, context: nil)
commit_message ||= s_("CommitMessage|Add %{file_name}") % { file_name: file_name }
project_new_blob_path(
project,
project.default_branch || 'master',
file_name: file_name,
commit_message: commit_message,
branch_name: branch_name,
context: context
)
end
def add_koding_stack_path(project)
project_new_blob_path(
project,
project.default_branch || 'master',
file_name: '.koding.yml',
commit_message: "Add Koding stack script",
content: <<-CONTENT.strip_heredoc
provider:
aws:
access_key: '${var.aws_access_key}'
secret_key: '${var.aws_secret_key}'
resource:
aws_instance:
#{project.path}-vm:
instance_type: t2.nano
user_data: |-
# Created by GitLab UI for :>
echo _KD_NOTIFY_@Installing Base packages...@
apt-get update -y
apt-get install git -y
echo _KD_NOTIFY_@Cloning #{project.name}...@
export KODING_USER=${var.koding_user_username}
export REPO_URL=#{root_url}${var.koding_queryString_repo}.git
export BRANCH=${var.koding_queryString_branch}
sudo -i -u $KODING_USER git clone $REPO_URL -b $BRANCH
echo _KD_NOTIFY_@#{project.name} cloned.@
CONTENT
)
end
def koding_project_url(project = nil, branch = nil, sha = nil) def koding_project_url(project = nil, branch = nil, sha = nil)
if project if project
import_path = "/Home/Stacks/import" import_path = "/Home/Stacks/import"
...@@ -455,36 +401,6 @@ module ProjectsHelper ...@@ -455,36 +401,6 @@ module ProjectsHelper
Gitlab::CurrentSettings.koding_url Gitlab::CurrentSettings.koding_url
end end
def contribution_guide_path(project)
if project && contribution_guide = project.repository.contribution_guide
project_blob_path(
project,
tree_join(project.default_branch,
contribution_guide.name)
)
end
end
def readme_path(project)
filename_path(project, :readme)
end
def changelog_path(project)
filename_path(project, :changelog)
end
def license_path(project)
filename_path(project, :license_blob)
end
def version_path(project)
filename_path(project, :version)
end
def ci_configuration_path(project)
filename_path(project, :gitlab_ci_yml)
end
def project_wiki_path_with_version(proj, page, version, is_newest) def project_wiki_path_with_version(proj, page, version, is_newest)
url_params = is_newest ? {} : { version_id: version } url_params = is_newest ? {} : { version_id: version }
project_wiki_path(proj, page, url_params) project_wiki_path(proj, page, url_params)
...@@ -510,15 +426,6 @@ module ProjectsHelper ...@@ -510,15 +426,6 @@ module ProjectsHelper
@ref || @repository.try(:root_ref) @ref || @repository.try(:root_ref)
end end
def filename_path(project, filename)
if project && blob = project.repository.public_send(filename) # rubocop:disable GitlabSecurity/PublicSend
project_blob_path(
project,
tree_join(project.default_branch, blob.name)
)
end
end
def sanitize_repo_path(project, message) def sanitize_repo_path(project, message)
return '' unless message.present? return '' unless message.present?
......
...@@ -55,7 +55,9 @@ module TreeHelper ...@@ -55,7 +55,9 @@ module TreeHelper
def tree_edit_branch(project = @project, ref = @ref) def tree_edit_branch(project = @project, ref = @ref)
return unless can_edit_tree?(project, ref) return unless can_edit_tree?(project, ref)
if can_push_branch?(project, ref) project = project.present(current_user: current_user)
if project.can_current_user_push_to_branch?(ref)
ref ref
else else
project = tree_edit_project(project) project = tree_edit_project(project)
......
...@@ -15,6 +15,7 @@ class Project < ActiveRecord::Base ...@@ -15,6 +15,7 @@ class Project < ActiveRecord::Base
include ValidAttribute include ValidAttribute
include ProjectFeaturesCompatibility include ProjectFeaturesCompatibility
include SelectForProjectAuthorization include SelectForProjectAuthorization
include Presentable
include Routable include Routable
include GroupDescendant include GroupDescendant
include Gitlab::SQL::Pattern include Gitlab::SQL::Pattern
......
class ProjectPresenter < Gitlab::View::Presenter::Delegated
include ActionView::Helpers::NumberHelper
include ActionView::Helpers::UrlHelper
include GitlabRoutingHelper
include StorageHelper
include TreeHelper
include Gitlab::Utils::StrongMemoize
presents :project
def statistics_anchors(show_auto_devops_callout:)
[
files_anchor_data,
commits_anchor_data,
branches_anchor_data,
tags_anchor_data,
readme_anchor_data,
changelog_anchor_data,
license_anchor_data,
contribution_guide_anchor_data,
gitlab_ci_anchor_data,
autodevops_anchor_data(show_auto_devops_callout: show_auto_devops_callout),
kubernetes_cluster_anchor_data
].compact.select { |item| item.enabled }
end
def statistics_buttons(show_auto_devops_callout:)
[
changelog_anchor_data,
license_anchor_data,
contribution_guide_anchor_data,
autodevops_anchor_data(show_auto_devops_callout: show_auto_devops_callout),
kubernetes_cluster_anchor_data,
gitlab_ci_anchor_data,
koding_anchor_data
].compact.reject { |item| item.enabled }
end
def empty_repo_statistics_anchors
[
autodevops_anchor_data,
kubernetes_cluster_anchor_data
].compact.select { |item| item.enabled }
end
def empty_repo_statistics_buttons
[
new_file_anchor_data,
readme_anchor_data,
license_anchor_data,
autodevops_anchor_data,
kubernetes_cluster_anchor_data
].compact.reject { |item| item.enabled }
end
def default_view
return anonymous_project_view unless current_user
user_view = current_user.project_view
if can?(current_user, :download_code, project)
user_view
elsif user_view == "activity"
"activity"
elsif can?(current_user, :read_wiki, project)
"wiki"
elsif feature_available?(:issues, current_user)
"projects/issues/issues"
else
"customize_workflow"
end
end
def readme_path
filename_path(:readme)
end
def changelog_path
filename_path(:changelog)
end
def license_path
filename_path(:license_blob)
end
def ci_configuration_path
filename_path(:gitlab_ci_yml)
end
def contribution_guide_path
if project && contribution_guide = repository.contribution_guide
project_blob_path(
project,
tree_join(project.default_branch,
contribution_guide.name)
)
end
end
def add_license_path
add_special_file_path(file_name: 'LICENSE')
end
def add_changelog_path
add_special_file_path(file_name: 'CHANGELOG')
end
def add_contribution_guide_path
add_special_file_path(file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide')
end
def add_ci_yml_path
add_special_file_path(file_name: '.gitlab-ci.yml')
end
def add_readme_path
add_special_file_path(file_name: 'README.md')
end
def add_koding_stack_path
project_new_blob_path(
project,
default_branch || 'master',
file_name: '.koding.yml',
commit_message: "Add Koding stack script",
content: <<-CONTENT.strip_heredoc
provider:
aws:
access_key: '${var.aws_access_key}'
secret_key: '${var.aws_secret_key}'
resource:
aws_instance:
#{project.path}-vm:
instance_type: t2.nano
user_data: |-
# Created by GitLab UI for :>
echo _KD_NOTIFY_@Installing Base packages...@
apt-get update -y
apt-get install git -y
echo _KD_NOTIFY_@Cloning #{project.name}...@
export KODING_USER=${var.koding_user_username}
export REPO_URL=#{root_url}${var.koding_queryString_repo}.git
export BRANCH=${var.koding_queryString_branch}
sudo -i -u $KODING_USER git clone $REPO_URL -b $BRANCH
echo _KD_NOTIFY_@#{project.name} cloned.@
CONTENT
)
end
def license_short_name
license = repository.license
license&.nickname || license&.name || 'LICENSE'
end
def can_current_user_push_code?
strong_memoize(:can_current_user_push_code) do
if empty_repo?
can?(current_user, :push_code, project)
else
can_current_user_push_to_branch?(default_branch)
end
end
end
def can_current_user_push_to_branch?(branch)
return false unless repository.branch_exists?(branch)
::Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
end
def files_anchor_data
OpenStruct.new(enabled: true,
label: _('Files (%{human_size})') % { human_size: storage_counter(statistics.total_repository_size) },
link: project_tree_path(project))
end
def commits_anchor_data
OpenStruct.new(enabled: true,
label: n_('Commit (%{commit_count})', 'Commits (%{commit_count})', statistics.commit_count) % { commit_count: number_with_delimiter(statistics.commit_count) },
link: project_commits_path(project, repository.root_ref))
end
def branches_anchor_data
OpenStruct.new(enabled: true,
label: n_('Branch (%{branch_count})', 'Branches (%{branch_count})', repository.branch_count) % { branch_count: number_with_delimiter(repository.branch_count) },
link: project_branches_path(project))
end
def tags_anchor_data
OpenStruct.new(enabled: true,
label: n_('Tag (%{tag_count})', 'Tags (%{tag_count})', repository.tag_count) % { tag_count: number_with_delimiter(repository.tag_count) },
link: project_tags_path(project))
end
def new_file_anchor_data
if current_user && can_current_user_push_code?
OpenStruct.new(enabled: false,
label: _('New file'),
link: project_new_blob_path(project, default_branch || 'master'),
class_modifier: 'new')
end
end
def readme_anchor_data
if current_user && can_current_user_push_code? && repository.readme.blank?
OpenStruct.new(enabled: false,
label: _('Add Readme'),
link: add_readme_path)
elsif repository.readme.present?
OpenStruct.new(enabled: true,
label: _('Readme'),
link: default_view != 'readme' ? readme_path : '#readme')
end
end
def changelog_anchor_data
if current_user && can_current_user_push_code? && repository.changelog.blank?
OpenStruct.new(enabled: false,
label: _('Add Changelog'),
link: add_changelog_path)
elsif repository.changelog.present?
OpenStruct.new(enabled: true,
label: _('Changelog'),
link: changelog_path)
end
end
def license_anchor_data
if current_user && can_current_user_push_code? && repository.license_blob.blank?
OpenStruct.new(enabled: false,
label: _('Add License'),
link: add_license_path)
elsif repository.license_blob.present?
OpenStruct.new(enabled: true,
label: license_short_name,
link: license_path)
end
end
def contribution_guide_anchor_data
if current_user && can_current_user_push_code? && repository.contribution_guide.blank?
OpenStruct.new(enabled: false,
label: _('Add Contribution guide'),
link: add_contribution_guide_path)
elsif repository.contribution_guide.present?
OpenStruct.new(enabled: true,
label: _('Contribution guide'),
link: contribution_guide_path)
end
end
def autodevops_anchor_data(show_auto_devops_callout: false)
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
OpenStruct.new(enabled: auto_devops_enabled?,
label: auto_devops_enabled? ? _('Auto DevOps enabled') : _('Enable Auto DevOps'),
link: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
elsif auto_devops_enabled?
OpenStruct.new(enabled: true,
label: _('Auto DevOps enabled'),
link: nil)
end
end
def kubernetes_cluster_anchor_data
if current_user && can?(current_user, :create_cluster, project)
cluster_link = clusters.count == 1 ? project_cluster_path(project, clusters.first) : project_clusters_path(project)
if clusters.empty?
cluster_link = new_project_cluster_path(project)
end
OpenStruct.new(enabled: !clusters.empty?,
label: clusters.empty? ? _('Add Kubernetes cluster') : _('Kubernetes configured'),
link: cluster_link)
end
end
def gitlab_ci_anchor_data
if current_user && can_current_user_push_code? && repository.gitlab_ci_yml.blank? && !auto_devops_enabled?
OpenStruct.new(enabled: false,
label: _('Set up CI/CD'),
link: add_ci_yml_path)
elsif repository.gitlab_ci_yml.present?
OpenStruct.new(enabled: true,
label: _('CI/CD configuration'),
link: ci_configuration_path)
end
end
def koding_anchor_data
if current_user && can_current_user_push_code? && koding_enabled? && repository.koding_yml.blank?
OpenStruct.new(enabled: false,
label: _('Set up Koding'),
link: add_koding_stack_path)
end
end
private
def filename_path(filename)
if blob = repository.public_send(filename) # rubocop:disable GitlabSecurity/PublicSend
project_blob_path(
project,
tree_join(default_branch, blob.name)
)
end
end
def anonymous_project_view
if !project.empty_repo? && can?(current_user, :download_code, project)
'files'
else
'activity'
end
end
def add_special_file_path(file_name:, commit_message: nil, branch_name: nil)
commit_message ||= s_("CommitMessage|Add %{file_name}") % { file_name: file_name }
project_new_blob_path(
project,
project.default_branch || 'master',
file_name: file_name,
commit_message: commit_message,
branch_name: branch_name
)
end
def koding_enabled?
Gitlab::CurrentSettings.koding_enabled?
end
end
...@@ -20,4 +20,4 @@ ...@@ -20,4 +20,4 @@
distributed with computer software, forming part of its documentation. distributed with computer software, forming part of its documentation.
GitLab will render it here instead of this message. GitLab will render it here instead of this message.
%p %p
= link_to "Add Readme", add_special_file_path(@project, file_name: 'README.md'), class: 'btn btn-new' = link_to "Add Readme", @project.add_readme_path, class: 'btn btn-new'
- anchors = local_assigns.fetch(:anchors, [])
- return unless anchors.any?
%ul.nav
- anchors.each do |anchor|
%li
= link_to_if anchor.link, anchor.label, anchor.link, class: anchor.enabled ? 'stat-link' : "btn btn-#{anchor.class_modifier || 'missing'}" do
%span.stat-text= anchor.label
- if koding_enabled? && current_user && @repository.koding_yml && can_push_branch?(@project, @project.default_branch) - if koding_enabled? && current_user && @repository.koding_yml && @project.can_current_user_push_code?
= link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do = link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank', rel: 'noopener noreferrer' do
_('Run in IDE (Koding)') _('Run in IDE (Koding)')
...@@ -5,38 +5,41 @@ ...@@ -5,38 +5,41 @@
= render "home_panel" = render "home_panel"
.row-content-block.second-block.center .project-empty-note-panel
%div{ class: [container_class, ("limit-container-width-sm" unless fluid_layout)] }
.prepend-top-20
%h4 %h4
The repository for this project is empty = _('The repository for this project is empty')
- if can?(current_user, :push_code, @project) - if @project.can_current_user_push_code?
%p %p
If you already have files you can push them using command line instructions below. - link_to_cli = link_to _('command line instructions'), '#repo-command-line-instructions'
= _('If you already have files you can push them using the %{link_to_cli} below.').html_safe % { link_to_cli: link_to_cli }
%p %p
Otherwise you can start with adding a %em
= succeed ',' do - link_to_protected_branches = link_to _('Learn more about protected branches'), help_page_path('user/project/protected_branches')
= link_to "README", add_special_file_path(@project, file_name: 'README.md') = _('Note that the master branch is automatically protected. %{link_to_protected_branches}').html_safe % { link_to_protected_branches: link_to_protected_branches }
a
= succeed ',' do %hr
= link_to "LICENSE", add_special_file_path(@project, file_name: 'LICENSE')
or a
= link_to '.gitignore', add_special_file_path(@project, file_name: '.gitignore')
to this project.
%p %p
You will need to be owner or have the master permission level for the initial push, as the master branch is automatically protected. - link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'))
- link_to_add_kubernetes_cluster = link_to(s_('AutoDevOps|add a Kubernetes cluster'), new_project_cluster_path(@project))
= s_('AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}.').html_safe % { link_to_auto_devops_settings: link_to_auto_devops_settings, link_to_add_kubernetes_cluster: link_to_add_kubernetes_cluster }
- if show_auto_devops_callout?(@project) %hr
%p %p
- link = link_to(s_('AutoDevOps|Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings')) = _('Otherwise it is recommended you start with one of the options below.')
= s_('AutoDevOps|You can activate %{link_to_settings} for this project.').html_safe % { link_to_settings: link } .prepend-top-20
%p= s_('AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.')
%p= link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master'), class: 'btn btn-new' %nav.project-stats{ class: container_class }
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_anchors
= render 'stat_anchor_list', anchors: @project.empty_repo_statistics_buttons
- if can?(current_user, :push_code, @project) - if can?(current_user, :push_code, @project)
%div{ class: container_class } %div{ class: [container_class, ("limit-container-width-sm" unless fluid_layout)] }
.prepend-top-20 .prepend-top-20
.empty_wrapper .empty_wrapper
%h3.page-title-empty %h3#repo-command-line-instructions.page-title-empty
Command line instructions Command line instructions
.git-empty .git-empty
%fieldset %fieldset
......
- @no_container = true - @no_container = true
- breadcrumb_title "Details" - breadcrumb_title "Details"
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- show_auto_devops_callout = show_auto_devops_callout?(@project)
= content_for :meta_tags do = content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity") = auto_discovery_link_tag(:atom, project_path(@project, rss_url_options), title: "#{@project.name} activity")
...@@ -14,65 +15,9 @@ ...@@ -14,65 +15,9 @@
- if can?(current_user, :download_code, @project) - if can?(current_user, :download_code, @project)
%nav.project-stats{ class: container_class } %nav.project-stats{ class: container_class }
%ul.nav = render 'stat_anchor_list', anchors: @project.statistics_anchors(show_auto_devops_callout: show_auto_devops_callout)
%li = render 'stat_anchor_list', anchors: @project.statistics_buttons(show_auto_devops_callout: show_auto_devops_callout)
= link_to project_tree_path(@project) do
#{_('Files')} (#{storage_counter(@project.statistics.total_repository_size)})
%li
= link_to project_commits_path(@project, current_ref) do
#{n_('Commit', 'Commits', @project.statistics.commit_count)} (#{number_with_delimiter(@project.statistics.commit_count)})
%li
= link_to project_branches_path(@project) do
#{n_('Branch', 'Branches', @repository.branch_count)} (#{number_with_delimiter(@repository.branch_count)})
%li
= link_to project_tags_path(@project) do
#{n_('Tag', 'Tags', @repository.tag_count)} (#{number_with_delimiter(@repository.tag_count)})
- if @repository.readme
%li
= link_to _('Readme'),
default_project_view != 'readme' ? readme_path(@project) : '#readme'
- if @repository.changelog
%li
= link_to _('Changelog'), changelog_path(@project)
- if @repository.license_blob
%li
= link_to license_short_name(@project), license_path(@project)
- if @repository.contribution_guide
%li
= link_to _('Contribution guide'), contribution_guide_path(@project)
- if @repository.gitlab_ci_yml
%li
= link_to _('CI/CD configuration'), ci_configuration_path(@project)
- if current_user && can_push_branch?(@project, @project.default_branch)
- unless @repository.changelog
%li.missing
= link_to add_special_file_path(@project, file_name: 'CHANGELOG') do
#{ _('Add Changelog') }
- unless @repository.license_blob
%li.missing
= link_to add_special_file_path(@project, file_name: 'LICENSE') do
#{ _('Add License') }
- unless @repository.contribution_guide
%li.missing
= link_to add_special_file_path(@project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide') do
#{ _('Add Contribution guide') }
- unless @repository.gitlab_ci_yml
%li.missing
= link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
#{ _('Set up CI/CD') }
- if koding_enabled? && @repository.koding_yml.blank?
%li.missing
= link_to _('Set up Koding'), add_koding_stack_path(@project)
- if @repository.gitlab_ci_yml.blank? && @project.deployment_platform.present?
%li.missing
= link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up auto deploy', branch_name: 'auto-deploy', context: 'autodeploy') do
#{ _('Set up auto deploy') }
%div{ class: [container_class, ("limit-container-width" unless fluid_layout)] } %div{ class: [container_class, ("limit-container-width" unless fluid_layout)] }
- if @project.archived? - if @project.archived?
...@@ -81,7 +26,7 @@ ...@@ -81,7 +26,7 @@
= icon("exclamation-triangle fw") = icon("exclamation-triangle fw")
#{ _('Archived project! Repository is read-only') } #{ _('Archived project! Repository is read-only') }
- view_path = default_project_view - view_path = @project.default_view
- if show_auto_devops_callout?(@project) - if show_auto_devops_callout?(@project)
= render 'shared/auto_devops_callout' = render 'shared/auto_devops_callout'
......
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
- else - else
= form.submit 'Save changes', class: 'btn btn-save' = form.submit 'Save changes', class: 'btn btn-save'
- if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = contribution_guide_path(issuable.project)) - if !issuable.persisted? && !issuable.project.empty_repo? && (guide_url = issuable.project.present.contribution_guide_path)
.inline.prepend-top-10 .inline.prepend-top-10
Please review the Please review the
%strong= link_to('contribution guidelines', guide_url) %strong= link_to('contribution guidelines', guide_url)
......
---
title: Add a button on the project page to set up a Kubernetes cluster and enable
Auto DevOps
merge_request: 16900
author:
type: added
require 'spec_helper'
describe 'Auto deploy' do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
shared_examples 'same behavior between KubernetesService and Platform::Kubernetes' do
context 'when no deployment service is active' do
before do
trun_off
end
it 'does not show a button to set up auto deploy' do
visit project_path(project)
expect(page).to have_no_content('Set up auto deploy')
end
end
context 'when a deployment service is active' do
before do
trun_on
visit project_path(project)
end
it 'shows a button to set up auto deploy' do
expect(page).to have_link('Set up auto deploy')
end
it 'includes OpenShift as an available template', :js do
click_link 'Set up auto deploy'
click_button 'Apply a GitLab CI Yaml template'
within '.gitlab-ci-yml-selector' do
expect(page).to have_content('OpenShift')
end
end
it 'creates a merge request using "auto-deploy" branch', :js do
click_link 'Set up auto deploy'
click_button 'Apply a GitLab CI Yaml template'
within '.gitlab-ci-yml-selector' do
click_on 'OpenShift'
end
wait_for_requests
click_button 'Commit changes'
expect(page).to have_content('New Merge Request From auto-deploy into master')
end
end
end
context 'when user configured kubernetes from Integration > Kubernetes' do
before do
create :kubernetes_service, project: project
project.add_master(user)
sign_in user
end
let(:trun_on) { project.deployment_platform.update!(active: true) }
let(:trun_off) { project.deployment_platform.update!(active: false) }
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
context 'when user configured kubernetes from CI/CD > Clusters' do
before do
create(:cluster, :provided_by_gcp, projects: [project])
project.add_master(user)
sign_in user
end
let(:trun_on) { project.deployment_platform.cluster.update!(enabled: true) }
let(:trun_off) { project.deployment_platform.cluster.update!(enabled: false) }
it_behaves_like 'same behavior between KubernetesService and Platform::Kubernetes'
end
end
...@@ -11,7 +11,7 @@ feature 'project owner sees a link to create a license file in empty project', : ...@@ -11,7 +11,7 @@ feature 'project owner sees a link to create a license file in empty project', :
scenario 'project master creates a license file from a template' do scenario 'project master creates a license file from a template' do
visit project_path(project) visit project_path(project)
click_on 'LICENSE' click_on 'Add License'
expect(page).to have_content('New file') expect(page).to have_content('New file')
expect(current_path).to eq( expect(current_path).to eq(
......
...@@ -17,4 +17,321 @@ describe 'Project show page', :feature do ...@@ -17,4 +17,321 @@ describe 'Project show page', :feature do
expect(page).to have_content("This project was scheduled for deletion, but failed with the following message: #{project.delete_error}") expect(page).to have_content("This project was scheduled for deletion, but failed with the following message: #{project.delete_error}")
end end
end end
describe 'stat button existence' do
# For "New file", "Add License" functionality,
# see spec/features/projects/files/project_owner_creates_license_file_spec.rb
# see spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb
let(:user) { create(:user) }
describe 'empty project' do
let(:project) { create(:project, :public, :empty_repo) }
let(:presenter) { project.present(current_user: user) }
describe 'as a normal user' do
before do
sign_in(user)
visit project_path(project)
end
it 'no Auto DevOps button if can not manage pipelines' do
page.within('.project-stats') do
expect(page).not_to have_link('Enable Auto DevOps')
expect(page).not_to have_link('Auto DevOps enabled')
end
end
it '"Auto DevOps enabled" button not linked' do
project.create_auto_devops!(enabled: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_text('Auto DevOps enabled')
end
end
end
describe 'as a master' do
before do
project.add_master(user)
sign_in(user)
visit project_path(project)
end
it '"New file" button linked to new file page' do
page.within('.project-stats') do
expect(page).to have_link('New file', href: project_new_blob_path(project, project.default_branch || 'master'))
end
end
it '"Add Readme" button linked to new file populated for a readme' do
page.within('.project-stats') do
expect(page).to have_link('Add Readme', href: presenter.add_readme_path)
end
end
it '"Add License" button linked to new file populated for a license' do
page.within('.project-stats') do
expect(page).to have_link('Add License', href: presenter.add_license_path)
end
end
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
end
end
it '"Auto DevOps enabled" anchor linked to settings page' do
project.create_auto_devops!(enabled: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
end
end
end
describe 'Kubernetes cluster button' do
it '"Add Kubernetes cluster" button linked to clusters page' do
page.within('.project-stats') do
expect(page).to have_link('Add Kubernetes cluster', href: new_project_cluster_path(project))
end
end
it '"Kubernetes cluster" anchor linked to cluster page' do
cluster = create(:cluster, :provided_by_gcp, projects: [project])
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Kubernetes configured', href: project_cluster_path(project, cluster))
end
end
end
end
end
describe 'populated project' do
let(:project) { create(:project, :public, :repository) }
let(:presenter) { project.present(current_user: user) }
describe 'as a normal user' do
before do
sign_in(user)
visit project_path(project)
end
it 'no Auto DevOps button if can not manage pipelines' do
page.within('.project-stats') do
expect(page).not_to have_link('Enable Auto DevOps')
expect(page).not_to have_link('Auto DevOps enabled')
end
end
it '"Auto DevOps enabled" button not linked' do
project.create_auto_devops!(enabled: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_text('Auto DevOps enabled')
end
end
it 'no Kubernetes cluster button if can not manage clusters' do
page.within('.project-stats') do
expect(page).not_to have_link('Add Kubernetes cluster')
expect(page).not_to have_link('Kubernetes configured')
end
end
end
describe 'as a master' do
before do
allow_any_instance_of(AutoDevopsHelper).to receive(:show_auto_devops_callout?).and_return(false)
project.add_master(user)
sign_in(user)
visit project_path(project)
end
it 'no "Add Changelog" button if the project already has a changelog' do
expect(project.repository.changelog).not_to be_nil
page.within('.project-stats') do
expect(page).not_to have_link('Add Changelog')
end
end
it 'no "Add License" button if the project already has a license' do
expect(project.repository.license_blob).not_to be_nil
page.within('.project-stats') do
expect(page).not_to have_link('Add License')
end
end
it 'no "Add Contribution guide" button if the project already has a contribution guide' do
expect(project.repository.contribution_guide).not_to be_nil
page.within('.project-stats') do
expect(page).not_to have_link('Add Contribution guide')
end
end
describe 'GitLab CI configuration button' do
it '"Set up CI/CD" button linked to new file populated for a .gitlab-ci.yml' do
expect(project.repository.gitlab_ci_yml).to be_nil
page.within('.project-stats') do
expect(page).to have_link('Set up CI/CD', href: presenter.add_ci_yml_path)
end
end
it 'no "Set up CI/CD" button if the project already has a .gitlab-ci.yml' do
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab-ci.yml",
file_path: '.gitlab-ci.yml',
file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
).execute
expect(project.repository.gitlab_ci_yml).not_to be_nil
visit project_path(project)
page.within('.project-stats') do
expect(page).not_to have_link('Set up CI/CD')
end
end
it 'no "Set up CI/CD" button if the project has Auto DevOps enabled' do
project.create_auto_devops!(enabled: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).not_to have_link('Set up CI/CD')
end
end
end
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
end
end
it '"Enable Auto DevOps" button linked to settings page' do
project.create_auto_devops!(enabled: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
end
end
it 'no Auto DevOps button if Auto DevOps callout is shown' do
allow_any_instance_of(AutoDevopsHelper).to receive(:show_auto_devops_callout?).and_return(true)
visit project_path(project)
expect(page).to have_selector('.js-autodevops-banner')
page.within('.project-stats') do
expect(page).not_to have_link('Enable Auto DevOps')
expect(page).not_to have_link('Auto DevOps enabled')
end
end
it 'no "Enable Auto DevOps" button when .gitlab-ci.yml already exists' do
Files::CreateService.new(
project,
project.creator,
start_branch: 'master',
branch_name: 'master',
commit_message: "Add .gitlab-ci.yml",
file_path: '.gitlab-ci.yml',
file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml'))
).execute
expect(project.repository.gitlab_ci_yml).not_to be_nil
visit project_path(project)
page.within('.project-stats') do
expect(page).not_to have_link('Enable Auto DevOps')
expect(page).not_to have_link('Auto DevOps enabled')
end
end
end
describe 'Kubernetes cluster button' do
it '"Add Kubernetes cluster" button linked to clusters page' do
page.within('.project-stats') do
expect(page).to have_link('Add Kubernetes cluster', href: new_project_cluster_path(project))
end
end
it '"Kubernetes cluster" button linked to cluster page' do
cluster = create(:cluster, :provided_by_gcp, projects: [project])
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Kubernetes configured', href: project_cluster_path(project, cluster))
end
end
end
describe '"Set up Koding" button' do
it 'no "Set up Koding" button if Koding disabled' do
stub_application_setting(koding_enabled?: false)
visit project_path(project)
page.within('.project-stats') do
expect(page).not_to have_link('Set up Koding')
end
end
it 'no "Set up Koding" button if the project already has a .koding.yml' do
stub_application_setting(koding_enabled?: true)
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:koding_url).and_return('http://koding.example.com')
expect(project.repository.changelog).not_to be_nil
allow_any_instance_of(Repository).to receive(:koding_yml).and_return(project.repository.changelog)
visit project_path(project)
page.within('.project-stats') do
expect(page).not_to have_link('Set up Koding')
end
end
it '"Set up Koding" button linked to new file populated for a .koding.yml' do
stub_application_setting(koding_enabled?: true)
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Set up Koding', href: presenter.add_koding_stack_path)
end
end
end
end
end
end
end end
...@@ -13,7 +13,7 @@ feature 'Master views tags' do ...@@ -13,7 +13,7 @@ feature 'Master views tags' do
before do before do
visit project_path(project) visit project_path(project)
click_on 'README' click_on 'Add Readme'
fill_in :commit_message, with: 'Add a README file', visible: true fill_in :commit_message, with: 'Add a README file', visible: true
click_button 'Commit changes' click_button 'Commit changes'
visit project_tags_path(project) visit project_tags_path(project)
......
...@@ -77,103 +77,6 @@ describe PreferencesHelper do ...@@ -77,103 +77,6 @@ describe PreferencesHelper do
end end
end end
describe '#default_project_view' do
context 'user not signed in' do
before do
helper.instance_variable_set(:@project, project)
stub_user
end
context 'when repository is empty' do
let(:project) { create(:project_empty_repo, :public) }
it 'returns activity if user has repository access' do
allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(true)
expect(helper.default_project_view).to eq('activity')
end
it 'returns activity if user does not have repository access' do
allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(false)
expect(helper.default_project_view).to eq('activity')
end
end
context 'when repository is not empty' do
let(:project) { create(:project, :public, :repository) }
it 'returns files and readme if user has repository access' do
allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(true)
expect(helper.default_project_view).to eq('files')
end
it 'returns activity if user does not have repository access' do
allow(helper).to receive(:can?).with(nil, :download_code, project).and_return(false)
expect(helper.default_project_view).to eq('activity')
end
end
end
context 'user signed in' do
let(:user) { create(:user, :readme) }
let(:project) { create(:project, :public, :repository) }
before do
helper.instance_variable_set(:@project, project)
allow(helper).to receive(:current_user).and_return(user)
end
context 'when the user is allowed to see the code' do
it 'returns the project view' do
allow(helper).to receive(:can?).with(user, :download_code, project).and_return(true)
expect(helper.default_project_view).to eq('readme')
end
end
context 'with wikis enabled and the right policy for the user' do
before do
project.project_feature.update_attribute(:issues_access_level, 0)
allow(helper).to receive(:can?).with(user, :download_code, project).and_return(false)
end
it 'returns wiki if the user has the right policy' do
allow(helper).to receive(:can?).with(user, :read_wiki, project).and_return(true)
expect(helper.default_project_view).to eq('wiki')
end
it 'returns customize_workflow if the user does not have the right policy' do
allow(helper).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(helper.default_project_view).to eq('customize_workflow')
end
end
context 'with issues as a feature available' do
it 'return issues' do
allow(helper).to receive(:can?).with(user, :download_code, project).and_return(false)
allow(helper).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(helper.default_project_view).to eq('projects/issues/issues')
end
end
context 'with no activity, no wikies and no issues' do
it 'returns customize_workflow as default' do
project.project_feature.update_attribute(:issues_access_level, 0)
allow(helper).to receive(:can?).with(user, :download_code, project).and_return(false)
allow(helper).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(helper.default_project_view).to eq('customize_workflow')
end
end
end
end
def stub_user(messages = {}) def stub_user(messages = {})
if messages.empty? if messages.empty?
allow(helper).to receive(:current_user).and_return(nil) allow(helper).to receive(:current_user).and_return(nil)
......
...@@ -264,32 +264,6 @@ describe ProjectsHelper do ...@@ -264,32 +264,6 @@ describe ProjectsHelper do
end end
end end
describe '#license_short_name' do
let(:project) { create(:project) }
context 'when project.repository has a license_key' do
it 'returns the nickname of the license if present' do
allow(project.repository).to receive(:license_key).and_return('agpl-3.0')
expect(helper.license_short_name(project)).to eq('GNU AGPLv3')
end
it 'returns the name of the license if nickname is not present' do
allow(project.repository).to receive(:license_key).and_return('mit')
expect(helper.license_short_name(project)).to eq('MIT License')
end
end
context 'when project.repository has no license_key but a license_blob' do
it 'returns LICENSE' do
allow(project.repository).to receive(:license_key).and_return(nil)
expect(helper.license_short_name(project)).to eq('LICENSE')
end
end
end
describe '#sanitized_import_error' do describe '#sanitized_import_error' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
......
require 'spec_helper'
describe ProjectPresenter do
let(:user) { create(:user) }
describe '#license_short_name' do
let(:project) { create(:project) }
let(:presenter) { described_class.new(project, current_user: user) }
context 'when project.repository has a license_key' do
it 'returns the nickname of the license if present' do
allow(project.repository).to receive(:license_key).and_return('agpl-3.0')
expect(presenter.license_short_name).to eq('GNU AGPLv3')
end
it 'returns the name of the license if nickname is not present' do
allow(project.repository).to receive(:license_key).and_return('mit')
expect(presenter.license_short_name).to eq('MIT License')
end
end
context 'when project.repository has no license_key but a license_blob' do
it 'returns LICENSE' do
allow(project.repository).to receive(:license_key).and_return(nil)
expect(presenter.license_short_name).to eq('LICENSE')
end
end
end
describe '#default_view' do
let(:presenter) { described_class.new(project, current_user: user) }
context 'user not signed in' do
let(:user) { nil }
context 'when repository is empty' do
let(:project) { create(:project_empty_repo, :public) }
it 'returns activity if user has repository access' do
allow(presenter).to receive(:can?).with(nil, :download_code, project).and_return(true)
expect(presenter.default_view).to eq('activity')
end
it 'returns activity if user does not have repository access' do
allow(project).to receive(:can?).with(nil, :download_code, project).and_return(false)
expect(presenter.default_view).to eq('activity')
end
end
context 'when repository is not empty' do
let(:project) { create(:project, :public, :repository) }
it 'returns files and readme if user has repository access' do
allow(presenter).to receive(:can?).with(nil, :download_code, project).and_return(true)
expect(presenter.default_view).to eq('files')
end
it 'returns activity if user does not have repository access' do
allow(presenter).to receive(:can?).with(nil, :download_code, project).and_return(false)
expect(presenter.default_view).to eq('activity')
end
end
end
context 'user signed in' do
let(:user) { create(:user, :readme) }
let(:project) { create(:project, :public, :repository) }
context 'when the user is allowed to see the code' do
it 'returns the project view' do
allow(presenter).to receive(:can?).with(user, :download_code, project).and_return(true)
expect(presenter.default_view).to eq('readme')
end
end
context 'with wikis enabled and the right policy for the user' do
before do
project.project_feature.update_attribute(:issues_access_level, 0)
allow(presenter).to receive(:can?).with(user, :download_code, project).and_return(false)
end
it 'returns wiki if the user has the right policy' do
allow(presenter).to receive(:can?).with(user, :read_wiki, project).and_return(true)
expect(presenter.default_view).to eq('wiki')
end
it 'returns customize_workflow if the user does not have the right policy' do
allow(presenter).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(presenter.default_view).to eq('customize_workflow')
end
end
context 'with issues as a feature available' do
it 'return issues' do
allow(presenter).to receive(:can?).with(user, :download_code, project).and_return(false)
allow(presenter).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(presenter.default_view).to eq('projects/issues/issues')
end
end
context 'with no activity, no wikies and no issues' do
it 'returns customize_workflow as default' do
project.project_feature.update_attribute(:issues_access_level, 0)
allow(presenter).to receive(:can?).with(user, :download_code, project).and_return(false)
allow(presenter).to receive(:can?).with(user, :read_wiki, project).and_return(false)
expect(presenter.default_view).to eq('customize_workflow')
end
end
end
end
describe '#can_current_user_push_code?' do
let(:project) { create(:project, :repository) }
let(:presenter) { described_class.new(project, current_user: user) }
context 'empty repo' do
let(:project) { create(:project) }
it 'returns true if user can push_code' do
project.add_developer(user)
expect(presenter.can_current_user_push_code?).to be(true)
end
it 'returns false if user cannot push_code' do
project.add_reporter(user)
expect(presenter.can_current_user_push_code?).to be(false)
end
end
context 'not empty repo' do
let(:project) { create(:project, :repository) }
it 'returns true if user can push to default branch' do
project.add_developer(user)
expect(presenter.can_current_user_push_code?).to be(true)
end
it 'returns false if default branch is protected' do
project.add_developer(user)
create(:protected_branch, project: project, name: project.default_branch)
expect(presenter.can_current_user_push_code?).to be(false)
end
end
end
context 'statistics anchors' do
let(:project) { create(:project, :repository) }
let(:presenter) { described_class.new(project, current_user: user) }
describe '#files_anchor_data' do
it 'returns files data' do
expect(presenter.files_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Files (0 Bytes)',
link: presenter.project_tree_path(project)))
end
end
describe '#commits_anchor_data' do
it 'returns commits data' do
expect(presenter.commits_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Commits (0)',
link: presenter.project_commits_path(project, project.repository.root_ref)))
end
end
describe '#branches_anchor_data' do
it 'returns branches data' do
expect(presenter.branches_anchor_data).to eq(OpenStruct.new(enabled: true,
label: "Branches (#{project.repository.branches.size})",
link: presenter.project_branches_path(project)))
end
end
describe '#tags_anchor_data' do
it 'returns tags data' do
expect(presenter.tags_anchor_data).to eq(OpenStruct.new(enabled: true,
label: "Tags (#{project.repository.tags.size})",
link: presenter.project_tags_path(project)))
end
end
describe '#new_file_anchor_data' do
it 'returns new file data if user can push' do
project.add_developer(user)
expect(presenter.new_file_anchor_data).to eq(OpenStruct.new(enabled: false,
label: "New file",
link: presenter.project_new_blob_path(project, 'master'),
class_modifier: 'new'))
end
it 'returns nil if user cannot push' do
expect(presenter.new_file_anchor_data).to be_nil
end
end
describe '#readme_anchor_data' do
context 'when user can push and README does not exists' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:readme).and_return(nil)
expect(presenter.readme_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Add Readme',
link: presenter.add_readme_path))
end
end
context 'when README exists' do
it 'returns anchor data' do
allow(project.repository).to receive(:readme).and_return(double(name: 'readme'))
expect(presenter.readme_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Readme',
link: presenter.readme_path))
end
end
end
describe '#changelog_anchor_data' do
context 'when user can push and CHANGELOG does not exists' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:changelog).and_return(nil)
expect(presenter.changelog_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Add Changelog',
link: presenter.add_changelog_path))
end
end
context 'when CHANGELOG exists' do
it 'returns anchor data' do
allow(project.repository).to receive(:changelog).and_return(double(name: 'foo'))
expect(presenter.changelog_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Changelog',
link: presenter.changelog_path))
end
end
end
describe '#license_anchor_data' do
context 'when user can push and LICENSE does not exists' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:license_blob).and_return(nil)
expect(presenter.license_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Add License',
link: presenter.add_license_path))
end
end
context 'when LICENSE exists' do
it 'returns anchor data' do
allow(project.repository).to receive(:license_blob).and_return(double(name: 'foo'))
expect(presenter.license_anchor_data).to eq(OpenStruct.new(enabled: true,
label: presenter.license_short_name,
link: presenter.license_path))
end
end
end
describe '#contribution_guide_anchor_data' do
context 'when user can push and CONTRIBUTING does not exists' do
it 'returns anchor data' do
project.add_developer(user)
allow(project.repository).to receive(:contribution_guide).and_return(nil)
expect(presenter.contribution_guide_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Add Contribution guide',
link: presenter.add_contribution_guide_path))
end
end
context 'when CONTRIBUTING exists' do
it 'returns anchor data' do
allow(project.repository).to receive(:contribution_guide).and_return(double(name: 'foo'))
expect(presenter.contribution_guide_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Contribution guide',
link: presenter.contribution_guide_path))
end
end
end
describe '#autodevops_anchor_data' do
context 'when Auto Devops is enabled' do
it 'returns anchor data' do
allow(project).to receive(:auto_devops_enabled?).and_return(true)
expect(presenter.autodevops_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Auto DevOps enabled',
link: nil))
end
end
context 'when user can admin pipeline and CI yml does not exists' do
it 'returns anchor data' do
project.add_master(user)
allow(project).to receive(:auto_devops_enabled?).and_return(false)
allow(project.repository).to receive(:gitlab_ci_yml).and_return(nil)
expect(presenter.autodevops_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Enable Auto DevOps',
link: presenter.project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings')))
end
end
end
describe '#kubernetes_cluster_anchor_data' do
context 'when user can create Kubernetes cluster' do
it 'returns link to cluster if only one exists' do
project.add_master(user)
cluster = create(:cluster, projects: [project])
expect(presenter.kubernetes_cluster_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Kubernetes configured',
link: presenter.project_cluster_path(project, cluster)))
end
it 'returns link to clusters page if more than one exists' do
project.add_master(user)
create(:cluster, projects: [project])
create(:cluster, projects: [project])
expect(presenter.kubernetes_cluster_anchor_data).to eq(OpenStruct.new(enabled: true,
label: 'Kubernetes configured',
link: presenter.project_clusters_path(project)))
end
it 'returns link to create a cluster if no cluster exists' do
project.add_master(user)
expect(presenter.kubernetes_cluster_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Add Kubernetes cluster',
link: presenter.new_project_cluster_path(project)))
end
end
context 'when user cannot create Kubernetes cluster' do
it 'returns nil' do
expect(presenter.kubernetes_cluster_anchor_data).to be_nil
end
end
end
describe '#koding_anchor_data' do
it 'returns link to setup Koding if user can push and no koding YML exists' do
project.add_developer(user)
allow(project.repository).to receive(:koding_yml).and_return(nil)
allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
expect(presenter.koding_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Set up Koding',
link: presenter.add_koding_stack_path))
end
it 'returns nil if user cannot push' do
expect(presenter.koding_anchor_data).to be_nil
end
it 'returns nil if koding is not enabled' do
project.add_developer(user)
allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(false)
expect(presenter.koding_anchor_data).to be_nil
end
it 'returns nil if koding YML already exists' do
project.add_developer(user)
allow(project.repository).to receive(:koding_yml).and_return(double)
allow(Gitlab::CurrentSettings).to receive(:koding_enabled?).and_return(true)
expect(presenter.koding_anchor_data).to be_nil
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment