From d3ffbf4836983d34f27113a0e1af1b3496d1ce17 Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 09:45:50 +0100 Subject: [PATCH 1/6] Boolean args --- .github/workflows/test_and_publish.yml | 74 +++++++++++++------------- .github/workflows/test_only.yml | 42 +++++++-------- .rubocop.yml | 4 +- .ruby-version | 2 +- CHANGELOG.md | 8 +++ Gemfile | 11 +++- dev_oops.gemspec | 15 ++---- dev_oops/example.json | 19 +++++++ dev_oops/example.sh | 13 +++++ lib/dev_oops/runner.rb | 4 +- lib/dev_oops/scripts_loader.rb | 29 +++++----- lib/dev_oops/version.rb | 2 +- 12 files changed, 132 insertions(+), 91 deletions(-) create mode 100644 dev_oops/example.json create mode 100755 dev_oops/example.sh diff --git a/.github/workflows/test_and_publish.yml b/.github/workflows/test_and_publish.yml index 4b1e4c9..db2c048 100644 --- a/.github/workflows/test_and_publish.yml +++ b/.github/workflows/test_and_publish.yml @@ -2,57 +2,57 @@ name: Test and Release on: push: - branches: + branches: - main jobs: tests: strategy: matrix: - ruby: [2.6, 2.7, 3.0] + ruby: [3.2, 3.3, 3.4] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - bundler-cache: true - - name: Run linter - run: bundle exec rubocop - - name: Run tests - run: bundle exec rspec + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run linter + run: bundle exec rubocop + - name: Run tests + run: bundle exec rspec prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Install yarn dep - run: yarn install - - name: Check prettier - run: yarn prettier -c '**/*.rb' + - uses: actions/checkout@v2 + - name: Set up Node + uses: actions/setup-node@v2 + with: + node-version: "24" + - name: Install yarn dep + run: yarn install + - name: Check prettier + run: yarn prettier -c '**/*.rb' release: needs: [tests, prettier] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: 3.0 - bundler-cache: true - - name: Prepare credentials - env: - RUBYGEM_KEY: ${{ secrets.RUBYGEM_KEY }} - run: "mkdir -p ~/.gem && echo -e \"---\\r\\n:rubygems_api_key: $RUBYGEM_KEY\" > ~/.gem/credentials && chmod 0600 ~/.gem/credentials" - - name: Setup username/email - run: "git config --global user.email zaratan@hey.com && git config --global user.name \"Denis Pasin\"" - - name: Fetch tags from remote - run: "git fetch -t" - - name: Publish if version change - run: 'git diff `git tag | tail -1` -- lib/dev_oops/version.rb | grep -E "^\+.*VERSION" && rake release || echo "No release for now"' + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.0 + bundler-cache: true + - name: Prepare credentials + env: + RUBYGEM_KEY: ${{ secrets.RUBYGEM_KEY }} + run: "mkdir -p ~/.gem && echo -e \"---\\r\\n:rubygems_api_key: $RUBYGEM_KEY\" > ~/.gem/credentials && chmod 0600 ~/.gem/credentials" + - name: Setup username/email + run: 'git config --global user.email zaratan@hey.com && git config --global user.name "Denis Pasin"' + - name: Fetch tags from remote + run: "git fetch -t" + - name: Publish if version change + run: 'git diff `git tag | tail -1` -- lib/dev_oops/version.rb | grep -E "^\+.*VERSION" && rake release || echo "No release for now"' diff --git a/.github/workflows/test_only.yml b/.github/workflows/test_only.yml index db66177..241b246 100644 --- a/.github/workflows/test_only.yml +++ b/.github/workflows/test_only.yml @@ -2,36 +2,36 @@ name: Tests on: push: - branches-ignore: + branches-ignore: - main jobs: tests: strategy: matrix: - ruby: [2.6, 2.7, 3.0] + ruby: [3.2, 3.3, 3.4] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Ruby - uses: ruby/setup-ruby@v1 - with: - ruby-version: ${{ matrix.ruby }} - bundler-cache: true - - name: Run linter - run: bundle exec rubocop - - name: Run tests - run: bundle exec rspec + - uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run linter + run: bundle exec rubocop + - name: Run tests + run: bundle exec rspec prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Node - uses: actions/setup-node@v2 - with: - node-version: '14' - - name: Install yarn dep - run: yarn install - - name: Check prettier - run: yarn prettier -c '**/*.rb' + - uses: actions/checkout@v2 + - name: Set up Node + uses: actions/setup-node@v2 + with: + node-version: "24" + - name: Install yarn dep + run: yarn install + - name: Check prettier + run: yarn prettier -c '**/*.rb' diff --git a/.rubocop.yml b/.rubocop.yml index 44c9be4..92e59ab 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,5 @@ inherit_from: - - http://relaxed.ruby.style/rubocop.yml + - ./.rubocop-http---relaxed-ruby-style-rubocop-yml inherit_gem: prettier: rubocop.yml @@ -14,7 +14,7 @@ AllCops: SuggestExtensions: false Exclude: - "bin/*" - - 'vendor/**/*' + - "vendor/**/*" - "node_modules/**/*" Gemspec/RequiredRubyVersion: diff --git a/.ruby-version b/.ruby-version index 9f55b2c..2aa5131 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.0 +3.4.7 diff --git a/CHANGELOG.md b/CHANGELOG.md index 283ca74..c73f29f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.1] - 2025-12-17 + +Accepting boolean args + +### Added + +- boolean args are supported + ## [0.2.0] - 2021-04-03 Refactoring architecture + Basic Documentation diff --git a/Gemfile b/Gemfile index 101257e..9ffacf0 100644 --- a/Gemfile +++ b/Gemfile @@ -5,5 +5,12 @@ source 'https://rubygems.org' # Specify your gem's dependencies in dev_oops.gemspec gemspec -gem 'rake', '~> 12.0' -gem 'rspec', '~> 3.0' +gem 'bundler' +gem 'bundler-audit', '> 0.6.0' +gem 'prettier' +gem 'pry-byebug' +gem 'rake' +gem 'rspec' +gem 'rubocop' +gem 'rubocop-performance' +gem 'solargraph' diff --git a/dev_oops.gemspec b/dev_oops.gemspec index 8f5286e..3125591 100644 --- a/dev_oops.gemspec +++ b/dev_oops.gemspec @@ -16,6 +16,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0') spec.metadata['homepage_uri'] = spec.homepage + spec.metadata['rubygems_mfa_required'] = 'true' # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." @@ -32,16 +33,6 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ['lib'] - spec.add_runtime_dependency 'thor' - spec.add_runtime_dependency 'zeitwerk' - - spec.add_development_dependency 'bundler' - spec.add_development_dependency 'bundler-audit', '> 0.6.0' - spec.add_development_dependency 'prettier' - spec.add_development_dependency 'pry-byebug' - spec.add_development_dependency 'rake' - spec.add_development_dependency 'rspec' - spec.add_development_dependency 'rubocop' - spec.add_development_dependency 'rubocop-performance' - spec.add_development_dependency 'solargraph' + spec.add_dependency 'thor' + spec.add_dependency 'zeitwerk' end diff --git a/dev_oops/example.json b/dev_oops/example.json new file mode 100644 index 0000000..2930665 --- /dev/null +++ b/dev_oops/example.json @@ -0,0 +1,19 @@ +{ + "desc": "Example command to demonstrate the gem usage", + "usage": "example [boolean_flag] [--test_me|-t]", + "args": [ + { + "name": "boolean_flag", + "desc": "A boolean flag to demonstrate functionality", + "aliases": ["b"], + "required": false, + "boolean": true + }, + { + "name": "test_me", + "desc": "An optional flag to test the command", + "aliases": ["t"], + "required": false + } + ] +} diff --git a/dev_oops/example.sh b/dev_oops/example.sh new file mode 100755 index 0000000..789d664 --- /dev/null +++ b/dev_oops/example.sh @@ -0,0 +1,13 @@ +if [[ $test_me == "yes" ]]; then + echo "Test me is set to yes" +else + echo "Test me is not set to yes" +fi + +if [[ -z $boolean_flag ]]; then + echo "Boolean flag is not set" +else + echo "Boolean flag is set to $boolean_flag" +fi + +echo "This is an example script." diff --git a/lib/dev_oops/runner.rb b/lib/dev_oops/runner.rb index 1e3b76e..03498bf 100644 --- a/lib/dev_oops/runner.rb +++ b/lib/dev_oops/runner.rb @@ -4,8 +4,8 @@ class Runner < Thor include Thor::Actions REGISTERED_CLASS_METHODS = {} # rubocop:disable Style/MutableConstant - CONFIG_DIR = "#{ENV['HOME']}/.dev_oops" - FileUtils.mkdir CONFIG_DIR unless Dir.exist?(CONFIG_DIR) + CONFIG_DIR = "#{Dir.home}/.dev_oops" + FileUtils.mkdir_p CONFIG_DIR def self.source_root "#{File.dirname(__FILE__)}/.." diff --git a/lib/dev_oops/scripts_loader.rb b/lib/dev_oops/scripts_loader.rb index 7f385aa..9df313f 100644 --- a/lib/dev_oops/scripts_loader.rb +++ b/lib/dev_oops/scripts_loader.rb @@ -56,7 +56,8 @@ def self.load def self.script_dir(script_name) scripts = self.load scripts.find { |script| script.name == script_name }&.dir || - Dir.exist?("#{Dir.pwd}/dev_oops") && "#{Dir.pwd}/dev_oops" || GLOBAL_DIR + (Dir.exist?("#{Dir.pwd}/dev_oops") && "#{Dir.pwd}/dev_oops") || + GLOBAL_DIR end def self.build_action(config) @@ -67,24 +68,26 @@ def self.build_action(config) desc: arg['desc'] || '', aliases: arg['aliases'] || [], required: arg['required'] || false, - default: arg['default'] + default: arg['default'], + boolean: arg['boolean'] || false ) end - define_singleton_method('banner') { config.usage } + define_singleton_method(:banner) { config.usage } - define_method('perform') do + define_method(:perform) do + require 'pry' + binding.pry env_vars = options.map { |k, v| "#{k}=#{v}" }.join(' ') - if config.script_location && !config.script_location.empty? - location = - if config.script_location.start_with?('/') - config.script_location - else - "#{ENV['HOME']}/#{config.script_location}" - end - system("#{env_vars} #{ENV['SHELL']} -c #{location}") - end + return unless config.script_location && !config.script_location.empty? + location = + if config.script_location.start_with?('/') + config.script_location + else + "#{Dir.home}/#{config.script_location}" + end + system("#{env_vars} #{ENV.fetch('SHELL', nil)} -c #{location}") end end end diff --git a/lib/dev_oops/version.rb b/lib/dev_oops/version.rb index b861627..950a4cd 100644 --- a/lib/dev_oops/version.rb +++ b/lib/dev_oops/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module DevOops - VERSION = '0.3.0.1' + VERSION = '0.3.1' end From cf6eda8d40ea693ba553906767b5a77ce230238d Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 09:59:59 +0100 Subject: [PATCH 2/6] Fixing prettier --- Gemfile | 20 +++--- dev_oops.gemspec | 35 +++++------ lib/dev_oops.rb | 10 +-- lib/dev_oops/commands/edit_script.rb | 8 +-- lib/dev_oops/commands/edit_script_sh.rb | 6 +- lib/dev_oops/commands/local_install.rb | 4 +- lib/dev_oops/commands/remove_script.rb | 6 +- lib/dev_oops/runner.rb | 22 +++---- lib/dev_oops/scripts_loader.rb | 82 +++++++++++++------------ lib/dev_oops/version.rb | 2 +- package.json | 18 +++++- spec/dev_oops_spec.rb | 2 +- spec/spec_helper.rb | 6 +- yarn.lock | 18 +++--- 14 files changed, 127 insertions(+), 112 deletions(-) diff --git a/Gemfile b/Gemfile index 9ffacf0..14dcb3a 100644 --- a/Gemfile +++ b/Gemfile @@ -1,16 +1,16 @@ # frozen_string_literal: true -source 'https://rubygems.org' +source "https://rubygems.org" # Specify your gem's dependencies in dev_oops.gemspec gemspec -gem 'bundler' -gem 'bundler-audit', '> 0.6.0' -gem 'prettier' -gem 'pry-byebug' -gem 'rake' -gem 'rspec' -gem 'rubocop' -gem 'rubocop-performance' -gem 'solargraph' +gem "bundler" +gem "bundler-audit", "> 0.6.0" +gem "prettier" +gem "pry-byebug" +gem "rake" +gem "rspec" +gem "rubocop" +gem "rubocop-performance" +gem "solargraph" diff --git a/dev_oops.gemspec b/dev_oops.gemspec index 3125591..f5d00f7 100644 --- a/dev_oops.gemspec +++ b/dev_oops.gemspec @@ -1,22 +1,22 @@ # frozen_string_literal: true -require_relative 'lib/dev_oops/version' +require_relative "lib/dev_oops/version" Gem::Specification.new do |spec| - spec.name = 'dev_oops' + spec.name = "dev_oops" spec.version = DevOops::VERSION - spec.authors = ['Denis Pasin'] - spec.email = ['zaratan@hey.com'] + spec.authors = ["Denis Pasin"] + spec.email = ["zaratan@hey.com"] - spec.summary = 'Shell snipets manager' + spec.summary = "Shell snipets manager" spec.description = - 'Shell snipets manager for those scripts you end up copy pasting over and over' - spec.homepage = 'https://zaratan.fr' - spec.license = 'MIT' - spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0') + "Shell snipets manager for those scripts you end up copy pasting over and over" + spec.homepage = "https://zaratan.fr" + spec.license = "MIT" + spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0") - spec.metadata['homepage_uri'] = spec.homepage - spec.metadata['rubygems_mfa_required'] = 'true' + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["rubygems_mfa_required"] = "true" # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here." # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here." @@ -25,14 +25,13 @@ Gem::Specification.new do |spec| # The `git ls-files -z` loads the files in the RubyGem that have been added into git. spec.files = Dir.chdir(File.expand_path(__dir__)) do - `git ls-files -z`.split("\x0").reject do |f| - f.match(%r{^(test|spec|features)/}) - end + `git ls-files -z`.split("\x0") + .reject { |f| f.match(%r{^(test|spec|features)/}) } end - spec.bindir = 'exe' + spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ['lib'] + spec.require_paths = ["lib"] - spec.add_dependency 'thor' - spec.add_dependency 'zeitwerk' + spec.add_dependency "thor" + spec.add_dependency "zeitwerk" end diff --git a/lib/dev_oops.rb b/lib/dev_oops.rb index 1c70e11..28ac0ee 100644 --- a/lib/dev_oops.rb +++ b/lib/dev_oops.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require 'dev_oops/version' +require "dev_oops/version" -require 'fileutils' -require 'json' -require 'thor' +require "fileutils" +require "json" +require "thor" -require 'zeitwerk' +require "zeitwerk" loader = Zeitwerk::Loader.for_gem loader.setup # ready! diff --git a/lib/dev_oops/commands/edit_script.rb b/lib/dev_oops/commands/edit_script.rb index 59be0a4..7b6241d 100644 --- a/lib/dev_oops/commands/edit_script.rb +++ b/lib/dev_oops/commands/edit_script.rb @@ -10,8 +10,8 @@ def self.source_root argument :script_name class_option :global, - desc: 'force the script to be global', - aliases: ['g'], + desc: "force the script to be global", + aliases: ["g"], type: :boolean def self.banner @@ -26,8 +26,8 @@ def edit ScriptsLoader.script_dir(script_name) end path = "#{script_dir}/#{script_name}.json" - template 'templates/empty_script.tt', path unless File.exist?(path) - system("#{ENV['EDITOR'] || 'vim'} #{path}") + template "templates/empty_script.tt", path unless File.exist?(path) + system("#{ENV["EDITOR"] || "vim"} #{path}") end end end diff --git a/lib/dev_oops/commands/edit_script_sh.rb b/lib/dev_oops/commands/edit_script_sh.rb index ffc27df..07c5077 100644 --- a/lib/dev_oops/commands/edit_script_sh.rb +++ b/lib/dev_oops/commands/edit_script_sh.rb @@ -10,8 +10,8 @@ def self.source_root argument :script_name class_option :global, - desc: 'force the script to be global', - aliases: ['g'], + desc: "force the script to be global", + aliases: ["g"], type: :boolean def self.banner @@ -28,7 +28,7 @@ def edit path = "#{script_dir}/#{script_name}.sh" create_file(path) unless File.exist?(path) FileUtils.chmod(0o750, path) - system("#{ENV['EDITOR'] || 'vim'} #{path}") + system("#{ENV["EDITOR"] || "vim"} #{path}") end end end diff --git a/lib/dev_oops/commands/local_install.rb b/lib/dev_oops/commands/local_install.rb index 67fd765..bd371bd 100644 --- a/lib/dev_oops/commands/local_install.rb +++ b/lib/dev_oops/commands/local_install.rb @@ -3,9 +3,9 @@ module DevOops module Commands class LocalInstall < Thor::Group def install - return if Dir.exist?('./dev_oops') + return if Dir.exist?("./dev_oops") - FileUtils.mkdir './dev_oops' + FileUtils.mkdir "./dev_oops" end end end diff --git a/lib/dev_oops/commands/remove_script.rb b/lib/dev_oops/commands/remove_script.rb index 6048a5e..3254a75 100644 --- a/lib/dev_oops/commands/remove_script.rb +++ b/lib/dev_oops/commands/remove_script.rb @@ -8,10 +8,10 @@ def self.source_root "#{File.dirname(__FILE__)}/../../../" end - argument :script_name, desc: 'name of the script' + argument :script_name, desc: "name of the script" class_option :global, - desc: 'force the script to be global', - aliases: ['g'], + desc: "force the script to be global", + aliases: ["g"], type: :boolean def self.banner diff --git a/lib/dev_oops/runner.rb b/lib/dev_oops/runner.rb index 03498bf..0c570f6 100644 --- a/lib/dev_oops/runner.rb +++ b/lib/dev_oops/runner.rb @@ -27,31 +27,31 @@ def self.register(klass, subcommand_name, usage, description, options = {}) register( Commands::EditScript, - 'edit', - 'edit SCRIPT_NAME', - 'Edit a script config' + "edit", + "edit SCRIPT_NAME", + "Edit a script config", ) register( Commands::EditScriptSh, - 'edit_sh', - 'edit_sh SCRIPT_NAME', - 'Edit the script bash' + "edit_sh", + "edit_sh SCRIPT_NAME", + "Edit the script bash", ) - register(Commands::RemoveScript, 'rm', 'rm SCRIPT_NAME', 'Remove a script') + register(Commands::RemoveScript, "rm", "rm SCRIPT_NAME", "Remove a script") register( Commands::LocalInstall, - 'install', - 'install', - 'Create the neccesary local directory for the gem' + "install", + "install", + "Create the neccesary local directory for the gem", ) def help(subcommand = nil) if subcommand && respond_to?(subcommand) klass = REGISTERED_CLASS_METHODS[subcommand] - klass.start(['-h']) + klass.start(["-h"]) else super end diff --git a/lib/dev_oops/scripts_loader.rb b/lib/dev_oops/scripts_loader.rb index 9df313f..7178f0b 100644 --- a/lib/dev_oops/scripts_loader.rb +++ b/lib/dev_oops/scripts_loader.rb @@ -8,11 +8,11 @@ module ScriptsLoader def self.create(script_name, script_location, json_config, dir) new( script_name, - json_config['desc'] || 'Missing description', - "#{script_name} #{json_config['usage'] || ''}", + json_config["desc"] || "Missing description", + "#{script_name} #{json_config["usage"] || ""}", script_location, - json_config['args'], - dir + json_config["args"], + dir, ) end end @@ -20,37 +20,41 @@ def self.create(script_name, script_location, json_config, dir) def self.find_dev_oops_dirs [ GLOBAL_DIR, - *Dir.pwd.gsub("#{Dir.home}/", '').split('/').reduce( - [] - ) { |res, new_dir| [*res, "#{res.last}/#{new_dir}"] }.map do |dir| - "#{Dir.home}#{dir}/dev_oops" - end.select { |dir| Dir.exist?(dir) } + *Dir + .pwd + .gsub("#{Dir.home}/", "") + .split("/") + .reduce([]) { |res, new_dir| [*res, "#{res.last}/#{new_dir}"] } + .map { |dir| "#{Dir.home}#{dir}/dev_oops" } + .select { |dir| Dir.exist?(dir) }, ] end def self.load - find_dev_oops_dirs.flat_map do |dir| - Dir.glob("#{dir}/*.json") - end.map do |filename| - script_location = filename.gsub(/\.json$/, '.sh') - script_location = '' unless File.exist?(script_location) - json_config = nil - File.open(filename) { |file| json_config = JSON.parse(file.read) } - script_name = File.basename(filename, '.json') + find_dev_oops_dirs + .flat_map { |dir| Dir.glob("#{dir}/*.json") } + .map do |filename| + script_location = filename.gsub(/\.json$/, ".sh") + script_location = "" unless File.exist?(script_location) + json_config = nil + File.open(filename) { |file| json_config = JSON.parse(file.read) } + script_name = File.basename(filename, ".json") - ScriptConfig.create( - script_name, - script_location, - json_config, - File.dirname(filename) - ) - end.reverse.reduce([]) do |res, script_config| - if res.any? { |script_c| script_c.name == script_config.name } - res - else - [*res, script_config] + ScriptConfig.create( + script_name, + script_location, + json_config, + File.dirname(filename), + ) + end + .reverse + .reduce([]) do |res, script_config| + if res.any? { |script_c| script_c.name == script_config.name } + res + else + [*res, script_config] + end end - end end def self.script_dir(script_name) @@ -64,30 +68,30 @@ def self.build_action(config) Class.new(Thor::Group) do (config.args || []).each do |arg| class_option( - arg['name'], - desc: arg['desc'] || '', - aliases: arg['aliases'] || [], - required: arg['required'] || false, - default: arg['default'], - boolean: arg['boolean'] || false + arg["name"], + desc: arg["desc"] || "", + aliases: arg["aliases"] || [], + required: arg["required"] || false, + default: arg["default"], + boolean: arg["boolean"] || false, ) end define_singleton_method(:banner) { config.usage } define_method(:perform) do - require 'pry' + require "pry" binding.pry - env_vars = options.map { |k, v| "#{k}=#{v}" }.join(' ') + env_vars = options.map { |k, v| "#{k}=#{v}" }.join(" ") return unless config.script_location && !config.script_location.empty? location = - if config.script_location.start_with?('/') + if config.script_location.start_with?("/") config.script_location else "#{Dir.home}/#{config.script_location}" end - system("#{env_vars} #{ENV.fetch('SHELL', nil)} -c #{location}") + system("#{env_vars} #{ENV.fetch("SHELL", nil)} -c #{location}") end end end diff --git a/lib/dev_oops/version.rb b/lib/dev_oops/version.rb index 950a4cd..008175d 100644 --- a/lib/dev_oops/version.rb +++ b/lib/dev_oops/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module DevOops - VERSION = '0.3.1' + VERSION = "0.3.1" end diff --git a/package.json b/package.json index d6103d0..3a9db00 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,21 @@ "author": "Denis Pasin ", "license": "MIT", "devDependencies": { - "@prettier/plugin-ruby": "^1.5.5", - "prettier": "^2.2.1" + "@prettier/plugin-ruby": "^4.0.4", + "prettier": "^3.8.1" + }, + "prettier": { + "trailingComma": "es5", + "plugins": [ + "@prettier/plugin-ruby" + ], + "overrides": [ + { + "files": "*.rb", + "options": { + "parser": "ruby" + } + } + ] } } diff --git a/spec/dev_oops_spec.rb b/spec/dev_oops_spec.rb index 5d0b876..fb02115 100644 --- a/spec/dev_oops_spec.rb +++ b/spec/dev_oops_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe DevOops do - it 'has a version number' do + it "has a version number" do expect(DevOops::VERSION).not_to be nil end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6d3d593..0f5ffb1 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -require 'bundler/setup' -require 'dev_oops' +require "bundler/setup" +require "dev_oops" RSpec.configure do |config| # Enable flags like --only-failures and --next-failure - config.example_status_persistence_file_path = '.rspec_status' + config.example_status_persistence_file_path = ".rspec_status" # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! diff --git a/yarn.lock b/yarn.lock index 5015a38..13c1f12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,14 +2,12 @@ # yarn lockfile v1 -"@prettier/plugin-ruby@^1.5.5": - version "1.5.5" - resolved "https://registry.yarnpkg.com/@prettier/plugin-ruby/-/plugin-ruby-1.5.5.tgz#9e206fc856a182a292fcfab9043f53c7a3d0af97" - integrity sha512-b387GdXU+LrnY+oaKWRUI5EnsUvrQ0G1jUSVPkvUTGzp/w+BB9/n4SICVPY3V9/wYsvWpAZq4LkE4FdBufXUtA== - dependencies: - prettier ">=1.10" +"@prettier/plugin-ruby@^4.0.4": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@prettier/plugin-ruby/-/plugin-ruby-4.0.4.tgz#73d85fc2a1731a3f62b57ac3116cf1c234027cb6" + integrity sha512-lCpvfS/dQU5WrwN3AQ5vR8qrvj2h5gE41X08NNzAAXvHdM4zwwGRcP2sHSxfu6n6No+ljWCVx95NvJPFTTjCTg== -prettier@>=1.10, prettier@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" - integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== +prettier@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173" + integrity sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg== From f980925b10354f84bd2f94e3c4204244497a3239 Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 10:14:33 +0100 Subject: [PATCH 3/6] Modern config for CI --- .github/workflows/test_and_publish.yml | 17 +++++++++++------ .github/workflows/test_only.yml | 13 +++++++++---- .github/workflows/verify_version_change.yml | 2 +- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test_and_publish.yml b/.github/workflows/test_and_publish.yml index db2c048..f4c43ac 100644 --- a/.github/workflows/test_and_publish.yml +++ b/.github/workflows/test_and_publish.yml @@ -9,11 +9,11 @@ jobs: tests: strategy: matrix: - ruby: [3.2, 3.3, 3.4] + ruby: [3.2, 3.3, 3.4, 4.0] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: @@ -26,9 +26,14 @@ jobs: prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.4 + bundler-cache: true - name: Set up Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: "24" - name: Install yarn dep @@ -40,11 +45,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.0 + ruby-version: 3.4 bundler-cache: true - name: Prepare credentials env: diff --git a/.github/workflows/test_only.yml b/.github/workflows/test_only.yml index 241b246..973c72a 100644 --- a/.github/workflows/test_only.yml +++ b/.github/workflows/test_only.yml @@ -9,11 +9,11 @@ jobs: tests: strategy: matrix: - ruby: [3.2, 3.3, 3.4] + ruby: [3.2, 3.3, 3.4, 4.0] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: @@ -26,9 +26,14 @@ jobs: prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.4 + bundler-cache: true - name: Set up Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: "24" - name: Install yarn dep diff --git a/.github/workflows/verify_version_change.yml b/.github/workflows/verify_version_change.yml index 0382d4e..ef7e67b 100644 --- a/.github/workflows/verify_version_change.yml +++ b/.github/workflows/verify_version_change.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Fetch main branch run: git fetch origin main:main - name: Verify if there's a change in version From e1850cc2ac1c59a35a0796ad1d281e4426c260a8 Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 10:17:11 +0100 Subject: [PATCH 4/6] Stupid Denis (bis) --- .rubocop.yml | 2 +- lib/dev_oops/scripts_loader.rb | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 92e59ab..12e6af2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,7 +4,7 @@ inherit_from: inherit_gem: prettier: rubocop.yml -require: +plugins: - rubocop-performance AllCops: diff --git a/lib/dev_oops/scripts_loader.rb b/lib/dev_oops/scripts_loader.rb index 7178f0b..6c1c816 100644 --- a/lib/dev_oops/scripts_loader.rb +++ b/lib/dev_oops/scripts_loader.rb @@ -80,8 +80,6 @@ def self.build_action(config) define_singleton_method(:banner) { config.usage } define_method(:perform) do - require "pry" - binding.pry env_vars = options.map { |k, v| "#{k}=#{v}" }.join(" ") return unless config.script_location && !config.script_location.empty? From 00198b5c9e667f5558c705941f061e704b6a48fa Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 10:19:57 +0100 Subject: [PATCH 5/6] Ignore vendor gems --- .github/workflows/test_and_publish.yml | 2 +- .github/workflows/test_only.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test_and_publish.yml b/.github/workflows/test_and_publish.yml index f4c43ac..040b38b 100644 --- a/.github/workflows/test_and_publish.yml +++ b/.github/workflows/test_and_publish.yml @@ -39,7 +39,7 @@ jobs: - name: Install yarn dep run: yarn install - name: Check prettier - run: yarn prettier -c '**/*.rb' + run: yarn prettier -c '**/*.rb' '!vendor/**' release: needs: [tests, prettier] runs-on: ubuntu-latest diff --git a/.github/workflows/test_only.yml b/.github/workflows/test_only.yml index 973c72a..23db563 100644 --- a/.github/workflows/test_only.yml +++ b/.github/workflows/test_only.yml @@ -39,4 +39,4 @@ jobs: - name: Install yarn dep run: yarn install - name: Check prettier - run: yarn prettier -c '**/*.rb' + run: yarn prettier -c '**/*.rb' '!vendor/**' From cff343869227ba2baafa1e1c67e39011a9ac6bce Mon Sep 17 00:00:00 2001 From: Denis Zaratan Pasin Date: Thu, 5 Mar 2026 10:26:00 +0100 Subject: [PATCH 6/6] Fixes post review --- CHANGELOG.md | 7 +-- lib/dev_oops/scripts_loader.rb | 8 ++-- spec/scripts_loader_spec.rb | 87 ++++++++++++++++++++++++++++++++++ 3 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 spec/scripts_loader_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index c73f29f..07aea5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ First working version - All the things -[unreleased]: https://github.com/zaratan/dev_oops/compare/v0.2.0...HEAD -[0.2.0]: https://github.com/zaratan/rspec_in_context/releases/tag/v0.2.0 -[0.1.1]: https://github.com/zaratan/rspec_in_context/releases/tag/v0.1.1 +[unreleased]: https://github.com/zaratan/dev_oops/compare/v0.3.1...HEAD +[0.3.1]: https://github.com/zaratan/dev_oops/compare/v0.2.0...v0.3.1 +[0.2.0]: https://github.com/zaratan/dev_oops/releases/tag/v0.2.0 +[0.1.1]: https://github.com/zaratan/dev_oops/releases/tag/v0.1.1 diff --git a/lib/dev_oops/scripts_loader.rb b/lib/dev_oops/scripts_loader.rb index 6c1c816..65eae70 100644 --- a/lib/dev_oops/scripts_loader.rb +++ b/lib/dev_oops/scripts_loader.rb @@ -67,14 +67,14 @@ def self.script_dir(script_name) def self.build_action(config) Class.new(Thor::Group) do (config.args || []).each do |arg| - class_option( - arg["name"], + option_params = { desc: arg["desc"] || "", aliases: arg["aliases"] || [], required: arg["required"] || false, default: arg["default"], - boolean: arg["boolean"] || false, - ) + } + option_params[:type] = :boolean if arg["boolean"] + class_option(arg["name"], **option_params) end define_singleton_method(:banner) { config.usage } diff --git a/spec/scripts_loader_spec.rb b/spec/scripts_loader_spec.rb new file mode 100644 index 0000000..cb363b6 --- /dev/null +++ b/spec/scripts_loader_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +RSpec.describe DevOops::ScriptsLoader do + describe ".build_action" do + let(:config) do + DevOops::ScriptsLoader::ScriptConfig.new( + "test_script", + "Missing description", + "test_script", + "/tmp/test_script.sh", + args, + "/tmp", + ) + end + let(:action_class) { described_class.build_action(config) } + + context "with boolean args" do + let(:args) do + [ + { + "name" => "verbose", + "desc" => "Enable verbose mode", + "aliases" => ["v"], + "required" => false, + "boolean" => true, + }, + ] + end + + it "registers a boolean option" do + option = action_class.class_options["verbose"] + expect(option).not_to be_nil + expect(option.type).to eq(:boolean) + end + + it "has no default when none is specified" do + option = action_class.class_options["verbose"] + expect(option.default).to be_nil + end + + context "with a default value" do + let(:args) do + [ + { + "name" => "verbose", + "desc" => "Enable verbose mode", + "boolean" => true, + "default" => false, + }, + ] + end + + it "uses the specified default" do + option = action_class.class_options["verbose"] + expect(option.default).to be false + end + end + end + + context "with non-boolean args" do + let(:args) do + [ + { + "name" => "output", + "desc" => "Output file", + "aliases" => ["o"], + "required" => false, + }, + ] + end + + it "registers a string option" do + option = action_class.class_options["output"] + expect(option).not_to be_nil + expect(option.type).to eq(:string) + end + end + + context "with no args" do + let(:args) { nil } + + it "builds an action without options" do + expect(action_class.class_options).to be_empty + end + end + end +end