From b866cba7f57025dad9e0c8dc93716d22baa87206 Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Fri, 2 Feb 2018 15:50:09 -0600 Subject: Add Auto DevOps and Kubernetes cluster button to project page --- app/assets/stylesheets/framework/buttons.scss | 13 + app/assets/stylesheets/framework/mobile.scss | 4 - app/assets/stylesheets/framework/sidebar.scss | 1 - app/assets/stylesheets/framework/typography.scss | 2 +- app/assets/stylesheets/framework/variables.scss | 6 +- app/assets/stylesheets/pages/projects.scss | 53 ++-- app/helpers/projects_helper.rb | 214 ++++++++++++++ app/views/projects/_stat_anchor_list.html.haml | 5 + .../projects/_stat_anchor_list_item.html.haml | 7 + app/views/projects/empty.html.haml | 53 ++-- app/views/projects/show.html.haml | 60 +--- ...auto-devops-and-clusters-button-to-projects.yml | 6 + spec/features/auto_deploy_spec.rb | 77 ----- ...to_create_license_file_in_empty_project_spec.rb | 2 +- spec/features/projects/show_project_spec.rb | 317 +++++++++++++++++++++ spec/features/tags/master_views_tags_spec.rb | 2 +- 16 files changed, 627 insertions(+), 195 deletions(-) create mode 100644 app/views/projects/_stat_anchor_list.html.haml create mode 100644 app/views/projects/_stat_anchor_list_item.html.haml create mode 100644 changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml delete mode 100644 spec/features/auto_deploy_spec.rb diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index c4b046a6d68..6b89387ab5f 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -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; } diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index a12f28efce6..8604e753c18 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -63,10 +63,6 @@ } } - .project-stats { - display: none; - } - .group-buttons { display: none; } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index d61809cb0a4..d1d98270ad9 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -3,7 +3,6 @@ transition: padding $sidebar-transition-duration; .container-fluid { - background: $white-light; padding: 0 $gl-padding; &.container-blank { diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index d0999e60e65..fef5a1f51fa 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -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, diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 25ee081ea9c..945978d2f76 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -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 diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index bf41005b6d5..93d232149c1 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -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; diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 6512617a02d..0c64b8abec3 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -604,4 +604,218 @@ module ProjectsHelper 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 diff --git a/app/views/projects/_stat_anchor_list.html.haml b/app/views/projects/_stat_anchor_list.html.haml new file mode 100644 index 00000000000..9ca51f8d68c --- /dev/null +++ b/app/views/projects/_stat_anchor_list.html.haml @@ -0,0 +1,5 @@ +- anchors = local_assigns.fetch(:anchors, []) + +- if anchors.size > 0 + %ul.nav + = render partial: 'stat_anchor_list_item', collection: anchors, as: :anchor diff --git a/app/views/projects/_stat_anchor_list_item.html.haml b/app/views/projects/_stat_anchor_list_item.html.haml new file mode 100644 index 00000000000..404dd24599f --- /dev/null +++ b/app/views/projects/_stat_anchor_list_item.html.haml @@ -0,0 +1,7 @@ +%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] diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml index ab225796b12..01fb9dab313 100644 --- a/app/views/projects/empty.html.haml +++ b/app/views/projects/empty.html.haml @@ -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 diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index 888d820b04e..3d23b19b815 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -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? diff --git a/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml b/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml new file mode 100644 index 00000000000..5613b2af763 --- /dev/null +++ b/changelogs/unreleased/42431-add-auto-devops-and-clusters-button-to-projects.yml @@ -0,0 +1,6 @@ +--- +title: Add a button on the project page to set up a Kubernetes cluster and enable + Auto DevOps +merge_request: 16900 +author: +type: added diff --git a/spec/features/auto_deploy_spec.rb b/spec/features/auto_deploy_spec.rb deleted file mode 100644 index 9aef68b7156..00000000000 --- a/spec/features/auto_deploy_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -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 diff --git a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb index 8ac9821b879..7f1d1934103 100644 --- a/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb +++ b/spec/features/projects/files/project_owner_sees_link_to_create_license_file_in_empty_project_spec.rb @@ -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 visit project_path(project) - click_on 'LICENSE' + click_on 'Add License' expect(page).to have_content('New file') expect(current_path).to eq( diff --git a/spec/features/projects/show_project_spec.rb b/spec/features/projects/show_project_spec.rb index 0b94c9eae5d..f5f2bbb49e0 100644 --- a/spec/features/projects/show_project_spec.rb +++ b/spec/features/projects/show_project_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe 'Project show page', :feature do + include ProjectsHelper + context 'when project pending delete' do let(:project) { create(:project, :empty_repo, pending_delete: true) } @@ -17,4 +19,319 @@ 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}") 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) } + + 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: add_special_file_path(project, file_name: 'README.md')) + 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: add_special_file_path(project, file_name: 'LICENSE')) + 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 cluster', href: project_cluster_path(project, cluster)) + end + end + end + end + end + + describe 'populated project' do + let(:project) { create(:project, :public, :repository) } + + 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 cluster') + 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: add_special_file_path(project, file_name: '.gitlab-ci.yml')) + 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 cluster', 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: add_koding_stack_path(project)) + end + end + end + end + end + end end diff --git a/spec/features/tags/master_views_tags_spec.rb b/spec/features/tags/master_views_tags_spec.rb index 4662367d843..b625e7065cc 100644 --- a/spec/features/tags/master_views_tags_spec.rb +++ b/spec/features/tags/master_views_tags_spec.rb @@ -13,7 +13,7 @@ feature 'Master views tags' do before do visit project_path(project) - click_on 'README' + click_on 'Add Readme' fill_in :commit_message, with: 'Add a README file', visible: true click_button 'Commit changes' visit project_tags_path(project) -- cgit v1.2.1