diff --git a/.gitignore b/.gitignore index d4e690f..b7cb9b2 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ /spec/reports/ /tmp/ .byebug_history +.rubocop-* diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..9790ad7 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,4 @@ +# Please keep AllCops, Bundler, Style, Metrics groups and then order cops +# alphabetically +inherit_from: + - https://raw.githubusercontent.com/hanami/devtools/master/.rubocop.yml diff --git a/.travis.yml b/.travis.yml index 7900aa2..e76ade8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ before_install: - gem update --system - rvm @global do gem uninstall bundler -a -x - rvm @global do gem install bundler -v 1.14.6 -script: 'bundle exec rake --trace' +script: ./script/ci rvm: - 2.3.4 - 2.4.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 8709aca..06010d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Hanami::CLI General purpose Command Line Interface (CLI) framework for Ruby +## v0.1.0.beta2 - 2017-10-03 +### Added +- [Alfonso Uceda] Allow default value for arguments + ## v0.1.0.beta1 - 2017-08-11 ### Added - [Alfonso Uceda, Luca Guidi] Commands banner and usage diff --git a/Gemfile b/Gemfile index 2df5360..21db384 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,6 @@ unless ENV['TRAVIS'] gem 'yard', require: false end -gem 'hanami-utils', '1.1.0.beta1', require: false, git: 'https://github.com/hanami/utils.git', branch: 'develop' +gem 'hanami-utils', '1.1.0.beta2', require: false, git: 'https://github.com/hanami/utils.git', branch: 'develop' -gem 'rubocop', '0.49.1', require: false +gem 'hanami-devtools', require: false, git: 'https://github.com/hanami/devtools.git' diff --git a/hanami-cli.gemspec b/hanami-cli.gemspec index 407f985..a50a619 100644 --- a/hanami-cli.gemspec +++ b/hanami-cli.gemspec @@ -1,4 +1,4 @@ -# coding: utf-8 + lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'hanami/cli/version' @@ -16,17 +16,18 @@ Gem::Specification.new do |spec| spec.metadata['allowed_push_host'] = "https://rubygems.org" - spec.files = `git ls-files -z`.split("\x0").reject do |f| - f.match(%r{^(test|spec|features)/}) - end spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - spec.add_dependency "hanami-utils", "1.1.0.beta1" + spec.files = `git ls-files -z`.split("\x0").reject do |f| + f.match(%r{^(test|spec|features)/}) + end + + spec.add_dependency "hanami-utils", "1.1.0.beta2" spec.add_dependency "concurrent-ruby", "~> 1.0" - spec.add_development_dependency "bundler", "~> 1.14" - spec.add_development_dependency "rake", "~> 10.0" - spec.add_development_dependency "rspec", "~> 3.5" + spec.add_development_dependency "bundler", "~> 1.15" + spec.add_development_dependency "rake", "~> 12.0" + spec.add_development_dependency "rspec", "~> 3.6" end diff --git a/lib/hanami/cli/banner.rb b/lib/hanami/cli/banner.rb index 30ea39f..2d4f6c7 100644 --- a/lib/hanami/cli/banner.rb +++ b/lib/hanami/cli/banner.rb @@ -76,7 +76,7 @@ module Hanami # @since 0.1.0 # @api private - def self.arguments(command) + def self.arguments(command) # rubocop:disable Metrics/AbcSize required_arguments = command.required_arguments optional_arguments = command.optional_arguments @@ -97,6 +97,9 @@ module Hanami # @since 0.1.0 # @api private + # + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength def self.extended_command_options(command) result = command.options.map do |option| name = Utils::String.dasherize(option.name) @@ -116,6 +119,8 @@ module Hanami result << " --#{'help, -h'.ljust(30)}\t# Print this help" result.join("\n") end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize end end end diff --git a/lib/hanami/cli/command_registry.rb b/lib/hanami/cli/command_registry.rb index 6e522a8..37345b3 100644 --- a/lib/hanami/cli/command_registry.rb +++ b/lib/hanami/cli/command_registry.rb @@ -30,6 +30,9 @@ module Hanami # @since 0.1.0 # @api private + # + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength def get(arguments) node = @root args = [] @@ -57,6 +60,8 @@ module Hanami result end + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/AbcSize private diff --git a/lib/hanami/cli/parser.rb b/lib/hanami/cli/parser.rb index 574c209..9096461 100644 --- a/lib/hanami/cli/parser.rb +++ b/lib/hanami/cli/parser.rb @@ -64,7 +64,7 @@ module Hanami end end - parse_params.reject! { |key, value| value.nil? } + parse_params.reject! { |_key, value| value.nil? } Result.success(parsed_options.merge(parse_params)) end # rubocop:enable Metrics/MethodLength diff --git a/lib/hanami/cli/version.rb b/lib/hanami/cli/version.rb index 7cd67f2..d8e3ae9 100644 --- a/lib/hanami/cli/version.rb +++ b/lib/hanami/cli/version.rb @@ -1,6 +1,6 @@ module Hanami class CLI # @since 0.1.0 - VERSION = "0.1.0.beta1".freeze + VERSION = "0.1.0.beta2".freeze end end diff --git a/script/ci b/script/ci new file mode 100755 index 0000000..c495767 --- /dev/null +++ b/script/ci @@ -0,0 +1,51 @@ +#!/bin/bash +set -euo pipefail +IFS=$'\n\t' + +run_code_quality_checks() { + bundle exec rubocop . +} + +run_unit_tests() { + bundle exec rake spec:coverage +} + +run_isolation_tests() { + local pwd=$PWD + local root="$pwd/spec/isolation" + + if [ -d $root ]; then + for test in $(find $root -name '*_spec.rb') + do + run_isolation_test $test + + if [ $? -ne 0 ]; then + local exit_code=$? + echo "Failing test: $test" + exit $exit_code + fi + done + fi +} + +run_isolation_test() { + local test=$1 + + printf "\n\n\nRunning: $test\n" + ruby $test --options spec/isolation/.rspec +} + +run_test() { + local test=$1 + + printf "\n\n\nRunning: $test\n" + COVERAGE=true bundle exec rspec $test +} + +main() { + run_code_quality_checks && + run_unit_tests && + run_isolation_tests +} + +main diff --git a/spec/integration/commands_spec.rb b/spec/integration/commands_spec.rb index 1df42c8..45a7988 100644 --- a/spec/integration/commands_spec.rb +++ b/spec/integration/commands_spec.rb @@ -73,33 +73,33 @@ RSpec.describe "Commands" do it "with help param" do output = `foo server --help` - expected = <<-DESC -Command: - foo server + expected = <<~DESC + Command: + foo server -Usage: - foo server + Usage: + foo server -Description: - Start Foo server (only for development) + Description: + Start Foo server (only for development) -Options: - --server=VALUE # Force a server engine (eg, webrick, puma, thin, etc..) - --host=VALUE # The host address to bind to - --port=VALUE, -p VALUE # The port to run the server on - --debug=VALUE # Turn on debug output - --warn=VALUE # Turn on warnings - --daemonize=VALUE # Daemonize the server - --pid=VALUE # Path to write a pid file after daemonize - --[no-]code-reloading # Code reloading, default: true - --help, -h # Print this help + Options: + --server=VALUE # Force a server engine (eg, webrick, puma, thin, etc..) + --host=VALUE # The host address to bind to + --port=VALUE, -p VALUE # The port to run the server on + --debug=VALUE # Turn on debug output + --warn=VALUE # Turn on warnings + --daemonize=VALUE # Daemonize the server + --pid=VALUE # Path to write a pid file after daemonize + --[no-]code-reloading # Code reloading, default: true + --help, -h # Print this help -Examples: - foo server # Basic usage (it uses the bundled server engine) - foo server --server=webrick # Force `webrick` server engine - foo server --host=0.0.0.0 # Bind to a host - foo server --port=2306 # Bind to a port - foo server --no-code-reloading # Disable code reloading + Examples: + foo server # Basic usage (it uses the bundled server engine) + foo server --server=webrick # Force `webrick` server engine + foo server --host=0.0.0.0 # Bind to a host + foo server --port=2306 # Bind to a port + foo server --no-code-reloading # Disable code reloading DESC expect(output).to eq(expected) @@ -126,9 +126,9 @@ DESC it "an error is displayed if there aren't required params" do output = `foo new` - expected_output = <<-DESC -ERROR: "foo new" was called with no arguments -Usage: "foo new PROJECT" + expected_output = <<~DESC + ERROR: "foo new" was called with no arguments + Usage: "foo new PROJECT" DESC expect(output).to eq(expected_output) end diff --git a/spec/integration/rendering_spec.rb b/spec/integration/rendering_spec.rb index 8efc123..3cab9f8 100644 --- a/spec/integration/rendering_spec.rb +++ b/spec/integration/rendering_spec.rb @@ -2,19 +2,19 @@ RSpec.describe "Rendering" do it "prints required params" do output = `foo` - expected = <<-DESC -Commands: - foo assets [SUBCOMMAND] - foo console # Starts Foo console - foo db [SUBCOMMAND] - foo destroy [SUBCOMMAND] - foo generate [SUBCOMMAND] - foo hello # Print a greeting - foo new PROJECT # Generate a new Foo project - foo routes # Print routes - foo server # Start Foo server (only for development) - foo sub [SUBCOMMAND] - foo version # Print Foo version + expected = <<~DESC + Commands: + foo assets [SUBCOMMAND] + foo console # Starts Foo console + foo db [SUBCOMMAND] + foo destroy [SUBCOMMAND] + foo generate [SUBCOMMAND] + foo hello # Print a greeting + foo new PROJECT # Generate a new Foo project + foo routes # Print routes + foo server # Start Foo server (only for development) + foo sub [SUBCOMMAND] + foo version # Print Foo version DESC expect(output).to eq(expected) @@ -23,13 +23,13 @@ DESC it "prints required params with labels" do output = `foo destroy` - expected = <<-DESC -Commands: - foo destroy action APP ACTION # Destroy an action from app - foo destroy app APP # Destroy an app - foo destroy mailer MAILER # Destroy a mailer - foo destroy migration MIGRATION # Destroy a migration - foo destroy model MODEL # Destroy a model + expected = <<~DESC + Commands: + foo destroy action APP ACTION # Destroy an action from app + foo destroy app APP # Destroy an app + foo destroy mailer MAILER # Destroy a mailer + foo destroy migration MIGRATION # Destroy a migration + foo destroy model MODEL # Destroy a model DESC expect(output).to eq(expected) @@ -38,15 +38,15 @@ DESC it "prints available commands for unknown subcommand" do output = `foo generate unknown` - expected = <<-DESC -Commands: - foo generate action APP ACTION # Generate an action for app - foo generate app APP # Generate an app - foo generate mailer MAILER # Generate a mailer - foo generate migration MIGRATION # Generate a migration - foo generate model MODEL # Generate a model - foo generate secret [APP] # Generate session secret - foo generate webpack # Generate webpack configuration + expected = <<~DESC + Commands: + foo generate action APP ACTION # Generate an action for app + foo generate app APP # Generate an app + foo generate mailer MAILER # Generate a mailer + foo generate migration MIGRATION # Generate a migration + foo generate model MODEL # Generate a model + foo generate secret [APP] # Generate session secret + foo generate webpack # Generate webpack configuration DESC expect(output).to eq(expected) @@ -55,19 +55,19 @@ DESC it "prints available commands for unknown command" do output = `foo unknown` - expected = <<-DESC -Commands: - foo assets [SUBCOMMAND] - foo console # Starts Foo console - foo db [SUBCOMMAND] - foo destroy [SUBCOMMAND] - foo generate [SUBCOMMAND] - foo hello # Print a greeting - foo new PROJECT # Generate a new Foo project - foo routes # Print routes - foo server # Start Foo server (only for development) - foo sub [SUBCOMMAND] - foo version # Print Foo version + expected = <<~DESC + Commands: + foo assets [SUBCOMMAND] + foo console # Starts Foo console + foo db [SUBCOMMAND] + foo destroy [SUBCOMMAND] + foo generate [SUBCOMMAND] + foo hello # Print a greeting + foo new PROJECT # Generate a new Foo project + foo routes # Print routes + foo server # Start Foo server (only for development) + foo sub [SUBCOMMAND] + foo version # Print Foo version DESC expect(output).to eq(expected) @@ -76,19 +76,19 @@ DESC it "prints first level" do output = `foo` - expected = <<-DESC -Commands: - foo assets [SUBCOMMAND] - foo console # Starts Foo console - foo db [SUBCOMMAND] - foo destroy [SUBCOMMAND] - foo generate [SUBCOMMAND] - foo hello # Print a greeting - foo new PROJECT # Generate a new Foo project - foo routes # Print routes - foo server # Start Foo server (only for development) - foo sub [SUBCOMMAND] - foo version # Print Foo version + expected = <<~DESC + Commands: + foo assets [SUBCOMMAND] + foo console # Starts Foo console + foo db [SUBCOMMAND] + foo destroy [SUBCOMMAND] + foo generate [SUBCOMMAND] + foo hello # Print a greeting + foo new PROJECT # Generate a new Foo project + foo routes # Print routes + foo server # Start Foo server (only for development) + foo sub [SUBCOMMAND] + foo version # Print Foo version DESC expect(output).to eq(expected) @@ -97,15 +97,15 @@ DESC it "prints subcommand's commands" do output = `foo generate` - expected = <<-DESC -Commands: - foo generate action APP ACTION # Generate an action for app - foo generate app APP # Generate an app - foo generate mailer MAILER # Generate a mailer - foo generate migration MIGRATION # Generate a migration - foo generate model MODEL # Generate a model - foo generate secret [APP] # Generate session secret - foo generate webpack # Generate webpack configuration + expected = <<~DESC + Commands: + foo generate action APP ACTION # Generate an action for app + foo generate app APP # Generate an app + foo generate mailer MAILER # Generate a mailer + foo generate migration MIGRATION # Generate a migration + foo generate model MODEL # Generate a model + foo generate secret [APP] # Generate session secret + foo generate webpack # Generate webpack configuration DESC expect(output).to eq(expected) @@ -114,15 +114,15 @@ DESC it "prints subcommand's subcommand" do output = `foo generate application` - expected = <<-DESC -Commands: - foo generate action APP ACTION # Generate an action for app - foo generate app APP # Generate an app - foo generate mailer MAILER # Generate a mailer - foo generate migration MIGRATION # Generate a migration - foo generate model MODEL # Generate a model - foo generate secret [APP] # Generate session secret - foo generate webpack # Generate webpack configuration + expected = <<~DESC + Commands: + foo generate action APP ACTION # Generate an action for app + foo generate app APP # Generate an app + foo generate mailer MAILER # Generate a mailer + foo generate migration MIGRATION # Generate a migration + foo generate model MODEL # Generate a model + foo generate secret [APP] # Generate session secret + foo generate webpack # Generate webpack configuration DESC expect(output).to eq(expected) end @@ -130,23 +130,23 @@ DESC it "prints list options when calling help" do output = `foo console --help` - expected = <<-DESC -Command: - foo console + expected = <<~DESC + Command: + foo console -Usage: - foo console + Usage: + foo console -Description: - Starts Foo console + Description: + Starts Foo console -Options: - --engine=VALUE # Force a console engine: (irb/pry/ripl) - --help, -h # Print this help + Options: + --engine=VALUE # Force a console engine: (irb/pry/ripl) + --help, -h # Print this help -Examples: - foo console # Uses the bundled engine - foo console --engine=pry # Force to use Pry + Examples: + foo console # Uses the bundled engine + foo console --engine=pry # Force to use Pry DESC expect(output).to eq(expected) diff --git a/spec/integration/subcommands_spec.rb b/spec/integration/subcommands_spec.rb index 0da58b9..cc45206 100644 --- a/spec/integration/subcommands_spec.rb +++ b/spec/integration/subcommands_spec.rb @@ -1,9 +1,9 @@ RSpec.describe "Subcommands" do it "calls subcommand" do output = `foo generate model` - expected = <<-DESC -ERROR: "foo generate model" was called with no arguments -Usage: "foo generate model MODEL" + expected = <<~DESC + ERROR: "foo generate model" was called with no arguments + Usage: "foo generate model MODEL" DESC expect(output).to eq(expected) @@ -12,9 +12,9 @@ DESC context "works with params" do it "without params" do output = `foo generate model` - expected = <<-DESC -ERROR: "foo generate model" was called with no arguments -Usage: "foo generate model MODEL" + expected = <<~DESC + ERROR: "foo generate model" was called with no arguments + Usage: "foo generate model MODEL" DESC expect(output).to eq(expected) @@ -38,26 +38,26 @@ DESC it "with help param" do output = `foo generate model --help` - expected = <<-DESC -Command: - foo generate model + expected = <<~DESC + Command: + foo generate model -Usage: - foo generate model MODEL + Usage: + foo generate model MODEL -Description: - Generate a model + Description: + Generate a model -Arguments: - MODEL # REQUIRED Model name (eg. `user`) + Arguments: + MODEL # REQUIRED Model name (eg. `user`) -Options: - --[no-]skip-migration # Skip migration, default: false - --help, -h # Print this help + Options: + --[no-]skip-migration # Skip migration, default: false + --help, -h # Print this help -Examples: - foo generate model user # Generate `User` entity, `UserRepository` repository, and the migration - foo generate model user --skip-migration # Generate `User` entity and `UserRepository` repository + Examples: + foo generate model user # Generate `User` entity, `UserRepository` repository, and the migration + foo generate model user --skip-migration # Generate `User` entity and `UserRepository` repository DESC expect(output).to eq(expected) @@ -91,9 +91,9 @@ DESC it "an error is displayed if there aren't required params" do output = `foo destroy action` - expected = <<-DESC -ERROR: "foo destroy action" was called with no arguments -Usage: "foo destroy action APP ACTION" + expected = <<~DESC + ERROR: "foo destroy action" was called with no arguments + Usage: "foo destroy action APP ACTION" DESC expect(output).to eq(expected) @@ -101,9 +101,9 @@ DESC it "an error is displayed if there are some required params" do output = `foo destroy action web` - expected = <<-DESC -ERROR: "foo destroy action" was called with arguments [\"web\"] -Usage: "foo destroy action APP ACTION" + expected = <<~DESC + ERROR: "foo destroy action" was called with arguments [\"web\"] + Usage: "foo destroy action APP ACTION" DESC expect(output).to eq(expected) diff --git a/spec/support/fixtures/foo b/spec/support/fixtures/foo index b60c561..2f92fc3 100755 --- a/spec/support/fixtures/foo +++ b/spec/support/fixtures/foo @@ -1,5 +1,5 @@ #!/usr/bin/env ruby -$:.unshift __dir__ + '/../../lib' +$LOAD_PATH.unshift __dir__ + '/../../lib' require 'hanami/cli' module Foo @@ -25,7 +25,7 @@ module Foo class Console < Hanami::CLI::Command desc "Starts Foo console" - option :engine, desc: "Force a console engine", values: %w(irb pry ripl) + option :engine, desc: "Force a console engine", values: %w[irb pry ripl] example [ " # Uses the bundled engine", @@ -96,10 +96,10 @@ module Foo class Rollback < Hanami::CLI::Command desc "Rollback the database" - argument :versions, desc: "Number of versions to rollback", default: 1 + argument :steps, desc: "Number of versions to rollback", default: 1 - def call(versions:, **) - puts versions + def call(steps:, **) + puts steps end end end diff --git a/spec/unit/hanami/cli/version_spec.rb b/spec/unit/hanami/cli/version_spec.rb index c99c3a3..a622c90 100644 --- a/spec/unit/hanami/cli/version_spec.rb +++ b/spec/unit/hanami/cli/version_spec.rb @@ -1,5 +1,5 @@ RSpec.describe "Hanami::CLI::VERSION" do it "exposes version" do - expect(Hanami::CLI::VERSION).to eq("0.1.0.beta1") + expect(Hanami::CLI::VERSION).to eq("0.1.0.beta2") end end