Commit 3c31f185 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch '17541-move-licenses-api-endpoint-to-templates-licenses' into 'master'

Resolve "Move `/licenses` api endpoint to `/templates/licenses`"

## What does this MR do?

It moves the `/licenses`, `/gitignores` and `/gitlab_ci_ymls` API endpoints under the `/templates` namespace

## Why was this MR needed?

In EE we now have somewhat ambiguous API endpoints. `/license` refers to the EE license while `/licenses` (plural) refers to license templates. @DouweM mentioned that we're adding .gitignore templates in #14106 so it may make sense to add a /templates namespace. Then, move the /license templates endpoint to be underneath, along with .gitignore endpoints. 

Closes #17541

See merge request !5717
parents 8aa381c9 b9b13ea8
...@@ -19,6 +19,7 @@ v 8.13.0 (unreleased) ...@@ -19,6 +19,7 @@ v 8.13.0 (unreleased)
- Replaced the check sign to arrow in the show build view. !6501 - Replaced the check sign to arrow in the show build view. !6501
- Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar) - Add a /wip slash command to toggle the Work In Progress status of a merge request. !6259 (tbalthazar)
- Fix Error 500 when viewing old merge requests with bad diff data - Fix Error 500 when viewing old merge requests with bad diff data
- Create a new /templates namespace for the /licenses, /gitignores and /gitlab_ci_ymls API endpoints. !5717 (tbalthazar)
- Speed-up group milestones show page - Speed-up group milestones show page
- Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps) - Fix inconsistent options dropdown caret on mobile viewports (ClemMakesApps)
- Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs) - Don't include archived projects when creating group milestones. !4940 (Jeroen Jacobs)
......
...@@ -6,11 +6,10 @@ ...@@ -6,11 +6,10 @@
groupProjectsPath: "/api/:version/groups/:id/projects.json", groupProjectsPath: "/api/:version/groups/:id/projects.json",
projectsPath: "/api/:version/projects.json?simple=true", projectsPath: "/api/:version/projects.json?simple=true",
labelsPath: "/:namespace_path/:project_path/labels", labelsPath: "/:namespace_path/:project_path/labels",
licensePath: "/api/:version/licenses/:key", licensePath: "/api/:version/templates/licenses/:key",
gitignorePath: "/api/:version/gitignores/:key", gitignorePath: "/api/:version/templates/gitignores/:key",
gitlabCiYmlPath: "/api/:version/gitlab_ci_ymls/:key", gitlabCiYmlPath: "/api/:version/templates/gitlab_ci_ymls/:key",
issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key", issuableTemplatePath: "/:namespace_path/:project_path/templates/:type/:key",
group: function(group_id, callback) { group: function(group_id, callback) {
var url = Api.buildUrl(Api.groupPath) var url = Api.buildUrl(Api.groupPath)
.replace(':id', group_id); .replace(':id', group_id);
......
...@@ -17,6 +17,8 @@ following locations: ...@@ -17,6 +17,8 @@ following locations:
- [Commits](commits.md) - [Commits](commits.md)
- [Deployments](deployments.md) - [Deployments](deployments.md)
- [Deploy Keys](deploy_keys.md) - [Deploy Keys](deploy_keys.md)
- [Gitignores templates](templates/gitignores.md)
- [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
- [Groups](groups.md) - [Groups](groups.md)
- [Group Access Requests](access_requests.md) - [Group Access Requests](access_requests.md)
- [Group Members](members.md) - [Group Members](members.md)
...@@ -25,7 +27,7 @@ following locations: ...@@ -25,7 +27,7 @@ following locations:
- [Labels](labels.md) - [Labels](labels.md)
- [Merge Requests](merge_requests.md) - [Merge Requests](merge_requests.md)
- [Milestones](milestones.md) - [Milestones](milestones.md)
- [Open source license templates](licenses.md) - [Open source license templates](templates/licenses.md)
- [Namespaces](namespaces.md) - [Namespaces](namespaces.md)
- [Notes](notes.md) (comments) - [Notes](notes.md) (comments)
- [Notification settings](notification_settings.md) - [Notification settings](notification_settings.md)
......
# Gitignores
## List gitignore templates
Get all gitignore templates.
```
GET /templates/gitignores
```
```bash
curl https://gitlab.example.com/api/v3/templates/gitignores
```
Example response:
```json
[
{
"name": "AppEngine"
},
{
"name": "Laravel"
},
{
"name": "Elisp"
},
{
"name": "SketchUp"
},
{
"name": "Ada"
},
{
"name": "Ruby"
},
{
"name": "Kohana"
},
{
"name": "Nanoc"
},
{
"name": "Erlang"
},
{
"name": "OCaml"
},
{
"name": "Lithium"
},
{
"name": "Fortran"
},
{
"name": "Scala"
},
{
"name": "Node"
},
{
"name": "Fancy"
},
{
"name": "Perl"
},
{
"name": "Zephir"
},
{
"name": "WordPress"
},
{
"name": "Symfony"
},
{
"name": "FuelPHP"
},
{
"name": "DM"
},
{
"name": "Sdcc"
},
{
"name": "Rust"
},
{
"name": "C"
},
{
"name": "Umbraco"
},
{
"name": "Actionscript"
},
{
"name": "Android"
},
{
"name": "Grails"
},
{
"name": "Composer"
},
{
"name": "ExpressionEngine"
},
{
"name": "Gcov"
},
{
"name": "Qt"
},
{
"name": "Phalcon"
},
{
"name": "ArchLinuxPackages"
},
{
"name": "TeX"
},
{
"name": "SCons"
},
{
"name": "Lilypond"
},
{
"name": "CommonLisp"
},
{
"name": "Rails"
},
{
"name": "Mercury"
},
{
"name": "Magento"
},
{
"name": "ChefCookbook"
},
{
"name": "GitBook"
},
{
"name": "C++"
},
{
"name": "Eagle"
},
{
"name": "Go"
},
{
"name": "OpenCart"
},
{
"name": "Scheme"
},
{
"name": "Typo3"
},
{
"name": "SeamGen"
},
{
"name": "Swift"
},
{
"name": "Elm"
},
{
"name": "Unity"
},
{
"name": "Agda"
},
{
"name": "CUDA"
},
{
"name": "VVVV"
},
{
"name": "Finale"
},
{
"name": "LemonStand"
},
{
"name": "Textpattern"
},
{
"name": "Julia"
},
{
"name": "Packer"
},
{
"name": "Scrivener"
},
{
"name": "Dart"
},
{
"name": "Plone"
},
{
"name": "Jekyll"
},
{
"name": "Xojo"
},
{
"name": "LabVIEW"
},
{
"name": "Autotools"
},
{
"name": "KiCad"
},
{
"name": "Prestashop"
},
{
"name": "ROS"
},
{
"name": "Smalltalk"
},
{
"name": "GWT"
},
{
"name": "OracleForms"
},
{
"name": "SugarCRM"
},
{
"name": "Nim"
},
{
"name": "SymphonyCMS"
},
{
"name": "Maven"
},
{
"name": "CFWheels"
},
{
"name": "Python"
},
{
"name": "ZendFramework"
},
{
"name": "CakePHP"
},
{
"name": "Concrete5"
},
{
"name": "PlayFramework"
},
{
"name": "Terraform"
},
{
"name": "Elixir"
},
{
"name": "CMake"
},
{
"name": "Joomla"
},
{
"name": "Coq"
},
{
"name": "Delphi"
},
{
"name": "Haskell"
},
{
"name": "Yii"
},
{
"name": "Java"
},
{
"name": "UnrealEngine"
},
{
"name": "AppceleratorTitanium"
},
{
"name": "CraftCMS"
},
{
"name": "ForceDotCom"
},
{
"name": "ExtJs"
},
{
"name": "MetaProgrammingSystem"
},
{
"name": "D"
},
{
"name": "Objective-C"
},
{
"name": "RhodesRhomobile"
},
{
"name": "R"
},
{
"name": "EPiServer"
},
{
"name": "Yeoman"
},
{
"name": "VisualStudio"
},
{
"name": "Processing"
},
{
"name": "Leiningen"
},
{
"name": "Stella"
},
{
"name": "Opa"
},
{
"name": "Drupal"
},
{
"name": "TurboGears2"
},
{
"name": "Idris"
},
{
"name": "Jboss"
},
{
"name": "CodeIgniter"
},
{
"name": "Qooxdoo"
},
{
"name": "Waf"
},
{
"name": "Sass"
},
{
"name": "Lua"
},
{
"name": "Clojure"
},
{
"name": "IGORPro"
},
{
"name": "Gradle"
},
{
"name": "Archives"
},
{
"name": "SynopsysVCS"
},
{
"name": "Ninja"
},
{
"name": "Tags"
},
{
"name": "OSX"
},
{
"name": "Dreamweaver"
},
{
"name": "CodeKit"
},
{
"name": "NotepadPP"
},
{
"name": "VisualStudioCode"
},
{
"name": "Mercurial"
},
{
"name": "BricxCC"
},
{
"name": "DartEditor"
},
{
"name": "Eclipse"
},
{
"name": "Cloud9"
},
{
"name": "TortoiseGit"
},
{
"name": "NetBeans"
},
{
"name": "GPG"
},
{
"name": "Espresso"
},
{
"name": "Redcar"
},
{
"name": "Xcode"
},
{
"name": "Matlab"
},
{
"name": "LyX"
},
{
"name": "SlickEdit"
},
{
"name": "Dropbox"
},
{
"name": "CVS"
},
{
"name": "Calabash"
},
{
"name": "JDeveloper"
},
{
"name": "Vagrant"
},
{
"name": "IPythonNotebook"
},
{
"name": "TextMate"
},
{
"name": "Ensime"
},
{
"name": "WebMethods"
},
{
"name": "VirtualEnv"
},
{
"name": "Emacs"
},
{
"name": "Momentics"
},
{
"name": "JetBrains"
},
{
"name": "SublimeText"
},
{
"name": "Kate"
},
{
"name": "ModelSim"
},
{
"name": "Redis"
},
{
"name": "KDevelop4"
},
{
"name": "Bazaar"
},
{
"name": "Linux"
},
{
"name": "Windows"
},
{
"name": "XilinxISE"
},
{
"name": "Lazarus"
},
{
"name": "EiffelStudio"
},
{
"name": "Anjuta"
},
{
"name": "Vim"
},
{
"name": "Otto"
},
{
"name": "MicrosoftOffice"
},
{
"name": "LibreOffice"
},
{
"name": "SBT"
},
{
"name": "MonoDevelop"
},
{
"name": "SVN"
},
{
"name": "FlexBuilder"
}
]
```
## Single gitignore template
Get a single gitignore template.
```
GET /templates/gitignores/:key
```
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `key` | string | yes | The key of the gitignore template |
```bash
curl https://gitlab.example.com/api/v3/templates/gitignores/Ruby
```
Example response:
```json
{
"name": "Ruby",
"content": "*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n#\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\n# Gemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n"
}
```
# GitLab CI YMLs
## List GitLab CI YML templates
Get all GitLab CI YML templates.
```
GET /templates/gitlab_ci_ymls
```
```bash
curl https://gitlab.example.com/api/v3/templates/gitlab_ci_ymls
```
Example response:
```json
[
{
"name": "C++"
},
{
"name": "Docker"
},
{
"name": "Elixir"
},
{
"name": "LaTeX"
},
{
"name": "Grails"
},
{
"name": "Rust"
},
{
"name": "Nodejs"
},
{
"name": "Ruby"
},
{
"name": "Scala"
},
{
"name": "Maven"
},
{
"name": "Harp"
},
{
"name": "Pelican"
},
{
"name": "Hyde"
},
{
"name": "Nanoc"
},
{
"name": "Octopress"
},
{
"name": "JBake"
},
{
"name": "HTML"
},
{
"name": "Hugo"
},
{
"name": "Metalsmith"
},
{
"name": "Hexo"
},
{
"name": "Lektor"
},
{
"name": "Doxygen"
},
{
"name": "Brunch"
},
{
"name": "Jekyll"
},
{
"name": "Middleman"
}
]
```
## Single GitLab CI YML template
Get a single GitLab CI YML template.
```
GET /templates/gitlab_ci_ymls/:key
```
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
| `key` | string | yes | The key of the GitLab CI YML template |
```bash
curl https://gitlab.example.com/api/v3/templates/gitlab_ci_ymls/Ruby
```
Example response:
```json
{
"name": "Ruby",
"content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.3\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - bundle exec rake db:migrate\n - bundle exec rake db:seed\n - bundle exec rake test\n"
}
```
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
Get all license templates. Get all license templates.
``` ```
GET /licenses GET /templates/licenses
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -13,7 +13,7 @@ GET /licenses ...@@ -13,7 +13,7 @@ GET /licenses
| `popular` | boolean | no | If passed, returns only popular licenses | | `popular` | boolean | no | If passed, returns only popular licenses |
```bash ```bash
curl https://gitlab.example.com/api/v3/licenses?popular=1 curl https://gitlab.example.com/api/v3/templates/licenses?popular=1
``` ```
Example response: Example response:
...@@ -102,7 +102,7 @@ Get a single license template. You can pass parameters to replace the license ...@@ -102,7 +102,7 @@ Get a single license template. You can pass parameters to replace the license
placeholder. placeholder.
``` ```
GET /licenses/:key GET /templates/licenses/:key
``` ```
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
...@@ -116,7 +116,7 @@ If you omit the `fullname` parameter but authenticate your request, the name of ...@@ -116,7 +116,7 @@ If you omit the `fullname` parameter but authenticate your request, the name of
the authenticated user will be used to replace the copyright holder placeholder. the authenticated user will be used to replace the copyright holder placeholder.
```bash ```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/licenses/mit?project=My+Cool+Project curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v3/templates/licenses/mit?project=My+Cool+Project
``` ```
Example response: Example response:
......
...@@ -46,7 +46,6 @@ module API ...@@ -46,7 +46,6 @@ module API
mount ::API::Boards mount ::API::Boards
mount ::API::Keys mount ::API::Keys
mount ::API::Labels mount ::API::Labels
mount ::API::LicenseTemplates
mount ::API::Lint mount ::API::Lint
mount ::API::Members mount ::API::Members
mount ::API::MergeRequests mount ::API::MergeRequests
......
module API
# License Templates API
class LicenseTemplates < Grape::API
PROJECT_TEMPLATE_REGEX =
/[\<\{\[]
(project|description|
one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
[\>\}\]]/xi.freeze
YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
FULLNAME_TEMPLATE_REGEX =
/[\<\{\[]
(fullname|name\sof\s(author|copyright\sowner))
[\>\}\]]/xi.freeze
# Get the list of the available license templates
#
# Parameters:
# popular - Filter licenses to only the popular ones
#
# Example Request:
# GET /licenses
# GET /licenses?popular=1
get 'licenses' do
options = {
featured: params[:popular].present? ? true : nil
}
present Licensee::License.all(options), with: Entities::RepoLicense
end
# Get text for specific license
#
# Parameters:
# key (required) - The key of a license
# project - Copyrighted project name
# fullname - Full name of copyright holder
#
# Example Request:
# GET /licenses/mit
#
get 'licenses/:key', requirements: { key: /[\w\.-]+/ } do
required_attributes! [:key]
not_found!('License') unless Licensee::License.find(params[:key])
# We create a fresh Licensee::License object since we'll modify its
# content in place below.
license = Licensee::License.new(params[:key])
license.content.gsub!(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
license.content.gsub!(PROJECT_TEMPLATE_REGEX, params[:project]) if params[:project].present?
fullname = params[:fullname].presence || current_user.try(:name)
license.content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname
present license, with: Entities::RepoLicense
end
end
end
module API module API
class Templates < Grape::API class Templates < Grape::API
GLOBAL_TEMPLATE_TYPES = { GLOBAL_TEMPLATE_TYPES = {
gitignores: Gitlab::Template::GitignoreTemplate, gitignores: {
gitlab_ci_ymls: Gitlab::Template::GitlabCiYmlTemplate klass: Gitlab::Template::GitignoreTemplate,
gitlab_version: 8.8
},
gitlab_ci_ymls: {
klass: Gitlab::Template::GitlabCiYmlTemplate,
gitlab_version: 8.9
}
}.freeze }.freeze
PROJECT_TEMPLATE_REGEX =
/[\<\{\[]
(project|description|
one\sline\s.+\swhat\sit\sdoes\.) # matching the start and end is enough here
[\>\}\]]/xi.freeze
YEAR_TEMPLATE_REGEX = /[<{\[](year|yyyy)[>}\]]/i.freeze
FULLNAME_TEMPLATE_REGEX =
/[\<\{\[]
(fullname|name\sof\s(author|copyright\sowner))
[\>\}\]]/xi.freeze
DEPRECATION_MESSAGE = ' This endpoint is deprecated and will be removed in GitLab 9.0.'.freeze
helpers do helpers do
def parsed_license_template
# We create a fresh Licensee::License object since we'll modify its
# content in place below.
template = Licensee::License.new(params[:name])
template.content.gsub!(YEAR_TEMPLATE_REGEX, Time.now.year.to_s)
template.content.gsub!(PROJECT_TEMPLATE_REGEX, params[:project]) if params[:project].present?
fullname = params[:fullname].presence || current_user.try(:name)
template.content.gsub!(FULLNAME_TEMPLATE_REGEX, fullname) if fullname
template
end
def render_response(template_type, template) def render_response(template_type, template)
not_found!(template_type.to_s.singularize) unless template not_found!(template_type.to_s.singularize) unless template
present template, with: Entities::Template present template, with: Entities::Template
end end
end end
GLOBAL_TEMPLATE_TYPES.each do |template_type, klass| { "licenses" => :deprecated, "templates/licenses" => :ok }.each do |route, status|
# Get the list of the available template desc 'Get the list of the available license template' do
# detailed_desc = 'This feature was introduced in GitLab 8.7.'
# Example Request: detailed_desc << DEPRECATION_MESSAGE unless status == :ok
# GET /gitignores detail detailed_desc
# GET /gitlab_ci_ymls success Entities::RepoLicense
get template_type.to_s do end
params do
optional :popular, type: Boolean, desc: 'If passed, returns only popular licenses'
end
get route do
options = {
featured: declared(params).popular.present? ? true : nil
}
present Licensee::License.all(options), with: Entities::RepoLicense
end
end
{ "licenses/:name" => :deprecated, "templates/licenses/:name" => :ok }.each do |route, status|
desc 'Get the text for a specific license' do
detailed_desc = 'This feature was introduced in GitLab 8.7.'
detailed_desc << DEPRECATION_MESSAGE unless status == :ok
detail detailed_desc
success Entities::RepoLicense
end
params do
requires :name, type: String, desc: 'The name of the template'
end
get route, requirements: { name: /[\w\.-]+/ } do
not_found!('License') unless Licensee::License.find(declared(params).name)
template = parsed_license_template
present template, with: Entities::RepoLicense
end
end
GLOBAL_TEMPLATE_TYPES.each do |template_type, properties|
klass = properties[:klass]
gitlab_version = properties[:gitlab_version]
{ template_type => :deprecated, "templates/#{template_type}" => :ok }.each do |route, status|
desc 'Get the list of the available template' do
detailed_desc = "This feature was introduced in GitLab #{gitlab_version}."
detailed_desc << DEPRECATION_MESSAGE unless status == :ok
detail detailed_desc
success Entities::TemplatesList
end
get route do
present klass.all, with: Entities::TemplatesList present klass.all, with: Entities::TemplatesList
end end
end
{ "#{template_type}/:name" => :deprecated, "templates/#{template_type}/:name" => :ok }.each do |route, status|
desc 'Get the text for a specific template present in local filesystem' do
detailed_desc = "This feature was introduced in GitLab #{gitlab_version}."
detailed_desc << DEPRECATION_MESSAGE unless status == :ok
detail detailed_desc
success Entities::Template
end
params do
requires :name, type: String, desc: 'The name of the template'
end
get route do
new_template = klass.find(declared(params).name)
# Get the text for a specific template present in local filesystem
#
# Parameters:
# name (required) - The name of a template
#
# Example Request:
# GET /gitignores/Elixir
# GET /gitlab_ci_ymls/Ruby
get "#{template_type}/:name" do
required_attributes! [:name]
new_template = klass.find(params[:name])
render_response(template_type, new_template) render_response(template_type, new_template)
end end
end end
end end
end
end end
require 'spec_helper'
describe API::API, api: true do
include ApiHelpers
describe 'Entity' do
before { get api('/licenses/mit') }
it { expect(json_response['key']).to eq('mit') }
it { expect(json_response['name']).to eq('MIT License') }
it { expect(json_response['nickname']).to be_nil }
it { expect(json_response['popular']).to be true }
it { expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/') }
it { expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT') }
it { expect(json_response['description']).to include('A permissive license that is short and to the point.') }
it { expect(json_response['conditions']).to eq(%w[include-copyright]) }
it { expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use]) }
it { expect(json_response['limitations']).to eq(%w[no-liability]) }
it { expect(json_response['content']).to include('The MIT License (MIT)') }
end
describe 'GET /licenses' do
it 'returns a list of available license templates' do
get api('/licenses')
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(15)
expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
end
describe 'the popular parameter' do
context 'with popular=1' do
it 'returns a list of available popular license templates' do
get api('/licenses?popular=1')
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(3)
expect(json_response.map { |l| l['key'] }).to include('apache-2.0')
end
end
end
end
describe 'GET /licenses/:key' do
context 'with :project and :fullname given' do
before do
get api("/licenses/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
end
context 'for the mit license' do
let(:license_type) { 'mit' }
it 'returns the license text' do
expect(json_response['content']).to include('The MIT License (MIT)')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton")
end
end
context 'for the agpl-3.0 license' do
let(:license_type) { 'agpl-3.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the gpl-3.0 license' do
let(:license_type) { 'gpl-3.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the gpl-2.0 license' do
let(:license_type) { 'gpl-2.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the apache-2.0 license' do
let(:license_type) { 'apache-2.0' }
it 'returns the license text' do
expect(json_response['content']).to include('Apache License')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include("Copyright #{Time.now.year} Anton")
end
end
context 'for an uknown license' do
let(:license_type) { 'muth-over9000' }
it 'returns a 404' do
expect(response).to have_http_status(404)
end
end
end
context 'with no :fullname given' do
context 'with an authenticated user' do
let(:user) { create(:user) }
it 'replaces the copyright owner placeholder with the name of the current user' do
get api('/licenses/mit', user)
expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}")
end
end
end
end
end
...@@ -3,53 +3,201 @@ require 'spec_helper' ...@@ -3,53 +3,201 @@ require 'spec_helper'
describe API::Templates, api: true do describe API::Templates, api: true do
include ApiHelpers include ApiHelpers
context 'global templates' do shared_examples_for 'the Template Entity' do |path|
describe 'the Template Entity' do before { get api(path) }
before { get api('/gitignores/Ruby') }
it { expect(json_response['name']).to eq('Ruby') } it { expect(json_response['name']).to eq('Ruby') }
it { expect(json_response['content']).to include('*.gem') } it { expect(json_response['content']).to include('*.gem') }
end end
describe 'the TemplateList Entity' do shared_examples_for 'the TemplateList Entity' do |path|
before { get api('/gitignores') } before { get api(path) }
it { expect(json_response.first['name']).not_to be_nil } it { expect(json_response.first['name']).not_to be_nil }
it { expect(json_response.first['content']).to be_nil } it { expect(json_response.first['content']).to be_nil }
end end
context 'requesting gitignores' do shared_examples_for 'requesting gitignores' do |path|
describe 'GET /gitignores' do
it 'returns a list of available gitignore templates' do it 'returns a list of available gitignore templates' do
get api('/gitignores') get api(path)
expect(response.status).to eq(200) expect(response).to have_http_status(200)
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.size).to be > 15 expect(json_response.size).to be > 15
end end
end end
end
context 'requesting gitlab-ci-ymls' do shared_examples_for 'requesting gitlab-ci-ymls' do |path|
describe 'GET /gitlab_ci_ymls' do
it 'returns a list of available gitlab_ci_ymls' do it 'returns a list of available gitlab_ci_ymls' do
get api('/gitlab_ci_ymls') get api(path)
expect(response.status).to eq(200) expect(response).to have_http_status(200)
expect(json_response).to be_an Array expect(json_response).to be_an Array
expect(json_response.first['name']).not_to be_nil expect(json_response.first['name']).not_to be_nil
end end
end end
end
describe 'GET /gitlab_ci_ymls/Ruby' do shared_examples_for 'requesting gitlab-ci-yml for Ruby' do |path|
it 'adds a disclaimer on the top' do it 'adds a disclaimer on the top' do
get api('/gitlab_ci_ymls/Ruby') get api(path)
expect(response).to have_http_status(200) expect(response).to have_http_status(200)
expect(json_response['name']).not_to be_nil
expect(json_response['content']).to start_with("# This file is a template,") expect(json_response['content']).to start_with("# This file is a template,")
end end
end end
shared_examples_for 'the License Template Entity' do |path|
before { get api(path) }
it 'returns a license template' do
expect(json_response['key']).to eq('mit')
expect(json_response['name']).to eq('MIT License')
expect(json_response['nickname']).to be_nil
expect(json_response['popular']).to be true
expect(json_response['html_url']).to eq('http://choosealicense.com/licenses/mit/')
expect(json_response['source_url']).to eq('https://opensource.org/licenses/MIT')
expect(json_response['description']).to include('A permissive license that is short and to the point.')
expect(json_response['conditions']).to eq(%w[include-copyright])
expect(json_response['permissions']).to eq(%w[commercial-use modifications distribution private-use])
expect(json_response['limitations']).to eq(%w[no-liability])
expect(json_response['content']).to include('The MIT License (MIT)')
end
end
shared_examples_for 'GET licenses' do |path|
it 'returns a list of available license templates' do
get api(path)
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(15)
expect(json_response.map { |l| l['key'] }).to include('agpl-3.0')
end
describe 'the popular parameter' do
context 'with popular=1' do
it 'returns a list of available popular license templates' do
get api("#{path}?popular=1")
expect(response).to have_http_status(200)
expect(json_response).to be_an Array
expect(json_response.size).to eq(3)
expect(json_response.map { |l| l['key'] }).to include('apache-2.0')
end
end
end
end
shared_examples_for 'GET licenses/:name' do |path|
context 'with :project and :fullname given' do
before do
get api("#{path}/#{license_type}?project=My+Awesome+Project&fullname=Anton+#{license_type.upcase}")
end
context 'for the mit license' do
let(:license_type) { 'mit' }
it 'returns the license text' do
expect(json_response['content']).to include('The MIT License (MIT)')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include("Copyright (c) #{Time.now.year} Anton")
end
end
context 'for the agpl-3.0 license' do
let(:license_type) { 'agpl-3.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU AFFERO GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the gpl-3.0 license' do
let(:license_type) { 'gpl-3.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the gpl-2.0 license' do
let(:license_type) { 'gpl-2.0' }
it 'returns the license text' do
expect(json_response['content']).to include('GNU GENERAL PUBLIC LICENSE')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include('My Awesome Project')
expect(json_response['content']).to include("Copyright (C) #{Time.now.year} Anton")
end
end
context 'for the apache-2.0 license' do
let(:license_type) { 'apache-2.0' }
it 'returns the license text' do
expect(json_response['content']).to include('Apache License')
end
it 'replaces placeholder values' do
expect(json_response['content']).to include("Copyright #{Time.now.year} Anton")
end
end
context 'for an uknown license' do
let(:license_type) { 'muth-over9000' }
it 'returns a 404' do
expect(response).to have_http_status(404)
end
end
end
context 'with no :fullname given' do
context 'with an authenticated user' do
let(:user) { create(:user) }
it 'replaces the copyright owner placeholder with the name of the current user' do
get api('/templates/licenses/mit', user)
expect(json_response['content']).to include("Copyright (c) #{Time.now.year} #{user.name}")
end
end
end
end
describe 'with /templates namespace' do
it_behaves_like 'the Template Entity', '/templates/gitignores/Ruby'
it_behaves_like 'the TemplateList Entity', '/templates/gitignores'
it_behaves_like 'requesting gitignores', '/templates/gitignores'
it_behaves_like 'requesting gitlab-ci-ymls', '/templates/gitlab_ci_ymls'
it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/templates/gitlab_ci_ymls/Ruby'
it_behaves_like 'the License Template Entity', '/templates/licenses/mit'
it_behaves_like 'GET licenses', '/templates/licenses'
it_behaves_like 'GET licenses/:name', '/templates/licenses'
end
describe 'without /templates namespace' do
it_behaves_like 'the Template Entity', '/gitignores/Ruby'
it_behaves_like 'the TemplateList Entity', '/gitignores'
it_behaves_like 'requesting gitignores', '/gitignores'
it_behaves_like 'requesting gitlab-ci-ymls', '/gitlab_ci_ymls'
it_behaves_like 'requesting gitlab-ci-yml for Ruby', '/gitlab_ci_ymls/Ruby'
it_behaves_like 'the License Template Entity', '/licenses/mit'
it_behaves_like 'GET licenses', '/licenses'
it_behaves_like 'GET licenses/:name', '/licenses'
end end
end end
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