Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions built_in/git_flow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module Shift
module BuiltIn
class GitFlow

class ValidationError < ShiftError
end

def self.execute(arguments)
raise UnknownAction.new({message: "You should provide a valid action."}) unless !arguments[0].nil?
case arguments[0]
when :validate
GitFlow.validate
else
raise UnknownAction.new({message: "Unknown action: #{arguments[0]}."})
end
end

def self.validate
branches = BuiltIn::Sh.execute(["git branch -a"])
raise ValidationError.new({message: "master branch is missing."}) if branches.match(/remotes\/origin\/master/).nil?
raise ValidationError.new({message: "develop branch is missing."}) if branches.match(/remotes\/origin\/develop/).nil?
non_git_flow_branches = branches.scan(/remotes\/origin\/(?!(feature|develop|master|release|hotfix))(.+)/)
raise ValidationError.new({message: "The following branches are not compatible with Git flow: #{non_git_flow_branches.join(', ')}"}) if non_git_flow_branches.count > 0
end
end
end
end
55 changes: 55 additions & 0 deletions built_in/github_community.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module Shift
module BuiltIn
class GithubCommunity

class UnknownAction < ShiftError
end

class ValidationError < ShiftErrors
end

def self.execute(arguments)
raise UnknownAction.new({message: "You should provide a valid action."}) unless !arguments[0].nil?
case arguments[0]
when :validate
GithubCommunity.validate
else
raise UnknownAction.new({message: "Unknown action: #{arguments[0]}."})
end
end

def self.validate
errors = []
errors.push({ severity: :error, message: "README.md is missing." }) if ! File.exists?("README.md")
GithubCommunity.validate_markdown("README.md", errors) if File.exists?("README.md")
errors.push({ severity: :error, message: "CONTRIBUTING.md is missing." }) if ! File.exists?("CONTRIBUTING.md")
GithubCommunity.validate_markdown("CONTRIBUTING.md", errors) if File.exists?("CONTRIBUTING.md")
errors.push({ severity: :warning, message: "MANIFESTO.md is missing." }) if ! File.exists?("MANIFESTO.md")
GithubCommunity.validate_markdown("MANIFESTO.md", errors) if File.exists?("MANIFESTO.md")
errors.push({ severity: :warning, message: "LICENSE is missing." }) if ! File.exists?("LICENSE")
errors.push({ severity: :warning, message: "CODE_OF_CONDUCT.md is missing." }) if ! File.exists?("CODE_OF_CONDUCT.md")
GithubCommunity.validate_markdown("CODE_OF_CONDUCT.md", errors) if File.exists?("CODE_OF_CONDUCT.md")
errors.push({ severity: :error, message: ".github is missing." }) if ! Dir.exist?(".github")
errors.push({ severity: :error, message: "ISSUE_TEMPLATE is missing." }) if ((! Dir.exist?(".github/ISSUE_TEMPLATE") || Dir.empty?(".github/ISSUE_TEMPLATE")) &&
(! Dir.exist?(".github/issue_template") || Dir.empty?(".github/issue_template")) &&
(! File.exists?(".github/ISSUE_TEMPLATE.md")) &&
(! File.exists?(".github/issue_template.md")))
errors.push({ severity: :error, message: "PULL_REQUEST_TEMPLATE is missing." }) if ((! Dir.exist?(".github/PULL_REQUEST_TEMPLATE") || Dir.empty?(".github/PULL_REQUEST_TEMPLATE")) &&
(! Dir.exist?(".github/pull_request_template") || Dir.empty?(".github/pull_request_template")) &&
(! File.exists?(".github/PULL_REQUEST_TEMPLATE.md")) &&
(! File.exists?(".github/pull_request_template.md")))
raise ValidationError.new(errors) if errors.count > 0
end

private

def self.validate_markdown(file_path, errors)
begin
BuiltIn::Markdown.validate(file_path)
rescue MarkdownError => markdown_error
errors.push({ severity: :error, message: markdown_error.message })
end
end
end
end
end
7 changes: 5 additions & 2 deletions built_in/markdown.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

module Shift

class MarkdownUnknownCommand < StandardError
class MarkdownError < StandardError
end

class MarkdownContainsNotFoundLink < StandardError
class MarkdownUnknownCommand < MarkdownError
end

class MarkdownContainsNotFoundLink < MarkdownError
end

module BuiltIn
Expand Down
2 changes: 1 addition & 1 deletion built_in/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def execute(built_in_name, arguments)
end

def self.built_in_class_ref(built_in_name)
class_name = "BuiltIn::" + built_in_name.capitalize
class_name = "BuiltIn::" + built_in_name.shift_class
begin
return Shift.const_get(class_name)
rescue NameError
Expand Down
2 changes: 1 addition & 1 deletion built_in/sh.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def self.execute(arguments)
exit_status = thread.value.exitstatus
end
raise BuiltInFailed.new(result) if exit_status != 0
return true
return result
end
end
end
Expand Down
48 changes: 44 additions & 4 deletions shift.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
module Shift
class CommandFailed < StandardError
end

class ShiftError < StandardError
attr_accessor :error

def initialize(error)
error[:severity] = :error if ! error.key?(:severity)
@error = error
super(error[:message])
end
end

class ShiftErrors < StandardError
attr_accessor :errors

def initialize(errors = [])
errors.each { |error| error[:severity] = :error if ! error.key?(:severity) }
@errors = errors
super(errors.map { |error| error[:message] }.join('\n'))
end
end
end

require_relative "string"
require_relative "built_in/service"
require_relative "filter/service"
require_relative "rule/service"
Expand Down Expand Up @@ -46,10 +67,20 @@ def respond_to_missing?(method_sym, private = false)

def method_missing(method_sym, *arguments, &_block)
return super if respond_to_missing?(method_sym) == false
return @filter_service.filter(method_sym.to_s, arguments) if @filter_service.can_be_executed?(method_sym.to_s) == true
return execute_rule(method_sym.to_s, arguments) if @rule_service.can_be_executed?(method_sym.to_s) == true
return @built_in_service.execute(method_sym.to_s, arguments) if @built_in_service.can_be_executed?(method_sym.to_s) == true
return super
begin
return @filter_service.filter(method_sym.to_s, arguments) if @filter_service.can_be_executed?(method_sym.to_s) == true
return execute_rule(method_sym.to_s, arguments) if @rule_service.can_be_executed?(method_sym.to_s) == true
return @built_in_service.execute(method_sym.to_s, arguments) if @built_in_service.can_be_executed?(method_sym.to_s) == true
return super
rescue Shift::ShiftError => shift_error
display_error(shift_error.error)
raise shift_error if shift_error.error[:severity] == :error
rescue Shift::ShiftErrors => shift_errors
shift_errors.errors.each { |error| display_error(error) }
raise shift_errors if shift_errors.errors.any? { |error| error[:severity] == :error }
rescue => e
raise e
end
end

private
Expand All @@ -69,5 +100,14 @@ def execute_rule(method_sym, arguments)
end
return nil
end

def display_error(error)
case error[:severity]
when :error
puts "💥 Error: #{error[:message]}"
when :warning
puts "⚠️ Warning: #{error[:message]}"
end
end
end
end
34 changes: 34 additions & 0 deletions spec/git_flow/git_flow_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require_relative "../../shift"

mock_folder_name = "./spec/git_flow/mock"

describe Shift::ShiftCore, "a user want to validate the presence of Git flow" do
context "with master branch missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
folder = Shift::ShiftFolder.new(mock_folder_name, 'missing_master')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GitFlow::ValidationError
end
end
context "with develop branch missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
folder = Shift::ShiftFolder.new(mock_folder_name, 'missing_develop')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GitFlow::ValidationError
end
end
context "with branch does not follow the Git flow standard" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
folder = Shift::ShiftFolder.new(mock_folder_name, 'not_follow_git_flow_standard')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GitFlow::ValidationError
end
end
context "with all the branches follow the Git flow standard" do
it "should execute the :beta lane" do
core = Shift::ShiftCore.new
folder = Shift::ShiftFolder.new(mock_folder_name, 'follow_git_flow_standard')
expect { core.execute_lane(:beta, folder) }.not_to raise_error
end
end
end
10 changes: 10 additions & 0 deletions spec/git_flow/mock/follow_git_flow_standard
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
before_all do
sh "rm -rf /tmp/follow_git_flow_standard"
sh "mkdir /tmp/follow_git_flow_standard; cd /tmp/follow_git_flow_standard; git init; touch empty; git add .; git commit -m 'Initial commit'; git checkout -b remotes/origin/master; git checkout -b remotes/origin/develop; git checkout -b remotes/origin/feature/toto; git checkout -b remotes/origin/release/0.4.1; git checkout -b remotes/origin/hotfix/fix-ci"
end

lane :beta do
Dir.chdir("/tmp/follow_git_flow_standard") do
git_flow :validate
end
end
10 changes: 10 additions & 0 deletions spec/git_flow/mock/missing_develop
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
before_all do
sh "rm -rf /tmp/missing_develop"
sh "mkdir /tmp/missing_develop; cd /tmp/missing_develop; git init; touch empty; git add .; git commit -m 'Initial commit'; git checkout -b remotes/origin/master"
end

lane :beta do
Dir.chdir("/tmp/missing_develop") do
git_flow :validate
end
end
10 changes: 10 additions & 0 deletions spec/git_flow/mock/missing_master
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
before_all do
sh "rm -rf /tmp/missing_master"
sh "mkdir /tmp/missing_master; cd /tmp/missing_master; git init"
end

lane :beta do
Dir.chdir("/tmp/missing_master") do
git_flow :validate
end
end
10 changes: 10 additions & 0 deletions spec/git_flow/mock/not_follow_git_flow_standard
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
before_all do
sh "rm -rf /tmp/not_follow_git_flow_standard"
sh "mkdir /tmp/not_follow_git_flow_standard; cd /tmp/not_follow_git_flow_standard; git init; touch empty; git add .; git commit -m 'Initial commit'; git checkout -b remotes/origin/master; git checkout -b remotes/origin/develop; git checkout -b remotes/origin/feature/toto; git checkout -b remotes/origin/toto"
end

lane :beta do
Dir.chdir("/tmp/not_follow_git_flow_standard") do
git_flow :validate
end
end
51 changes: 51 additions & 0 deletions spec/github_community/github_community_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require_relative "../../shift"

mock_folder_name = "./spec/github_community/mock"

describe Shift::ShiftCore, "a user want to validate the implementation of Github community standard" do
context "with issue template files missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
Dir.chdir(mock_folder_name + '/missing_issue_template') do
folder = Shift::ShiftFolder.new('missing_issue_template')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GithubCommunity::ValidationError
end
end
end
context "with pull request template files missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
Dir.chdir(mock_folder_name + '/missing_pr_template') do
folder = Shift::ShiftFolder.new('missing_pr_template')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GithubCommunity::ValidationError
end
end
end
context "with readme file missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
Dir.chdir(mock_folder_name + '/missing_readme') do
folder = Shift::ShiftFolder.new('missing_readme')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GithubCommunity::ValidationError
end
end
end
context "with contibuting file missing" do
it "should not execute the :beta lane" do
core = Shift::ShiftCore.new
Dir.chdir(mock_folder_name + '/missing_contributing') do
folder = Shift::ShiftFolder.new('missing_contributing')
expect { core.execute_lane(:beta, folder) }.to raise_error Shift::BuiltIn::GithubCommunity::ValidationError
end
end
end
context "with all existing Github community files" do
it "should execute the :beta lane" do
core = Shift::ShiftCore.new
Dir.chdir(mock_folder_name + '/existing_github_community_files') do
folder = Shift::ShiftFolder.new('existing_github_community_files')
expect { core.execute_lane(:beta, folder) }.not_to raise_error
end
end
end
end
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lane :beta do
github_community :validate
end
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions spec/github_community/mock/missing_contributing/Shiftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lane :beta do
github_community :validate
end
Empty file.
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions spec/github_community/mock/missing_issue_template/Shiftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lane :beta do
github_community :validate
end
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions spec/github_community/mock/missing_pr_template/Shiftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lane :beta do
github_community :validate
end
Empty file.
Empty file.
Empty file.
Empty file.
3 changes: 3 additions & 0 deletions spec/github_community/mock/missing_readme/Shiftfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lane :beta do
github_community :validate
end
5 changes: 5 additions & 0 deletions string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class String
def shift_class
split('_').collect!(&:capitalize).join
end
end