diff --git a/Gemfile.lock b/Gemfile.lock index 7af8de6..576295e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -126,4 +126,4 @@ DEPENDENCIES solargraph BUNDLED WITH - 2.4.13 + 2.4.22 diff --git a/LICENSE.txt b/LICENSE.txt index aa92e03..a405c55 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2022 Paul DobbinSchmaltz +Copyright (c) 2023 Paul DobbinSchmaltz Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Rakefile b/Rakefile index 1f537ab..d7544f5 100644 --- a/Rakefile +++ b/Rakefile @@ -1,37 +1,30 @@ # frozen_string_literal: true -require "bundler/gem_tasks" -require "rake/testtask" - -Rake::TestTask.new(:test) do |t| - t.libs << "test" - t.libs << "lib" - t.test_files = FileList["test/**/*_test.rb"] -end - -require "rubocop/rake_task" - -RuboCop::RakeTask.new do |t| - t.fail_on_error = false -end - -require "reek/rake/task" +# See ./rakelib/ for additional tasks automatically loaded by rake. -Reek::Rake::Task.new do |t| - t.fail_on_error = false -end +require "bundler/gem_tasks" task :default do - tasks = %i[ + run_tasks(%i[ test rubocop reek - ] + yard + ]) +end +def run_tasks(tasks) tasks.each_with_index do |name, index| - puts "== Running #{name} #{"=" * (70 - name.size)}\n" - Rake::Task[name].invoke - puts "== Done #{"=" * 74}" + annotate_run(name) do + Rake::Task[name].invoke + end + puts unless index.next == tasks.size end end + +def annotate_run(name) + puts "= Running #{name} #{"=" * (71 - name.size)}\n" + yield + puts "= Done #{"=" * 75}" +end diff --git a/rakelib/bump.rake b/rakelib/bump.rake new file mode 100644 index 0000000..d2ff8b0 --- /dev/null +++ b/rakelib/bump.rake @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +require "date" +require "open-uri" +require "yaml" + +desc "Update Bundler version, Ruby version, and LICENSE year in relevant files" +task :bump do + run_tasks(%w[ + bump:bundler + bump:ruby + bump:year + ]) +end + +namespace :bump do + desc "Update Bundler version to latest in Gemfile.lock" + task :bundler do + version = Gem.latest_version_for("bundler").to_s + replace_in_file("Gemfile.lock", /^BUNDLED WITH\n\s+(\d\S+)$/ => version) + end + + desc "Update Ruby version targets in relevant files" + task :ruby do + replace_in_file( + "object_identifier.gemspec", + /ruby_version = .*">= (.*)"/ => RubyVersions.lowest_supported_minor) + replace_in_file( + ".rubocop.yml", + /TargetRubyVersion: (.*)/ => RubyVersions.lowest_supported_minor) + replace_in_file( + ".github/workflows/ci.yml", + /ruby-version: "([\d.]+)"/ => RubyVersions.latest) + replace_in_file( + ".github/workflows/ci.yml", + /ruby-version: (\[(?:"[\d.]+"(?:, )?)*\])/ => + RubyVersions.latest_supported_minors.to_s) + end + + desc "Update year to current in LICENSE.txt" + task :year do + replace_in_file("LICENSE.txt", /\(c\) (\d+)/ => Date.today.year.to_s) + end +end + +def replace_in_file(path, replacements) + file_contents = File.read(path) + original_file_contents = file_contents.dup + + replacements.each do |regex, text| + raise "Can't find #{regex} in #{path}" unless regex.match?(file_contents) + + file_contents.gsub!(regex) do |match| + match[regex, 1] = text + match + end + end + + File.write(path, file_contents) if file_contents != original_file_contents +end + +# RubyVersions extracts current Ruby versions info from +# https://raw.githubusercontent.com/ruby/www.ruby-lang.org/HEAD/_data/downloads.yml +# -- which specifies the Ruby releases that will be listed on +# https://www.ruby-lang.org/en/downloads/ +module RubyVersions + MINOR_VERSION_REGEX = /\d+\.\d+/.freeze + RUBY_VERSIONS_YAML_PATH = + "https://raw.githubusercontent.com/ruby/www.ruby-lang.org/HEAD/_data/downloads.yml" + VERSION_TYPES = %i[ + eol + security_maintenance + stable + ].freeze + + def self.latest + latest_supported_patches.last + end + + def self.latest_supported_minors + latest_supported_patches.map { |version_string| + version_string[MINOR_VERSION_REGEX] + } + end + + def self.latest_supported_patches + @latest_supported_patches ||= begin + patches = versions.fetch_values(*VERSION_TYPES).compact.flatten + patches.map { |patch| Gem::Version.new(patch) }.sort!.map(&:to_s) + end + end + + def self.lowest_supported_minor + latest_supported_patches.first[MINOR_VERSION_REGEX] + end + + private + + def self.versions + @versions ||= begin + raw_yaml = URI.parse(RUBY_VERSIONS_YAML_PATH).open + YAML.safe_load(raw_yaml, symbolize_names: true) + end + end + private_class_method :versions +end diff --git a/rakelib/reek.rake b/rakelib/reek.rake new file mode 100644 index 0000000..95ed869 --- /dev/null +++ b/rakelib/reek.rake @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require "reek/rake/task" + +Reek::Rake::Task.new do |t| + t.fail_on_error = false +end diff --git a/rakelib/rubocop.rake b/rakelib/rubocop.rake new file mode 100644 index 0000000..2d21007 --- /dev/null +++ b/rakelib/rubocop.rake @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require "rubocop/rake_task" + +RuboCop::RakeTask.new do |t| + t.fail_on_error = false +end diff --git a/rakelib/tests.rake b/rakelib/tests.rake new file mode 100644 index 0000000..5744b6e --- /dev/null +++ b/rakelib/tests.rake @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require "rake/testtask" + +Rake::TestTask.new(:test) do |t| + t.libs << "test" + t.libs << "lib" + t.test_files = FileList["test/**/*_test.rb"] +end diff --git a/rakelib/yard.rake b/rakelib/yard.rake new file mode 100644 index 0000000..347b504 --- /dev/null +++ b/rakelib/yard.rake @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +require "yard" + +YARD::Rake::YardocTask.new do |t| + t.stats_options = ["--list-undoc"] +end