diff options
-rw-r--r-- | app/controllers/projects/pipelines_controller.rb | 3 | ||||
-rw-r--r-- | app/services/projects/create_from_template_service.rb | 23 | ||||
-rw-r--r-- | doc/api/projects.md | 3 | ||||
-rw-r--r-- | doc/development/testing_guide/end_to_end/style_guide.md | 38 | ||||
-rw-r--r-- | lib/api/helpers/projects_helpers.rb | 8 | ||||
-rw-r--r-- | lib/api/projects.rb | 4 | ||||
-rw-r--r-- | locale/gitlab.pot | 3 | ||||
-rw-r--r-- | spec/requests/api/projects_spec.rb | 31 | ||||
-rw-r--r-- | spec/services/projects/create_from_template_service_spec.rb | 4 |
9 files changed, 100 insertions, 17 deletions
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 28c25dbc1e6..10a6d2d3f26 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -8,6 +8,9 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_read_build!, only: [:index] before_action :authorize_create_pipeline!, only: [:new, :create] before_action :authorize_update_pipeline!, only: [:retry, :cancel] + before_action do + push_frontend_feature_flag(:hide_dismissed_vulnerabilities) + end around_action :allow_gitaly_ref_name_caching, only: [:index, :show] diff --git a/app/services/projects/create_from_template_service.rb b/app/services/projects/create_from_template_service.rb index 31977a7c76a..91ece024e13 100644 --- a/app/services/projects/create_from_template_service.rb +++ b/app/services/projects/create_from_template_service.rb @@ -9,7 +9,9 @@ module Projects end def execute - file = Gitlab::ProjectTemplate.find(template_name)&.file + return project unless validate_template! + + file = built_in_template&.file override_params = params.dup params[:file] = file @@ -24,6 +26,25 @@ module Projects params.delete(:template_name).presence end end + + private + + def validate_template! + return true if built_in_template + + project.errors.add(:template_name, _("'%{template_name}' is unknown or invalid" % { template_name: template_name })) + false + end + + def built_in_template + strong_memoize(:built_in_template) do + Gitlab::ProjectTemplate.find(template_name) + end + end + + def project + @project ||= ::Project.new(namespace_id: params[:namespace_id]) + end end end diff --git a/doc/api/projects.md b/doc/api/projects.md index 3ea1434d5ca..7617620e52d 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -991,6 +991,9 @@ POST /projects/user/:user_id | `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project | | `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project | | `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds | +| `template_name` | string | no | When used without `use_custom_template`, name of a [built-in project template](../gitlab-basics/create-project.md#built-in-templates). When used with `use_custom_template`, name of a custom project template | +| `use_custom_template` | boolean | no | **(PREMIUM)** Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template | +| `group_with_project_templates_id` | integer | no | **(PREMIUM)** For group-level custom templates, specifies ID of group from which all the custom project templates are sourced. Leave empty for instance-level templates. Requires `use_custom_template` to be true | NOTE: **Note:** If your HTTP repository is not publicly accessible, add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git` diff --git a/doc/development/testing_guide/end_to_end/style_guide.md b/doc/development/testing_guide/end_to_end/style_guide.md index 54ed3f34c89..9088e9e9bfb 100644 --- a/doc/development/testing_guide/end_to_end/style_guide.md +++ b/doc/development/testing_guide/end_to_end/style_guide.md @@ -101,43 +101,59 @@ end ## Block argument naming -To have a standard on how we call pages when using the `.perform` method, we use the name of page object being called, all lowercased, and separated by underscore, if needed (see good and bad examples below.) This also applies to resources. We chose not to simply use `page` because that would shadow the Capybara DSL, potentially leading to confusion and bugs. +To have a standard on what we call pages and resources when using the `.perform` method, +we use the name of the page object in [snake_case](https://en.wikipedia.org/wiki/Snake_case) +(all lowercase, with words separated by an underscore). See good and bad examples below. + +While we prefer to follow the standard in most cases, it is also acceptable to +use common abbreviations (e.g., mr) or other alternatives, as long as +the name is not ambiguous. This can include appending `_page` if it helps to +avoid confusion or make the code more readable. For example, if a page object is +named `New`, it could be confusing to name the block argument `new` because that +is used to instantiate objects, so `new_page` would be acceptable. + +We chose not to simply use `page` because that would shadow the +Capybara DSL, potentially leading to confusion and bugs. ### Examples **Good** ```ruby -# qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb - Page::Project::Settings::Members.perform do |members| members.do_something end ``` ```ruby -# qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb - Resource::MergeRequest.fabricate! do |merge_request| merge_request.do_something_else end ``` -**Bad** +```ruby +Resource::MergeRequest.fabricate! do |mr| + mr.do_something_else +end +``` ```ruby -# qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb +Page::Project::New.peform do |new_page| + new_page.do_something +end +``` +**Bad** + +```ruby Page::Project::Settings::Members.perform do |project_settings_members_page| project_settings_members_page.do_something end ``` ```ruby -# qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb - -Resource::MergeRequest.fabricate! do |merge_request_page| - merge_request_page.do_something_else +Page::Project::New.peform do |page| + page.do_something end ``` diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index f247c722c44..07f0386d14d 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -56,6 +56,14 @@ module API use :optional_project_params_ee end + params :optional_create_project_params_ee do + end + + params :optional_create_project_params do + use :optional_project_params + use :optional_create_project_params_ee + end + params :optional_filter_params_ee do end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 74de9fcec68..c28b03ac6c9 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -68,6 +68,8 @@ module API params :create_params do optional :namespace_id, type: Integer, desc: 'Namespace ID for the new project. Default to the user namespace.' optional :import_url, type: String, desc: 'URL from which the project is imported' + optional :template_name, type: String, desc: "Name of template from which to create project" + mutually_exclusive :import_url, :template_name end def load_projects @@ -155,7 +157,7 @@ module API optional :name, type: String, desc: 'The name of the project' optional :path, type: String, desc: 'The path of the repository' at_least_one_of :name, :path - use :optional_project_params + use :optional_create_project_params use :create_params end post do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 37b589d902d..23882383200 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -391,6 +391,9 @@ msgstr "" msgid "'%{source}' is not a import source" msgstr "" +msgid "'%{template_name}' is unknown or invalid" +msgstr "" + msgid "(%d closed)" msgid_plural "(%d closed)" msgstr[0] "" diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 550c7d135a6..f52e36e6bcd 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -631,6 +631,33 @@ describe API::Projects do expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED) end + it 'creates a project using a template' do + expect { post api('/projects', user), params: { template_name: 'rails', name: 'rails-test' } } + .to change { Project.count }.by(1) + + expect(response).to have_gitlab_http_status(201) + + project = Project.find(json_response['id']) + expect(project).to be_saved + expect(project.import_type).to eq('gitlab_project') + end + + it 'returns 400 for an invalid template' do + expect { post api('/projects', user), params: { template_name: 'unknown', name: 'rails-test' } } + .not_to change { Project.count } + + expect(response).to have_gitlab_http_status(400) + expect(json_response['message']['template_name']).to eq(["'unknown' is unknown or invalid"]) + end + + it 'disallows creating a project with an import_url and template' do + project_params = { import_url: 'http://example.com', template_name: 'rails', name: 'rails-test' } + expect { post api('/projects', user), params: project_params } + .not_to change { Project.count } + + expect(response).to have_gitlab_http_status(400) + end + it 'sets a project as public' do project = attributes_for(:project, visibility: 'public') @@ -867,7 +894,7 @@ describe API::Projects do expect { post api("/projects/user/#{user.id}", admin), params: { name: 'Foo Project' } }.to change { Project.count }.by(1) expect(response).to have_gitlab_http_status(201) - project = Project.last + project = Project.find(json_response['id']) expect(project.name).to eq('Foo Project') expect(project.path).to eq('foo-project') @@ -878,7 +905,7 @@ describe API::Projects do .to change { Project.count }.by(1) expect(response).to have_gitlab_http_status(201) - project = Project.last + project = Project.find(json_response['id']) expect(project.name).to eq('Foo Project') expect(project.path).to eq('path-project-Foo') diff --git a/spec/services/projects/create_from_template_service_spec.rb b/spec/services/projects/create_from_template_service_spec.rb index 6c244d23877..0b4772e8f02 100644 --- a/spec/services/projects/create_from_template_service_spec.rb +++ b/spec/services/projects/create_from_template_service_spec.rb @@ -25,7 +25,7 @@ describe Projects::CreateFromTemplateService do subject.execute end - it 'returns the project thats created' do + it 'returns the project that is created' do project = subject.execute expect(project).to be_saved @@ -37,7 +37,7 @@ describe Projects::CreateFromTemplateService do let(:project) { subject.execute } before do - expect(project).to be_saved + expect(project).not_to be_saved end it 'does not set import set import type' do |