Commit 48c77599 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 274ea604
...@@ -8,6 +8,9 @@ class Projects::PipelinesController < Projects::ApplicationController ...@@ -8,6 +8,9 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_read_build!, only: [:index] before_action :authorize_read_build!, only: [:index]
before_action :authorize_create_pipeline!, only: [:new, :create] before_action :authorize_create_pipeline!, only: [:new, :create]
before_action :authorize_update_pipeline!, only: [:retry, :cancel] 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] around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
......
...@@ -9,7 +9,9 @@ module Projects ...@@ -9,7 +9,9 @@ module Projects
end end
def execute def execute
file = Gitlab::ProjectTemplate.find(template_name)&.file return project unless validate_template!
file = built_in_template&.file
override_params = params.dup override_params = params.dup
params[:file] = file params[:file] = file
...@@ -24,6 +26,25 @@ module Projects ...@@ -24,6 +26,25 @@ module Projects
params.delete(:template_name).presence params.delete(:template_name).presence
end end
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
end end
......
...@@ -991,6 +991,9 @@ POST /projects/user/:user_id ...@@ -991,6 +991,9 @@ POST /projects/user/:user_id
| `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project | | `external_authorization_classification_label` | string | no | **(PREMIUM)** The classification label for the project |
| `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project | | `mirror` | boolean | no | **(STARTER)** Enables pull mirroring in a project |
| `mirror_trigger_builds` | boolean | no | **(STARTER)** Pull mirroring triggers builds | | `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, 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` add authentication information to the URL: `https://username:password@gitlab.company.com/group/project.git`
......
...@@ -101,43 +101,59 @@ end ...@@ -101,43 +101,59 @@ end
## Block argument naming ## 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 ### Examples
**Good** **Good**
```ruby ```ruby
# qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
Page::Project::Settings::Members.perform do |members| Page::Project::Settings::Members.perform do |members|
members.do_something members.do_something
end end
``` ```
```ruby ```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| Resource::MergeRequest.fabricate! do |merge_request|
merge_request.do_something_else merge_request.do_something_else
end end
``` ```
**Bad** ```ruby
Resource::MergeRequest.fabricate! do |mr|
mr.do_something_else
end
```
```ruby ```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| Page::Project::Settings::Members.perform do |project_settings_members_page|
project_settings_members_page.do_something project_settings_members_page.do_something
end end
``` ```
```ruby ```ruby
# qa/specs/features/ee/browser_ui/3_create/merge_request/add_batch_comments_in_merge_request_spec.rb Page::Project::New.peform do |page|
page.do_something
Resource::MergeRequest.fabricate! do |merge_request_page|
merge_request_page.do_something_else
end end
``` ```
......
...@@ -56,6 +56,14 @@ module API ...@@ -56,6 +56,14 @@ module API
use :optional_project_params_ee use :optional_project_params_ee
end 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 params :optional_filter_params_ee do
end end
......
...@@ -68,6 +68,8 @@ module API ...@@ -68,6 +68,8 @@ module API
params :create_params do params :create_params do
optional :namespace_id, type: Integer, desc: 'Namespace ID for the new project. Default to the user namespace.' 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 :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 end
def load_projects def load_projects
...@@ -155,7 +157,7 @@ module API ...@@ -155,7 +157,7 @@ module API
optional :name, type: String, desc: 'The name of the project' optional :name, type: String, desc: 'The name of the project'
optional :path, type: String, desc: 'The path of the repository' optional :path, type: String, desc: 'The path of the repository'
at_least_one_of :name, :path at_least_one_of :name, :path
use :optional_project_params use :optional_create_project_params
use :create_params use :create_params
end end
post do post do
......
...@@ -391,6 +391,9 @@ msgstr "" ...@@ -391,6 +391,9 @@ msgstr ""
msgid "'%{source}' is not a import source" msgid "'%{source}' is not a import source"
msgstr "" msgstr ""
msgid "'%{template_name}' is unknown or invalid"
msgstr ""
msgid "(%d closed)" msgid "(%d closed)"
msgid_plural "(%d closed)" msgid_plural "(%d closed)"
msgstr[0] "" msgstr[0] ""
......
...@@ -631,6 +631,33 @@ describe API::Projects do ...@@ -631,6 +631,33 @@ describe API::Projects do
expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED) expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
end 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 it 'sets a project as public' do
project = attributes_for(:project, visibility: 'public') project = attributes_for(:project, visibility: 'public')
...@@ -867,7 +894,7 @@ describe API::Projects do ...@@ -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 { 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) 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.name).to eq('Foo Project')
expect(project.path).to eq('foo-project') expect(project.path).to eq('foo-project')
...@@ -878,7 +905,7 @@ describe API::Projects do ...@@ -878,7 +905,7 @@ describe API::Projects do
.to change { Project.count }.by(1) .to change { Project.count }.by(1)
expect(response).to have_gitlab_http_status(201) 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.name).to eq('Foo Project')
expect(project.path).to eq('path-project-Foo') expect(project.path).to eq('path-project-Foo')
......
...@@ -25,7 +25,7 @@ describe Projects::CreateFromTemplateService do ...@@ -25,7 +25,7 @@ describe Projects::CreateFromTemplateService do
subject.execute subject.execute
end end
it 'returns the project thats created' do it 'returns the project that is created' do
project = subject.execute project = subject.execute
expect(project).to be_saved expect(project).to be_saved
...@@ -37,7 +37,7 @@ describe Projects::CreateFromTemplateService do ...@@ -37,7 +37,7 @@ describe Projects::CreateFromTemplateService do
let(:project) { subject.execute } let(:project) { subject.execute }
before do before do
expect(project).to be_saved expect(project).not_to be_saved
end end
it 'does not set import set import type' do it 'does not set import set import type' do
......
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