Commit a84434ae authored by Jan Beckmann's avatar Jan Beckmann Committed by Michael Kozono

Add API support for getting description templates

Closes https://gitlab.com/gitlab-org/gitlab/-/issues/23664
parent 08edb3c1
......@@ -7,7 +7,9 @@ class TemplateFinder
dockerfiles: ::Gitlab::Template::DockerfileTemplate,
gitignores: ::Gitlab::Template::GitignoreTemplate,
gitlab_ci_ymls: ::Gitlab::Template::GitlabCiYmlTemplate,
metrics_dashboard_ymls: ::Gitlab::Template::MetricsDashboardTemplate
metrics_dashboard_ymls: ::Gitlab::Template::MetricsDashboardTemplate,
issues: ::Gitlab::Template::IssueTemplate,
merge_requests: ::Gitlab::Template::MergeRequestTemplate
).freeze
class << self
......@@ -35,9 +37,9 @@ class TemplateFinder
def execute
if params[:name]
vendored_templates.find(params[:name])
vendored_templates.find(params[:name], project)
else
vendored_templates.all
vendored_templates.all(project)
end
end
end
......
---
title: Add API support for issue and merge request templates
merge_request: 37890
author: Jan Beckmann
type: added
......@@ -13,15 +13,15 @@ This API is a project-specific version of these endpoints:
- [Gitignore templates](templates/gitignores.md)
- [GitLab CI/CD Configuration templates](templates/gitlab_ci_ymls.md)
- [Open source license templates](templates/licenses.md)
- [Issue and merge request templates](../user/project/description_templates.md)
([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37890) in GitLab 13.3 as a
community contribution)
It deprecates these endpoints, which will be removed for API version 5.
In addition to templates common to the entire instance, project-specific
templates are also available from this API endpoint.
Support will be added for [Issue and Merge Request templates](../user/project/description_templates.md)
in a future release.
Support for [Group-level file templates](../user/group/index.md#group-file-templates-premium)
**(PREMIUM)** was [added](https://gitlab.com/gitlab-org/gitlab/-/issues/5987)
in GitLab 11.5
......@@ -35,7 +35,7 @@ GET /projects/:id/templates/:type
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template |
| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template |
Example response (licenses):
......@@ -101,7 +101,7 @@ GET /projects/:id/templates/:type/:key
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `id` | integer / string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses)` of the template |
| `type` | string | yes| The type `(dockerfiles|gitignores|gitlab_ci_ymls|licenses|issues|merge_requests)` of the template |
| `key` | string | yes | The key of the template, as obtained from the collection endpoint |
| `project` | string | no | The project name to use when expanding placeholders in the template. Only affects licenses |
| `fullname` | string | no | The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses |
......
......@@ -17,13 +17,15 @@ module EE
def initialize(type, project, *args, &blk)
super
finder = CUSTOM_TEMPLATES.fetch(type)
@custom_templates = ::Gitlab::CustomFileTemplates.new(finder, project)
if CUSTOM_TEMPLATES.key?(type)
finder = CUSTOM_TEMPLATES.fetch(type)
@custom_templates = ::Gitlab::CustomFileTemplates.new(finder, project)
end
end
override :execute
def execute
return super unless custom_templates.enabled?
return super if custom_templates.nil? || !custom_templates.enabled?
if params[:name]
custom_templates.find(params[:name]) || super
......
......@@ -4,7 +4,7 @@ module API
class ProjectTemplates < Grape::API::Instance
include PaginationParams
TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses metrics_dashboard_ymls].freeze
TEMPLATE_TYPES = %w[dockerfiles gitignores gitlab_ci_ymls licenses metrics_dashboard_ymls issues merge_requests].freeze
# The regex is needed to ensure a period (e.g. agpl-3.0)
# isn't confused with a format type. We also need to allow encoded
# values (e.g. C%2B%2B for C++), so allow % and + as well.
......@@ -14,7 +14,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses|metrics_dashboard_ymls) of the template'
requires :type, type: String, values: TEMPLATE_TYPES, desc: 'The type (dockerfiles|gitignores|gitlab_ci_ymls|licenses|metrics_dashboard_ymls|issues|merge_requests) of the template'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get a list of templates available to this project' do
......@@ -42,9 +42,13 @@ module API
end
get ':id/templates/:type/:name', requirements: TEMPLATE_NAMES_ENDPOINT_REQUIREMENTS do
template = TemplateFinder
.build(params[:type], user_project, name: params[:name])
.execute
begin
template = TemplateFinder
.build(params[:type], user_project, name: params[:name])
.execute
rescue ::Gitlab::Template::Finders::RepoTemplateFinder::FileNotFoundError
not_found!('Template')
end
not_found!('Template') unless template.present?
......
......@@ -3,8 +3,8 @@
require 'spec_helper'
RSpec.describe API::ProjectTemplates do
let_it_be(:public_project) { create(:project, :public, path: 'path.with.dot') }
let_it_be(:private_project) { create(:project, :private) }
let_it_be(:public_project) { create(:project, :public, :repository, create_templates: :merge_request, path: 'path.with.dot') }
let_it_be(:private_project) { create(:project, :private, :repository, create_templates: :issue) }
let_it_be(:developer) { create(:user) }
let(:url_encoded_path) { "#{public_project.namespace.path}%2F#{public_project.path}" }
......@@ -71,6 +71,24 @@ RSpec.describe API::ProjectTemplates do
expect(json_response).to satisfy_one { |template| template['key'] == 'Default' }
end
it 'returns issue templates' do
get api("/projects/#{private_project.id}/templates/issues", developer)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/template_list')
expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
end
it 'returns merge request templates' do
get api("/projects/#{public_project.id}/templates/merge_requests")
expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
expect(response).to match_response_schema('public_api/v4/template_list')
expect(json_response.map {|t| t['key']}).to match_array(%w(bug feature_proposal template_test))
end
it 'returns 400 for an unknown template type' do
get api("/projects/#{public_project.id}/templates/unknown")
......@@ -160,12 +178,42 @@ RSpec.describe API::ProjectTemplates do
expect(response).to match_response_schema('public_api/v4/license')
end
it 'returns a specific issue template' do
get api("/projects/#{private_project.id}/templates/issues/bug", developer)
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/template')
expect(json_response['name']).to eq('bug')
expect(json_response['content']).to eq('something valid')
end
it 'returns a specific merge request template' do
get api("/projects/#{public_project.id}/templates/merge_requests/feature_proposal")
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/template')
expect(json_response['name']).to eq('feature_proposal')
expect(json_response['content']).to eq('feature_proposal') # Content is identical to filename here
end
it 'returns 404 for an unknown specific template' do
get api("/projects/#{public_project.id}/templates/licenses/unknown")
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 404 for an unknown issue template' do
get api("/projects/#{public_project.id}/templates/issues/unknown")
expect(response).to have_gitlab_http_status(:not_found)
end
it 'returns 404 for an unknown merge request template' do
get api("/projects/#{public_project.id}/templates/merge_requests/unknown")
expect(response).to have_gitlab_http_status(:not_found)
end
it 'denies access to an anonymous user on a private project' do
get api("/projects/#{private_project.id}/templates/licenses/mit")
......
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