Read about our upcoming Code of Conduct on this issue

Commit 95f0a03b authored by Eric Eastwood's avatar Eric Eastwood
Browse files

Add Auto DevOps and Kubernetes cluster button to project page

parent 19ba12e4d00b
......@@ -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 {
@include btn-svg;
}
......
......@@ -63,10 +63,6 @@
}
}
.project-stats {
display: none;
}
.group-buttons {
display: none;
}
......
......@@ -3,7 +3,6 @@
transition: padding $sidebar-transition-duration;
.container-fluid {
background: $white-light;
padding: 0 $gl-padding;
&.container-blank {
......
......@@ -296,7 +296,7 @@ body {
line-height: 1.3;
font-size: 1.25em;
font-weight: $gl-font-weight-bold;
margin: 12px 7px;
margin: 12px 0;
}
h1,
......
......@@ -215,8 +215,8 @@ $tooltip-font-size: 12px;
*/
$gl-padding: 16px;
$gl-padding-8: 8px;
$gl-padding-4: 4px;
$gl-col-padding: 15px;
$gl-btn-padding: 10px;
$gl-input-padding: 10px;
$gl-vert-padding: 6px;
$gl-padding-top: 10px;
......@@ -377,6 +377,10 @@ $inactive-badge-background: rgba(0, 0, 0, .08);
$btn-active-gray: #ececec;
$btn-active-gray-light: e4e7ed;
$btn-white-active: #848484;
$gl-btn-padding: 10px;
$gl-btn-line-height: 16px;
$gl-btn-vert-padding: 8px;
$gl-btn-horz-padding: 12px;
/*
* Badges
......
......@@ -678,6 +678,9 @@ a.deploy-project-label {
}
}
.project-empty-note-panel {
border-bottom: 1px solid $border-color;
}
.project-stats {
font-size: 0;
......@@ -686,11 +689,13 @@ a.deploy-project-label {
border-bottom: 1px solid $border-color;
.nav {
padding-top: 12px;
padding-bottom: 12px;
margin-top: $gl-padding-8;
margin-bottom: $gl-padding-8;
> li {
display: inline-block;
margin-top: $gl-padding-4;
margin-bottom: $gl-padding-4;
&:not(:last-child) {
margin-right: $gl-padding;
......@@ -704,36 +709,32 @@ a.deploy-project-label {
float: right;
}
}
}
> a {
padding: 0;
background-color: transparent;
font-size: 14px;
line-height: 29px;
color: $notes-light-color;
.stat-text,
.stat-link {
padding: $gl-btn-vert-padding 0;
background-color: transparent;
font-size: $gl-font-size;
line-height: $gl-btn-line-height;
color: $notes-light-color;
}
&:hover,
&:focus {
color: $gl-text-color;
text-decoration: underline;
}
.stat-link {
&:hover,
&:focus {
color: $gl-text-color;
text-decoration: underline;
}
}
}
li.missing {
border: 1px dashed $border-gray-normal-dashed;
border-radius: $border-radius-default;
a {
padding-left: 10px;
padding-right: 10px;
color: $notes-light-color;
display: block;
.btn {
padding: $gl-btn-vert-padding $gl-btn-horz-padding;
line-height: $gl-btn-line-height;
}
&:hover {
background-color: $gray-normal;
.btn-missing {
@extend .btn-missing;
}
}
}
......@@ -743,7 +744,7 @@ pre.light-well {
}
.git-empty {
margin: 0 7px 7px;
margin-bottom: 7px;
h5 {
color: $gl-text-color;
......
......@@ -604,4 +604,218 @@ def find_file_path
project_find_file_path(@project, ref)
end
def can_current_user_push_code?(project)
project.empty_repo? ? can?(current_user, :push_code, project) : can_push_branch?(project, project.default_branch)
end
def files_anchor_data(project)
{
enabled: true,
label: _('Files (%{human_size})') % { human_size: storage_counter(@project.statistics.total_repository_size) },
link: project_tree_path(@project)
}
end
def commits_anchor_data(project)
{
enabled: true,
label: n_('Commit (%{commit_count})', 'Commits (%{commit_count})', @project.statistics.commit_count) % { commit_count: number_with_delimiter(@project.statistics.commit_count) },
link: project_commits_path(@project, current_ref)
}
end
def branches_anchor_data(project)
{
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(project)
{
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(project)
if current_user && can_current_user_push_code?(project)
{
enabled: false,
label: _('New file'),
link: project_new_blob_path(project, project.default_branch || 'master'),
class_modifier: 'new'
}
end
end
def readme_anchor_data(project)
if current_user && can_current_user_push_code?(project) && project.repository.readme.blank?
{
enabled: false,
label: _('Add Readme'),
link: add_special_file_path(project, file_name: 'README.md')
}
elsif project.repository.readme.present?
{
enabled: true,
label: _('Readme'),
link: default_project_view != 'readme' ? readme_path(@project) : '#readme'
}
end
end
def changelog_anchor_data(project)
if current_user && can_current_user_push_code?(project) && project.repository.changelog.blank?
{
enabled: false,
label: _('Add Changelog'),
link: add_special_file_path(project, file_name: 'CHANGELOG')
}
elsif project.repository.changelog.present?
{
enabled: true,
label: _('Changelog'),
link: changelog_path(project)
}
end
end
def license_anchor_data(project)
if current_user && can_current_user_push_code?(project) && project.repository.license_blob.blank?
{
enabled: false,
label: _('Add License'),
link: add_special_file_path(project, file_name: 'LICENSE')
}
elsif project.repository.license_blob.present?
{
enabled: true,
label: license_short_name(project),
link: license_path(project)
}
end
end
def contribution_guide_anchor_data(project)
if current_user && can_current_user_push_code?(project) && project.repository.contribution_guide.blank?
{
enabled: false,
label: _('Add Contribution guide'),
link: add_special_file_path(project, file_name: 'CONTRIBUTING.md', commit_message: 'Add contribution guide')
}
elsif project.repository.contribution_guide.present?
{
enabled: true,
label: _('Contribution guide'),
link: contribution_guide_path(@project)
}
end
end
def autodevops_anchor_data(project, ignore_callout: false)
if current_user && can?(current_user, :admin_pipeline, project) && project.repository.gitlab_ci_yml.blank? && (ignore_callout || !show_auto_devops_callout?(project))
{
enabled: project.auto_devops_enabled?,
label: project.auto_devops_enabled? ? _('Auto DevOps enabled') : _('Enable Auto DevOps'),
link: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings')
}
elsif project.auto_devops_enabled?
{
enabled: true,
label: _('Auto DevOps enabled'),
link: nil
}
end
end
def kubernetes_cluster_anchor_data(project)
if current_user && can?(current_user, :create_cluster, project)
cluster_link = project.clusters.size == 1 ? project_cluster_path(project, project.clusters.first) : project_clusters_path(project)
if project.clusters.empty?
cluster_link = new_project_cluster_path(project)
end
{
enabled: !project.clusters.empty?,
label: project.clusters.empty? ? _('Add Kubernetes cluster') : n_('Kubernetes cluster', 'Kubernetes clusters', project.clusters.size),
link: cluster_link
}
end
end
def gitlab_ci_anchor_data(project)
if current_user && can_current_user_push_code?(project) && project.repository.gitlab_ci_yml.blank? && !project.auto_devops_enabled?
{
enabled: false,
label: _('Set up CI/CD'),
link: add_special_file_path(project, file_name: '.gitlab-ci.yml')
}
elsif project.repository.gitlab_ci_yml.present?
{
enabled: true,
label: _('CI/CD configuration'),
link: ci_configuration_path(@project)
}
end
end
def koding_anchor_data(project)
if current_user && can_current_user_push_code?(project) && koding_enabled? && project.repository.koding_yml.blank?
{
enabled: false,
label: _('Set up Koding'),
link: add_koding_stack_path(project)
}
end
end
def empty_project_stat_anchor_items(project)
[
autodevops_anchor_data(project, ignore_callout: true),
kubernetes_cluster_anchor_data(project)
].compact.reject { |i| !i[:enabled] }
end
def empty_project_stat_button_items(project)
[
new_file_anchor_data(project),
readme_anchor_data(project),
license_anchor_data(project),
autodevops_anchor_data(project, ignore_callout: true),
kubernetes_cluster_anchor_data(project)
].compact.reject { |i| i[:enabled] }
end
def project_stat_anchor_items(project)
[
files_anchor_data(project),
commits_anchor_data(project),
branches_anchor_data(project),
tags_anchor_data(project),
readme_anchor_data(project),
changelog_anchor_data(project),
license_anchor_data(project),
contribution_guide_anchor_data(project),
gitlab_ci_anchor_data(project),
autodevops_anchor_data(project),
kubernetes_cluster_anchor_data(project)
].compact.reject { |i| !i[:enabled] }
end
def project_stat_button_items(project)
[
changelog_anchor_data(project),
license_anchor_data(project),
contribution_guide_anchor_data(project),
autodevops_anchor_data(project),
kubernetes_cluster_anchor_data(project),
gitlab_ci_anchor_data(project),
koding_anchor_data(project)
].compact.reject { |i| i[:enabled] }
end
end
- anchors = local_assigns.fetch(:anchors, [])
- if anchors.size > 0
%ul.nav
= render partial: 'stat_anchor_list_item', collection: anchors, as: :anchor
%li
- if anchor[:link]
= link_to anchor[:link], class: anchor[:enabled] ? 'stat-link' : "btn btn-#{anchor[:class_modifier] || 'missing'}" do
= anchor[:label]
- else
%span.stat-text
= anchor[:label]
......@@ -5,38 +5,41 @@
= render "home_panel"
.row-content-block.second-block.center
%h4
The repository for this project is empty
.project-empty-note-panel
%div{ class: [container_class, ("limit-container-width-sm" unless fluid_layout)] }
.prepend-top-20
%h4
= _('The repository for this project is empty')
- if can?(current_user, :push_code, @project)
%p
- 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
%em
- link_to_protected_branches = link_to _('Learn more about protected branches'), help_page_path('user/project/protected_branches')
= _('Note that the master branch is automatically protected. %{link_to_protected_branches}').html_safe % { link_to_protected_branches: link_to_protected_branches }
- if can?(current_user, :push_code, @project)
%p
If you already have files you can push them using command line instructions below.
%p
Otherwise you can start with adding a
= succeed ',' do
= link_to "README", add_special_file_path(@project, file_name: 'README.md')
a
= succeed ',' do
= 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
You will need to be owner or have the master permission level for the initial push, as the master branch is automatically protected.
%hr
%p
- 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'), project_clusters_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
- link = link_to(s_('AutoDevOps|Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'))
= s_('AutoDevOps|You can activate %{link_to_settings} for this project.').html_safe % { link_to_settings: link }
%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'
= _('Otherwise it is recommended you start with one of the options below.')
.prepend-top-20
%nav.project-stats{ class: container_class }
= render 'stat_anchor_list', anchors: empty_project_stat_anchor_items(@project)
= render 'stat_anchor_list', anchors: empty_project_stat_button_items(@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
.empty_wrapper
%h3.page-title-empty
%h3#repo-command-line-instructions.page-title-empty
Command line instructions
.git-empty
%fieldset
......
......@@ -14,65 +14,9 @@
- if can?(current_user, :download_code, @project)
%nav.project-stats{ class: container_class }
%ul.nav
%li
= 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)})
= render 'stat_anchor_list', anchors: project_stat_anchor_items(@project)
= render 'stat_anchor_list', anchors: project_stat_button_items(@project)
- 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)] }
- if @project.archived?
......
---
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) }