summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects/pipelines_controller.rb3
-rw-r--r--app/services/projects/create_from_template_service.rb23
-rw-r--r--doc/api/projects.md3
-rw-r--r--doc/development/testing_guide/end_to_end/style_guide.md38
-rw-r--r--lib/api/helpers/projects_helpers.rb8
-rw-r--r--lib/api/projects.rb4
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/requests/api/projects_spec.rb31
-rw-r--r--spec/services/projects/create_from_template_service_spec.rb4
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