Commit 620d014a authored by Z.J. van de Weg's avatar Z.J. van de Weg Committed by Alfredo Sumaran

Implement backend gitlab ci dropdown

This commit builds on the groundwork in
ee008e300b1ec0abcc90e6a30816ec0754cea0dd, which refactored the backend
so the same code could be used for new dropdowns. In this commit its
used for templates for the `.gitlab-ci.yml` files.
parent 567f6a7b
...@@ -186,10 +186,16 @@ module BlobHelper ...@@ -186,10 +186,16 @@ module BlobHelper
end end
def gitignore_names def gitignore_names
return @gitignore_names if defined?(@gitignore_names) @gitignore_names ||=
Gitlab::Template::Gitignore.categories.keys.map do |k|
[k, Gitlab::Template::Gitignore.by_category(k).map { |t| { name: t.name } }]
end.to_h
end
@gitignore_names = Gitlab::Template::Gitignore.categories.map do |k, _| def gitlab_ci_ymls
[k, Gitlab::Template::Gitignore.by_category(k)] @gitlab_ci_ymls ||=
end.to_h Gitlab::Template::GitlabCIYml.categories.keys.map do |k|
[k, Gitlab::Template::GitlabCIYml.by_category(k).map { |t| { name: t.name } }]
end.to_h
end end
end end
module API module API
class Templates < Grape::API class Templates < Grape::API
TEMPLATE_TYPES = { TEMPLATE_TYPES = {
gitignores: Gitlab::Template::Gitignore gitignores: Gitlab::Template::Gitignore,
gitlab_ci_ymls: Gitlab::Template::GitlabCIYml
}.freeze }.freeze
TEMPLATE_TYPES.each do |template, klass| TEMPLATE_TYPES.each do |template, klass|
......
...@@ -13,40 +13,53 @@ module Gitlab ...@@ -13,40 +13,53 @@ module Gitlab
File.read(@path) File.read(@path)
end end
def categories
raise NotImplementedError
end
def extension
raise NotImplementedError
end
def base_dir
raise NotImplementedError
end
class << self class << self
def all def all
self.category_directories.flat_map do |dir| self.categories.keys.flat_map { |cat| by_category(cat) }
templates_for_folder(dir)
end
end end
def find(key) def find(key)
file_name = "#{key}#{self.extension}" file_name = "#{key}#{self.extension}"
directory = select_directory(file_name) directory = select_directory(file_name)
directory ? new(File.join(directory, file_name)) : nil directory ? new(File.join(category_directory(directory), file_name)) : nil
end end
def by_category(category) def by_category(category)
templates_for_folder(categories[category]) templates_for_directory(category_directory(category))
end end
def category_directories def category_directory(category)
self.categories.values.map { |subdir| File.join(base_dir, subdir)} File.join(base_dir, categories[category])
end end
private private
def select_directory(file_name) def select_directory(file_name)
category_directories.find { |dir| File.exist?(File.join(dir, file_name)) } categories.keys.find do |category|
File.exist?(File.join(category_directory(category), file_name))
end
end end
def templates_for_folder(dir) def templates_for_directory(dir)
Dir.glob("#{dir.to_s}/*#{self.extension}").select { |f| f =~ filter_regex }.map { |f| new(f) } dir << '/' unless dir.end_with?('/')
Dir.glob(File.join(dir, "*#{self.extension}")).select { |f| f =~ filter_regex }.map { |f| new(f) }
end end
def filter_regex def filter_regex
/#{Regexp.escape(extension)}\z/ @filter_reges ||= /#{Regexp.escape(extension)}\z/
end end
end end
end end
......
module Gitlab module Gitlab
module Template module Template
class Gitignore < BaseTemplate class Gitignore < BaseTemplate
class << self class << self
def extension def extension
'.gitignore' '.gitignore'
...@@ -9,8 +8,8 @@ module Gitlab ...@@ -9,8 +8,8 @@ module Gitlab
def categories def categories
{ {
Languages: '', "Languages" => '',
Global: 'Global' "Global" => 'Global'
} }
end end
......
module Gitlab
module Template
class GitlabCIYml < BaseTemplate
class << self
def extension
'.gitlab-ci.yml'
end
def categories
{
"General" => '',
"Pages" =>'Pages'
}
end
def base_dir
Rails.root.join('vendor/gitlab-ci-yml')
end
end
end
end
end
namespace :gitlab do namespace :gitlab do
desc "GitLab | Update templates" desc "GitLab | Update templates"
task :update_templates do task :update_templates do
update("gitignore") TEMPLATE_DATA.each { |template| update(template) }
update("gitlab-ci-yml")
end end
def update(directory) def update(template)
unless clone_repository(directory) sub_dir = template.repo_url.match(/([a-z-]+)\.git\z/)[1]
puts "Cloning the #{directory} templates failed".red dir = File.join(vendor_directory, sub_dir)
unless clone_repository(template.repo_url, dir)
puts "Cloning the #{sub_dir} templates failed".red
return return
end end
remove_unneeded_files(directory) remove_unneeded_files(dir, template.cleanup_regex)
puts "Done".green puts "Done".green
end end
def clone_repository(directory) def clone_repository(url, directory)
dir = File.join(vendor_directory, directory) FileUtils.rm_rf(directory) if Dir.exist?(directory)
FileUtils.rm_rf(dir) if Dir.exist?(dir)
FileUtils.cd vendor_directory
system("git clone --depth=1 --branch=master #{TEMPLATE_DATA[directory]}") system("git clone #{url} --depth=1 --branch=master #{directory}")
end end
# Retain only certain files: # Retain only certain files:
# - The LICENSE, because we have to # - The LICENSE, because we have to
# - The sub dir global # - The sub dirs so we can organise the file by category
# - The gitignores themself # - The templates themself
# - Dir.entires returns also the entries '.' and '..' # - Dir.entires returns also the entries '.' and '..'
def remove_unneeded_files(directory) def remove_unneeded_files(directory, regex)
regex = CLEANUP_REGEX[directory]
Dir.foreach(directory) do |file| Dir.foreach(directory) do |file|
FileUtils.rm_rf(File.join(directory, file)) unless file =~ regex FileUtils.rm_rf(File.join(directory, file)) unless file =~ regex
end end
...@@ -37,25 +36,17 @@ namespace :gitlab do ...@@ -37,25 +36,17 @@ namespace :gitlab do
private private
TEMPLATE_DATA = { Template = Struct.new(:repo_url, :cleanup_regex)
"gitignore" => "https://github.com/github/gitignore.git", TEMPLATE_DATA = [Template.new(
"gitlab-ci-yml" => "https://gitlab.com/gitlab-org/gitlab-ci-yml.git" "https://github.com/github/gitignore.git",
}.freeze /(\.{1,2}|LICENSE|Global|\.gitignore)\z/
),
CLEANUP_REGEX = { Template.new(
"gitignore" => /(\.{1,2}|LICENSE|Global|\.gitignore)\z/, "https://gitlab.com/gitlab-org/gitlab-ci-yml.git",
"gitlab-ci-yml" => /(\.{1,2}|LICENSE|Pages|\.gitignore)\z/ /(\.{1,2}|LICENSE|Pages|\.gitignore)\z/
}.freeze )]
def vendor_directory def vendor_directory
Rails.root.join('vendor') Rails.root.join('vendor')
end end
def gitignore_directory
File.join(vendor_directory, 'gitignore')
end
def gitlab_ci_directory
File.join(vendor_directory, 'gitlab-ci')
end
end end
...@@ -3,27 +3,41 @@ require 'spec_helper' ...@@ -3,27 +3,41 @@ require 'spec_helper'
describe API::Templates, api: true do describe API::Templates, api: true do
include ApiHelpers include ApiHelpers
describe 'Entity Gitignore' do describe 'the Template Entity' do
before { get api('/gitignores/Ruby') } 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 'Entity GitignoresList' do describe 'the TemplateList Entity' do
before { get api('/gitignores') } before { get api('/gitignores') }
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
describe 'GET /gitignores' do context 'requesting gitignores' do
it 'returns a list of available license templates' do describe 'GET /gitignores' do
get api('/gitignores') it 'returns a list of available gitignore templates' do
get api('/gitignores')
expect(response.status).to eq(200) expect(response.status).to eq(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
context 'requesting gitlab-ci-ymls' do
describe 'GET /gitlab_ci_ymls' do
it 'returns a list of available gitlab_ci_ymls' do
get api('/gitlab_ci_ymls')
expect(response.status).to eq(200)
expect(json_response).to be_an Array
expect(json_response.first['name']).not_to be_nil
end
end end
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