From b0882c35b1354c35a18d1140baa02901e0c91bde Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 15:29:53 -0600 Subject: [PATCH 01/29] =?UTF-8?q?=F0=9F=93=8C=20ruby@3.4.5=20for=20develop?= =?UTF-8?q?ment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index ae5ecdb..27a8619 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.4.2 +ruby 3.4.5 From f68fed57c83957c08fa48b3829aebc89e9f62338 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 15:52:06 -0600 Subject: [PATCH 02/29] =?UTF-8?q?=E2=9E=96=20appraisal=20(fork)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Appraisal.root.gemfile | 2 -- Appraisals | 15 --------------- Gemfile | 2 -- 3 files changed, 19 deletions(-) diff --git a/Appraisal.root.gemfile b/Appraisal.root.gemfile index 89968f9..dbfd485 100644 --- a/Appraisal.root.gemfile +++ b/Appraisal.root.gemfile @@ -10,5 +10,3 @@ source "https://rubygems.org" # We do not load the standard Gemfile, as it is tailored for local development & GitLab CI. gemspec - -gem "appraisal", github: "pboling/appraisal", branch: "galtzo" diff --git a/Appraisals b/Appraisals index 7f405cf..f2a8c69 100644 --- a/Appraisals +++ b/Appraisals @@ -9,7 +9,6 @@ appraise "head" do gem "mutex_m", ">= 0.2" gem "stringio", ">= 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end # Used for current releases of ruby, truffleruby, and jruby. @@ -17,59 +16,48 @@ end appraise "current" do gem "mutex_m", ">= 0.2" gem "stringio", ">= 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-2" do - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-3" do - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-4" do - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-5" do - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-6" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-2-7" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-3-0" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-3-1" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-3-2" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end appraise "ruby-3-3" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end # Only run security audit on latest Ruby version @@ -77,7 +65,6 @@ appraise "audit" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" eval_gemfile "modular/audit.gemfile" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end # Only run coverage on latest Ruby version @@ -85,7 +72,6 @@ appraise "coverage" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" eval_gemfile "modular/coverage.gemfile" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end # Only run linter on latest Ruby version (but, in support of oldest supported Ruby version) @@ -93,5 +79,4 @@ appraise "style" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" eval_gemfile "modular/style.gemfile" - remove_gem "appraisal" # only present because it must be in the gemfile because we target a git branch end diff --git a/Gemfile b/Gemfile index ea12543..a4c96e7 100644 --- a/Gemfile +++ b/Gemfile @@ -46,5 +46,3 @@ eval_gemfile "gemfiles/modular/style.gemfile" # Documentation eval_gemfile "gemfiles/modular/documentation.gemfile" - -gem "appraisal", github: "pboling/appraisal", branch: "galtzo" From de8bd044aebb10e90863968126a70b951c9d12d3 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 15:53:00 -0600 Subject: [PATCH 03/29] =?UTF-8?q?=E2=9E=95=20kettle-dev?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 151 ++++++++++++++++++++++++++---------------- Rakefile | 157 ++++++++++++++++---------------------------- version_gem.gemspec | 14 +--- 3 files changed, 149 insertions(+), 173 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 812b866..0ef0c4d 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,13 +1,3 @@ -GIT - remote: https://github.com/pboling/appraisal - revision: a3a3e4b7db67d9b085f96b2ffddd2b51bd8a1196 - branch: galtzo - specs: - appraisal (3.0.0.rc1) - bundler (>= 1.17.3) - rake (>= 10) - thor (>= 0.14) - GIT remote: https://github.com/pboling/yard-junk revision: 54ccebabbfa9a9cd44d0b991687ebbfd22c32b55 @@ -29,21 +19,26 @@ GEM remote: https://rubygems.org/ specs: ansi (1.5.0) + appraisal2 (3.0.0) + bundler (>= 1.17.3) + rake (>= 10) + thor (>= 0.14) ast (2.4.3) backports (3.25.1) - benchmark (0.4.0) - bigdecimal (3.1.9) + benchmark (0.4.1) + bigdecimal (3.2.2) bundler-audit (0.9.2) bundler (>= 1.2.0, < 3) thor (~> 1.0) coderay (1.1.3) concurrent-ruby (1.3.5) date (3.4.1) - debug (1.10.0) + debug (1.11.0) irb (~> 1.10) reline (>= 0.3.8) - diff-lcs (1.6.1) - diffy (3.4.3) + delegate (0.4.0) + diff-lcs (1.6.2) + diffy (3.4.4) docile (1.4.1) dry-configurable (1.3.0) dry-core (~> 1.1) @@ -67,36 +62,59 @@ GEM dry-logic (~> 1.5) dry-types (~> 1.8) zeitwerk (~> 2.6) - dry-types (1.8.2) + dry-types (1.8.3) bigdecimal (~> 3.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0) dry-inflector (~> 1.0) dry-logic (~> 1.4) zeitwerk (~> 2.6) + erb (5.0.2) github-markup (5.0.1) - io-console (0.8.0) + gitmoji-regex (1.0.3) + version_gem (~> 1.1, >= 1.1.8) + io-console (0.8.1) irb (1.15.2) pp (>= 0.6.0) rdoc (>= 4.0.0) reline (>= 0.4.2) - json (2.11.3) - kettle-soup-cover (1.0.6) + json (2.13.2) + kettle-dev (1.0.25) + appraisal2 (~> 3.0) + bundler-audit (~> 0.9.2) + gitmoji-regex (~> 1.0, >= 1.0.3) + kettle-test (~> 1.0) + rake (~> 13.0) + require_bench (~> 1.0, >= 1.0.4) + rspec-pending_for + ruby-progressbar (~> 1.13) + stone_checksums (~> 1.0, >= 1.0.2) + version_gem (~> 1.1, >= 1.1.8) + kettle-soup-cover (1.0.10) simplecov (~> 0.22) - simplecov-cobertura (~> 2.1) - simplecov-console (~> 0.9, >= 0.9.1) - simplecov-html (~> 0.12) + simplecov-cobertura (~> 3.0) + simplecov-console (~> 0.9, >= 0.9.3) + simplecov-html (~> 0.13, >= 0.13.1) simplecov-lcov (~> 0.8) - simplecov-rcov (~> 0.3, >= 0.3.3) + simplecov-rcov (~> 0.3, >= 0.3.7) simplecov_json_formatter (~> 0.1, >= 0.1.4) - version_gem (~> 1.1, >= 1.1.7) - language_server-protocol (3.17.0.4) + version_gem (~> 1.1, >= 1.1.8) + kettle-test (1.0.3) + appraisal2 (~> 3.0) + rspec (~> 3.0) + rspec-block_is_expected (~> 1.0, >= 1.0.6) + rspec-stubbed_env (~> 1.0, >= 1.0.4) + rspec_junit_formatter (~> 0.6) + silent_stream (~> 1.0, >= 1.0.12) + timecop-rspec (~> 1.0, >= 1.0.3) + version_gem (~> 1.1, >= 1.1.8) + language_server-protocol (3.17.0.5) lint_roller (1.1.0) logger (1.7.0) method_source (1.1.0) - ostruct (0.6.1) + ostruct (0.6.3) parallel (1.27.0) - parser (3.3.8.0) + parser (3.3.9.0) ast (~> 2.4.1) racc pp (0.6.2) @@ -106,13 +124,14 @@ GEM pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) - psych (5.2.4) + psych (5.2.6) date stringio racc (1.8.1) rainbow (3.1.1) - rake (13.2.1) - rdoc (6.13.1) + rake (13.3.0) + rdoc (6.14.2) + erb psych (>= 4.0.0) redcarpet (3.6.1) reek (6.5.0) @@ -121,25 +140,34 @@ GEM parser (~> 3.3.0) rainbow (>= 2.0, < 4.0) rexml (~> 3.1) - regexp_parser (2.10.0) - reline (0.6.1) + regexp_parser (2.11.2) + reline (0.6.2) io-console (~> 0.5) - rexml (3.4.1) - rspec (3.13.0) + require_bench (1.0.4) + version_gem (>= 1.1.3, < 4) + rexml (3.4.2) + rspec (3.13.1) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) rspec-block_is_expected (1.0.6) - rspec-core (3.13.3) + rspec-core (3.13.5) rspec-support (~> 3.13.0) - rspec-expectations (3.13.4) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.4) + rspec-mocks (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.3) - rubocop (1.75.5) + rspec-pending_for (0.1.18) + rspec-core (~> 3.0) + ruby_engine (~> 2.0) + ruby_version (~> 1.0) + rspec-stubbed_env (1.0.4) + rspec-support (3.13.5) + rspec_junit_formatter (0.6.0) + rspec-core (>= 2, < 4, != 2.12.0) + rubocop (1.75.8) json (~> 2.3) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.1.0) @@ -150,7 +178,7 @@ GEM rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 4.0) - rubocop-ast (1.44.1) + rubocop-ast (1.46.0) parser (>= 3.3.7.2) prism (~> 1.4) rubocop-gradual (0.3.6) @@ -186,32 +214,38 @@ GEM rubocop-thread_safety (~> 0.5, >= 0.5.1) standard-rubocop-lts (~> 1.0, >= 1.0.7) version_gem (>= 1.1.3, < 3) - rubocop-shopify (2.17.0) + rubocop-shopify (2.17.1) rubocop (~> 1.62) - rubocop-thread_safety (0.7.2) + rubocop-thread_safety (0.7.3) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) + rubocop-ast (>= 1.44.0, < 2.0) ruby-progressbar (1.13.0) + ruby_engine (2.0.3) + ruby_version (1.0.3) + silent_stream (1.0.12) + logger (~> 1.2) + version_gem (>= 1.1.8, < 3) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-cobertura (2.1.0) + simplecov-cobertura (3.1.0) rexml simplecov (~> 0.19) - simplecov-console (0.9.3) + simplecov-console (0.9.4) ansi simplecov terminal-table - simplecov-html (0.13.1) - simplecov-lcov (0.8.0) + simplecov-html (0.13.2) + simplecov-lcov (0.9.0) simplecov-rcov (0.3.7) simplecov (>= 0.4.1) simplecov_json_formatter (0.1.4) - standard (1.49.0) + standard (1.50.0) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) - rubocop (~> 1.75.2) + rubocop (~> 1.75.5) standard-custom (~> 1.0.0) standard-performance (~> 1.8) standard-custom (1.0.2) @@ -226,17 +260,22 @@ GEM standard-custom (>= 1.0.2, < 2) standard-performance (>= 1.3.1, < 2) version_gem (>= 1.1.4, < 3) - stone_checksums (1.0.0) - version_gem (>= 1.1.5, < 3) + stone_checksums (1.0.2) + version_gem (~> 1.1, >= 1.1.8) stringio (3.1.7) terminal-table (4.0.0) unicode-display_width (>= 1.1.1, < 4) - thor (1.3.2) - unicode-display_width (3.1.4) + thor (1.4.0) + timecop (0.9.10) + timecop-rspec (1.0.3) + delegate (~> 0.1) + rspec (~> 3.0) + timecop (>= 0.7, < 1) + unicode-display_width (3.1.5) unicode-emoji (~> 4.0, >= 4.0.4) unicode-emoji (4.0.4) yard (0.9.37) - zeitwerk (2.7.2) + zeitwerk (2.7.3) PLATFORMS arm64-darwin-22 @@ -246,25 +285,21 @@ PLATFORMS x86_64-linux DEPENDENCIES - appraisal! benchmark (~> 0.4) bundler-audit (~> 0.9.2) debug (>= 1.0.0) github-markup (~> 5.0, >= 5.0.1) + kettle-dev (~> 1.0, >= 1.0.25) kettle-soup-cover (~> 1.0, >= 1.0.6) pry (~> 0.14) - rake (~> 13.0) rdoc (~> 6.11) redcarpet (~> 3.6) reek (~> 6.4) - rspec (~> 3.13) - rspec-block_is_expected (~> 1.0) rubocop (~> 1.73, >= 1.73.2) rubocop-lts (~> 8.1, >= 8.1.1) rubocop-packaging (~> 0.5, >= 0.5.2) rubocop-rspec (~> 3.2) standard (~> 1.47) - stone_checksums (~> 1.0) version_gem! yard (~> 0.9, >= 0.9.37) yard-junk (~> 0.0, >= 0.0.10)! diff --git a/Rakefile b/Rakefile index 585c6be..e225475 100644 --- a/Rakefile +++ b/Rakefile @@ -1,117 +1,70 @@ # frozen_string_literal: true -require "bundler/gem_tasks" - -defaults = [] - -### DEVELOPMENT TASKS -# Setup Kettle Soup Cover -begin - require "kettle-soup-cover" - - Kettle::Soup::Cover.install_tasks - # NOTE: Coverage on CI is configured independent of this task. - # This task is for local development, as it opens results in browser - defaults << "coverage" unless Kettle::Soup::Cover::IS_CI -rescue LoadError - desc("(stub) coverage is unavailable") - task("coverage") do - warn("NOTE: kettle-soup-cover isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end +# kettle-dev Rakefile v1.0.25 - 2025-08-31 +# Ruby 2.3 (Safe Navigation) or higher required +# +# MIT License (see License.txt) +# +# Copyright (c) 2025 Peter H. Boling (galtzo.com) +# +# Expected to work in any project that uses Bundler. +# +# Sets up tasks for appraisal, floss_funding, rspec, minitest, rubocop, reek, yard, and stone_checksums. +# +# rake appraisal:update # Update Appraisal gemfiles and run RuboCop... +# rake bench # Run all benchmarks (alias for bench:run) +# rake bench:list # List available benchmark scripts +# rake bench:run # Run all benchmark scripts (skips on CI) +# rake build # Build kettle-dev-1.0.0.gem into the pkg d... +# rake build:checksum # Generate SHA512 checksum of kettle-dev-1.... +# rake build:generate_checksums # Generate both SHA256 & SHA512 checksums i... +# rake bundle:audit:check # Checks the Gemfile.lock for insecure depe... +# rake bundle:audit:update # Updates the bundler-audit vulnerability d... +# rake ci:act[opt] # Run 'act' with a selected workflow +# rake clean # Remove any temporary products +# rake clobber # Remove any generated files +# rake coverage # Run specs w/ coverage and open results in... +# rake default # Default tasks aggregator +# rake install # Build and install kettle-dev-1.0.0.gem in... +# rake install:local # Build and install kettle-dev-1.0.0.gem in... +# rake kettle:dev:install # Install kettle-dev GitHub automation and ... +# rake kettle:dev:template # Template kettle-dev files into the curren... +# rake reek # Check for code smells +# rake reek:update # Run reek and store the output into the RE... +# rake release[remote] # Create tag v1.0.0 and build and push kett... +# rake rubocop_gradual # Run RuboCop Gradual +# rake rubocop_gradual:autocorrect # Run RuboCop Gradual with autocorrect (onl... +# rake rubocop_gradual:autocorrect_all # Run RuboCop Gradual with autocorrect (saf... +# rake rubocop_gradual:check # Run RuboCop Gradual to check the lock file +# rake rubocop_gradual:force_update # Run RuboCop Gradual to force update the l... +# rake rubocop_gradual_debug # Run RuboCop Gradual +# rake rubocop_gradual_debug:autocorrect # Run RuboCop Gradual with autocorrect (onl... +# rake rubocop_gradual_debug:autocorrect_all # Run RuboCop Gradual with autocorrect (saf... +# rake rubocop_gradual_debug:check # Run RuboCop Gradual to check the lock file +# rake rubocop_gradual_debug:force_update # Run RuboCop Gradual to force update the l... +# rake spec # Run RSpec code examples +# rake test # Run tests +# rake yard # Generate YARD Documentation +# + +require "bundler/gem_tasks" if !Dir[File.join(__dir__, "*.gemspec")].empty? + +# Define a base default task early so other files can enhance it. +desc "Default tasks aggregator" +task :default do + puts "Default task complete." end -# Setup Bundle Audit -begin - require "bundler/audit/task" - - Bundler::Audit::Task.new - defaults.push("bundle:audit:update", "bundle:audit") -rescue LoadError - desc("(stub) bundle:audit is unavailable") - task("bundle:audit") do - warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end - desc("(stub) bundle:audit:update is unavailable") - task("bundle:audit:update") do - warn("NOTE: bundler-audit isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end -end - -begin - require "rspec/core/rake_task" - - RSpec::Core::RakeTask.new(:spec) - # This takes the place of `coverage` task when running as CI=true - defaults << "spec" if !defined?(Kettle::Soup::Cover) || Kettle::Soup::Cover::IS_CI -rescue LoadError - desc("spec task stub") - task(:spec) do - warn("NOTE: rspec isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end -end - -desc "run spec task with test task" -task test: :spec - -# Setup RuboCop-LTS -begin - require "rubocop/lts" - - Rubocop::Lts.install_tasks - defaults << "rubocop_gradual" -rescue LoadError - desc("(stub) rubocop_gradual is unavailable") - task(:rubocop_gradual) do - warn("NOTE: rubocop-lts isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end -end - -# Setup Yard -begin - require "yard" - - YARD::Rake::YardocTask.new(:yard) do |t| - t.files = [ - # Splats (alphabetical) - "lib/**/*.rb", - ] - end - defaults << "yard" -rescue LoadError - desc("(stub) yard is unavailable") - task(:yard) do - warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end -end - -# Setup Reek -begin - require "reek/rake/task" - - Reek::Rake::Task.new do |t| - t.fail_on_error = true - t.verbose = false - t.source_files = "{lib,spec}/**/*.rb" - end - defaults << "reek" -rescue LoadError - desc("(stub) reek is unavailable") - task(:reek) do - warn("NOTE: reek isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") - end -end +# External gems that define tasks - add here! +require "kettle/dev" ### RELEASE TASKS # Setup stone_checksums begin require "stone_checksums" - - GemChecksums.install_tasks rescue LoadError desc("(stub) build:generate_checksums is unavailable") task("build:generate_checksums") do warn("NOTE: stone_checksums isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") end end - -task default: defaults diff --git a/version_gem.gemspec b/version_gem.gemspec index dc64ce6..4a9e410 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -76,17 +76,5 @@ Gem::Specification.new do |spec| ] spec.require_paths = ["lib"] - # Tests - spec.add_development_dependency("rspec", "~> 3.13") # ruby >= 0 - spec.add_development_dependency("rspec-block_is_expected", "~> 1.0") # ruby >= 1.8.7 - - # Development Tasks - spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2 - spec.add_development_dependency("stone_checksums", "~> 1.0") # ruby >= 2.2 - - # Linting - rubocop-lts v8 is a rubocop wrapper for Ruby >= 2.2, - # and should only be bumped when dropping old Ruby support - # NOTE: it can only be installed on, and run on Ruby >= 2.7, so we add the dependency in the Gemfile. - # see: https://rubocop-lts.gitlab.io - # spec.add_development_dependency 'rubocop-lts', ['~> 8.1', '>= 8.1.1'] + spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.25") # ruby >= 2.3 end From 51ab32541b6336504c7ed380388510785708e62b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 16:00:05 -0600 Subject: [PATCH 04/29] =?UTF-8?q?=F0=9F=94=A8=20binstubs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/erb | 27 +++++++++++++++++++++++++++ bin/kettle-changelog | 27 +++++++++++++++++++++++++++ bin/kettle-commit-msg | 27 +++++++++++++++++++++++++++ bin/kettle-readme-backers | 27 +++++++++++++++++++++++++++ bin/kettle-release | 27 +++++++++++++++++++++++++++ bin/rdoc | 27 +++++++++++++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 bin/erb create mode 100644 bin/kettle-changelog create mode 100644 bin/kettle-commit-msg create mode 100644 bin/kettle-readme-backers create mode 100644 bin/kettle-release create mode 100644 bin/rdoc diff --git a/bin/erb b/bin/erb new file mode 100644 index 0000000..59d3df9 --- /dev/null +++ b/bin/erb @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'erb' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("erb", "erb") diff --git a/bin/kettle-changelog b/bin/kettle-changelog new file mode 100644 index 0000000..a3cb771 --- /dev/null +++ b/bin/kettle-changelog @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-changelog' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-changelog") diff --git a/bin/kettle-commit-msg b/bin/kettle-commit-msg new file mode 100644 index 0000000..78e6700 --- /dev/null +++ b/bin/kettle-commit-msg @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-commit-msg' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-commit-msg") diff --git a/bin/kettle-readme-backers b/bin/kettle-readme-backers new file mode 100644 index 0000000..33ffcde --- /dev/null +++ b/bin/kettle-readme-backers @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-readme-backers' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-readme-backers") diff --git a/bin/kettle-release b/bin/kettle-release new file mode 100644 index 0000000..ab7ff00 --- /dev/null +++ b/bin/kettle-release @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-release' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-release") diff --git a/bin/rdoc b/bin/rdoc new file mode 100644 index 0000000..d2b6bcf --- /dev/null +++ b/bin/rdoc @@ -0,0 +1,27 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rdoc' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +bundle_binstub = File.expand_path("bundle", __dir__) + +if File.file?(bundle_binstub) + if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") + load(bundle_binstub) + else + abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. +Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") + end +end + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rdoc", "rdoc") From 42f4d614a55e075e8aebbea67fa771750a608fb1 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 16:00:54 -0600 Subject: [PATCH 05/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20bundle=20update=20--?= =?UTF-8?q?bundler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0ef0c4d..873498c 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -305,4 +305,4 @@ DEPENDENCIES yard-junk (~> 0.0, >= 0.0.10)! BUNDLED WITH - 2.6.8 + 2.7.1 From f849b6c97c9ff6049d0d26e56659046ce31b10d5 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Sun, 31 Aug 2025 23:20:15 -0600 Subject: [PATCH 06/29] =?UTF-8?q?=F0=9F=8E=A8=20kettle-dev=20v1.0.25=20tem?= =?UTF-8?q?plating?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .envrc | 12 +- .git-hooks/commit-msg | 41 ++ .git-hooks/commit-subjects-goalie.txt | 8 + .git-hooks/footer-template.erb.txt | 16 + .git-hooks/prepare-commit-msg | 20 + .github/FUNDING.yml | 4 +- .github/dependabot.yml | 7 +- .github/workflows/ancient.yml | 14 +- .github/workflows/auto-assign.yml | 21 + .github/workflows/codeql-analysis.yml | 4 +- .github/workflows/coverage.yml | 71 ++-- .github/workflows/current.yml | 17 +- .github/workflows/discord-notifier.yml | 39 ++ .github/workflows/heads.yml | 33 +- .github/workflows/jruby.yml | 38 +- .github/workflows/legacy.yml | 23 +- .github/workflows/locked_deps.yml | 85 ++++ .github/workflows/opencollective.yml | 40 ++ .github/workflows/style.yml | 11 +- .github/workflows/supported.yml | 23 +- .github/workflows/truffle.yml | 56 +-- .github/workflows/unlocked_deps.yml | 84 ++++ .github/workflows/unsupported.yml | 15 +- .gitignore | 54 ++- .idea/.gitignore | 8 + .idea/GitCommitMessageStorage.xml | 20 + .idea/GitLink.xml | 6 + .idea/active-tab-highlighter.xml | 13 + .idea/codestream.xml | 6 + .idea/dbnavigator.xml | 427 +++++++++++++++++++ .idea/git_toolbox_prj.xml | 15 + .idea/misc.xml | 4 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/version_gem.iml | 167 ++++++++ .junie/guidelines-rbs.md | 49 +++ .junie/guidelines.md | 135 ++++++ .opencollective.yml | 3 + .qlty/qlty.toml | 79 ++++ .rspec | 7 +- .rubocop.yml | 14 + .simplecov | 4 + .tool-versions | 2 +- .yard_gfm_support.rb | 22 + .yardopts | 10 + Appraisal.root.gemfile | 4 +- Appraisals | 40 +- CHANGELOG.md | 40 +- CITATION.cff | 10 +- CODE_OF_CONDUCT.md | 7 +- CONTRIBUTING.md | 164 +++++--- FUNDING.md | 77 ++++ Gemfile | 27 +- Gemfile.lock | 53 ++- README.md | 548 ++++++++++++++++--------- RUBOCOP.md | 71 ++++ gemfiles/modular/coverage.gemfile | 2 +- gemfiles/modular/documentation.gemfile | 7 +- gemfiles/modular/optional.gemfile | 1 + gemfiles/modular/style.gemfile | 25 +- version_gem.gemspec | 108 +++-- 61 files changed, 2396 insertions(+), 529 deletions(-) create mode 100644 .git-hooks/commit-msg create mode 100644 .git-hooks/commit-subjects-goalie.txt create mode 100644 .git-hooks/footer-template.erb.txt create mode 100644 .git-hooks/prepare-commit-msg create mode 100644 .github/workflows/auto-assign.yml create mode 100644 .github/workflows/discord-notifier.yml create mode 100644 .github/workflows/locked_deps.yml create mode 100644 .github/workflows/opencollective.yml create mode 100644 .github/workflows/unlocked_deps.yml create mode 100644 .idea/.gitignore create mode 100644 .idea/GitCommitMessageStorage.xml create mode 100644 .idea/GitLink.xml create mode 100644 .idea/active-tab-highlighter.xml create mode 100644 .idea/codestream.xml create mode 100644 .idea/dbnavigator.xml create mode 100644 .idea/git_toolbox_prj.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/version_gem.iml create mode 100644 .junie/guidelines-rbs.md create mode 100644 .junie/guidelines.md create mode 100644 .opencollective.yml create mode 100644 .qlty/qlty.toml create mode 100644 .yard_gfm_support.rb create mode 100644 FUNDING.md create mode 100644 RUBOCOP.md create mode 100644 gemfiles/modular/optional.gemfile diff --git a/.envrc b/.envrc index 8312305..661b35f 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1,6 @@ # Run any command in this library's bin/ without the bin/ prefix! +# Prefer exe version over binstub +PATH_add exe PATH_add bin # Only add things to this file that should be shared with the team. @@ -16,18 +18,24 @@ PATH_add bin ### External Testing Controls export K_SOUP_COV_DO=true # Means you want code coverage +export K_SOUP_COV_COMMAND_NAME="Test Coverage" # Available formats are html, xml, rcov, lcov, json, tty -export K_SOUP_COV_COMMAND_NAME="RSpec Coverage" -export K_SOUP_COV_FORMATTERS="html,tty" +export K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty" export K_SOUP_COV_MIN_BRANCH=100 # Means you want to enforce X% branch coverage export K_SOUP_COV_MIN_LINE=100 # Means you want to enforce X% line coverage export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met export K_SOUP_COV_MULTI_FORMATTERS=true export K_SOUP_COV_OPEN_BIN= # Means don't try to open coverage results in browser export MAX_ROWS=1 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage +export KETTLE_TEST_SILENT=true # Internal Debugging Controls export DEBUG=false # do not allow byebug statements (override in .env.local) +export FLOSS_CFG_FUND_DEBUG=false # extra logging to help diagnose issues (override in .env.local) +export FLOSS_CFG_FUND_LOGFILE=tmp/log/debug.log + +# Concurrently developing the rubocop-lts suite? +export RUBOCOP_LTS_LOCAL=false # .env would override anything in this file, if `dotenv` is uncommented below. # .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments, diff --git a/.git-hooks/commit-msg b/.git-hooks/commit-msg new file mode 100644 index 0000000..cd918f6 --- /dev/null +++ b/.git-hooks/commit-msg @@ -0,0 +1,41 @@ +#!/usr/bin/env ruby +# vim: set syntax=ruby + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +# External gems +require "gitmoji/regex" + +full_text = File.read(ARGV[0]) +# Is the first character a GitMoji? +gitmoji_index = full_text =~ Gitmoji::Regex::REGEX +if gitmoji_index == 0 + exit 0 +else + denied = < (& many more) are a full-time endeavor. +- [❤️] Though I adore my work, it lacks financial sustainability. +- [❤️] Please, help me continue enhancing your tools by becoming a sponsor: + - [💲] https://liberapay.com/pboling/donate + - [💲] https://github.com/sponsors/pboling + +<% if ENV["GIT_HOOK_FOOTER_APPEND_DEBUG"] == "true" %> + @pwd = <%= @pwd %> + @gemspecs = <%= @gemspecs %> + @spec = <%= @spec %> + @gemspec_path = <%= @gemspec_path %> + @gem_name <%= @gem_name %> + @spec_name <%= @spec_name %> + @content <%= @content %> +<% end %> diff --git a/.git-hooks/prepare-commit-msg b/.git-hooks/prepare-commit-msg new file mode 100644 index 0000000..48c7547 --- /dev/null +++ b/.git-hooks/prepare-commit-msg @@ -0,0 +1,20 @@ +#!/bin/sh + +# Fail on error and unset variables +set -eu + +# Determine project root as the parent directory of this hook script +PROJECT_ROOT="$(CDPATH= cd -- "$(dirname -- "$0")"/.. && pwd)" + +# Run the Ruby hook within the direnv context (if available), +# so ENV from .envrc/.env.local at project root is loaded. +# One of the things .envrc needs to do is add $PROJECT_ROOT/bin/ to the path. +# You should have this line at the top of .envrc +# PATH_add bin +# NOTE: this project needs to also add exe as well, +# but other libraries won't generally need to do that. +if command -v direnv >/dev/null 2>&1; then + exec direnv exec "$PROJECT_ROOT" "kettle-commit-msg" "$@" +else + raise "direnv not found. Local development of this project ($PROJECT_ROOT) with tools from the kettle-dev gem may not work properly. Please run 'brew install direnv'." +fi diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 10e995a..7a5dc66 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -6,8 +6,8 @@ github: [pboling] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., issuehunt: pboling # Replace with a single IssueHunt username ko_fi: pboling # Replace with a single Ko-fi username liberapay: pboling # Replace with a single Liberapay username -open_collective: ruby-oauth # Replace with a single Open Collective username +open_collective: ruby-oauth patreon: galtzo # Replace with a single Patreon username polar: pboling thanks_dev: u/gh/pboling -tidelift: rubygems/version_gem # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +tidelift: rubygems/version_gem diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1bfb45a..956aa5a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,12 +3,11 @@ updates: - package-ecosystem: bundler directory: "/" schedule: - interval: daily - time: "04:36" - open-pull-requests-limit: 10 + interval: "weekly" + open-pull-requests-limit: 5 ignore: - dependency-name: "rubocop-lts" - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "daily" + interval: "weekly" diff --git a/.github/workflows/ancient.yml b/.github/workflows/ancient.yml index 8da80fe..3cc6e37 100644 --- a/.github/workflows/ancient.yml +++ b/.github/workflows/ancient.yml @@ -1,9 +1,13 @@ name: MRI 2.3, 2.4, 2.5 (EOL) +permissions: + contents: read + on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -20,8 +24,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-22.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -33,7 +37,7 @@ jobs: # Ruby 2.3 - ruby: "ruby-2.3" appraisal: "ruby-2-3" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: "3.3.27" bundler: "2.3.27" @@ -41,7 +45,7 @@ jobs: # Ruby 2.4 - ruby: "ruby-2.4" appraisal: "ruby-2-4" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: "3.3.27" bundler: "2.3.27" @@ -49,7 +53,7 @@ jobs: # Ruby 2.5 - ruby: "ruby-2.5" appraisal: "ruby-2-5" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: "3.3.27" bundler: "2.3.27" @@ -68,7 +72,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} diff --git a/.github/workflows/auto-assign.yml b/.github/workflows/auto-assign.yml new file mode 100644 index 0000000..96975f2 --- /dev/null +++ b/.github/workflows/auto-assign.yml @@ -0,0 +1,21 @@ +name: Auto Assign +on: + issues: + types: [opened] + pull_request: + types: [opened] +jobs: + run: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - name: 'Auto-assign issue' + uses: pozil/auto-assign-issue@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + assignees: pboling + abortIfPreviousAssignees: true + allowSelfAssign: true + numOfAssignee: 1 \ No newline at end of file diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a03c20f..45a8ec2 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ main, "*-stable" ] + branches: [ main, '*-stable' ] pull_request: # The branches below must be a subset of the branches above - branches: [ main, "*-stable" ] + branches: [ main, '*-stable' ] schedule: - cron: '35 1 * * 5' diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 0a8fd30..c9d6a2e 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,16 +1,24 @@ name: Test Coverage +permissions: + contents: read + pull-requests: write + id-token: write + env: K_SOUP_COV_MIN_BRANCH: 100 K_SOUP_COV_MIN_LINE: 100 K_SOUP_COV_MIN_HARD: true + K_SOUP_COV_FORMATTERS: "xml,rcov,lcov,tty" K_SOUP_COV_DO: true - K_SOUP_COV_COMMAND_NAME: "RSpec Coverage" + K_SOUP_COV_MULTI_FORMATTERS: true + K_SOUP_COV_COMMAND_NAME: "Test Coverage" on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -19,9 +27,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -30,8 +35,8 @@ concurrency: jobs: coverage: - name: Code Coverage on ${{ matrix.ruby }}@current if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Code Coverage on ${{ matrix.ruby }}@current runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -43,7 +48,7 @@ jobs: # Coverage - ruby: "ruby" appraisal: "coverage" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: latest bundler: latest @@ -62,7 +67,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} @@ -70,9 +75,37 @@ jobs: - name: Tests for ${{ matrix.ruby }}@current via ${{ matrix.exec_cmd }} run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} + # Do SaaS coverage uploads first + - name: Upload coverage to Coveralls + if: ${{ !env.ACT }} + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: ${{ matrix.experimental != 'false' }} + + - name: Upload coverage to QLTY + if: ${{ !env.ACT }} + uses: qltysh/qlty-action/coverage@main + with: + token: ${{secrets.QLTY_COVERAGE_TOKEN}} + files: coverage/.resultset.json + continue-on-error: ${{ matrix.experimental != 'false' }} + + # Build will fail here if coverage upload fails + # which will hopefully be noticed for the lack of code coverage comments + - name: Upload coverage to CodeCov + if: ${{ !env.ACT }} + uses: codecov/codecov-action@v5 + with: + use_oidc: true + fail_ci_if_error: false # optional (default = false) + files: coverage/lcov.info,coverage/coverage.xml + verbose: true # optional (default = false) + + # Then PR comments - name: Code Coverage Summary Report + if: ${{ !env.ACT && github.event_name == 'pull_request' }} uses: irongut/CodeCoverageSummary@v1.3.0 - if: ${{ github.event_name == 'pull_request' }} with: filename: ./coverage/coverage.xml badge: true @@ -87,28 +120,8 @@ jobs: - name: Add Coverage PR Comment uses: marocchino/sticky-pull-request-comment@v2 - if: ${{ github.event_name == 'pull_request' }} + if: ${{ !env.ACT && github.event_name == 'pull_request' }} with: recreate: true path: code-coverage-results.md continue-on-error: ${{ matrix.experimental != 'false' }} - - - name: Upload coverage to Coveralls - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - continue-on-error: ${{ matrix.experimental != 'false' }} - - - name: Upload coverage to QLTY - uses: qltysh/qlty-action/coverage@main - with: - coverage-token: ${{secrets.QLTY_COVERAGE_TOKEN}} - files: coverage/.resultset.json - continue-on-error: ${{ matrix.experimental != 'false' }} - - - name: Upload coverage to CodeCov - uses: codecov/codecov-action@v5 - with: - fail_ci_if_error: true # optional (default = false) - token: ${{ secrets.CODECOV_TOKEN }} - verbose: true # optional (default = false) diff --git a/.github/workflows/current.yml b/.github/workflows/current.yml index cfef85e..aca52ba 100644 --- a/.github/workflows/current.yml +++ b/.github/workflows/current.yml @@ -1,6 +1,9 @@ # Targets the evergreen latest release of ruby, truffleruby, and jruby name: Current +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -8,6 +11,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -16,9 +20,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -27,8 +28,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }} runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -39,7 +40,7 @@ jobs: # Ruby 3.4 - ruby: "ruby" appraisal: "current" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: latest bundler: latest @@ -49,7 +50,7 @@ jobs: # (according to runtime: targets Ruby 3.2 compatibility) - ruby: "truffleruby" appraisal: "current" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -57,7 +58,7 @@ jobs: # jruby-10.0 (targets Ruby 3.4 compatibility) - ruby: "jruby" appraisal: "current" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -76,7 +77,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }} diff --git a/.github/workflows/discord-notifier.yml b/.github/workflows/discord-notifier.yml new file mode 100644 index 0000000..ad98367 --- /dev/null +++ b/.github/workflows/discord-notifier.yml @@ -0,0 +1,39 @@ +name: Discord Notify + +on: + check_run: + types: [completed] + discussion: + types: [ created ] + discussion_comment: + types: [ created ] + fork: + gollum: + issues: + types: [ opened ] + issue_comment: + types: [ created ] + pull_request: + types: [ opened, reopened, closed ] + release: + types: [ published ] + watch: + types: [ started ] + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + # This workflow contains a single job called "build" + notify: + if: false + # The type of runner that the job will run on + runs-on: ubuntu-latest + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - name: Actions Status Discord + uses: sarisia/actions-status-discord@v1 + if: always() + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + status: ${{ job.status }} + username: GitHub Actions diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml index fe7f04a..e2046e6 100644 --- a/.github/workflows/heads.yml +++ b/.github/workflows/heads.yml @@ -1,5 +1,8 @@ name: Heads +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }}@${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -40,7 +41,7 @@ jobs: # ruby-head - ruby: "ruby-head" appraisal: "head" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -48,7 +49,7 @@ jobs: # truffleruby-head - ruby: "truffleruby-head" appraisal: "head" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -56,7 +57,7 @@ jobs: # jruby-head - ruby: "jruby-head" appraisal: "head" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -75,10 +76,22 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. - - name: Install Root Appraisal + # NOTE: This does not use the primary Gemfile at all. + - name: "Install Root Appraisal" run: bundle - - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }} + + - name: "[Attempt 1] Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }}" + id: bundleAttempt1 run: bundle exec appraisal ${{ matrix.appraisal }} bundle + # Continue to the next step on failure + continue-on-error: true + + # Effectively an automatic retry of the previous step. + - name: "[Attempt 2] Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }}" + id: bundleAttempt2 + # If bundleAttempt1 failed, try again here; Otherwise skip. + if: steps.bundleAttempt1.outcome == 'failure' + run: bundle exec appraisal ${{ matrix.appraisal }} bundle + - name: Tests for ${{ matrix.ruby }}@${{ matrix.appraisal }} via ${{ matrix.exec_cmd }} run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/jruby.yml b/.github/workflows/jruby.yml index 5035ed8..99ea13d 100644 --- a/.github/workflows/jruby.yml +++ b/.github/workflows/jruby.yml @@ -1,5 +1,8 @@ name: JRuby +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-22.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -35,35 +36,10 @@ jobs: strategy: matrix: include: - # TODO: truffleruby does not support upgrading rubygems; VALIDATE ASSUMPTION that same applies to JRuby - # jruby-9.1 (targets Ruby 2.3 compatibility) - - ruby: "jruby-9.1" - appraisal: "ruby-2-3" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default - - # jruby-9.2 (targets Ruby 2.5 compatibility) - - ruby: "jruby-9.2" - appraisal: "ruby-2-5" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default - - # jruby-9.3 (targets Ruby 2.6 compatibility) - - ruby: "jruby-9.3" - appraisal: "ruby-2-6" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default - # jruby-9.4 (targets Ruby 3.1 compatibility) - ruby: "jruby-9.4" appraisal: "ruby-3-1" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -82,7 +58,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 286d8f1..7f1fc29 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -1,4 +1,7 @@ -name: MRI 3.0 (EOL) +name: MRI 3.0, 3.1 (EOL) + +permissions: + contents: read env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-22.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -39,11 +40,19 @@ jobs: # Ruby 3.0 - ruby: "ruby-3.0" appraisal: "ruby-3-0" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: '3.5.23' bundler: '2.5.23' + # Ruby 3.1 + - ruby: "ruby-3.1" + appraisal: "ruby-3-1" + exec_cmd: "rake test" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + steps: - name: Checkout uses: actions/checkout@v5 @@ -58,7 +67,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} diff --git a/.github/workflows/locked_deps.yml b/.github/workflows/locked_deps.yml new file mode 100644 index 0000000..7d946ad --- /dev/null +++ b/.github/workflows/locked_deps.yml @@ -0,0 +1,85 @@ +--- +# Lock/Unlock Deps Pattern +# +# Two often conflicting goals resolved! +# +# - unlocked_deps.yml +# - All runtime & dev dependencies, but does not have a `gemfiles/*.gemfile.lock` committed +# - Uses an Appraisal2 "unlocked_deps" gemfile, and the current MRI Ruby release +# - Know when new dependency releases will break local dev with unlocked dependencies +# - Broken workflow indicates that new releases of dependencies may not work +# +# - locked_deps.yml +# - All runtime & dev dependencies, and has a `Gemfile.lock` committed +# - Uses the project's main Gemfile, and the current MRI Ruby release +# - Matches what contributors and maintainers use locally for development +# - Broken workflow indicates that a new contributor will have a bad time +# +name: Deps Locked + +permissions: + contents: read + +env: + # Running coverage, but not validating minimum coverage, + # because it would be redundant with the coverage workflow. + # Also we can validate all output formats without breaking CodeCov, + # since we aren't submitting these reports anywhere. + K_SOUP_COV_MIN_BRANCH: 71 + K_SOUP_COV_MIN_LINE: 86 + K_SOUP_COV_MIN_HARD: false + K_SOUP_COV_FORMATTERS: "html,xml,rcov,lcov,json,tty" + K_SOUP_COV_DO: true + K_SOUP_COV_MULTI_FORMATTERS: true + K_SOUP_COV_COMMAND_NAME: "Test Coverage" + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Default rake task w/ main Gemfile.lock ${{ matrix.name_extra || '' }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental }} + strategy: + fail-fast: false + matrix: + include: + # Ruby + - ruby: "ruby" + exec_cmd: "rake" + rubygems: latest + bundler: latest + experimental: false + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: true + + - name: Checks the kitchen sink via ${{ matrix.exec_cmd }} + run: bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/opencollective.yml b/.github/workflows/opencollective.yml new file mode 100644 index 0000000..6122df4 --- /dev/null +++ b/.github/workflows/opencollective.yml @@ -0,0 +1,40 @@ +name: Open Collective Backers + +on: + schedule: + # Run once a week on Sunday at 12:00 AM UTC + - cron: '0 0 * * 0' + workflow_dispatch: + +permissions: + contents: write + +jobs: + update-backers: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + with: + persist-credentials: false + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ruby + rubygems: default + bundler: default + bundler-cache: true + + - name: README Update + env: + # Keep GITHUB_TOKEN for any tools/scripts expecting it, mapped to the same secret + GITHUB_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} + README_UPDATER_TOKEN: ${{ secrets.README_UPDATER_TOKEN }} + REPO: ${{ github.repository }} + run: | + git config user.name 'autobolt' + git config user.email 'autobots@9thbit.net' + # Use the configured token for authenticated pushes + git remote set-url origin "https://x-access-token:${README_UPDATER_TOKEN}@github.com/${REPO}.git" + bin/kettle-readme-backers + # Push back to the same branch/ref that triggered the workflow (default branch for schedule) + git push origin HEAD diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index d6b1a37..2fe1e03 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -1,9 +1,13 @@ name: Style +permissions: + contents: read + on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -12,9 +16,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -23,8 +24,8 @@ concurrency: jobs: rubocop: - name: Style on ${{ matrix.ruby }}@current if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Style on ${{ matrix.ruby }}@current runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -55,7 +56,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} diff --git a/.github/workflows/supported.yml b/.github/workflows/supported.yml index 4e93000..887034b 100644 --- a/.github/workflows/supported.yml +++ b/.github/workflows/supported.yml @@ -1,5 +1,8 @@ name: MRI Non-EOL +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -35,18 +36,10 @@ jobs: strategy: matrix: include: - # Ruby 3.1 - - ruby: "ruby-3.1" - appraisal: "ruby-3-1" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: latest - bundler: latest - # Ruby 3.2 - ruby: "ruby-3.2" appraisal: "ruby-3-2" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: latest bundler: latest @@ -54,7 +47,7 @@ jobs: # Ruby 3.3 - ruby: "ruby-3.3" appraisal: "ruby-3-3" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: latest bundler: latest @@ -73,7 +66,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.ruby }} ${{ matrix.appraisal }} diff --git a/.github/workflows/truffle.yml b/.github/workflows/truffle.yml index 0a14af0..db65188 100644 --- a/.github/workflows/truffle.yml +++ b/.github/workflows/truffle.yml @@ -1,5 +1,8 @@ name: Truffle +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-22.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -36,26 +37,10 @@ jobs: matrix: include: # NOTE: truffleruby does not support upgrading rubygems. - # truffleruby-22.3 (targets Ruby 3.0 compatibility) - - ruby: "truffleruby-22.3" - appraisal: "ruby-3-0" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default - - # truffleruby-23.0 (targets Ruby 3.1 compatibility) - - ruby: "truffleruby-23.0" - appraisal: "ruby-3-1" - exec_cmd: "rake spec" - gemfile: "Appraisal.root" - rubygems: default - bundler: default - # truffleruby-23.1 (targets Ruby 3.2 compatibility) - ruby: "truffleruby-23.1" appraisal: "ruby-3-2" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: default bundler: default @@ -74,10 +59,35 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - - name: Appraisal for ${{ matrix.appraisal }} + + - name: "[Attempt 1] Install Root Appraisal" + id: bundleAttempt1 + run: bundle + # Continue to the next step on failure + continue-on-error: true + + # Effectively an automatic retry of the previous step. + - name: "[Attempt 2] Install Root Appraisal" + id: bundleAttempt2 + # If bundleAttempt1 failed, try again here; Otherwise skip. + if: steps.bundleAttempt1.outcome == 'failure' + run: bundle + + - name: "[Attempt 1] Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }}" + id: bundleAppraisalAttempt1 run: bundle exec appraisal ${{ matrix.appraisal }} bundle + # Continue to the next step on failure + continue-on-error: true + + # Effectively an automatic retry of the previous step. + - name: "[Attempt 2] Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal }}" + id: bundleAppraisalAttempt2 + # If bundleAttempt1 failed, try again here; Otherwise skip. + if: steps.bundleAppraisalAttempt1.outcome == 'failure' + run: bundle exec appraisal ${{ matrix.appraisal }} bundle + - name: Tests for ${{ matrix.ruby }} via ${{ matrix.exec_cmd }} run: bundle exec appraisal ${{ matrix.appraisal }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/unlocked_deps.yml b/.github/workflows/unlocked_deps.yml new file mode 100644 index 0000000..7faffa1 --- /dev/null +++ b/.github/workflows/unlocked_deps.yml @@ -0,0 +1,84 @@ +--- +# Lock/Unlock Deps Pattern +# +# Two often conflicting goals resolved! +# +# - unlocked_deps.yml +# - All runtime & dev dependencies, but does not have a `gemfiles/*.gemfile.lock` committed +# - Uses an Appraisal2 "unlocked_deps" gemfile, and the current MRI Ruby release +# - Know when new dependency releases will break local dev with unlocked dependencies +# - Broken workflow indicates that new releases of dependencies may not work +# +# - locked_deps.yml +# - All runtime & dev dependencies, and has a `Gemfile.lock` committed +# - Uses the project's main Gemfile, and the current MRI Ruby release +# - Matches what contributors and maintainers use locally for development +# - Broken workflow indicates that a new contributor will have a bad time +# +name: Deps Unlocked + +permissions: + contents: read + +env: + K_SOUP_COV_DO: false + +on: + push: + branches: + - 'main' + - '*-stable' + tags: + - '!*' # Do not execute on tags + pull_request: + branches: + - '*' + # Allow manually triggering the workflow. + workflow_dispatch: + +# Cancels all previous workflow runs for the same branch that have not yet completed. +concurrency: + # The concurrency group contains the workflow name and the branch name. + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: true + +jobs: + test: + if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Default rake task w/ unlocked deps ${{ matrix.name_extra || '' }} + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/${{ matrix.gemfile }}.gemfile + strategy: + matrix: + include: + # Ruby + - ruby: "ruby" + appraisal_name: "unlocked_deps" + exec_cmd: "rake" + gemfile: "Appraisal.root" + rubygems: latest + bundler: latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Ruby & RubyGems + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + rubygems: ${{ matrix.rubygems }} + bundler: ${{ matrix.bundler }} + bundler-cache: false + + # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) + # We need to do this first to get appraisal installed. + # NOTE: This does not use the primary Gemfile at all. + - name: Install Root Appraisal + run: bundle + - name: Appraisal for ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle + - name: Run ${{ matrix.exec_cmd }} on ${{ matrix.ruby }}@${{ matrix.appraisal_name }} + run: bundle exec appraisal ${{ matrix.appraisal_name }} bundle exec ${{ matrix.exec_cmd }} diff --git a/.github/workflows/unsupported.yml b/.github/workflows/unsupported.yml index 5a80ef3..9833699 100644 --- a/.github/workflows/unsupported.yml +++ b/.github/workflows/unsupported.yml @@ -1,5 +1,8 @@ name: MRI 2.6 & 2.7 (EOL) +permissions: + contents: read + env: K_SOUP_COV_DO: false @@ -7,6 +10,7 @@ on: push: branches: - 'main' + - '*-stable' tags: - '!*' # Do not execute on tags pull_request: @@ -15,9 +19,6 @@ on: # Allow manually triggering the workflow. workflow_dispatch: -permissions: - contents: read - # Cancels all previous workflow runs for the same branch that have not yet completed. concurrency: # The concurrency group contains the workflow name and the branch name. @@ -26,8 +27,8 @@ concurrency: jobs: test: - name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: Specs ${{ matrix.ruby }} ${{ matrix.appraisal }}${{ matrix.name_extra || '' }} runs-on: ubuntu-22.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} env: # $BUNDLE_GEMFILE must be set at job level, so it is set for all steps @@ -39,7 +40,7 @@ jobs: # Ruby 2.6 - ruby: "ruby-2.6" appraisal: "ruby-2-6" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: '3.4.22' bundler: '2.4.22' @@ -47,7 +48,7 @@ jobs: # Ruby 2.7 - ruby: "ruby-2.7" appraisal: "ruby-2-7" - exec_cmd: "rake spec" + exec_cmd: "rake test" gemfile: "Appraisal.root" rubygems: '3.4.22' bundler: '2.4.22' @@ -66,7 +67,7 @@ jobs: # Raw `bundle` will use the BUNDLE_GEMFILE set to matrix.gemfile (i.e. Appraisal.root) # We need to do this first to get appraisal installed. - # NOTE: This does not use the main Gemfile at all. + # NOTE: This does not use the primary Gemfile at all. - name: Install Root Appraisal run: bundle - name: Appraisal for ${{ matrix.appraisal }} diff --git a/.gitignore b/.gitignore index f9970e7..83000f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,22 +1,48 @@ +# Build Artifacts +/pkg/ +/tmp/ +*.gem + +# Bundler /.bundle/ -/.yardoc -/_yardoc/ +/gemfiles/*.lock +/gemfiles/.bundle/ +/gemfiles/.bundle/config +/gemfiles/vendor/ +Appraisal.*.gemfile.lock + +# Specs +.rspec_status /coverage/ -/doc/ -/pkg/ /spec/reports/ -/tmp/ +/results/ + +# Documentation +/.yardoc/ +/_yardoc/ +/rdoc/ +/doc/ + +# Ruby Version Managers (RVM, rbenv, etc) +# Ignored because we currently use .tool-versions +.rvmrc +.ruby-version +.ruby-gemset + +# Benchmarking +/measurement/ + +# Debugger detritus .byebug_history -# rspec failure tracking -.rspec_status +# direnv - brew install direnv +.env.local -# IDEs -/.idea/ +# OS Detritus +.DS_Store -# Packaging Artifacts -*.gem +# Editors +*~ -# gemfile locks for CI -gemfiles/*.gemfile.lock -Appraisal.*.gemfile.lock +# Sentinels +.floss_funding.*.lock diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/GitCommitMessageStorage.xml b/.idea/GitCommitMessageStorage.xml new file mode 100644 index 0000000..3b56900 --- /dev/null +++ b/.idea/GitCommitMessageStorage.xml @@ -0,0 +1,20 @@ + + + + + + \ No newline at end of file diff --git a/.idea/GitLink.xml b/.idea/GitLink.xml new file mode 100644 index 0000000..000fa35 --- /dev/null +++ b/.idea/GitLink.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/active-tab-highlighter.xml b/.idea/active-tab-highlighter.xml new file mode 100644 index 0000000..409aba9 --- /dev/null +++ b/.idea/active-tab-highlighter.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codestream.xml b/.idea/codestream.xml new file mode 100644 index 0000000..e4f5ed1 --- /dev/null +++ b/.idea/codestream.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 0000000..b9e7cc8 --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,427 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml new file mode 100644 index 0000000..02b915b --- /dev/null +++ b/.idea/git_toolbox_prj.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..b4353a6 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..fa3396c --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml new file mode 100644 index 0000000..4a9d042 --- /dev/null +++ b/.idea/version_gem.iml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.junie/guidelines-rbs.md b/.junie/guidelines-rbs.md new file mode 100644 index 0000000..9de8973 --- /dev/null +++ b/.junie/guidelines-rbs.md @@ -0,0 +1,49 @@ +# Junie Project Guidelines Addendum: RBS Documentation + +This repository ships RBS type signatures under `sig/` which are included in the published gem and referenced by documentation tooling. + +RBS files must contain only valid RBS syntax. Do not embed Ruby code or YARD-style Ruby documentation constructs in `.rbs` files. + +Requirements for RBS documentation and signatures: + +- Use RBS comment style (`# ...`) for notes and documentation inside `.rbs` files. +- Do not use Ruby heredocs (`<<-DOC`, `<<~RUBY`, etc.) or any Ruby code constructs in `.rbs` files. +- Do not use Ruby metaprogramming notation like `class << self` in `.rbs`. For singleton methods, use: + - `def self.method_name: ...` +- Do not use `extend self` or `module self` in `.rbs`. Declare singleton methods explicitly with `def self.method_name: ...`. +- Keep type aliases, interfaces, and method signatures in proper RBS form only (e.g., `def foo: (String) -> Integer`). +- If you need to document parameters or returns, place brief comments above the signature lines using `#` and keep them RBS-friendly (no `@param` / `@return` tags from YARD). + +Examples: + +Valid (RBS): + +``` +module Foo + # Runs tasks + def self.run: () -> void +end +``` + +Invalid (not allowed in .rbs): + +``` +# Ruby syntax – not RBS +class << self + def run: () -> void +end + +# Not supported across RBS versions; avoid in this project +module self + def run: () -> void +end + +# Heredocs or any Ruby bodies are not allowed in .rbs +def self.run: () -> void + <<~DOC +DOC +end +``` + +Enforcement: +- CI and local builds may parse `.rbs` files during gem install or doc generation. Any non-RBS syntax can cause installation to fail. Keep `.rbs` clean to avoid such failures. diff --git a/.junie/guidelines.md b/.junie/guidelines.md new file mode 100644 index 0000000..61ee0cd --- /dev/null +++ b/.junie/guidelines.md @@ -0,0 +1,135 @@ +Project: version_gem — Development Guidelines (for advanced contributors) + +This document captures project-specific knowledge to streamline setup, testing, and ongoing development. + +1. Build and configuration +- ENV is controlled by `direnv`. + - Two files are loaded: + - .envrc — environment variables for local development, committed to source control + - .env.local — environment variables that are not committed to source control. These setting override .envrc. + - Run `direnv allow` after making changes to .envrc or .env.local. + - See .envrc for details. + - See .env.local.example for an example of what to put in .env.local. + - See CONTRIBUTING.md for details on how to set up your local environment. +- Ruby and Bundler + - Runtime supports very old Rubies (>= 2.2), but development tooling targets >= 2.3 because of CI/setup-ruby and dev dependencies. + - Use a recent Ruby (>= 3.1 recommended) for fastest setup and to exercise modern coverage behavior. + - Install dependencies via Bundler in project root: + - bundle install +- Rake tasks (preferred entry points) + - The Rakefile wires common workflows. Useful targets: + - rake spec — run RSpec suite (also aliased via rake test) + - rake coverage — run specs with coverage locally and open a report (requires kettle-soup-cover) + - rake rubocop_gradual:autocorrect — RuboCop-LTS Gradual, with autocorrect as default task + - rake reek and rake reek:update — code smell checks and persisted snapshots in REEK + - rake yard — generate YARD docs for lib and selected extra files + - rake bundle:audit and rake bundle:audit:update — dependency vulnerability checks + - rake build / rake release — gem build/release helper tasks (Bundler + stone_checksums) + - The default rake target runs a curated set of tasks; this varies for CI vs local (see CI env var logic in Rakefile). + - Always run the default rake task prior commits, and after making changes to lib/ code, or *.md files, to allow the linter to autocorrect, and to generate updated documentation. +- Coverage orchestration + - Coverage is controlled by kettle-soup-cover and .simplecov. Thresholds (line and branch) are enforced and can fail the process. + - Thresholds are primarily controlled by environment variables (see .simplecov and comments therein) typically loaded via direnv (.envrc) and CI workflow (.github/workflows/coverage.yml). When running only a test subset, thresholds may fail; see Testing below. +- Gem signing (for releases) + - Signing is enabled unless SKIP_GEM_SIGNING is set. If enabled and certificates are present (certs/.pem), gem build will attempt to sign using ~/.ssh/gem-private_key.pem. + - See CONTRIBUTING.md for releasing details; use SKIP_GEM_SIGNING when building in environments without the private key. + - Important for local testing (to avoid hanging prompts): ALWAYS skip signing when building locally to test the packaging or install process. Without the private key password, the build will wait indefinitely at a signing prompt. + - One-off commands (recommended): + - SKIP_GEM_SIGNING=true gem build version_gem.gemspec + - SKIP_GEM_SIGNING=true bundle exec rake build + - SKIP_GEM_SIGNING=true bundle exec rake release # only to test workflow; do not actually push + - direnv option (optional, not recommended globally): add `export SKIP_GEM_SIGNING=true` to your .env.local when you know you won’t be signing in this environment. + - Remove or unset SKIP_GEM_SIGNING when performing a real, signed release in the environment that has the private key. + +2. Testing +- Framework and helpers + - RSpec 3.13 with custom spec/spec_helper.rb configuration: + - silent_stream: STDOUT is silenced by default for examples to keep logs clean. + - To explicitly test console output, tag the example or group with :check_output. + - Global state hygiene: Around each example, FlossFunding.namespaces and FlossFunding.silenced are snapshotted and restored to prevent cross-test pollution. + - DEBUG toggle: Set DEBUG=true to require 'debug' and avoid silencing output during your run. + - ENV seeding: The suite sets ENV["FLOSS_FUNDING_FLOSS_FUNDING"] = "Free-as-in-beer" so that the library’s own namespace is considered activated (avoids noisy warnings). + - Coverage: kettle-soup-cover integrates SimpleCov; .simplecov is invoked from spec_helper when enabled by Kettle::Soup::Cover::DO_COV, which is controlled by K_SOUP_COV_DO being set to true / false. + - RSpec.describe usage: + - Use `describe "#"` to contain a block of specs that test instance method behavior. + - Use `describe "::"` to contain a block of specs that test class method behavior. + - Do not use `describe "."` because the dot is ambiguous w.r.t instance vs. class methods. + - When adding new code or modifying existing code always add tests to cover the updated behavior, including branches, and different types of expected and unexpected inputs. + - Additional test utilities: + - rspec-stubbed_env: Use stub_env to control ENV safely within examples. + - timecop-rspec: Time manipulation is available, and is setup by kettle-test. + - To freeze time use `freeze: Time.new(*args)` tag on an example or group +- Running tests (verified) + - Full suite (recommended to satisfy coverage thresholds): + - bin/rspec + - or: bundle exec rspec + - or: bundle exec rake spec + - Progress format (less verbose): + - bundle exec rspec --format progress + - Focused runs + - You can run a single file or example, but note: coverage thresholds need to be disabled with K_SOUP_COV_MIN_HARD=false + - Example: K_SOUP_COV_MIN_HARD=false bin/rspec spec/version_gem/class_spec.rb:42 + - Output visibility + - To see STDOUT from the code under test, use the :check_output tag on the example or group. + Example: + RSpec.describe "output", :check_output do + it "prints" do + puts "This output should be visible" + expect(true).to be true + end + end + - Alternatively, run with DEBUG=true to disable silencing for the entire run. + - During a spec run, the presence of output about missing activation keys is often expected, since it is literally what this library is for. It only indicates a failure if the spec expected all activation keys to be present, and not all specs do. +- Adding new tests (guidelines) + - Organize specs by class/module. Do not create per-task umbrella spec files; add examples to the existing spec for the class/module under test, or create a new spec file for that class/module if one does not exist. Only create a standalone scenario spec when it intentionally spans multiple classes for an integration/benchmark scenario (e.g., bench_integration_spec), and name it accordingly. + - Spec file names must map to a real class or module under lib/ (mirror the path). Do not introduce specs for non-existent classes or ad-hoc names (e.g., avoid template_helpers_replacements_spec.rb when testing VersionGem::TemplateHelpers; add those examples to template_helpers_spec.rb). + - REQUIRED: Provide unit tests for every class, module, constant, and public method. Place them in spec/ mirroring the path under lib/. When a file under lib/ is added or changed, ensure a corresponding spec file exists/updated for it. + - Add tests for all public methods and add contexts for variations of their arguments, and arity. + - This repository targets near-100% coverage of its public API; when you add new public methods, rake tasks to a rakelib, or config behavior, add or update specs accordingly. + - Place new specs under spec/ mirroring lib/ structure where possible. Do not require "spec_helper" at the top of spec files, as it is automatically loaded by .rspec. + - If your code relies on environment variables that drive activation (see "Activation env vars" below), prefer using rspec-stubbed_env: + - it does not support stubbing with blocks, but it does automatically clean up after itself. + - outside the example: + include_context 'with stubbed env' + - in a before hook, or in an example: + stub_env("FLOSS_FUNDING_MY_NS" => "Free-as-in-beer") + # example code continues + - If your spec needs to assert on console output, tag it with :check_output. By default, STDOUT is silenced. + - Use Timecop for deterministic time-sensitive behavior as needed (require config/timecop is already done by spec_helper). + +- Types and documentation + - REQUIRED: All public APIs must have RBS type signatures checked into sig/ under the corresponding path. When you add a new public method or change a signature, update the matching .rbs file. + - REQUIRED: All public methods must include inline YARD docs with @param/@return (and @yield/@option where applicable). Generate docs with `bundle exec rake yard` to verify formatting. + +3. Additional development information +- Code style and static analysis + - RuboCop-LTS (Gradual) is integrated. Use: + - bundle exec rake rubocop_gradual:autocorrect + - bundle exec rake rubocop_gradual:force_update # only run if there are still linting violations the default rake task, which includes autocorrect locally, or a standalone autocorrect task, has run, and failed, and the violations won't be fixed + - Reek is configured to scan {lib,spec,tests}/**/*.rb. Use: + - bundle exec rake reek + - bundle exec rake reek:update # writes current output to REEK, fails on smells + - Keep REEK file updated with intentional smells snapshot when appropriate (e.g., after refactors). + - Locally, the default rake task includes reek:update. +- Documentation + - Generate YARD docs with: bundle exec rake yard. It includes lib/**/*.rb and extra docs like README.md, CHANGELOG.md, RUBOCOP.md, REEK, etc. +- Appraisal and multi-gemfile testing + - appraisal2 is present to manage multiple dependency sets; see Appraisals and gemfiles/modular/*.gemfile. If you need to verify against alternate dependency versions, use Appraisal to install and run rspec under those Gemfiles. + - You can run a single github workflow by running `act -W /github/workflows/.yml` +- CI/local differences and defaults + - The Rakefile adjusts default tasks based on CI env var. Locally, rake default may include coverage, reek:update, yard, etc. On CI, it tends to just run spec. + +Quick start +1) bundle install +2) K_SOUP_COV_FORMATTERS="json" bin/rspec (generates a JSON coverage report with both line and branch data in coverage/. Use this single format.) +3) Static analysis: bundle exec rake rubocop_gradual:check && bundle exec rake reek + +Notes +- ALWAYS Run bundle exec rake rubocop_gradual:autocorrect as the final step before completing a task, to lint and autocorrect any remaining issues. Then if there are new lint failures, attempt to correct them manually. +- NEVER run vanilla rubocop, as it won't handle the linting config properly. Always run rubocop_gradual:autocorrect or rubocop_gradual. +- Running only a subset of specs is supported but in order to bypass the hard failure due to coverage thresholds, you need to run with K_SOUP_COV_MIN_HARD=false. +- When adding code that writes to STDOUT, remember most specs silence output unless tagged with :check_output or DEBUG=true. +- Completion criteria after changes: Only consider your change “done” when the relevant examples pass, as verified by .rspec_status. Do not rely on STDOUT impressions; consult .rspec_status (and example IDs) to confirm green results for the affected files/examples. If you ran a subset, re-run the full suite before finalizing to restore coverage thresholds. +- Coverage reports: NEVER review the HTML report. Use JSON (preferred), XML, LCOV, or RCOV. For this project, always run tests with K_SOUP_COV_FORMATTERS set to "json". +- Do NOT modify .envrc in tasks; when running tests locally or in scripts, manually prefix each run, e.g.: K_SOUP_COV_FORMATTERS="json" bin/rspec +- For all the kettle-soup-cover options, see .envrc and find the K_SOUP_COV_* env vars. diff --git a/.opencollective.yml b/.opencollective.yml new file mode 100644 index 0000000..30032d6 --- /dev/null +++ b/.opencollective.yml @@ -0,0 +1,3 @@ +collective: "ruby-oauth" +readme-backers-commit-subject: "💸 Thanks 🙏 to our new backers 🎒 and subscribers 📜" +readme-osc-tag: "OPENCOLLECTIVE" diff --git a/.qlty/qlty.toml b/.qlty/qlty.toml new file mode 100644 index 0000000..9ae9cae --- /dev/null +++ b/.qlty/qlty.toml @@ -0,0 +1,79 @@ +# For a guide to configuration, visit https://qlty.sh/d/config +# Or for a full reference, visit https://qlty.sh/d/qlty-toml +config_version = "0" + +exclude_patterns = [ + "*_min.*", + "*-min.*", + "*.min.*", + "**/.yarn/**", + "**/*.d.ts", + "**/assets/**", + "**/bin/**", + "**/bower_components/**", + "**/build/**", + "**/cache/**", + "**/config/**", + "**/.devcontainer", + "**/db/**", + "**/deps/**", + "**/dist/**", + "**/doc/**", + "**/docs/**", + "**/extern/**", + "**/external/**", + "**/generated/**", + "**/Godeps/**", + "**/gradlew/**", + "**/mvnw/**", + "**/node_modules/**", + "**/protos/**", + "**/seed/**", + "**/target/**", + "**/templates/**", + "**/testdata/**", + "**/vendor/**", + ".github/workflows/codeql-analysis.yml" +] + +test_patterns = [ + "**/test/**", + "**/spec/**", + "**/*.test.*", + "**/*.spec.*", + "**/*_test.*", + "**/*_spec.*", + "**/test_*.*", + "**/spec_*.*", +] + +[smells] +mode = "comment" + +[smells.boolean_logic] +threshold = 4 +enabled = true + +[smells.file_complexity] +threshold = 55 +enabled = false + +[smells.return_statements] +threshold = 4 +enabled = true + +[smells.nested_control_flow] +threshold = 4 +enabled = true + +[smells.function_parameters] +threshold = 4 +enabled = true + +[smells.function_complexity] +threshold = 5 +enabled = true + +[smells.duplication] +enabled = true +threshold = 20 \ No newline at end of file diff --git a/.rspec b/.rspec index b95daa8..a43744c 100644 --- a/.rspec +++ b/.rspec @@ -1,4 +1,9 @@ ---format documentation +--format progress --color +--order random --require spec_helper --warnings +--format html +--out results/test_results.html +--format RspecJunitFormatter +--out results/test_results.xml diff --git a/.rubocop.yml b/.rubocop.yml index 6de99cd..9dad2b7 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,2 +1,16 @@ inherit_gem: rubocop-lts: config/rubygem_rspec.yml + +plugins: rubocop-on-rbs + +RBS: + Enabled: true + +Layout/IndentationConsistency: + Exclude: ['*.md'] + +RSpec/ExampleLength: + Enabled: false + +RSpec/MultipleExpectations: + Enabled: false diff --git a/.simplecov b/.simplecov index bfe90c0..af5bd1c 100644 --- a/.simplecov +++ b/.simplecov @@ -1,3 +1,7 @@ require "kettle/soup/cover/config" +# Minimum coverage thresholds are set by kettle-soup-cover. +# It is controlled by ENV variables, which are set in .envrc and loaded via `direnv allow` +# If the values for minimum coverage need to change, they should be changed both there, +# and in 2 places in .github/workflows/coverage.yml. SimpleCov.start diff --git a/.tool-versions b/.tool-versions index 27a8619..5184db8 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 3.4.5 +ruby 3.4.5 \ No newline at end of file diff --git a/.yard_gfm_support.rb b/.yard_gfm_support.rb new file mode 100644 index 0000000..4f2f140 --- /dev/null +++ b/.yard_gfm_support.rb @@ -0,0 +1,22 @@ +# Gratefully and liberally taken from the MIT-licensed https://github.com/bensheldon/good_job/pull/113/files +require "kramdown" +require "kramdown-parser-gfm" + +# Custom markup provider class that always renders Kramdown using GFM (Github Flavored Markdown). +# GFM is needed to render markdown tables and fenced code blocks in the README. +class KramdownGfmDocument < Kramdown::Document + def initialize(source, options = {}) + options[:input] = "GFM" unless options.key?(:input) + super(source, options) + end +end + +# Insert the new provider as the highest priority option for Markdown. +# See: +# - https://github.com/lsegal/yard/issues/1157 +# - https://github.com/lsegal/yard/issues/1017 +# - https://github.com/lsegal/yard/blob/main/lib/yard/templates/helpers/markup_helper.rb +YARD::Templates::Helpers::MarkupHelper::MARKUP_PROVIDERS[:markdown].insert( + 0, + {const: "KramdownGfmDocument"}, +) diff --git a/.yardopts b/.yardopts index f9cf06c..479134d 100644 --- a/.yardopts +++ b/.yardopts @@ -1 +1,11 @@ --plugin junk +--plugin relative_markdown_links +--readme README.md +--charset utf-8 +--markup markdown +--output docs +--load .yard_gfm_support.rb +'lib/**/*.rb' +- +'*.md' +'*.txt' \ No newline at end of file diff --git a/Appraisal.root.gemfile b/Appraisal.root.gemfile index dbfd485..02afd18 100644 --- a/Appraisal.root.gemfile +++ b/Appraisal.root.gemfile @@ -6,7 +6,7 @@ source "https://rubygems.org" # Appraisal Root Gemfile is for running appraisal to generate the Appraisal Gemfiles # in gemfiles/*gemfile. -# On GHA CI, we use it for the Appraisal-based builds. -# We do not load the standard Gemfile, as it is tailored for local development & GitLab CI. +# On CI, we use it for the Appraisal-based builds. +# We do not load the standard Gemfile, as it is tailored for local development. gemspec diff --git a/Appraisals b/Appraisals index f2a8c69..edfb05e 100644 --- a/Appraisals +++ b/Appraisals @@ -1,14 +1,37 @@ # frozen_string_literal: true -# HOW TO UPDATE APPRAISALS: -# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle -# BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +# HOW TO UPDATE APPRAISALS (will run rubocop_gradual's autocorrect afterward): +# bin/rake appraisals:update + +# Lock/Unlock Deps Pattern +# +# Two often conflicting goals resolved! +# +# - unlocked_deps.yml +# - All runtime & dev dependencies, but does not have a `gemfiles/*.gemfile.lock` committed +# - Uses an Appraisal2 "unlocked_deps" gemfile, and the current MRI Ruby release +# - Know when new dependency releases will break local dev with unlocked dependencies +# - Broken workflow indicates that new releases of dependencies may not work +# +# - locked_deps.yml +# - All runtime & dev dependencies, and has a `Gemfile.lock` committed +# - Uses the project's main Gemfile, and the current MRI Ruby release +# - Matches what contributors and maintainers use locally for development +# - Broken workflow indicates that a new contributor will have a bad time +# +appraise "unlocked_deps" do + eval_gemfile "modular/coverage.gemfile" + eval_gemfile "modular/documentation.gemfile" + eval_gemfile "modular/style.gemfile" + eval_gemfile "modular/optional.gemfile" +end # Used for head (nightly) releases of ruby, truffleruby, and jruby. # Split into discrete appraisals if one of them needs a dependency locked discretely. appraise "head" do gem "mutex_m", ">= 0.2" gem "stringio", ">= 3.0" + gem "benchmark", "~> 0.4", ">= 0.4.1" end # Used for current releases of ruby, truffleruby, and jruby. @@ -18,9 +41,6 @@ appraise "current" do gem "stringio", ">= 3.0" end -appraise "ruby-2-2" do -end - appraise "ruby-2-3" do end @@ -60,21 +80,21 @@ appraise "ruby-3-3" do gem "stringio", "~> 3.0" end -# Only run security audit on latest Ruby version +# Only run security audit on the latest version of Ruby appraise "audit" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" - eval_gemfile "modular/audit.gemfile" end -# Only run coverage on latest Ruby version +# Only run coverage on the latest version of Ruby appraise "coverage" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" eval_gemfile "modular/coverage.gemfile" + eval_gemfile "modular/optional.gemfile" end -# Only run linter on latest Ruby version (but, in support of oldest supported Ruby version) +# Only run linter on the latest version of Ruby (but, in support of oldest supported Ruby version) appraise "style" do gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a5863..51d3485 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,10 +19,13 @@ Please file a bug if you notice a violation of semantic versioning. ## [Unreleased] ### Added ### Changed -### Fixed +### Deprecated ### Removed +### Fixed +### Security -## [1.1.8] 2025-05-06 ([tag][1.1.8t]) +## [1.1.8] 2025-05-06 +- TAG: [1.1.8][1.1.8t] - COVERAGE: 100.00% -- 118/118 lines in 8 files - BRANCH COVERAGE: 100.00% -- 4/4 branches in 8 files - 84.62% documented @@ -34,7 +37,8 @@ Please file a bug if you notice a violation of semantic versioning. - Addressed entire REEK list (@pboling) - GitLab CI, as an addition to existing GHA (@pboling) -## [1.1.7] 2025-04-15 ([tag][1.1.7t]) +## [1.1.7] 2025-04-15 +- TAG: [1.1.7][1.1.7t] - Line Coverage: 100.0% (117 / 117) - Branch Coverage: 100.0% (4 / 4) - 76.92% documented @@ -47,7 +51,8 @@ Please file a bug if you notice a violation of semantic versioning. - Ruby 2.2 removed from CI, though technically still supported - can't run directly in GHA anymore -## [1.1.6] 2025-02-24 ([tag][1.1.6t]) +## [1.1.6] 2025-02-24 +- TAG: [1.1.6][1.1.6t] - Line Coverage: 100.0% (77 / 77) - Branch Coverage: 100.0% (2 / 2) - 77.78% documented @@ -62,7 +67,8 @@ Please file a bug if you notice a violation of semantic versioning. ### Changed - Code of Conduct updated - Contributor Covenant v2.0 => v2.1 (@pboling) -## [1.1.5] 2025-02-22 ([tag][1.1.5t]) +## [1.1.5] 2025-02-22 +- TAG: [1.1.5][1.1.5t] - Line Coverage: 100.0% (77 / 77) - Branch Coverage: 100.0% (2 / 2) - 77.78% documented @@ -77,13 +83,15 @@ Please file a bug if you notice a violation of semantic versioning. - Documentation of usage in gemspec via `Kernel.load` (@pboling) - Improved gemspec config (@pboling) -## [1.1.4] 2024-03-21 ([tag][1.1.4t]) +## [1.1.4] 2024-03-21 +- TAG: [1.1.4][1.1.4t] ### Added - Ruby 3.3 to CI (@pboling) ### Fixed - Remove the executable bit from non-executable files (@Fryguy) -## [1.1.3] 2023-06-05 ([tag][1.1.3t]) +## [1.1.3] 2023-06-05 +- TAG: [1.1.3][1.1.3t] ### Added - More test coverage (now 100% 🎉) (@pboling) - Improved documentation (now 77% 🎉) (@pboling) @@ -103,14 +111,16 @@ Please file a bug if you notice a violation of semantic versioning. - Formally drop Ruby 2.2 support - Ruby 2.2 was already de facto minimum version supported, which is why this wasn't a 2.0 release. -## [1.1.2] - 2023-03-17 ([tag][1.1.2t]) +## [1.1.2] - 2023-03-17 +- TAG: [1.1.2][1.1.2t] ### Added - `VersionGem::Ruby` to help library CI integration against many different versions of Ruby (@pboling) - Experimental, optional, require (not loaded by default, which is why this can be in a patch) - Spec coverage is now 100%, lines and branches, including the fabled `version.rb` (@pboling) - Full RBS Signatures (@pboling) -## [1.1.1] - 2022-09-19 ([tag][1.1.1t]) +## [1.1.1] - 2022-09-19 +- TAG: [1.1.1][1.1.1t] ### Added - Alternatives section to README.md (@pboling) - Signing cert for gem releases (@pboling) @@ -121,24 +131,28 @@ Please file a bug if you notice a violation of semantic versioning. - Version methods are now memoized (||=) on initial call for performance (@pboling) - Gem releases are now cryptographically signed (@pboling) -## [1.1.0] - 2022-06-24 ([tag][1.1.0t]) +## [1.1.0] - 2022-06-24 +- TAG: [1.1.0][1.1.0t] ### Added - RSpec Matchers and Shared Example (@pboling) ### Fixed - `to_a` uses same type casting as major, minor, patch, and pre (@pboling) -## [1.0.2] - 2022-06-23 ([tag][1.0.2t]) +## [1.0.2] - 2022-06-23 +- TAG: [1.0.2][1.0.2t] ### Added - Delay loading of library code until after code coverage tool is loaded (@pboling) -## [1.0.1] - 2022-06-23 ([tag][1.0.1t]) +## [1.0.1] - 2022-06-23 +- TAG: [1.0.1][1.0.1t] ### Added - CI Build improvements (@pboling) - Code coverage reporting (@pboling) - Documentation improvements (@pboling) - Badges! (@pboling) -## [1.0.0] - 2022-06-21 ([tag][1.0.0t]) +## [1.0.0] - 2022-06-21 +- TAG: [1.0.0][1.0.0t] ### Added - Initial release, with basic version parsing API (@pboling) diff --git a/CITATION.cff b/CITATION.cff index 46659bb..c7da8b7 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,5 +1,5 @@ cff-version: 1.2.0 -title: VersionGem +title: version_gem message: >- If you use this work and you want to cite it, then you can use the metadata from this file. @@ -12,9 +12,9 @@ authors: orcid: 'https://orcid.org/0009-0008-8519-441X' identifiers: - type: url - value: 'https://github.com/oauth-xx/version_gem/' - description: VersionGem -repository-code: 'https://github.com/oauth-xx/version_gem/' + value: 'https://github.com/ruby-oauth/version_gem' + description: version_gem +repository-code: 'https://github.com/ruby-oauth/version_gem' abstract: >- - VersionGem + version_gem license: See license file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 6be4700..7ad4c15 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,3 @@ - # Contributor Covenant Code of Conduct ## Our Pledge @@ -61,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -[![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact]. +[![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the @@ -131,5 +130,5 @@ For answers to common questions about this code of conduct, see the FAQ at [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations -[🚂bdfl-contact]: http://www.railsbling.com/contact -[🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red +[🚂maint-contact]: http://www.railsbling.com/contact +[🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bec282b..73fd4ce 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,42 +1,74 @@ # Contributing -Bug reports and pull requests are welcome on GitHub at [https://gitlab.com/oauth-xx/version_gem][🚎src-main] -. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to +Bug reports and pull requests are welcome on [CodeBerg][📜src-cb], [GitLab][📜src-gl], or [GitHub][📜src-gh]. +This project should be a safe, welcoming space for collaboration, so contributors agree to adhere to the [code of conduct][🤝conduct]. -To submit a patch, please fork the project and create a patch with -tests. Once you're happy with it send a pull request and post a message to the -[google group][⛳mail-list] or on the [gitter chat][🏘chat]. +To submit a patch, please fork the project, create a patch with tests, and send a pull request. +Post a message to the [google group][⛳mail-list] if you want to. -We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it. +Remember to [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] if you make changes. -## You can help! +## Help out! -Simply follow these instructions: +Take a look at the `reek` list which is the file called `REEK` and find something to improve. + +Follow these instructions: 1. Fork the repository -2. Create your feature branch (`git checkout -b my-new-feature`) +2. Create a feature branch (`git checkout -b my-new-feature`) 3. Make some fixes. -4. Commit your changes (`git commit -am 'Added some feature'`) +4. Commit changes (`git commit -am 'Added some feature'`) 5. Push to the branch (`git push origin my-new-feature`) 6. Make sure to add tests for it. This is important, so it doesn't break in a future release. 7. Create new Pull Request. -## Appraisals +## Environment Variables for Local Development -From time to time the appraisal gemfiles in `gemfiles/` will need to be updated. -They are created and updated with the commands: +Below are the primary environment variables recognized by stone_checksums (and its integrated tools). Unless otherwise noted, set boolean values to the string "true" to enable. + +General/runtime +- DEBUG: Enable extra internal logging for this library (default: false) +- REQUIRE_BENCH: Enable `require_bench` to profile requires (default: false) +- CI: When set to true, adjusts default rake tasks toward CI behavior + +Coverage (kettle-soup-cover / SimpleCov) +- K_SOUP_COV_DO: Enable coverage collection (default: true in .envrc) +- K_SOUP_COV_FORMATTERS: Comma-separated list of formatters (html, xml, rcov, lcov, json, tty) +- K_SOUP_COV_MIN_LINE: Minimum line coverage threshold (integer, e.g., 100) +- K_SOUP_COV_MIN_BRANCH: Minimum branch coverage threshold (integer, e.g., 100) +- K_SOUP_COV_MIN_HARD: Fail the run if thresholds are not met (true/false) +- K_SOUP_COV_MULTI_FORMATTERS: Enable multiple formatters at once (true/false) +- K_SOUP_COV_OPEN_BIN: Path to browser opener for HTML (empty disables auto-open) +- MAX_ROWS: Limit console output rows for simplecov-console (e.g., 1) + Tip: When running a single spec file locally, you may want `K_SOUP_COV_MIN_HARD=false` to avoid failing thresholds for a partial run. -NOTE: We run on a [fork][🚎appraisal-fork] of Appraisal. +GitHub API and CI helpers +- GITHUB_TOKEN or GH_TOKEN: Token used by `ci:act` and release workflow checks to query GitHub Actions status at higher rate limits + +Releasing and signing +- SKIP_GEM_SIGNING: If set, skip gem signing during build/release +- GEM_CERT_USER: Username for selecting your public cert in `certs/.pem` (defaults to $USER) +- SOURCE_DATE_EPOCH: Reproducible build timestamp. `kettle-release` will set this automatically for the session. + +Git hooks and commit message helpers (exe/kettle-commit-msg) +- GIT_HOOK_BRANCH_VALIDATE: Branch name validation mode (e.g., `jira`) or `false` to disable +- GIT_HOOK_FOOTER_APPEND: Append a footer to commit messages when goalie allows (true/false) +- GIT_HOOK_FOOTER_SENTINEL: Required when footer append is enabled — a unique first-line sentinel to prevent duplicates +- GIT_HOOK_FOOTER_APPEND_DEBUG: Extra debug output in the footer template (true/false) + +For a quick starting point, this repository’s `.envrc` shows sane defaults, and `.env.local` can override them locally. + +## Appraisals -Please upvote the PR for `eval_gemfile` [support][🚎appraisal-eval-gemfile-pr] +From time to time the [appraisal2][🚎appraisal2] gemfiles in `gemfiles/` will need to be updated. +They are created and updated with the commands: -```shell -BUNDLE_GEMFILE=Appraisal.root.gemfile bundle -BUNDLE_GEMFILE=Appraisal.root.gemfile bundle exec appraisal update +```console +bin/rake appraisal:update ``` -When adding an appraisal to CI check the [runner tool cache][🏃‍♂️runner-tool-cache] to see which runner to use. +When adding an appraisal to CI, check the [runner tool cache][🏃‍♂️runner-tool-cache] to see which runner to use. ## The Reek List @@ -44,7 +76,7 @@ Take a look at the `reek` list which is the file called `REEK` and find somethin To refresh the `reek` list: -```bash +```console bundle exec reek > REEK ``` @@ -52,24 +84,43 @@ bundle exec reek > REEK To run all tests -```bash +```console bundle exec rake test ``` +### Spec organization (required) + +- For each class or module under `lib/`, keep all of its unit tests in a single spec file under `spec/` that mirrors the path and file name (e.g., specs for `lib/version_gem/release_cli.rb` live in `spec/version_gem/release_cli_spec.rb`). +- Do not create ad-hoc "_more" or split spec files for the same class/module. Consolidate all unit tests into the main spec file for that class/module. +- Only integration scenarios that intentionally span multiple classes belong in `spec/integration/`. + ## Lint It Run all the default tasks, which includes running the gradually autocorrecting linter, `rubocop-gradual`. -```bash +```console bundle exec rake ``` Or just run the linter. -```bash +```console bundle exec rake rubocop_gradual:autocorrect ``` +For more detailed information about using RuboCop in this project, please see the [RUBOCOP.md](RUBOCOP.md) guide. This project uses `rubocop_gradual` instead of vanilla RuboCop, which requires specific commands for checking violations. + +### Important: Do not add inline RuboCop disables + +Never add `# rubocop:disable ...` / `# rubocop:enable ...` comments to code or specs (except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). Instead: + +- Prefer configuration-based exclusions when a rule should not apply to certain paths or files (e.g., via `.rubocop.yml`). +- When a violation is temporary and you plan to fix it later, record it in `.rubocop_gradual.lock` using the gradual workflow: + - `bundle exec rake rubocop_gradual:autocorrect` (preferred) + - `bundle exec rake rubocop_gradual:force_update` (only when you cannot fix the violations immediately) + +As a general rule, fix style issues rather than ignoring them. For example, our specs should follow RSpec conventions like using `described_class` for the class under test. + ## Contributors Your picture could be here! @@ -78,60 +129,71 @@ Your picture could be here! Made with [contributors-img][🖐contrib-rocks]. -Also see GitLab Contributors: [https://gitlab.com/oauth-xx/version_gem/-/graphs/main][🚎contributors-gl] +Also see GitLab Contributors: [https://gitlab.com/ruby-oauth/version_gem/-/graphs/main][🚎contributors-gl] ## For Maintainers ### One-time, Per-maintainer, Setup -**IMPORTANT**: If you want to sign the build you create, -your public key for signing gems will need to be picked up by the line in the +**IMPORTANT**: To sign a build, +a public key for signing gems will need to be picked up by the line in the `gemspec` defining the `spec.cert_chain` (check the relevant ENV variables there). -All releases to RubyGems.org will be signed. +All releases to RubyGems.org are signed releases. See: [RubyGems Security Guide][🔒️rubygems-security-guide] -NOTE: To build without signing the gem you must set `SKIP_GEM_SIGNING` to some value in your environment. +NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in the environment. ### To release a new version: -1. Run `bin/setup && bin/rake` as a tests, coverage, & linting sanity check +#### Automated process + +Run `bundle exec kettle-release`. + +#### Manual process + +1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check 2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes 3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock` 4. Run `git commit -am "🔖 Prepare release v"` to commit the changes -5. Run `git push` to trigger the final CI pipeline before release, & merge PRs - - NOTE: Remember to [check the build][🧪build]! +5. Run `git push` to trigger the final CI pipeline before release, and merge PRs + - NOTE: Remember to [check the build][🧪build]. 6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME` 7. Run `git checkout $GIT_TRUNK_BRANCH_NAME` -8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure you will release the latest trunk code -9. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums - - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` - - If the echo above has no output, then it didn't work. - - Note that you'll need the `zsh/datetime` module, if running `zsh`. - - In `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` +8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure latest trunk code +9. Optional for older Bundler (< 2.7.0): Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use the same timestamp and generate the same checksums + - If your Bundler is >= 2.7.0, you can skip this; builds are reproducible by default. + - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` + - If the echo above has no output, then it didn't work. + - Note: `zsh/datetime` module is needed, if running `zsh`. + - In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` 10. Run `bundle exec rake build` -11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr] and [2][🔒️rubygems-guides-pr]) - to create SHA-256 and SHA-512 checksums - - Checksums will be committed automatically by the script, but not pushed -12. Run `bundle exec rake release` which will create a git tag for the version, - push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] +11. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr]) + to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums` + [gem][💎stone_checksums]. + - The script automatically commits but does not push the checksums +12. Sanity check the SHA256, comparing with the output from the `bin/gem_checksums` command: + - `sha256sum pkg/-.gem` +13. Run `bundle exec rake release` which will create a git tag for the version, + push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] [⛳mail-list]: http://groups.google.com/group/oauth-ruby -[🚎src-main]: https://gitlab.com/oauth-xx/version_gem -[🧪build]: https://github.com/oauth-xx/version_gem/actions -[🏘chat]: https://matrix.to/#/#pboling_version_gem:gitter.im -[🤝conduct]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/CODE_OF_CONDUCT.md +[📜src-gl]: https://gitlab.com/ruby-oauth/version_gem/ +[📜src-cb]: https://codeberg.org/ruby-oauth/version_gem +[📜src-gh]: https://github.com/ruby-oauth/version_gem +[🧪build]: https://github.com/ruby-oauth/version_gem/actions +[🤝conduct]: https://gitlab.com/ruby-oauth/version_gem/-/blob/main/CODE_OF_CONDUCT.md [🖐contrib-rocks]: https://contrib.rocks -[🖐contributors]: https://github.com/oauth-xx/version_gem/graphs/contributors -[🚎contributors-gl]: https://gitlab.com/oauth-xx/version_gem/-/graphs/main -[🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/version_gem +[🖐contributors]: https://github.com/ruby-oauth/version_gem/graphs/contributors +[🚎contributors-gl]: https://gitlab.com/ruby-oauth/version_gem/-/graphs/main +[🖐contributors-img]: https://contrib.rocks/image?repo=ruby-oauth/version_gem [💎rubygems]: https://rubygems.org [🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems [🔒️rubygems-checksums-pr]: https://github.com/rubygems/rubygems/pull/6022 [🔒️rubygems-guides-pr]: https://github.com/rubygems/guides/pull/325 +[💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ [📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139 [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html -[🚎appraisal-eval-gemfile-pr]: https://github.com/thoughtbot/appraisal/pull/248 -[🚎appraisal-fork]: https://github.com/pboling/appraisal/tree/galtzo +[🚎appraisal2]: https://github.com/appraisal-rb/appraisal2 [🏃‍♂️runner-tool-cache]: https://github.com/ruby/ruby-builder/releases/tag/toolcache diff --git a/FUNDING.md b/FUNDING.md new file mode 100644 index 0000000..19197a2 --- /dev/null +++ b/FUNDING.md @@ -0,0 +1,77 @@ + + +Official Discord 👉️ [![Live Chat on Discord][✉️discord-invite-img]][✉️discord-invite] + +Many paths lead to being a sponsor or a backer of this project. Are you on such a path? + +[![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] + +[![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] + +[⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat +[⛳liberapay]: https://liberapay.com/pboling/donate +[🖇osc-backers]: https://opencollective.com/ruby-oauth#backer +[🖇osc-backers-i]: https://opencollective.com/ruby-oauth/backers/badge.svg?style=flat +[🖇osc-sponsors]: https://opencollective.com/ruby-oauth#sponsor +[🖇osc-sponsors-i]: https://opencollective.com/ruby-oauth/sponsors/badge.svg?style=flat +[🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github +[🖇sponsor]: https://github.com/sponsors/pboling +[🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat +[🖇polar]: https://polar.sh/pboling +[🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat +[🖇kofi]: https://ko-fi.com/O5O86SNP4 +[🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat +[🖇patreon]: https://patreon.com/galtzo +[🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat +[🖇buyme]: https://www.buymeacoffee.com/pboling +[🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal +[🖇paypal]: https://www.paypal.com/paypalme/peterboling +[✉️discord-invite]: https://discord.gg/3qme4XHNKN +[✉️discord-invite-img]: https://img.shields.io/discord/1373797679469170758?style=flat + + + +# 🤑 Request for Help + +Maintainers have teeth and need to pay their dentists. +After getting laid off in an RIF in March and filled with many dozens of rejections, +I'm now spending ~60+ hours a week building open source tools. +I'm hoping to be able to pay for my kids' health insurance this month, +so if you value the work I am doing, I need your support. +Please consider sponsoring me or the project. + +To join the community or get help 👇️ Join the Discord. + +[![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] + +To say "thanks for maintaining such a great tool" ☝️ Join the Discord or 👇️ send money. + +[![Sponsor ruby-oauth/version_gem on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay-img] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal-img] + +# Another Way to Support Open Source Software + +> How wonderful it is that nobody need wait a single moment before starting to improve the world.
+>—Anne Frank + +I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats). + +If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`. + +I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look. + +**[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags** + +[⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611 +[🖇osc-all-img]: https://img.shields.io/opencollective/all/ruby-oauth +[🖇osc-sponsors-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth +[🖇osc-backers-img]: https://img.shields.io/opencollective/backers/ruby-oauth +[🖇osc-all-bottom-img]: https://img.shields.io/opencollective/all/ruby-oauth?style=for-the-badge +[🖇osc-sponsors-bottom-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth?style=for-the-badge +[🖇osc-backers-bottom-img]: https://img.shields.io/opencollective/backers/ruby-oauth?style=for-the-badge +[🖇osc]: https://opencollective.com/ruby-oauth +[🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github +[🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff +[🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A +[🖇floss-funding.dev]: https://floss-funding.dev +[🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding +[✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge diff --git a/Gemfile b/Gemfile index a4c96e7..af3abbf 100644 --- a/Gemfile +++ b/Gemfile @@ -6,38 +6,22 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" } #### IMPORTANT ####################################################### -# Gemfile is for local development and GitLab CI # -# Gemfile is NOT loaded in GitHub Actions CI # +# Gemfile is for local development ONLY; Gemfile is NOT loaded in CI # ####################################################### IMPORTANT #### -# For Ruby version specific dependencies -ruby_version = Gem::Version.create(RUBY_VERSION) - # Include dependencies from .gemspec gemspec platform :mri do # Debugging - Ensure ENV["DEBUG"] == "true" to use debuggers within spec suite - if ruby_version < Gem::Version.create("2.7") - # Use byebug in code - gem "byebug", ">= 11" - else - # Use binding.break, binding.b, or debugger in code - gem "debug", ">= 1.0.0" - end + # Use binding.break, binding.b, or debugger in code + gem "debug", ">= 1.0.0" # ruby >= 2.7 + gem "gem_bench", "~> 2.0", ">= 2.0.5" # Dev Console - Binding.pry - Irb replacement gem "pry", "~> 0.14" # ruby >= 2.0 end -# Security Audit -if ruby_version >= Gem::Version.create("3") - # NOTE: Audit fails on Ruby 2.7 because nokogiri has dropped support for Ruby < 3 - # See: https://github.com/sparklemotion/nokogiri/security/advisories/GHSA-r95h-9x8f-r3f7 - # We can't add upgraded nokogiri here unless we are developing on Ruby 3+ - eval_gemfile "gemfiles/modular/audit.gemfile" -end - # Code Coverage eval_gemfile "gemfiles/modular/coverage.gemfile" @@ -46,3 +30,6 @@ eval_gemfile "gemfiles/modular/style.gemfile" # Documentation eval_gemfile "gemfiles/modular/documentation.gemfile" + +# Optional +eval_gemfile "gemfiles/modular/optional.gemfile" diff --git a/Gemfile.lock b/Gemfile.lock index 873498c..8222f9c 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,6 +14,7 @@ PATH remote: . specs: version_gem (1.1.8) + version_gem (~> 1.1, >= 1.1.8) GEM remote: https://rubygems.org/ @@ -70,7 +71,9 @@ GEM dry-logic (~> 1.4) zeitwerk (~> 2.6) erb (5.0.2) - github-markup (5.0.1) + gem_bench (2.0.5) + bundler (>= 1.14) + version_gem (~> 1.1, >= 1.1.4) gitmoji-regex (1.0.3) version_gem (~> 1.1, >= 1.1.8) io-console (0.8.1) @@ -108,10 +111,20 @@ GEM silent_stream (~> 1.0, >= 1.0.12) timecop-rspec (~> 1.0, >= 1.0.3) version_gem (~> 1.1, >= 1.1.8) + kramdown (2.5.1) + rexml (>= 3.3.9) + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) language_server-protocol (3.17.0.5) lint_roller (1.1.0) logger (1.7.0) method_source (1.1.0) + nokogiri (1.18.9-arm64-darwin) + racc (~> 1.4) + nokogiri (1.18.9-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.18.9-x86_64-linux-gnu) + racc (~> 1.4) ostruct (0.6.3) parallel (1.27.0) parser (3.3.9.0) @@ -130,10 +143,11 @@ GEM racc (1.8.1) rainbow (3.1.1) rake (13.3.0) + rbs (3.9.4) + logger rdoc (6.14.2) erb psych (>= 4.0.0) - redcarpet (3.6.1) reek (6.5.0) dry-schema (~> 1.13) logger (~> 1.6) @@ -193,6 +207,11 @@ GEM version_gem (>= 1.1.2, < 3) rubocop-md (1.2.4) rubocop (>= 1.45) + rubocop-on-rbs (1.8.0) + lint_roller (~> 1.1) + rbs (~> 3.5) + rubocop (>= 1.72.1, < 2.0) + zlib rubocop-packaging (0.6.0) lint_roller (~> 1.1.0) rubocop (>= 1.72.1, < 2.0) @@ -275,34 +294,38 @@ GEM unicode-emoji (~> 4.0, >= 4.0.4) unicode-emoji (4.0.4) yard (0.9.37) + yard-relative_markdown_links (0.5.0) + nokogiri (>= 1.14.3, < 2) zeitwerk (2.7.3) + zlib (3.2.1) PLATFORMS arm64-darwin-22 arm64-darwin-24 - ruby x86_64-darwin-19 x86_64-linux DEPENDENCIES - benchmark (~> 0.4) - bundler-audit (~> 0.9.2) + benchmark (~> 0.4, >= 0.4.1) debug (>= 1.0.0) - github-markup (~> 5.0, >= 5.0.1) - kettle-dev (~> 1.0, >= 1.0.25) - kettle-soup-cover (~> 1.0, >= 1.0.6) + gem_bench (~> 2.0, >= 2.0.5) + kettle-dev (~> 1.0.17) + kettle-soup-cover (~> 1.0, >= 1.0.10) + kramdown (~> 2.5, >= 2.5.1) + kramdown-parser-gfm (~> 1.1) pry (~> 0.14) rdoc (~> 6.11) - redcarpet (~> 3.6) - reek (~> 6.4) - rubocop (~> 1.73, >= 1.73.2) - rubocop-lts (~> 8.1, >= 8.1.1) - rubocop-packaging (~> 0.5, >= 0.5.2) - rubocop-rspec (~> 3.2) - standard (~> 1.47) + reek (~> 6.5) + rubocop-lts (~> 8.0) + rubocop-on-rbs (~> 1.8) + rubocop-packaging (~> 0.6, >= 0.6.0) + rubocop-rspec (~> 3.6) + rubocop-ruby2_2 + standard (>= 1.50) version_gem! yard (~> 0.9, >= 0.9.37) yard-junk (~> 0.0, >= 0.0.10)! + yard-relative_markdown_links (~> 0.5.0) BUNDLED WITH 2.7.1 diff --git a/README.md b/README.md index eea6c9d..65bb416 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,42 @@ +[![Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0][🖼️galtzo-i]][🖼️galtzo-discord] [![ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5][🖼️ruby-lang-i]][🖼️ruby-lang] [![version_gem Logo by Aboling0, CC BY-SA 4.0][🖼️version_gem-i]][🖼️version_gem] + +[🖼️galtzo-i]: https://logos.galtzo.com/assets/images/galtzo-floss/avatar-192px.svg +[🖼️galtzo-discord]: https://discord.gg/3qme4XHNKN +[🖼️ruby-lang-i]: https://logos.galtzo.com/assets/images/ruby-lang/avatar-192px.svg +[🖼️ruby-lang]: https://www.ruby-lang.org/ +[🖼️version_gem-i]: https://logos.galtzo.com/assets/images/ruby-oauth/version_gem/avatar-192px.svg +[🖼️version_gem]: https://github.com/ruby-oauth/version_gem + # 🔖 VersionGem -[![Version][👽versioni]][👽version] -[![License: MIT][📄license-img]][📄license-ref] -[![Downloads Rank][👽dl-ranki]][👽dl-rank] -[![Open Source Helpers][👽oss-helpi]][👽oss-help] -[![Depfu][🔑depfui♻️]][🔑depfu] -[![CodeCov Test Coverage][🔑codecovi♻️]][🔑codecov] -[![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] -[![CodeClimate Test Coverage][🔑cc-covi♻️]][🔑cc-cov] -[![Maintainability][🔑cc-mnti♻️]][🔑cc-mnt] -[![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] -[![CI Current][🚎11-c-wfi]][🚎11-c-wf] -[![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] -[![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] -[![CI Supported][🚎6-s-wfi]][🚎6-s-wf] -[![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] -[![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] -[![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] -[![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] -[![CI Style][🚎5-st-wfi]][🚎5-st-wf] +[![Version][👽versioni]][👽version] [![GitHub tag (latest SemVer)][⛳️tag-img]][⛳️tag] [![License: MIT][📄license-img]][📄license-ref] [![Downloads Rank][👽dl-ranki]][👽dl-rank] [![Open Source Helpers][👽oss-helpi]][👽oss-help] [![CodeCov Test Coverage][🔑codecovi]][🔑codecov] [![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] [![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov] [![QLTY Maintainability][🔑qlty-mnti]][🔑qlty-mnt] [![CI Heads][🚎3-hd-wfi]][🚎3-hd-wf] [![CI Current][🚎11-c-wfi]][🚎11-c-wf] [![CI Truffle Ruby][🚎9-t-wfi]][🚎9-t-wf] [![CI JRuby][🚎10-j-wfi]][🚎10-j-wf] [![Deps Locked][🚎13-🔒️-wfi]][🚎13-🔒️-wf] [![Deps Unlocked][🚎14-🔓️-wfi]][🚎14-🔓️-wf] [![CI Supported][🚎6-s-wfi]][🚎6-s-wf] [![CI Legacy][🚎4-lg-wfi]][🚎4-lg-wf] [![CI Unsupported][🚎7-us-wfi]][🚎7-us-wf] [![CI Ancient][🚎1-an-wfi]][🚎1-an-wf] [![CI Test Coverage][🚎2-cov-wfi]][🚎2-cov-wf] [![CI Style][🚎5-st-wfi]][🚎5-st-wf] [![CodeQL][🖐codeQL-img]][🖐codeQL] + +If ☝️ `ci_badges.map(&:color).detect { it != "green"}` [let me know][🖼️galtzo-discord], as I may have missed the [discord notification][🖼️galtzo-discord]. --- -[![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] -[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] -[![Buy me a coffee][🖇buyme-small-img]][🖇buyme] -[![Donate on Polar][🖇polar-img]][🖇polar] -[![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] -[![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] +OTOH, if `ci_badges.map(&:color).all? { it == "green"}` 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job. + +[![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] + +## 🌻 Synopsis + +Give your next library an introspectable `Version` module without breaking your Gemspec. + +```ruby +MyLib::Version.to_s # => "1.2.3.rc3" +MyLib::Version.major # => 1 +MyLib::Version.minor # => 2 +MyLib::Version.patch # => 3 +MyLib::Version.pre # => "rc3" +MyLib::Version.to_a # => [1, 2, 3, "rc3"] +MyLib::Version.to_h # => { major: 1, minor: 2, patch: 3, pre: "rc3" } +``` + +This library was extracted from the gem _[oauth2](https://gitlab.com/oauth-xx/oauth2)_. + +This gem has no runtime dependencies. + ## 🧐 Alternatives @@ -47,65 +56,101 @@ gem from the Alchemists, or _[version_sorter](https://rubygems.org/gems/version_ For more discussion about this [see issue #2](https://gitlab.com/oauth-xx/version_gem/-/issues/2) -## 🚀 Still here? +## 💡 Info you can shake a stick at -Give your next library an introspectable `Version` module without breaking your Gemspec. +| Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Works with JRuby | ![JRuby 9.1 Compat][💎jruby-9.1i] ![JRuby 9.2 Compat][💎jruby-9.2i] ![JRuby 9.3 Compat][💎jruby-9.3i]
[![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] | +| Works with Truffle Ruby | ![Truffle Ruby 22.3 Compat][💎truby-22.3i] ![Truffle Ruby 23.0 Compat][💎truby-23.0i]
[![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] | +| Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] | +| Works with MRI Ruby 2 | ![Ruby 2.2 Compat][💎ruby-2.2i]
[![Ruby 2.3 Compat][💎ruby-2.3i]][🚎1-an-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] | +| Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on CodeBerg.org][📜src-cb-img]][📜src-cb] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] | +| Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![YARD on Galtzo.com][📜docs-head-rd-img]][🚎yard-head] [![Maintainer Blog][🚂maint-blog-img]][🚂maint-blog] [![Wiki][📜wiki-img]][📜wiki] | +| Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] | +| Style | [![Enforced Code Style Linter][💎rlts-img]][💎rlts] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] [![Compatibility appraised by: appraisal2][💎appraisal2-img]][💎appraisal2] | +| Support | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] | +| Maintainer 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact Maintainer][🚂maint-contact-img]][🚂maint-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] | +| `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] | -```ruby -MyLib::Version.to_s # => "1.2.3.rc3" -MyLib::Version.major # => 1 -MyLib::Version.minor # => 2 -MyLib::Version.patch # => 3 -MyLib::Version.pre # => "rc3" -MyLib::Version.to_a # => [1, 2, 3, "rc3"] -MyLib::Version.to_h # => { major: 1, minor: 2, patch: 3, pre: "rc3" } -``` +### Compatibility -This library was extracted from the gem _[oauth2](https://gitlab.com/oauth-xx/oauth2)_. +Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby. -This gem has no runtime dependencies. +| 🚚 _Amazing_ test matrix was brought to you by | 🔎 appraisal2 🔎 | +|------------------------------------------------|-------------------------------------------------------------------------------------| +| 👟 Check it out! | ✨ [github.com/appraisal-rb/appraisal2][💎appraisal2] ✨ | -## 💡 Info you can shake a stick at +### Federated DVCS + +
+ Find this repo on other forges (Coming soon!) + +| Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | +|-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| +| 🧪 [ruby-oauth/version_gem on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ | +| 🧊 [ruby-oauth/version_gem on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ | +| 🐙 [ruby-oauth/version_gem on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | [💚][gh-discussions] | +| 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] | + +
+ +[gh-discussions]: https://github.com/ruby-oauth/version_gem/discussions + +### Enterprise Support [![Tidelift](https://tidelift.com/badges/package/rubygems/version_gem)](https://tidelift.com/subscription/pkg/rubygems-version_gem?utm_source=rubygems-version_gem&utm_medium=referral&utm_campaign=readme) + +Available as part of the Tidelift Subscription. + +
+ Need enterprise-level guarantees? + +The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. + +[![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift] + +- 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies +- 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar] +- 💡Tidelift pays maintainers to maintain the software you depend on!
📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers -| Tokens to Remember | [![Gem name][⛳️name-img]][⛳️gem-name] [![Gem namespace][⛳️namespace-img]][⛳️gem-namespace] | -|-------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Works with JRuby | [![JRuby 9.1 Compat][💎jruby-9.1i]][🚎10-j-wf] [![JRuby 9.2 Compat][💎jruby-9.2i]][🚎10-j-wf] [![JRuby 9.3 Compat][💎jruby-9.3i]][🚎10-j-wf] [![JRuby 9.4 Compat][💎jruby-9.4i]][🚎10-j-wf] [![JRuby 10.0 Compat][💎jruby-c-i]][🚎11-c-wf] [![JRuby HEAD Compat][💎jruby-headi]][🚎3-hd-wf] | -| Works with Truffle Ruby | [![Truffle Ruby 22.3 Compat][💎truby-22.3i]][🚎9-t-wf] [![Truffle Ruby 23.0 Compat][💎truby-23.0i]][🚎9-t-wf] [![Truffle Ruby 23.1 Compat][💎truby-23.1i]][🚎9-t-wf] [![Truffle Ruby 24.1 Compat][💎truby-c-i]][🚎11-c-wf] [![Truffle Ruby HEAD Compat][💎truby-headi]][🚎3-hd-wf] | -| Works with MRI Ruby 3 | [![Ruby 3.0 Compat][💎ruby-3.0i]][🚎4-lg-wf] [![Ruby 3.1 Compat][💎ruby-3.1i]][🚎6-s-wf] [![Ruby 3.2 Compat][💎ruby-3.2i]][🚎6-s-wf] [![Ruby 3.3 Compat][💎ruby-3.3i]][🚎6-s-wf] [![Ruby 3.4 Compat][💎ruby-c-i]][🚎11-c-wf] [![Ruby HEAD Compat][💎ruby-headi]][🚎3-hd-wf] | -| Works with MRI Ruby 2 | [![Ruby 2.3 Compat][💎ruby-2.3i]][🚎1-an-wf] [![Ruby 2.4 Compat][💎ruby-2.4i]][🚎1-an-wf] [![Ruby 2.5 Compat][💎ruby-2.5i]][🚎1-an-wf] [![Ruby 2.6 Compat][💎ruby-2.6i]][🚎7-us-wf] [![Ruby 2.7 Compat][💎ruby-2.7i]][🚎7-us-wf] | -| Source | [![Source on GitLab.com][📜src-gl-img]][📜src-gl] [![Source on Github.com][📜src-gh-img]][📜src-gh] [![The best SHA: dQw4w9WgXcQ!][🧮kloc-img]][🧮kloc] | -| Documentation | [![Current release on RubyDoc.info][📜docs-cr-rd-img]][🚎yard-current] [![HEAD on RubyDoc.info][📜docs-head-rd-img]][🚎yard-head] [![BDFL Blog][🚂bdfl-blog-img]][🚂bdfl-blog] [![Wiki][📜wiki-img]][📜wiki] | -| Compliance | [![License: MIT][📄license-img]][📄license-ref] [![📄ilo-declaration-img]][📄ilo-declaration] [![Security Policy][🔐security-img]][🔐security] [![Enforced Code Style][💎rlts-img]][💎rlts] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct] [![SemVer 2.0.0][📌semver-img]][📌semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] [![Gitmoji Commits][📌gitmoji-img]][📌gitmoji] | -| Expert 1:1 Support | [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] `or` [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] | -| Enterprise Support | [![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift]
💡Subscribe for support guarantees covering _all_ FLOSS dependencies!
💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar]!
💡Tidelift pays maintainers to maintain the software you depend on!
📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers! | -| Comrade BDFL 🎖️ | [![Follow Me on LinkedIn][💖🖇linkedin-img]][💖🖇linkedin] [![Follow Me on Ruby.Social][💖🐘ruby-mast-img]][💖🐘ruby-mast] [![Follow Me on Bluesky][💖🦋bluesky-img]][💖🦋bluesky] [![Contact BDFL][🚂bdfl-contact-img]][🚂bdfl-contact] [![My technical writing][💖💁🏼‍♂️devto-img]][💖💁🏼‍♂️devto] | -| `...` 💖 | [![Find Me on WellFound:][💖✌️wellfound-img]][💖✌️wellfound] [![Find Me on CrunchBase][💖💲crunchbase-img]][💖💲crunchbase] [![My LinkTree][💖🌳linktree-img]][💖🌳linktree] [![More About Me][💖💁🏼‍♂️aboutme-img]][💖💁🏼‍♂️aboutme] [🧊][💖🧊berg] [🐙][💖🐙hub] [🛖][💖🛖hut] [🧪][💖🧪lab] | +Alternatively: + +- [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] +- [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] +- [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] + +
## ✨ Installation Install the gem and add to the application's Gemfile by executing: - $ bundle add version_gem +```console +bundle add version_gem +``` If bundler is not being used to manage dependencies, install the gem by executing: - $ gem install version_gem +```console +gem install version_gem +``` ### 🔒 Secure Installation -`version_gem` is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by +
+ For Medium or High Security Installations + +This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by [stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with by following the instructions below. Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate: -```shell -gem cert --add <(curl -Ls https://raw.github.com/oauth-xx/version_gem/main/certs/pboling.pem) +```console +gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem) ``` You only need to do that once. Then proceed to install with: -```shell +```console gem install version_gem -P HighSecurity ``` @@ -113,7 +158,7 @@ The `HighSecurity` trust profile will verify signed gems, and not allow the inst If you want to up your security game full-time: -```shell +```console bundle config set --global trust-policy MediumSecurity ``` @@ -121,7 +166,9 @@ bundle config set --global trust-policy MediumSecurity NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine. -## 🔧 Basic Usage +
+ +## ⚙️ Configuration In the standard `bundle gem my_lib` code you get the following in `lib/my_lib/version.rb`: @@ -156,7 +203,9 @@ MyLib::Version.class_eval do end ``` -And now you have some version introspection methods available: +## 🔧 Basic Usage + +Now you have some version introspection methods available: ```ruby MyLib::Version.to_s # => "0.1.0" @@ -388,10 +437,59 @@ RSpec.describe(MyLib::Version) do end end ``` +## 🦷 FLOSS Funding -### 🚀 Release Instructions +While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding. +Raising a monthly budget of... "dollars" would make the project more sustainable. -See [CONTRIBUTING.md][🤝contributing]. +We welcome both individual and corporate sponsors! We also offer a +wide array of funding channels to account for your preferences +(although currently [Open Collective][🖇osc] is our preferred funding platform). + +**If you're working in a company that's making significant use of ruby-oauth tools we'd +appreciate it if you suggest to your company to become a ruby-oauth sponsor.** + +You can support the development of ruby-oauth tools via +[GitHub Sponsors][🖇sponsor], +[Liberapay][⛳liberapay], +[PayPal][🖇paypal], +[Open Collective][🖇osc] +and [Tidelift][🏙️entsup-tidelift]. + +| 📍 NOTE | +|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| If doing a sponsorship in the form of donation is problematic for your company
from an accounting standpoint, we'd recommend the use of Tidelift,
where you can get a support-like subscription instead. | + +### Open Collective for Individuals + + +No backers yet. Be the first! + + +Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/ruby-oauth#backer)] + +### Open Collective for Organizations + + +No sponsors yet. Be the first! + + +Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor](https://opencollective.com/ruby-oauth#sponsor)] + +### Another way to support open-source + +> How wonderful it is that nobody need wait a single moment before starting to improve the world.
+>—Anne Frank + +I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats). + +If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in `bundle fund`. + +I’m developing a new library, [floss_funding][🖇floss-funding-gem], designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look. + +**[Floss-Funding.dev][🖇floss-funding.dev]: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags** + +[![OpenCollective Backers][🖇osc-backers-i]][🖇osc-backers] [![OpenCollective Sponsors][🖇osc-sponsors-i]][🖇osc-sponsors] [![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] [![Liberapay Goal Progress][⛳liberapay-img]][⛳liberapay] [![Donate on PayPal][🖇paypal-img]][🖇paypal] [![Buy me a coffee][🖇buyme-small-img]][🖇buyme] [![Donate on Polar][🖇polar-img]][🖇polar] [![Donate to my FLOSS or refugee efforts at ko-fi.com][🖇kofi-img]][🖇kofi] [![Donate to my FLOSS or refugee efforts using Patreon][🖇patreon-img]][🖇patreon] ## 🔐 Security @@ -400,21 +498,29 @@ See [SECURITY.md][🔐security]. ## 🤝 Contributing If you need some ideas of where to help, you could work on adding more code coverage, -or if it is already 💯 (see [below](#code-coverage)) then check [issues][🤝issues], or [PRs][🤝pulls], +or if it is already 💯 (see [below](#code-coverage)) check [reek](REEK), [issues][🤝gh-issues], or [PRs][🤝gh-pulls], or use the gem and think about how it could be better. We [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] so if you make changes, remember to update it. See [CONTRIBUTING.md][🤝contributing] for more detailed instructions. +### 🚀 Release Instructions + +See [CONTRIBUTING.md][🤝contributing]. + ### Code Coverage -[![Coverage Graph][🔑codecov-g♻️]][🔑codecov] +[![Coverage Graph][🔑codecov-g]][🔑codecov] + +[![Coveralls Test Coverage][🔑coveralls-img]][🔑coveralls] + +[![QLTY Test Coverage][🔑qlty-covi]][🔑qlty-cov] ### 🪇 Code of Conduct -Everyone interacting in this project's codebases, issue trackers, -chat rooms and mailing lists is expected to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct]. +Everyone interacting with this project's codebases, issue trackers, +chat rooms and mailing lists agrees to follow the [![Contributor Covenant 2.1][🪇conduct-img]][🪇conduct]. ## 🌈 Contributors @@ -422,56 +528,58 @@ chat rooms and mailing lists is expected to follow the [![Contributor Covenant 2 Made with [contributors-img][🖐contrib-rocks]. -Also see GitLab Contributors: [https://gitlab.com/oauth-xx/version_gem/-/graphs/main][🚎contributors-gl] +Also see GitLab Contributors: [https://gitlab.com/ruby-oauth/version_gem/-/graphs/main][🚎contributors-gl] -## ⭐️ Star History +
+ ⭐️ Star History - + - - - Star History Chart + + + Star History Chart +
+ ## 📌 Versioning -This Library adheres to [![Epoch Semantic Versioning][📌semver-img]][📌semver]. +This Library adheres to [![Semantic Versioning 2.0.0][📌semver-img]][📌semver]. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. -Breaking changes to the public API, including dropping a supported platform (i.e. minor version of Ruby), -will only be introduced with new major versions. -Epoch will only be bumped if there are dramatic changes, and that is not expected to happen ever. +Breaking changes to the public API will only be introduced with new major versions. -### 📌 Is "Platform Support" part of the public API? +> dropping support for a platform is both obviously and objectively a breaking change
+>—Jordan Harband ([@ljharb](https://github.com/ljharb), maintainer of SemVer) [in SemVer issue 716][📌semver-breaking] -Yes. But I'm obligated to include notes... +I understand that policy doesn't work universally ("exceptions to every rule!"), +but it is the policy here. +As such, in many cases it is good to specify a dependency on this library using +the [Pessimistic Version Constraint][📌pvc] with two digits of precision. -SemVer should, but doesn't explicitly, say that dropping support for specific Platforms -is a *breaking change* to an API. -It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. +For example: -> dropping support for a platform is both obviously and objectively a breaking change +```ruby +spec.add_dependency("version_gem", "~> 1.0") +``` -- Jordan Harband (@ljharb, maintainer of SemVer) [in SemVer issue 716][📌semver-breaking] +
+📌 Is "Platform Support" part of the public API? More details inside. + +SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms +is a *breaking change* to an API. +It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. To get a better understanding of how SemVer is intended to work over a project's lifetime, read this article from the creator of SemVer: - ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred] -As a result of this policy, and the interpretive lens used by the maintainer, -you can (and should) specify a dependency on these libraries using -the [Pessimistic Version Constraint][📌pvc] with two digits of precision. - -For example: - -```ruby -spec.add_dependency("version_gem", "~> 1.1") -``` +
-See [CHANGELOG.md][📌changelog] for list of releases. +See [CHANGELOG.md][📌changelog] for a list of releases. ## 📄 License @@ -481,41 +589,87 @@ See [LICENSE.txt][📄license] for the official [Copyright Notice][📄copyright ### © Copyright -

- Copyright (c) 2022 - 2025 Peter H. Boling, - - RailsBling.com - - Rails Bling - - -

+ -## 🤑 One more thing +## 🤑 A request for help -You made it to the bottom of the page, -so perhaps you'll indulge me for another 20 seconds. -I maintain many dozens of gems, including this one, -because I want Ruby to be a great place for people to solve problems, big and small. -Please consider supporting my efforts via the giant yellow link below, -or one of the others at the head of this README. +Maintainers have teeth and need to pay their dentists. +After getting laid off in an RIF in March and filled with many dozens of rejections, +I'm now spending ~60+ hours a week building open source tools. +I'm hoping to be able to pay for my kids' health insurance this month, +so if you value the work I am doing, I need your support. +Please consider sponsoring me or the project. -[![Buy me a latte][🖇buyme-img]][🖇buyme] +To join the community or get help 👇️ Join the Discord. + +[![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] + +To say "thanks for maintaining such a great tool" ☝️ Join the Discord or 👇️ send money. + +[![Sponsor ruby-oauth/version_gem on Open Source Collective][🖇osc-all-bottom-img]][🖇osc] 💌 [![Sponsor me on GitHub Sponsors][🖇sponsor-bottom-img]][🖇sponsor] 💌 [![Sponsor me on Liberapay][⛳liberapay-bottom-img]][⛳liberapay-img] 💌 [![Donate on PayPal][🖇paypal-bottom-img]][🖇paypal-img] + +### Please give the project a star ⭐ ♥. + +Thanks for RTFM. ☺️ + +[⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay&color=a51611&style=flat +[⛳liberapay-bottom-img]: https://img.shields.io/liberapay/goal/pboling.svg?style=for-the-badge&logo=liberapay&color=a51611 +[⛳liberapay]: https://liberapay.com/pboling/donate +[🖇osc-all-img]: https://img.shields.io/opencollective/all/ruby-oauth +[🖇osc-sponsors-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth +[🖇osc-backers-img]: https://img.shields.io/opencollective/backers/ruby-oauth +[🖇osc-backers]: https://opencollective.com/ruby-oauth#backer +[🖇osc-backers-i]: https://opencollective.com/ruby-oauth/backers/badge.svg?style=flat +[🖇osc-sponsors]: https://opencollective.com/ruby-oauth#sponsor +[🖇osc-sponsors-i]: https://opencollective.com/ruby-oauth/sponsors/badge.svg?style=flat +[🖇osc-all-bottom-img]: https://img.shields.io/opencollective/all/ruby-oauth?style=for-the-badge +[🖇osc-sponsors-bottom-img]: https://img.shields.io/opencollective/sponsors/ruby-oauth?style=for-the-badge +[🖇osc-backers-bottom-img]: https://img.shields.io/opencollective/backers/ruby-oauth?style=for-the-badge +[🖇osc]: https://opencollective.com/ruby-oauth +[🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github +[🖇sponsor-bottom-img]: https://img.shields.io/badge/Sponsor_Me!-pboling-blue?style=for-the-badge&logo=github +[🖇sponsor]: https://github.com/sponsors/pboling +[🖇polar-img]: https://img.shields.io/badge/polar-donate-a51611.svg?style=flat +[🖇polar]: https://polar.sh/pboling +[🖇kofi-img]: https://img.shields.io/badge/ko--fi-✓-a51611.svg?style=flat +[🖇kofi]: https://ko-fi.com/O5O86SNP4 +[🖇patreon-img]: https://img.shields.io/badge/patreon-donate-a51611.svg?style=flat +[🖇patreon]: https://patreon.com/galtzo +[🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-a51611.svg?style=flat +[🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff +[🖇buyme]: https://www.buymeacoffee.com/pboling +[🖇paypal-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=flat&logo=paypal +[🖇paypal-bottom-img]: https://img.shields.io/badge/donate-paypal-a51611.svg?style=for-the-badge&logo=paypal&color=0A0A0A +[🖇paypal]: https://www.paypal.com/paypalme/peterboling +[🖇floss-funding.dev]: https://floss-funding.dev +[🖇floss-funding-gem]: https://github.com/galtzo-floss/floss_funding +[✉️discord-invite]: https://discord.gg/3qme4XHNKN +[✉️discord-invite-img-ftb]: https://img.shields.io/discord/1373797679469170758?style=for-the-badge [✇bundle-group-pattern]: https://gist.github.com/pboling/4564780 -[🏘chat]: https://gitter.im/oauth-xx/version_gem -[🏘chat-img]: https://img.shields.io/gitter/room/oauth-xx/version_gem.svg -[⛳️gem-namespace]: https://github.com/oauth-xx/version_gem -[⛳️namespace-img]: https://img.shields.io/badge/namespace-VersionGem-brightgreen.svg?style=flat&logo=ruby&logoColor=white +[⛳️gem-namespace]: https://github.com/ruby-oauth/version_gem +[⛳️namespace-img]: https://img.shields.io/badge/namespace-VersionGem-3C2D2D.svg?style=square&logo=ruby&logoColor=white [⛳️gem-name]: https://rubygems.org/gems/version_gem -[⛳️name-img]: https://img.shields.io/badge/name-version__gem-brightgreen.svg?style=flat&logo=rubygems&logoColor=red -[🚂bdfl-blog]: http://www.railsbling.com/tags/version_gem -[🚂bdfl-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange -[🚂bdfl-contact]: http://www.railsbling.com/contact -[🚂bdfl-contact-img]: https://img.shields.io/badge/Contact-BDFL-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red +[⛳️name-img]: https://img.shields.io/badge/name-version__gem-3C2D2D.svg?style=square&logo=rubygems&logoColor=red +[⛳️tag-img]: https://img.shields.io/github/tag/ruby-oauth/version_gem.svg +[⛳️tag]: http://github.com/ruby-oauth/version_gem/releases +[🚂maint-blog]: http://www.railsbling.com/tags/version_gem +[🚂maint-blog-img]: https://img.shields.io/badge/blog-railsbling-0093D0.svg?style=for-the-badge&logo=rubyonrails&logoColor=orange +[🚂maint-contact]: http://www.railsbling.com/contact +[🚂maint-contact-img]: https://img.shields.io/badge/Contact-Maintainer-0093D0.svg?style=flat&logo=rubyonrails&logoColor=red [💖🖇linkedin]: http://www.linkedin.com/in/peterboling [💖🖇linkedin-img]: https://img.shields.io/badge/PeterBoling-LinkedIn-0B66C2?style=flat&logo=newjapanprowrestling -[💖✌️wellfound]: https://angel.co/u/peter-boling +[💖✌️wellfound]: https://wellfound.com/u/peter-boling [💖✌️wellfound-img]: https://img.shields.io/badge/peter--boling-orange?style=flat&logo=wellfound [💖💲crunchbase]: https://www.crunchbase.com/person/peter-boling [💖💲crunchbase-img]: https://img.shields.io/badge/peter--boling-purple?style=flat&logo=crunchbase @@ -537,70 +691,64 @@ or one of the others at the head of this README. [👨🏼‍🏫expsup-upwork-img]: https://img.shields.io/badge/UpWork-13544E?style=for-the-badge&logo=Upwork&logoColor=white [👨🏼‍🏫expsup-codementor]: https://www.codementor.io/peterboling?utm_source=github&utm_medium=button&utm_term=peterboling&utm_campaign=github [👨🏼‍🏫expsup-codementor-img]: https://img.shields.io/badge/CodeMentor-Get_Help-1abc9c?style=for-the-badge&logo=CodeMentor&logoColor=white -[🏙️entsup-tidelift]: https://tidelift.com/subscription +[🏙️entsup-tidelift]: https://tidelift.com/subscription/pkg/rubygems-version_gem?utm_source=rubygems-version_gem&utm_medium=referral&utm_campaign=readme [🏙️entsup-tidelift-img]: https://img.shields.io/badge/Tidelift_and_Sonar-Enterprise_Support-FD3456?style=for-the-badge&logo=sonar&logoColor=white [🏙️entsup-tidelift-sonar]: https://blog.tidelift.com/tidelift-joins-sonar [💁🏼‍♂️peterboling]: http://www.peterboling.com [🚂railsbling]: http://www.railsbling.com [📜src-gl-img]: https://img.shields.io/badge/GitLab-FBA326?style=for-the-badge&logo=Gitlab&logoColor=orange -[📜src-gl]: https://gitlab.com/oauth-xx/version_gem/ +[📜src-gl]: https://gitlab.com/ruby-oauth/version_gem/ +[📜src-cb-img]: https://img.shields.io/badge/CodeBerg-4893CC?style=for-the-badge&logo=CodeBerg&logoColor=blue +[📜src-cb]: https://codeberg.org/ruby-oauth/version_gem [📜src-gh-img]: https://img.shields.io/badge/GitHub-238636?style=for-the-badge&logo=Github&logoColor=green -[📜src-gh]: https://github.com/oauth-xx/version_gem +[📜src-gh]: https://github.com/ruby-oauth/version_gem [📜docs-cr-rd-img]: https://img.shields.io/badge/RubyDoc-Current_Release-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white -[📜docs-head-rd-img]: https://img.shields.io/badge/RubyDoc-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white -[📜wiki]: https://gitlab.com/oauth-xx/version_gem/-/wikis/home +[📜docs-head-rd-img]: https://img.shields.io/badge/YARD_on_Galtzo.com-HEAD-943CD2?style=for-the-badge&logo=readthedocs&logoColor=white +[📜wiki]: https://gitlab.com/ruby-oauth/version_gem/-/wikis/home [📜wiki-img]: https://img.shields.io/badge/wiki-examples-943CD2.svg?style=for-the-badge&logo=Wiki&logoColor=white [👽dl-rank]: https://rubygems.org/gems/version_gem [👽dl-ranki]: https://img.shields.io/gem/rd/version_gem.svg -[👽oss-help]: https://www.codetriage.com/oauth-xx/version_gem -[👽oss-helpi]: https://www.codetriage.com/oauth-xx/version_gem/badges/users.svg +[👽oss-help]: https://www.codetriage.com/ruby-oauth/version_gem +[👽oss-helpi]: https://www.codetriage.com/ruby-oauth/version_gem/badges/users.svg [👽version]: https://rubygems.org/gems/version_gem [👽versioni]: https://img.shields.io/gem/v/version_gem.svg -[🔑cc-mnt]: https://qlty.sh/gh/oauth-xx/projects/version_gem -[🔑cc-mnti♻️]: https://qlty.sh/badges/19404e90-9168-451a-8dac-882382cb768d/maintainability.svg -[🔑cc-cov]: https://qlty.sh/gh/oauth-xx/projects/version_gem -[🔑cc-covi♻️]: https://qlty.sh/badges/19404e90-9168-451a-8dac-882382cb768d/test_coverage.svg -[🔑codecov]: https://codecov.io/gh/oauth-xx/version_gem -[🔑codecovi♻️]: https://codecov.io/gh/oauth-xx/version_gem/branch/main/graph/badge.svg?token=cc6UdZCpAL -[🔑coveralls]: https://coveralls.io/github/oauth-xx/version_gem?branch=main -[🔑coveralls-img]: https://coveralls.io/repos/github/oauth-xx/version_gem/badge.svg?branch=main -[🔑depfu]: https://depfu.com/github/oauth-xx/version_gem -[🔑depfui♻️]: https://badges.depfu.com/badges/6c9b45362951b872127f9e46d39bed76/count.svg -[🖐codeQL]: https://github.com/oauth-xx/version_gem/security/code-scanning -[🖐codeQL-img]: https://github.com/oauth-xx/version_gem/actions/workflows/codeql-analysis.yml/badge.svg -[🚎1-an-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/ancient.yml -[🚎1-an-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/ancient.yml/badge.svg -[🚎2-cov-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/coverage.yml -[🚎2-cov-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/coverage.yml/badge.svg -[🚎3-hd-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/heads.yml -[🚎3-hd-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/heads.yml/badge.svg -[🚎4-lg-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/legacy.yml -[🚎4-lg-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/legacy.yml/badge.svg -[🚎5-st-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/style.yml -[🚎5-st-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/style.yml/badge.svg -[🚎6-s-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/supported.yml -[🚎6-s-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/supported.yml/badge.svg -[🚎7-us-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/unsupported.yml -[🚎7-us-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/unsupported.yml/badge.svg -[🚎9-t-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/truffle.yml -[🚎9-t-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/truffle.yml/badge.svg -[🚎10-j-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/jruby.yml -[🚎10-j-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/jruby.yml/badge.svg -[🚎11-c-wf]: https://github.com/oauth-xx/version_gem/actions/workflows/current.yml -[🚎11-c-wfi]: https://github.com/oauth-xx/version_gem/actions/workflows/current.yml/badge.svg -[⛳liberapay-img]: https://img.shields.io/liberapay/goal/pboling.svg?logo=liberapay -[⛳liberapay]: https://liberapay.com/pboling/donate -[🖇sponsor-img]: https://img.shields.io/badge/Sponsor_Me!-pboling.svg?style=social&logo=github -[🖇sponsor]: https://github.com/sponsors/pboling -[🖇polar-img]: https://img.shields.io/badge/polar-donate-yellow.svg -[🖇polar]: https://polar.sh/pboling -[🖇kofi-img]: https://img.shields.io/badge/a_more_different_coffee-✓-yellow.svg -[🖇kofi]: https://ko-fi.com/O5O86SNP4 -[🖇patreon-img]: https://img.shields.io/badge/patreon-donate-yellow.svg -[🖇patreon]: https://patreon.com/galtzo -[🖇buyme-img]: https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20latte&emoji=&slug=pboling&button_colour=FFDD00&font_colour=000000&font_family=Cookie&outline_colour=000000&coffee_colour=ffffff -[🖇buyme]: https://www.buymeacoffee.com/pboling -[🖇buyme-small-img]: https://img.shields.io/badge/buy_me_a_coffee-✓-yellow.svg?style=flat +[🔑qlty-mnt]: https://qlty.sh/gh/ruby-oauth/projects/version_gem +[🔑qlty-mnti]: https://qlty.sh/gh/ruby-oauth/projects/version_gem/maintainability.svg +[🔑qlty-cov]: https://qlty.sh/gh/ruby-oauth/projects/version_gem/metrics/code?sort=coverageRating +[🔑qlty-covi]: https://qlty.sh/gh/ruby-oauth/projects/version_gem/coverage.svg +[🔑codecov]: https://codecov.io/gh/ruby-oauth/version_gem +[🔑codecovi]: https://codecov.io/gh/ruby-oauth/version_gem/graph/badge.svg +[🔑coveralls]: https://coveralls.io/github/ruby-oauth/version_gem?branch=main +[🔑coveralls-img]: https://coveralls.io/repos/github/ruby-oauth/version_gem/badge.svg?branch=main +[🖐codeQL]: https://github.com/ruby-oauth/version_gem/security/code-scanning +[🖐codeQL-img]: https://github.com/ruby-oauth/version_gem/actions/workflows/codeql-analysis.yml/badge.svg +[🚎1-an-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/ancient.yml +[🚎1-an-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/ancient.yml/badge.svg +[🚎2-cov-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/coverage.yml +[🚎2-cov-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/coverage.yml/badge.svg +[🚎3-hd-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/heads.yml +[🚎3-hd-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/heads.yml/badge.svg +[🚎4-lg-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/legacy.yml +[🚎4-lg-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/legacy.yml/badge.svg +[🚎5-st-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/style.yml +[🚎5-st-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/style.yml/badge.svg +[🚎6-s-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/supported.yml +[🚎6-s-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/supported.yml/badge.svg +[🚎7-us-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/unsupported.yml +[🚎7-us-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/unsupported.yml/badge.svg +[🚎8-ho-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/hoary.yml +[🚎8-ho-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/hoary.yml/badge.svg +[🚎9-t-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/truffle.yml +[🚎9-t-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/truffle.yml/badge.svg +[🚎10-j-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/jruby.yml +[🚎10-j-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/jruby.yml/badge.svg +[🚎11-c-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/current.yml +[🚎11-c-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/current.yml/badge.svg +[🚎13-🔒️-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/locked_deps.yml +[🚎13-🔒️-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/locked_deps.yml/badge.svg +[🚎14-🔓️-wf]: https://github.com/ruby-oauth/version_gem/actions/workflows/unlocked_deps.yml +[🚎14-🔓️-wfi]: https://github.com/ruby-oauth/version_gem/actions/workflows/unlocked_deps.yml/badge.svg +[💎ruby-2.2i]: https://img.shields.io/badge/Ruby-2.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.3i]: https://img.shields.io/badge/Ruby-2.3-DF00CA?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.4i]: https://img.shields.io/badge/Ruby-2.4-DF00CA?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-2.5i]: https://img.shields.io/badge/Ruby-2.5-DF00CA?style=for-the-badge&logo=ruby&logoColor=white @@ -612,50 +760,58 @@ or one of the others at the head of this README. [💎ruby-3.3i]: https://img.shields.io/badge/Ruby-3.3-CC342D?style=for-the-badge&logo=ruby&logoColor=white [💎ruby-c-i]: https://img.shields.io/badge/Ruby-current-CC342D?style=for-the-badge&logo=ruby&logoColor=green [💎ruby-headi]: https://img.shields.io/badge/Ruby-HEAD-CC342D?style=for-the-badge&logo=ruby&logoColor=blue -[💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink -[💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink +[💎truby-22.3i]: https://img.shields.io/badge/Truffle_Ruby-22.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink +[💎truby-23.0i]: https://img.shields.io/badge/Truffle_Ruby-23.0_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=pink [💎truby-23.1i]: https://img.shields.io/badge/Truffle_Ruby-23.1-34BCB1?style=for-the-badge&logo=ruby&logoColor=pink [💎truby-c-i]: https://img.shields.io/badge/Truffle_Ruby-current-34BCB1?style=for-the-badge&logo=ruby&logoColor=green [💎truby-headi]: https://img.shields.io/badge/Truffle_Ruby-HEAD-34BCB1?style=for-the-badge&logo=ruby&logoColor=blue -[💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1-FBE742?style=for-the-badge&logo=ruby&logoColor=red -[💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2-FBE742?style=for-the-badge&logo=ruby&logoColor=red -[💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3-FBE742?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-9.1i]: https://img.shields.io/badge/JRuby-9.1_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-9.2i]: https://img.shields.io/badge/JRuby-9.2_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red +[💎jruby-9.3i]: https://img.shields.io/badge/JRuby-9.3_(%F0%9F%9A%ABCI)-AABBCC?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-9.4i]: https://img.shields.io/badge/JRuby-9.4-FBE742?style=for-the-badge&logo=ruby&logoColor=red [💎jruby-c-i]: https://img.shields.io/badge/JRuby-current-FBE742?style=for-the-badge&logo=ruby&logoColor=green [💎jruby-headi]: https://img.shields.io/badge/JRuby-HEAD-FBE742?style=for-the-badge&logo=ruby&logoColor=blue -[🤝issues]: https://github.com/oauth-xx/version_gem/issues -[🤝pulls]: https://github.com/oauth-xx/version_gem/pulls +[🤝gh-issues]: https://github.com/ruby-oauth/version_gem/issues +[🤝gh-pulls]: https://github.com/ruby-oauth/version_gem/pulls +[🤝gl-issues]: https://gitlab.com/ruby-oauth/version_gem/-/issues +[🤝gl-pulls]: https://gitlab.com/ruby-oauth/version_gem/-/merge_requests +[🤝cb-issues]: https://codeberg.org/ruby-oauth/version_gem/issues +[🤝cb-pulls]: https://codeberg.org/ruby-oauth/version_gem/pulls +[🤝cb-donate]: https://donate.codeberg.org/ [🤝contributing]: CONTRIBUTING.md -[🔑codecov-g♻️]: https://codecov.io/gh/oauth-xx/version_gem/graphs/tree.svg?token=cc6UdZCpAL +[🔑codecov-g]: https://codecov.io/gh/ruby-oauth/version_gem/graphs/tree.svg [🖐contrib-rocks]: https://contrib.rocks -[🖐contributors]: https://github.com/oauth-xx/version_gem/graphs/contributors -[🖐contributors-img]: https://contrib.rocks/image?repo=oauth-xx/version_gem -[🚎contributors-gl]: https://gitlab.com/oauth-xx/version_gem/-/graphs/main +[🖐contributors]: https://github.com/ruby-oauth/version_gem/graphs/contributors +[🖐contributors-img]: https://contrib.rocks/image?repo=ruby-oauth/version_gem +[🚎contributors-gl]: https://gitlab.com/ruby-oauth/version_gem/-/graphs/main [🪇conduct]: CODE_OF_CONDUCT.md -[🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-4baaaa.svg +[🪇conduct-img]: https://img.shields.io/badge/Contributor_Covenant-2.1-259D6C.svg [📌pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint -[📌semver]: https://antfu.me/posts/epoch-semver -[📌semver-img]: https://img.shields.io/badge/epoch-semver-FFDD67.svg?style=flat +[📌semver]: https://semver.org/spec/v2.0.0.html +[📌semver-img]: https://img.shields.io/badge/semver-2.0.0-259D6C.svg?style=flat [📌semver-breaking]: https://github.com/semver/semver/issues/716#issuecomment-869336139 [📌major-versions-not-sacred]: https://tom.preston-werner.com/2022/05/23/major-version-numbers-are-not-sacred.html [📌changelog]: CHANGELOG.md [📗keep-changelog]: https://keepachangelog.com/en/1.0.0/ -[📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-FFDD67.svg?style=flat +[📗keep-changelog-img]: https://img.shields.io/badge/keep--a--changelog-1.0.0-34495e.svg?style=flat [📌gitmoji]:https://gitmoji.dev -[📌gitmoji-img]:https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=flat-square +[📌gitmoji-img]:https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ [🧮kloc-img]: https://img.shields.io/badge/KLOC-0.118-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue [🔐security]: SECURITY.md -[🔐security-img]: https://img.shields.io/badge/security-policy-brightgreen.svg?style=flat +[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year [📄license]: LICENSE.txt [📄license-ref]: https://opensource.org/licenses/MIT -[📄license-img]: https://img.shields.io/badge/License-MIT-green.svg +[📄license-img]: https://img.shields.io/badge/License-MIT-259D6C.svg [📄ilo-declaration]: https://www.ilo.org/declaration/lang--en/index.htm -[📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-brightgreen.svg?style=flat +[📄ilo-declaration-img]: https://img.shields.io/badge/ILO_Fundamental_Principles-✓-259D6C.svg?style=flat [🚎yard-current]: http://rubydoc.info/gems/version_gem -[🚎yard-head]: https://rubydoc.info/github/oauth-xx/version_gem/main -[💎stone_checksums]: https://github.com/pboling/stone_checksums -[💎SHA_checksums]: https://gitlab.com/oauth-xx/version_gem/-/tree/main/checksums +[🚎yard-head]: https://version-gem.galtzo.com +[💎stone_checksums]: https://github.com/galtzo-floss/stone_checksums +[💎SHA_checksums]: https://gitlab.com/ruby-oauth/version_gem/-/tree/main/checksums [💎rlts]: https://github.com/rubocop-lts/rubocop-lts -[💎rlts-img]: https://img.shields.io/badge/code_style-rubocop--lts-brightgreen.svg?plastic&logo=ruby&logoColor=white +[💎rlts-img]: https://img.shields.io/badge/code_style_%26_linting-rubocop--lts-34495e.svg?plastic&logo=ruby&logoColor=white +[💎appraisal2]: https://github.com/appraisal-rb/appraisal2 +[💎appraisal2-img]: https://img.shields.io/badge/appraised_by-appraisal2-34495e.svg?plastic&logo=ruby&logoColor=white +[💎d-in-dvcs]: https://railsbling.com/posts/dvcs/put_the_d_in_dvcs/ diff --git a/RUBOCOP.md b/RUBOCOP.md new file mode 100644 index 0000000..f15b980 --- /dev/null +++ b/RUBOCOP.md @@ -0,0 +1,71 @@ +# RuboCop Usage Guide + +## Overview + +A tale of two RuboCop plugin gems. + +### RuboCop Gradual + +This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file. + +### RuboCop LTS + +This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2. +RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more. + +## Checking RuboCop Violations + +To check for RuboCop violations in this project, always use: + +```bash +bundle exec rake rubocop_gradual:check +``` + +**Do not use** the standard RuboCop commands like: +- `bundle exec rubocop` +- `rubocop` + +## Understanding the Lock File + +The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to: + +1. Prevent new violations while gradually fixing existing ones +2. Track progress on code style improvements +3. Ensure CI builds don't fail due to pre-existing violations + +## Common Commands + +- **Check violations** + - `bundle exec rake rubocop_gradual` + - `bundle exec rake rubocop_gradual:check` +- **(Safe) Autocorrect violations, and update lockfile if no new violations** + - `bundle exec rake rubocop_gradual:autocorrect` +- **Force update the lock file (w/o autocorrect) to match violations present in code** + - `bundle exec rake rubocop_gradual:force_update` + +## Workflow + +1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect` + a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task. +2. If there are new violations, either: + - Fix them in your code + - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately) +3. Commit the updated `.rubocop_gradual.lock` file along with your changes + +## Never add inline RuboCop disables + +Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways: + +- Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide. +- Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow: + - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced) + - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately) + +In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test. + +## Benefits of rubocop_gradual + +- Allows incremental adoption of code style rules +- Prevents CI failures due to pre-existing violations +- Provides a clear record of code style debt +- Enables focused efforts on improving code quality over time diff --git a/gemfiles/modular/coverage.gemfile b/gemfiles/modular/coverage.gemfile index 5ef0c45..ee32b0a 100644 --- a/gemfiles/modular/coverage.gemfile +++ b/gemfiles/modular/coverage.gemfile @@ -3,4 +3,4 @@ # We run code coverage on the latest version of Ruby only. # Coverage -gem "kettle-soup-cover", "~> 1.0", ">= 1.0.6", require: false +gem "kettle-soup-cover", "~> 1.0", ">= 1.0.10", require: false diff --git a/gemfiles/modular/documentation.gemfile b/gemfiles/modular/documentation.gemfile index fdfa2fb..7853390 100644 --- a/gemfiles/modular/documentation.gemfile +++ b/gemfiles/modular/documentation.gemfile @@ -1,10 +1,11 @@ # frozen_string_literal: true # Documentation -gem "github-markup", "~> 5.0", ">= 5.0.1" -gem "redcarpet", "~> 3.6" +gem "kramdown", "~> 2.5", ">= 2.5.1" # Ruby >= 2.5 +gem "kramdown-parser-gfm", "~> 1.1" # Ruby >= 2.3 gem "yard", "~> 0.9", ">= 0.9.37", require: false -gem "yard-junk", "~> 0.0", ">= 0.0.10", github: "pboling/yard-junk", branch: "next" +gem "yard-junk", "~> 0.0", ">= 0.0.10", github: "pboling/yard-junk", branch: "next", require: false +gem "yard-relative_markdown_links", "~> 0.5.0" # Std Lib extractions gem "rdoc", "~> 6.11" diff --git a/gemfiles/modular/optional.gemfile b/gemfiles/modular/optional.gemfile new file mode 100644 index 0000000..dae6a95 --- /dev/null +++ b/gemfiles/modular/optional.gemfile @@ -0,0 +1 @@ +# Optional dependencies are not depended on directly, but may be used if present. diff --git a/gemfiles/modular/style.gemfile b/gemfiles/modular/style.gemfile index f09c5e5..b4c80c9 100644 --- a/gemfiles/modular/style.gemfile +++ b/gemfiles/modular/style.gemfile @@ -3,12 +3,23 @@ # We run rubocop on the latest version of Ruby, # but in support of the oldest supported version of Ruby -gem "reek", "~> 6.4" -gem "rubocop", "~> 1.73", ">= 1.73.2" -gem "rubocop-lts", "~> 8.1", ">= 8.1.1" # Linting for Ruby >= 2.2 -gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" -gem "rubocop-rspec", "~> 3.2" -gem "standard", "~> 1.47" +gem "reek", "~> 6.5" +# gem "rubocop", "~> 1.73", ">= 1.73.2" # constrained by standard +gem "rubocop-packaging", "~> 0.6", ">= 0.6.0" +gem "standard", ">= 1.50" +gem "rubocop-on-rbs", "~> 1.8" # ruby >= 3.1.0 # Std Lib extractions -gem "benchmark", "~> 0.4" # Removed from Std Lib in Ruby 3.5 +gem "benchmark", "~> 0.4", ">= 0.4.1" # Removed from Std Lib in Ruby 3.5 + +if ENV.fetch("RUBOCOP_LTS_LOCAL", "false").casecmp("true").zero? + home = ENV["HOME"] + gem "rubocop-lts", path: "#{home}/src/rubocop-lts/rubocop-lts" + gem "rubocop-lts-rspec", path: "#{home}/src/rubocop-lts/rubocop-lts-rspec" + gem "rubocop-ruby2_2", path: "#{home}/src/rubocop-lts/rubocop-ruby2_2" + gem "standard-rubocop-lts", path: "#{home}/src/rubocop-lts/standard-rubocop-lts" +else + gem "rubocop-lts", "~> 8.0" + gem "rubocop-ruby2_2" + gem "rubocop-rspec", "~> 3.6" +end diff --git a/version_gem.gemspec b/version_gem.gemspec index 4a9e410..e7f63b4 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -1,68 +1,81 @@ +# coding: utf-8 # frozen_string_literal: true gem_version = - if RUBY_VERSION >= "3.1" - # Loading version into an anonymous module allows version.rb to get code coverage from SimpleCov! + if RUBY_VERSION >= "3.1" # rubocop:disable Gemspec/RubyVersionGlobalsUsage + # Loading Version into an anonymous module allows version.rb to get code coverage from SimpleCov! # See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-2630782358 - Module.new.tap { |mod| Kernel.load("lib/version_gem/version.rb", mod) }::VersionGem::Version::VERSION + # See: https://github.com/panorama-ed/memo_wise/pull/397 + Module.new.tap { |mod| Kernel.load("#{__dir__}/lib/version_gem/version.rb", mod) }::VersionGem::Version::VERSION else - # TODO: Remove this hack once support for Ruby 3.0 and below is removed - Kernel.load("lib/version_gem/version.rb") - g_ver = VersionGem::Version::VERSION - VersionGem::Version.send(:remove_const, :VERSION) - g_ver + require_relative "lib/version_gem/version" + VersionGem::Version::VERSION end Gem::Specification.new do |spec| - # Linux distros may package ruby gems differently, - # and securely certify them independently via alternate package management systems. - # Ref: https://gitlab.com/oauth-xx/version_gem/-/issues/3 - # Hence, only enable signing if `SKIP_GEM_SIGNING` is not set in ENV. - # See CONTRIBUTING.md - user_cert = "certs/#{ENV.fetch("GEM_CERT_USER", ENV["USER"])}.pem" - cert_file_path = File.join(__dir__, user_cert) - cert_chain = cert_file_path.split(",") - cert_chain.select! { |fp| File.exist?(fp) } - if cert_file_path && cert_chain.any? - spec.cert_chain = cert_chain - if $PROGRAM_NAME.end_with?("gem") && ARGV[0] == "build" && !ENV.include?("SKIP_GEM_SIGNING") - spec.signing_key = File.join(Gem.user_home, ".ssh", "gem-private_key.pem") - end - end - spec.name = "version_gem" spec.version = gem_version spec.authors = ["Peter Boling"] - spec.email = ["peter.boling@gmail.com", "oauth-ruby@googlegroups.com"] + spec.email = ["floss@galtzo.com", "oauth-ruby@googlegroups.com"] spec.summary = "🔖 Enhance your VERSION! Sugar for Version modules." spec.description = "🔖 Versions are good. Versions are cool. Versions will win." - spec.homepage = "https://gitlab.com/oauth-xx/version_gem" - spec.license = "MIT" + spec.homepage = "https://github.com/ruby-oauth/version_gem" + spec.licenses = ["MIT"] spec.required_ruby_version = ">= 2.2" - spec.metadata["homepage_uri"] = "https://railsbling.com/tags/#{spec.name}/" - spec.metadata["source_code_uri"] = "#{spec.homepage}/-/tree/v#{spec.version}" - spec.metadata["changelog_uri"] = "#{spec.homepage}/-/blob/v#{spec.version}/CHANGELOG.md" - spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/-/issues" + # Linux distros often package gems and securely certify them independent + # of the official RubyGem certification process. Allowed via ENV["SKIP_GEM_SIGNING"] + # Ref: https://gitlab.com/ruby-oauth/version_gem/-/issues/3 + # Hence, only enable signing if `SKIP_GEM_SIGNING` is not set in ENV. + # See CONTRIBUTING.md + unless ENV.include?("SKIP_GEM_SIGNING") + user_cert = "certs/#{ENV.fetch("GEM_CERT_USER", ENV["USER"])}.pem" + cert_file_path = File.join(__dir__, user_cert) + cert_chain = cert_file_path.split(",") + cert_chain.select! { |fp| File.exist?(fp) } + if cert_file_path && cert_chain.any? + spec.cert_chain = cert_chain + if $PROGRAM_NAME.end_with?("gem") && ARGV[0] == "build" + spec.signing_key = File.join(Gem.user_home, ".ssh", "gem-private_key.pem") + end + end + end + + spec.metadata["homepage_uri"] = "https://#{spec.name.tr("_", "-")}.galtzo.com/" + spec.metadata["source_code_uri"] = "#{spec.homepage}/tree/v#{spec.version}" + spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/v#{spec.version}/CHANGELOG.md" + spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues" spec.metadata["documentation_uri"] = "https://www.rubydoc.info/gems/#{spec.name}/#{spec.version}" - spec.metadata["wiki_uri"] = "#{spec.homepage}/-/wiki" + spec.metadata["funding_uri"] = "https://github.com/sponsors/pboling" + spec.metadata["wiki_uri"] = "#{spec.homepage}/wiki" spec.metadata["mailing_list_uri"] = "https://groups.google.com/g/oauth-ruby" - spec.metadata["funding_uri"] = "https://liberapay.com/pboling" + spec.metadata["news_uri"] = "https://www.railsbling.com/tags/#{spec.name}" + spec.metadata["discord_uri"] = "https://discord.gg/3qme4XHNKN" spec.metadata["rubygems_mfa_required"] = "true" + # Specify which files are part of the released package. spec.files = Dir[ - # Files (alphabetical) - "lib/**/*", + # Executables and tasks + "exe/*", + "lib/**/*.rb", + "lib/**/*.rake", + # Signatures + "sig/**/*.rbs", ] + # Automatically included with gem package, no need to list again in files. spec.extra_rdoc_files = Dir[ # Files (alphabetical) "CHANGELOG.md", + "CITATION.cff", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", + "FUNDING.md", "LICENSE.txt", "README.md", + "REEK", + "RUBOCOP.md", "SECURITY.md", ] spec.rdoc_options += [ @@ -70,11 +83,34 @@ Gem::Specification.new do |spec| "#{spec.name} - #{spec.summary}", "--main", "README.md", + "--exclude", + "^sig/", "--line-numbers", "--inline-source", "--quiet", ] spec.require_paths = ["lib"] + spec.bindir = "bin" + # files listed are relative paths from bindir above. + spec.executables = [] + + # Utilities + spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.8") # ruby >= 2.2.0 + + # NOTE: It is preferable to list development dependencies in the gemspec due to increased + # visibility and discoverability on RubyGems.org. + # However, development dependencies in gemspec will install on + # all versions of Ruby that will run in CI. + # This gem, and its gemspec runtime dependencies, will install on Ruby down to 2.3.x. + # This gem, and its gemspec development dependencies, will install on Ruby down to 2.3.x. + # This is because in CI easy installation of Ruby, via setup-ruby, is for >= 2.3. + # Thus, dev dependencies in gemspec must have + # + # required_ruby_version ">= 2.3" (or lower) + # + # Development dependencies that require strictly newer Ruby versions should be in a "gemfile", + # and preferably a modular one (see gemfiles/modular/*.gemfile). - spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.25") # ruby >= 2.3 + # Dev, Test, & Release Tasks + spec.add_development_dependency("kettle-dev", "~> 1.0.17") # ruby >= 2.3.0 end From 763f83f9099ec0139505b7aa75a96e3338fda99d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 02:28:42 -0600 Subject: [PATCH 07/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.0.26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 4 ++-- version_gem.gemspec | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8222f9c..9f49bcf 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.0.25) + kettle-dev (1.0.26) appraisal2 (~> 3.0) bundler-audit (~> 0.9.2) gitmoji-regex (~> 1.0, >= 1.0.3) @@ -309,7 +309,7 @@ DEPENDENCIES benchmark (~> 0.4, >= 0.4.1) debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) - kettle-dev (~> 1.0.17) + kettle-dev (~> 1.0, >= 1.0.26) kettle-soup-cover (~> 1.0, >= 1.0.10) kramdown (~> 2.5, >= 2.5.1) kramdown-parser-gfm (~> 1.1) diff --git a/version_gem.gemspec b/version_gem.gemspec index e7f63b4..d788b06 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,5 +112,5 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.0.17") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.26") # ruby >= 2.3.0 end From 292fc94764cb6ba8fcb53d619b0d891e598d1665 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 02:31:37 -0600 Subject: [PATCH 08/29] =?UTF-8?q?=F0=9F=8E=A8=20kettle-dev=20v1.0.26=20tem?= =?UTF-8?q?plate=20.env.local.example?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.local.example | 14 ++++++++++++++ .idea/version_gem.iml | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 .env.local.example diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 0000000..f07a00a --- /dev/null +++ b/.env.local.example @@ -0,0 +1,14 @@ +# +# DO NOT EDIT THIS FILE +# +# COPT THIS FILE TO .env.local +# +# That file is ignored by .gitignore. This file is not. +# +export DEBUG=false # do not allow byebug statements (override in .env.local) +export FLOSS_FUNDING_DEBUG=false # extra logging to help diagnose issues (override in .env.local) +export AUTOGEN_FIXTURE_CLEANUP=false # autogenerated gem fixture cleanup after every RSpec run +export GIT_HOOK_FOOTER_APPEND=false +export GIT_HOOK_FOOTER_APPEND_DEBUG=false +export GIT_HOOK_FOOTER_SENTINEL="⚡️ A message from a fellow meat-based-AI ⚡️" +export GITHUB_TOKEN= diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml index 4a9d042..6954010 100644 --- a/.idea/version_gem.iml +++ b/.idea/version_gem.iml @@ -40,7 +40,7 @@ - + From fcef1cf15923aef96e121ef3da3e780be370c344 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 02:56:10 -0600 Subject: [PATCH 09/29] =?UTF-8?q?=F0=9F=8F=B7=EF=B8=8F=20Update=20RBS=20ty?= =?UTF-8?q?pes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ sig/version_gem.rbs | 2 -- sig/version_gem/api.rbs | 34 ++++++++++++++-------------------- sig/version_gem/basic.rbs | 2 +- sig/version_gem/epoch.rbs | 26 ++++++++++++++++++++++++++ sig/version_gem/error.rbs | 4 ++++ sig/version_gem/ruby.rbs | 8 +++++--- sig/version_gem/version.rbs | 4 ++++ 8 files changed, 56 insertions(+), 26 deletions(-) create mode 100644 sig/version_gem/epoch.rbs create mode 100644 sig/version_gem/error.rbs diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d3485..0e96fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,10 +18,12 @@ Please file a bug if you notice a violation of semantic versioning. ## [Unreleased] ### Added +- More RBS types ### Changed ### Deprecated ### Removed ### Fixed +- RBS types are more accurate ### Security ## [1.1.8] 2025-05-06 diff --git a/sig/version_gem.rbs b/sig/version_gem.rbs index bfb673c..645ef44 100644 --- a/sig/version_gem.rbs +++ b/sig/version_gem.rbs @@ -1,4 +1,2 @@ module VersionGem - VERSION: String - # See the writing guide of rbs: https://github.com/ruby/rbs#guides end diff --git a/sig/version_gem/api.rbs b/sig/version_gem/api.rbs index ebd369b..d2001d7 100644 --- a/sig/version_gem/api.rbs +++ b/sig/version_gem/api.rbs @@ -1,33 +1,27 @@ module VersionGem module Api + # Internal memoized version string segments @_to_a: Array[String] + # Memoized components @major: Integer - @minor: Integer - @patch: Integer - @pre: String? - - @to_a: Array - - @to_h: Hash - - def major: -> Integer - - def minor: -> Integer - - def patch: -> Integer - - def pre: -> String? - - def to_a: -> Array - - def to_h: -> Hash + @to_a: Array[Integer | String | nil] + @to_h: Hash[Symbol, (Integer | String | nil)] + + # Public API + def to_s: () -> String + def major: () -> Integer + def minor: () -> Integer + def patch: () -> Integer + def pre: () -> String? + def to_a: () -> Array[Integer | String | nil] + def to_h: () -> Hash[Symbol, (Integer | String | nil)] private - def _to_a: -> Array[String] + def _to_a: () -> Array[String] end end diff --git a/sig/version_gem/basic.rbs b/sig/version_gem/basic.rbs index 76fac75..a75dd0e 100644 --- a/sig/version_gem/basic.rbs +++ b/sig/version_gem/basic.rbs @@ -1,5 +1,5 @@ module VersionGem module Basic - def self.extended: -> void + def self.extended: () -> void end end diff --git a/sig/version_gem/epoch.rbs b/sig/version_gem/epoch.rbs new file mode 100644 index 0000000..3b2760d --- /dev/null +++ b/sig/version_gem/epoch.rbs @@ -0,0 +1,26 @@ +module VersionGem + module Epoch + EPOCH_SIZE: Integer + + # Hook used when this module is extended + def self.extended: (untyped) -> void + + module OverloadApiForEpoch + # The epoch component (derived) + def epoch: () -> Integer + + # Override of Api#major returning the derived major component + def major: () -> Integer + + # Hash representation including epoch + def to_h: () -> Hash[Symbol, (Integer | String | nil)] + + # Array of components [epoch, major, minor, patch, pre] + def to_a: () -> Array[Integer | String | nil] + + private + + def _major: () -> Integer + end + end +end diff --git a/sig/version_gem/error.rbs b/sig/version_gem/error.rbs new file mode 100644 index 0000000..89aca76 --- /dev/null +++ b/sig/version_gem/error.rbs @@ -0,0 +1,4 @@ +module VersionGem + class Error < ::RuntimeError + end +end diff --git a/sig/version_gem/ruby.rbs b/sig/version_gem/ruby.rbs index 54a75a4..91f10f2 100644 --- a/sig/version_gem/ruby.rbs +++ b/sig/version_gem/ruby.rbs @@ -1,9 +1,11 @@ module VersionGem module Ruby - RUBY_VER: Gem::Version + RUBY_VER: ::Gem::Version - def actual_minor_version?: -> bool + # Check if the current Ruby version is >= given version for the engine + def self.gte_minimum_version?: (String, ?String) -> bool - def gte_minimum_version?: -> bool + # Check if the current Ruby MAJOR.MINOR equals the given values for the engine + def self.actual_minor_version?: ((Integer | String), (Integer | String), ?String) -> bool end end diff --git a/sig/version_gem/version.rbs b/sig/version_gem/version.rbs index 8f4f3c3..042b3c7 100644 --- a/sig/version_gem/version.rbs +++ b/sig/version_gem/version.rbs @@ -1,5 +1,9 @@ module VersionGem module Version VERSION: String + + # At runtime this module is extended with Basic via class_eval in lib/version_gem.rb + # Declare the intended extension so class methods are available in typing + extend VersionGem::Basic end end From 5e94b2613713acc4d2c4619e3ed5bae3c37bab33 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 02:56:42 -0600 Subject: [PATCH 10/29] =?UTF-8?q?=F0=9F=93=9D=20Initial=20version=20of=20d?= =?UTF-8?q?ocs=20site?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + docs/VersionGem.html | 129 +++ docs/VersionGem/Api.html | 674 ++++++++++++++++ docs/VersionGem/Basic.html | 212 +++++ docs/VersionGem/Epoch.html | 241 ++++++ .../VersionGem/Epoch/OverloadApiForEpoch.html | 454 +++++++++++ docs/VersionGem/Error.html | 134 ++++ docs/VersionGem/Ruby.html | 306 +++++++ docs/VersionGem/Version.html | 121 +++ docs/_index.html | 304 +++++++ docs/class_list.html | 54 ++ docs/css/common.css | 1 + docs/css/full_list.css | 58 ++ docs/css/style.css | 503 ++++++++++++ docs/file.CHANGELOG.html | 319 ++++++++ docs/file.CITATION.html | 92 +++ docs/file.CODE_OF_CONDUCT.html | 201 +++++ docs/file.CONTRIBUTING.html | 285 +++++++ docs/file.FUNDING.html | 114 +++ docs/file.LICENSE.html | 70 ++ docs/file.README.html | 754 ++++++++++++++++++ docs/file.REEK.html | 71 ++ docs/file.RUBOCOP.html | 171 ++++ docs/file.SECURITY.html | 101 +++ docs/file.all_formatters.html | 71 ++ docs/file.api.html | 102 +++ docs/file.basic.html | 75 ++ docs/file.debug.html | 71 ++ docs/file.debug_ide.html | 71 ++ docs/file.debug_jruby.html | 71 ++ docs/file.debugging.html | 71 ++ docs/file.ruby.html | 78 ++ docs/file.run_coverage.html | 71 ++ docs/file.version.html | 75 ++ docs/file.version_gem-1.1.1.gem.html | 71 ++ docs/file.version_gem-1.1.2.gem.html | 71 ++ docs/file.version_gem-1.1.3.gem.html | 71 ++ docs/file.version_gem-1.1.4.gem.html | 71 ++ docs/file.version_gem-1.1.5.gem.html | 71 ++ docs/file.version_gem-1.1.6.gem.html | 71 ++ docs/file.version_gem-1.1.7.gem.html | 71 ++ docs/file.version_gem-1.1.8.gem.html | 71 ++ docs/file.version_gem.html | 74 ++ docs/file_list.html | 239 ++++++ docs/frames.html | 22 + docs/index.html | 754 ++++++++++++++++++ docs/js/app.js | 344 ++++++++ docs/js/full_list.js | 242 ++++++ docs/js/jquery.js | 4 + docs/method_list.html | 174 ++++ docs/top-level-namespace.html | 110 +++ 51 files changed, 8657 insertions(+) create mode 100644 docs/VersionGem.html create mode 100644 docs/VersionGem/Api.html create mode 100644 docs/VersionGem/Basic.html create mode 100644 docs/VersionGem/Epoch.html create mode 100644 docs/VersionGem/Epoch/OverloadApiForEpoch.html create mode 100644 docs/VersionGem/Error.html create mode 100644 docs/VersionGem/Ruby.html create mode 100644 docs/VersionGem/Version.html create mode 100644 docs/_index.html create mode 100644 docs/class_list.html create mode 100644 docs/css/common.css create mode 100644 docs/css/full_list.css create mode 100644 docs/css/style.css create mode 100644 docs/file.CHANGELOG.html create mode 100644 docs/file.CITATION.html create mode 100644 docs/file.CODE_OF_CONDUCT.html create mode 100644 docs/file.CONTRIBUTING.html create mode 100644 docs/file.FUNDING.html create mode 100644 docs/file.LICENSE.html create mode 100644 docs/file.README.html create mode 100644 docs/file.REEK.html create mode 100644 docs/file.RUBOCOP.html create mode 100644 docs/file.SECURITY.html create mode 100644 docs/file.all_formatters.html create mode 100644 docs/file.api.html create mode 100644 docs/file.basic.html create mode 100644 docs/file.debug.html create mode 100644 docs/file.debug_ide.html create mode 100644 docs/file.debug_jruby.html create mode 100644 docs/file.debugging.html create mode 100644 docs/file.ruby.html create mode 100644 docs/file.run_coverage.html create mode 100644 docs/file.version.html create mode 100644 docs/file.version_gem-1.1.1.gem.html create mode 100644 docs/file.version_gem-1.1.2.gem.html create mode 100644 docs/file.version_gem-1.1.3.gem.html create mode 100644 docs/file.version_gem-1.1.4.gem.html create mode 100644 docs/file.version_gem-1.1.5.gem.html create mode 100644 docs/file.version_gem-1.1.6.gem.html create mode 100644 docs/file.version_gem-1.1.7.gem.html create mode 100644 docs/file.version_gem-1.1.8.gem.html create mode 100644 docs/file.version_gem.html create mode 100644 docs/file_list.html create mode 100644 docs/frames.html create mode 100644 docs/index.html create mode 100644 docs/js/app.js create mode 100644 docs/js/full_list.js create mode 100644 docs/js/jquery.js create mode 100644 docs/method_list.html create mode 100644 docs/top-level-namespace.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e96fbc..84139d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Please file a bug if you notice a violation of semantic versioning. ## [Unreleased] ### Added - More RBS types +- docs site: https://version-gem.galtzo.com ### Changed ### Deprecated ### Removed diff --git a/docs/VersionGem.html b/docs/VersionGem.html new file mode 100644 index 0000000..c742b07 --- /dev/null +++ b/docs/VersionGem.html @@ -0,0 +1,129 @@ + + + + + + + Module: VersionGem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem.rb,
+ lib/version_gem/api.rb,
lib/version_gem/ruby.rb,
lib/version_gem/basic.rb,
lib/version_gem/epoch.rb,
lib/version_gem/error.rb,
lib/version_gem/version.rb
+
+
+ +
+ +

Overview

+
+

Namespace of this library

+ + +
+
+
+ + +

Defined Under Namespace

+

+ + + Modules: Api, Basic, Epoch, Ruby, Version + + + + Classes: Error + + +

+ + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Api.html b/docs/VersionGem/Api.html new file mode 100644 index 0000000..41987c7 --- /dev/null +++ b/docs/VersionGem/Api.html @@ -0,0 +1,674 @@ + + + + + + + Module: VersionGem::Api + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Api + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/api.rb
+
+ +
+ +

Overview

+
+

Public API of this library

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #majorInteger + + + + + +

+
+

The major version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Integer) + + + +
  • + +
+ +
+ + + + +
+
+
+
+16
+17
+18
+
+
# File 'lib/version_gem/api.rb', line 16
+
+def major
+  @major ||= _to_a[0].to_i
+end
+
+
+ +
+

+ + #minorInteger + + + + + +

+
+

The minor version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Integer) + + + +
  • + +
+ +
+ + + + +
+
+
+
+23
+24
+25
+
+
# File 'lib/version_gem/api.rb', line 23
+
+def minor
+  @minor ||= _to_a[1].to_i
+end
+
+
+ +
+

+ + #patchInteger + + + + + +

+
+

The patch version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Integer) + + + +
  • + +
+ +
+ + + + +
+
+
+
+30
+31
+32
+
+
# File 'lib/version_gem/api.rb', line 30
+
+def patch
+  @patch ||= _to_a[2].to_i
+end
+
+
+ +
+

+ + #preString, NilClass + + + + + +

+
+

The pre-release version, if any

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (String, NilClass) + + + +
  • + +
+ +
+ + + + +
+
+
+
+37
+38
+39
+
+
# File 'lib/version_gem/api.rb', line 37
+
+def pre
+  @pre ||= _to_a[3]
+end
+
+
+ +
+

+ + #to_aArray<[Integer, String, NilClass]> + + + + + +

+
+

The version number as an array of cast values

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Array<[Integer, String, NilClass]>) + + + +
  • + +
+ +
+ + + + +
+
+
+
+56
+57
+58
+
+
# File 'lib/version_gem/api.rb', line 56
+
+def to_a
+  @to_a ||= [major, minor, patch, pre]
+end
+
+
+ +
+

+ + #to_hHash + + + + + +

+
+

The version number as a hash

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Hash) + + + +
  • + +
+ +
+ + + + +
+
+
+
+44
+45
+46
+47
+48
+49
+50
+51
+
+
# File 'lib/version_gem/api.rb', line 44
+
+def to_h
+  @to_h ||= {
+    major: major,
+    minor: minor,
+    patch: patch,
+    pre: pre,
+  }
+end
+
+
+ +
+

+ + #to_sString + + + + + +

+
+

The version number as a string

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (String) + + + +
  • + +
+ +
+ + + + +
+
+
+
+9
+10
+11
+
+
# File 'lib/version_gem/api.rb', line 9
+
+def to_s
+  self::VERSION
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Basic.html b/docs/VersionGem/Basic.html new file mode 100644 index 0000000..d0a8324 --- /dev/null +++ b/docs/VersionGem/Basic.html @@ -0,0 +1,212 @@ + + + + + + + Module: VersionGem::Basic + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Basic + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/basic.rb
+
+ +
+ +

Overview

+
+

This is a very basic version parser. Others could be built based on this pattern!

+ + +
+
+
+ + +
+ + + + + + + +

+ Class Method Summary + collapse +

+ + + + + + +
+

Class Method Details

+ + +
+

+ + .extended(base) ⇒ Object + + + + + +

+
+ + + +
+
+
+ +

Raises:

+
    + +
  • + + + (Error) + + + +
  • + +
+ +
+ + + + +
+
+
+
+10
+11
+12
+13
+14
+
+
# File 'lib/version_gem/basic.rb', line 10
+
+def extended(base)
+  raise Error, "VERSION must be defined before 'extend #{name}'" unless defined?(base::VERSION)
+
+  base.extend(Api)
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Epoch.html b/docs/VersionGem/Epoch.html new file mode 100644 index 0000000..a5c01a5 --- /dev/null +++ b/docs/VersionGem/Epoch.html @@ -0,0 +1,241 @@ + + + + + + + Module: VersionGem::Epoch + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Epoch + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/epoch.rb
+
+ +
+ +

Overview

+
+

Support for Epoch Semantic Versioning
+See: https://antfu.me/posts/epoch-semver

+ + +
+
+
+ + +

Defined Under Namespace

+

+ + + Modules: OverloadApiForEpoch + + + + +

+ + +

+ Constant Summary + collapse +

+ +
+ +
EPOCH_SIZE = + +
+
1_000
+ +
+ + + + + + + + + +

+ Class Method Summary + collapse +

+ + + + + + +
+

Class Method Details

+ + +
+

+ + .extended(base) ⇒ Object + + + + + +

+
+ + + +
+
+
+ +

Raises:

+
    + +
  • + + + (Error) + + + +
  • + +
+ +
+ + + + +
+
+
+
+13
+14
+15
+16
+17
+18
+
+
# File 'lib/version_gem/epoch.rb', line 13
+
+def extended(base)
+  raise Error, "VERSION must be defined before 'extend #{name}'" unless defined?(base::VERSION)
+
+  base.extend(Api)
+  base.extend(OverloadApiForEpoch)
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Epoch/OverloadApiForEpoch.html b/docs/VersionGem/Epoch/OverloadApiForEpoch.html new file mode 100644 index 0000000..1a0f1bd --- /dev/null +++ b/docs/VersionGem/Epoch/OverloadApiForEpoch.html @@ -0,0 +1,454 @@ + + + + + + + Module: VersionGem::Epoch::OverloadApiForEpoch + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Epoch::OverloadApiForEpoch + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/epoch.rb
+
+ +
+ +

Overview

+
+

Tweak the basic API so it will support Epoch Semantic Versioning

+ + +
+
+
+ + +
+ + + + + + + +

+ Instance Method Summary + collapse +

+ + + + + + +
+

Instance Method Details

+ + +
+

+ + #epochInteger + + + + + +

+
+

** OVERLOAD METHODS FROM API **

+ +

The epoch version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Integer) + + + +
  • + +
+ +
+ + + + +
+
+
+
+28
+29
+30
+
+
# File 'lib/version_gem/epoch.rb', line 28
+
+def epoch
+  @epoch ||= _major / EPOCH_SIZE
+end
+
+
+ +
+

+ + #majorInteger + + + + + +

+
+

The major version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Integer) + + + +
  • + +
+ +
+ + + + +
+
+
+
+35
+36
+37
+
+
# File 'lib/version_gem/epoch.rb', line 35
+
+def major
+  @major ||= _major % EPOCH_SIZE
+end
+
+
+ +
+

+ + #to_aArray<[Integer, String, NilClass]> + + + + + +

+
+

NOTE: This is not the same as _to_a, which returns an array of strings

+ +

The version number as an array of cast values
+where epoch and major are derived from a single string:
+ EPOCH * 1000 + MAJOR

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Array<[Integer, String, NilClass]>) + + + +
  • + +
+ +
+ + + + +
+
+
+
+59
+60
+61
+
+
# File 'lib/version_gem/epoch.rb', line 59
+
+def to_a
+  @to_a ||= [epoch, major, minor, patch, pre]
+end
+
+
+ +
+

+ + #to_hHash + + + + + +

+
+

The version number as a hash

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Hash) + + + +
  • + +
+ +
+ + + + +
+
+
+
+42
+43
+44
+45
+46
+47
+48
+49
+50
+
+
# File 'lib/version_gem/epoch.rb', line 42
+
+def to_h
+  @to_h ||= {
+    epoch: epoch,
+    major: major,
+    minor: minor,
+    patch: patch,
+    pre: pre,
+  }
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Error.html b/docs/VersionGem/Error.html new file mode 100644 index 0000000..60e6225 --- /dev/null +++ b/docs/VersionGem/Error.html @@ -0,0 +1,134 @@ + + + + + + + Exception: VersionGem::Error + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Exception: VersionGem::Error + + + +

+
+ +
+
Inherits:
+
+ RuntimeError + +
    +
  • Object
  • + + + + + +
+ show all + +
+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/error.rb
+
+ +
+ +

Overview

+
+

Errors raised by VersionGem will be of this class

+ + +
+
+
+ + +
+ + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Ruby.html b/docs/VersionGem/Ruby.html new file mode 100644 index 0000000..8d8a731 --- /dev/null +++ b/docs/VersionGem/Ruby.html @@ -0,0 +1,306 @@ + + + + + + + Module: VersionGem::Ruby + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Ruby + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/ruby.rb
+
+ +
+ +

Overview

+
+

Helpers for library CI integration against many different versions of Ruby

+ + +
+
+
+ + +
+ +

+ Constant Summary + collapse +

+ +
+ +
RUBY_VER = + +
+
::Gem::Version.new(RUBY_VERSION)
+ +
+ + + + + + + + + +

+ Class Method Summary + collapse +

+ + + + + + +
+

Class Method Details

+ + +
+

+ + .actual_minor_version?(major, minor, engine = "ruby") ⇒ Boolean + + + + + +

+
+

Check if the current Ruby version (MAJOR.MINOR) is equal to the given version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+15
+16
+17
+18
+19
+20
+
+
# File 'lib/version_gem/ruby.rb', line 15
+
+def actual_minor_version?(major, minor, engine = "ruby")
+  segs = RUBY_VER.segments
+  major.to_i == segs[0] &&
+    minor.to_i == segs[1] &&
+    ::RUBY_ENGINE == engine
+end
+
+
+ +
+

+ + .gte_minimum_version?(version, engine = "ruby") ⇒ Boolean + + + + + +

+
+

Check if the current Ruby version is greater than or equal to the given version

+ + +
+
+
+ +

Returns:

+
    + +
  • + + + (Boolean) + + + +
  • + +
+ +
+ + + + +
+
+
+
+9
+10
+11
+
+
# File 'lib/version_gem/ruby.rb', line 9
+
+def gte_minimum_version?(version, engine = "ruby")
+  RUBY_VER >= ::Gem::Version.new(version) && ::RUBY_ENGINE == engine
+end
+
+
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/VersionGem/Version.html b/docs/VersionGem/Version.html new file mode 100644 index 0000000..2c24bba --- /dev/null +++ b/docs/VersionGem/Version.html @@ -0,0 +1,121 @@ + + + + + + + Module: VersionGem::Version + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Module: VersionGem::Version + + + +

+
+ + + + + + + + + + + +
+
Defined in:
+
lib/version_gem/version.rb
+
+ +
+ + + +

+ Constant Summary + collapse +

+ +
+ +
VERSION = + +
+
"1.1.8"
+ +
+ + + + + + + + + + +
+ + + +
+ + \ No newline at end of file diff --git a/docs/_index.html b/docs/_index.html new file mode 100644 index 0000000..287ac27 --- /dev/null +++ b/docs/_index.html @@ -0,0 +1,304 @@ + + + + + + + Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
+ + +

Documentation by YARD 0.9.37

+
+

Alphabetic Index

+ +

File Listing

+ + +
+

Namespace Listing A-Z

+ + + + + + + + +
+ + +
    +
  • A
  • +
      + +
    • + Api + + (VersionGem) + +
    • + +
    +
+ + +
    +
  • B
  • +
      + +
    • + Basic + + (VersionGem) + +
    • + +
    +
+ + +
    +
  • E
  • +
      + +
    • + Epoch + + (VersionGem) + +
    • + +
    • + Error + + (VersionGem) + +
    • + +
    +
+ + + + + +
    +
  • R
  • +
      + +
    • + Ruby + + (VersionGem) + +
    • + +
    +
+ + + + +
+ +
+ +
+ + + +
+ + \ No newline at end of file diff --git a/docs/class_list.html b/docs/class_list.html new file mode 100644 index 0000000..614a59e --- /dev/null +++ b/docs/class_list.html @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + Class List + + + +
+
+

Class List

+ + + +
+ + +
+ + diff --git a/docs/css/common.css b/docs/css/common.css new file mode 100644 index 0000000..cf25c45 --- /dev/null +++ b/docs/css/common.css @@ -0,0 +1 @@ +/* Override this file with custom rules */ \ No newline at end of file diff --git a/docs/css/full_list.css b/docs/css/full_list.css new file mode 100644 index 0000000..6eef5e4 --- /dev/null +++ b/docs/css/full_list.css @@ -0,0 +1,58 @@ +body { + margin: 0; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + height: 101%; + overflow-x: hidden; + background: #fafafa; +} + +h1 { padding: 12px 10px; padding-bottom: 0; margin: 0; font-size: 1.4em; } +.clear { clear: both; } +.fixed_header { position: fixed; background: #fff; width: 100%; padding-bottom: 10px; margin-top: 0; top: 0; z-index: 9999; height: 70px; } +#search { position: absolute; right: 5px; top: 9px; padding-left: 24px; } +#content.insearch #search, #content.insearch #noresults { background: url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAAPr6+pKSkoiIiO7u7sjIyNjY2J6engAAAI6OjsbGxjIyMlJSUuzs7KamppSUlPLy8oKCghwcHLKysqSkpJqamvT09Pj4+KioqM7OzkRERAwMDGBgYN7e3ujo6Ly8vCoqKjY2NkZGRtTU1MTExDw8PE5OTj4+PkhISNDQ0MrKylpaWrS0tOrq6nBwcKysrLi4uLq6ul5eXlxcXGJiYoaGhuDg4H5+fvz8/KKiohgYGCwsLFZWVgQEBFBQUMzMzDg4OFhYWBoaGvDw8NbW1pycnOLi4ubm5kBAQKqqqiQkJCAgIK6urnJyckpKSjQ0NGpqatLS0sDAwCYmJnx8fEJCQlRUVAoKCggICLCwsOTk5ExMTPb29ra2tmZmZmhoaNzc3KCgoBISEiIiIgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCAAAACwAAAAAEAAQAAAHaIAAgoMgIiYlg4kACxIaACEJCSiKggYMCRselwkpghGJBJEcFgsjJyoAGBmfggcNEx0flBiKDhQFlIoCCA+5lAORFb4AJIihCRbDxQAFChAXw9HSqb60iREZ1omqrIPdJCTe0SWI09GBACH5BAkIAAAALAAAAAAQABAAAAdrgACCgwc0NTeDiYozCQkvOTo9GTmDKy8aFy+NOBA7CTswgywJDTIuEjYFIY0JNYMtKTEFiRU8Pjwygy4ws4owPyCKwsMAJSTEgiQlgsbIAMrO0dKDGMTViREZ14kYGRGK38nHguHEJcvTyIEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDAggPg4iJAAMJCRUAJRIqiRGCBI0WQEEJJkWDERkYAAUKEBc4Po1GiKKJHkJDNEeKig4URLS0ICImJZAkuQAhjSi/wQyNKcGDCyMnk8u5rYrTgqDVghgZlYjcACTA1sslvtHRgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCQARAtOUoQRGRiFD0kJUYWZhUhKT1OLhR8wBaaFBzQ1NwAlkIszCQkvsbOHL7Y4q4IuEjaqq0ZQD5+GEEsJTDCMmIUhtgk1lo6QFUwJVDKLiYJNUd6/hoEAIfkECQgAAAAsAAAAABAAEAAAB2iAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4uen4ICCA+IkIsDCQkVACWmhwSpFqAABQoQF6ALTkWFnYMrVlhWvIKTlSAiJiVVPqlGhJkhqShHV1lCW4cMqSkAR1ofiwsjJyqGgQAh+QQJCAAAACwAAAAAEAAQAAAHZ4AAgoOEhYaCJSWHgxGDJCSMhREZGIYYGY2ElYebi56fhyWQniSKAKKfpaCLFlAPhl0gXYNGEwkhGYREUywag1wJwSkHNDU3D0kJYIMZQwk8MjPBLx9eXwuETVEyAC/BOKsuEjYFhoEAIfkECQgAAAAsAAAAABAAEAAAB2eAAIKDhIWGgiUlh4MRgyQkjIURGRiGGBmNhJWHm4ueICImip6CIQkJKJ4kigynKaqKCyMnKqSEK05StgAGQRxPYZaENqccFgIID4KXmQBhXFkzDgOnFYLNgltaSAAEpxa7BQoQF4aBACH5BAkIAAAALAAAAAAQABAAAAdogACCg4SFggJiPUqCJSWGgkZjCUwZACQkgxGEXAmdT4UYGZqCGWQ+IjKGGIUwPzGPhAc0NTewhDOdL7Ykji+dOLuOLhI2BbaFETICx4MlQitdqoUsCQ2vhKGjglNfU0SWmILaj43M5oEAOwAAAAAAAAAAAA==) no-repeat center left; } +#full_list { padding: 0; list-style: none; margin-left: 0; margin-top: 80px; font-size: 1.1em; } +#full_list ul { padding: 0; } +#full_list li { padding: 0; margin: 0; list-style: none; } +#full_list li .item { padding: 5px 5px 5px 12px; } +#noresults { padding: 7px 12px; background: #fff; } +#content.insearch #noresults { margin-left: 7px; } +li.collapsed ul { display: none; } +li a.toggle { cursor: default; position: relative; left: -5px; top: 4px; text-indent: -999px; width: 10px; height: 9px; margin-left: -10px; display: block; float: left; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAK8AAACvABQqw0mAAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTM5jWRgMAAAAVdEVYdENyZWF0aW9uIFRpbWUAMy8xNC8wOeNZPpQAAAE2SURBVDiNrZTBccIwEEXfelIAHUA6CZ24BGaWO+FuzZAK4k6gg5QAdGAq+Bxs2Yqx7BzyL7Llp/VfzZeQhCTc/ezuGzKKnKSzpCxXJM8fwNXda3df5RZETlIt6YUzSQDs93sl8w3wBZxCCE10GM1OcWbWjB2mWgEH4Mfdyxm3PSepBHibgQE2wLe7r4HjEidpnXMYdQPKEMJcsZ4zs2POYQOcaPfwMVOo58zsAdMt18BuoVDPxUJRacELbXv3hUIX2vYmOUvi8C8ydz/ThjXrqKqqLbDIAdsCKBd+Wo7GWa7o9qzOQHVVVXeAbs+yHHCH4aTsaCOQqunmUy1yBUAXkdMIfMlgF5EXLo2OpV/c/Up7jG4hhHcYLgWzAZXUc2b2ixsfvc/RmNNfOXD3Q/oeL9axJE1yT9IOoUu6MGUkAAAAAElFTkSuQmCC) no-repeat bottom left; } +li.collapsed a.toggle { cursor: default; background-position: top left; } +li { color: #666; cursor: pointer; } +li.deprecated { text-decoration: line-through; font-style: italic; } +li.odd { background: #f0f0f0; } +li.even { background: #fafafa; } +.item:hover { background: #ddd; } +li small:before { content: "("; } +li small:after { content: ")"; } +li small.search_info { display: none; } +a, a:visited { text-decoration: none; color: #05a; } +li.clicked > .item { background: #05a; color: #ccc; } +li.clicked > .item a, li.clicked > .item a:visited { color: #eee; } +li.clicked > .item a.toggle { opacity: 0.5; background-position: bottom right; } +li.collapsed.clicked a.toggle { background-position: top right; } +#search input { border: 1px solid #bbb; border-radius: 3px; } +#full_list_nav { margin-left: 10px; font-size: 0.9em; display: block; color: #aaa; } +#full_list_nav a, #nav a:visited { color: #358; } +#full_list_nav a:hover { background: transparent; color: #5af; } +#full_list_nav span:after { content: ' | '; } +#full_list_nav span:last-child:after { content: ''; } + +#content h1 { margin-top: 0; } +li { white-space: nowrap; cursor: normal; } +li small { display: block; font-size: 0.8em; } +li small:before { content: ""; } +li small:after { content: ""; } +li small.search_info { display: none; } +#search { width: 170px; position: static; margin: 3px; margin-left: 10px; font-size: 0.9em; color: #666; padding-left: 0; padding-right: 24px; } +#content.insearch #search { background-position: center right; } +#search input { width: 110px; } + +#full_list.insearch ul { display: block; } +#full_list.insearch .item { display: none; } +#full_list.insearch .found { display: block; padding-left: 11px !important; } +#full_list.insearch li a.toggle { display: none; } +#full_list.insearch li small.search_info { display: block; } diff --git a/docs/css/style.css b/docs/css/style.css new file mode 100644 index 0000000..f169a65 --- /dev/null +++ b/docs/css/style.css @@ -0,0 +1,503 @@ +html { + width: 100%; + height: 100%; +} +body { + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-size: 13px; + width: 100%; + margin: 0; + padding: 0; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; +} + +#nav { + position: relative; + width: 100%; + height: 100%; + border: 0; + border-right: 1px dotted #eee; + overflow: auto; +} +.nav_wrap { + margin: 0; + padding: 0; + width: 20%; + height: 100%; + position: relative; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; + flex-shrink: 0; + -webkit-flex-shrink: 0; + -ms-flex: 1 0; +} +#resizer { + position: absolute; + right: -5px; + top: 0; + width: 10px; + height: 100%; + cursor: col-resize; + z-index: 9999; +} +#main { + flex: 5 1; + -webkit-flex: 5 1; + -ms-flex: 5 1; + outline: none; + position: relative; + background: #fff; + padding: 1.2em; + padding-top: 0.2em; + box-sizing: border-box; +} + +@media (max-width: 920px) { + .nav_wrap { width: 100%; top: 0; right: 0; overflow: visible; position: absolute; } + #resizer { display: none; } + #nav { + z-index: 9999; + background: #fff; + display: none; + position: absolute; + top: 40px; + right: 12px; + width: 500px; + max-width: 80%; + height: 80%; + overflow-y: scroll; + border: 1px solid #999; + border-collapse: collapse; + box-shadow: -7px 5px 25px #aaa; + border-radius: 2px; + } +} + +@media (min-width: 920px) { + body { height: 100%; overflow: hidden; } + #main { height: 100%; overflow: auto; } + #search { display: none; } +} + +@media (max-width: 320px) { + body { height: 100%; overflow: hidden; overflow-wrap: break-word; } + #main { height: 100%; overflow: auto; } +} + +#main img { max-width: 100%; } +h1 { font-size: 25px; margin: 1em 0 0.5em; padding-top: 4px; border-top: 1px dotted #d5d5d5; } +h1.noborder { border-top: 0px; margin-top: 0; padding-top: 4px; } +h1.title { margin-bottom: 10px; } +h1.alphaindex { margin-top: 0; font-size: 22px; } +h2 { + padding: 0; + padding-bottom: 3px; + border-bottom: 1px #aaa solid; + font-size: 1.4em; + margin: 1.8em 0 0.5em; + position: relative; +} +h2 small { font-weight: normal; font-size: 0.7em; display: inline; position: absolute; right: 0; } +h2 small a { + display: block; + height: 20px; + border: 1px solid #aaa; + border-bottom: 0; + border-top-left-radius: 5px; + background: #f8f8f8; + position: relative; + padding: 2px 7px; +} +a { font-weight: 550; } +.clear { clear: both; } +.inline { display: inline; } +.inline p:first-child { display: inline; } +.docstring, .tags, #filecontents { font-size: 15px; line-height: 1.5145em; } +.docstring p > code, .docstring p > tt, .tags p > code, .tags p > tt { + color: #c7254e; background: #f9f2f4; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.docstring h1, .docstring h2, .docstring h3, .docstring h4 { padding: 0; border: 0; border-bottom: 1px dotted #bbb; } +.docstring h1 { font-size: 1.2em; } +.docstring h2 { font-size: 1.1em; } +.docstring h3, .docstring h4 { font-size: 1em; border-bottom: 0; padding-top: 10px; } +.summary_desc .object_link a, .docstring .object_link a { + font-family: monospace; font-size: 1.05em; + color: #05a; background: #EDF4FA; padding: 2px 4px; font-size: 1em; + border-radius: 4px; +} +.rdoc-term { padding-right: 25px; font-weight: bold; } +.rdoc-list p { margin: 0; padding: 0; margin-bottom: 4px; } +.summary_desc pre.code .object_link a, .docstring pre.code .object_link a { + padding: 0px; background: inherit; color: inherit; border-radius: inherit; +} + +/* style for */ +#filecontents table, .docstring table { border-collapse: collapse; } +#filecontents table th, #filecontents table td, +.docstring table th, .docstring table td { border: 1px solid #ccc; padding: 8px; padding-right: 17px; } +#filecontents table tr:nth-child(odd), +.docstring table tr:nth-child(odd) { background: #eee; } +#filecontents table tr:nth-child(even), +.docstring table tr:nth-child(even) { background: #fff; } +#filecontents table th, .docstring table th { background: #fff; } + +/* style for
    */ +#filecontents li > p, .docstring li > p { margin: 0px; } +#filecontents ul, .docstring ul { padding-left: 20px; } +/* style for
    */ +#filecontents dl, .docstring dl { border: 1px solid #ccc; } +#filecontents dt, .docstring dt { background: #ddd; font-weight: bold; padding: 3px 5px; } +#filecontents dd, .docstring dd { padding: 5px 0px; margin-left: 18px; } +#filecontents dd > p, .docstring dd > p { margin: 0px; } + +.note { + color: #222; + margin: 20px 0; + padding: 10px; + border: 1px solid #eee; + border-radius: 3px; + display: block; +} +.docstring .note { + border-left-color: #ccc; + border-left-width: 5px; +} +.note.todo { background: #ffffc5; border-color: #ececaa; } +.note.returns_void { background: #efefef; } +.note.deprecated { background: #ffe5e5; border-color: #e9dada; } +.note.title.deprecated { background: #ffe5e5; border-color: #e9dada; } +.note.private { background: #ffffc5; border-color: #ececaa; } +.note.title { padding: 3px 6px; font-size: 0.9em; font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; display: inline; } +.summary_signature + .note.title { margin-left: 7px; } +h1 .note.title { font-size: 0.5em; font-weight: normal; padding: 3px 5px; position: relative; top: -3px; text-transform: capitalize; } +.note.title { background: #efefef; } +.note.title.constructor { color: #fff; background: #6a98d6; border-color: #6689d6; } +.note.title.writeonly { color: #fff; background: #45a638; border-color: #2da31d; } +.note.title.readonly { color: #fff; background: #6a98d6; border-color: #6689d6; } +.note.title.private { background: #d5d5d5; border-color: #c5c5c5; } +.note.title.not_defined_here { background: transparent; border: none; font-style: italic; } +.discussion .note { margin-top: 6px; } +.discussion .note:first-child { margin-top: 0; } + +h3.inherited { + font-style: italic; + font-family: "Lucida Sans", "Lucida Grande", Verdana, Arial, sans-serif; + font-weight: normal; + padding: 0; + margin: 0; + margin-top: 12px; + margin-bottom: 3px; + font-size: 13px; +} +p.inherited { + padding: 0; + margin: 0; + margin-left: 25px; +} + +.box_info dl { + margin: 0; + border: 0; + width: 100%; + font-size: 1em; + display: flex; + display: -webkit-flex; + display: -ms-flexbox; +} +.box_info dl dt { + flex-shrink: 0; + -webkit-flex-shrink: 1; + -ms-flex-shrink: 1; + width: 100px; + text-align: right; + font-weight: bold; + border: 1px solid #aaa; + border-width: 1px 0px 0px 1px; + padding: 6px 0; + padding-right: 10px; +} +.box_info dl dd { + flex-grow: 1; + -webkit-flex-grow: 1; + -ms-flex: 1; + max-width: 420px; + padding: 6px 0; + padding-right: 20px; + border: 1px solid #aaa; + border-width: 1px 1px 0 0; + overflow: hidden; + position: relative; +} +.box_info dl:last-child > * { + border-bottom: 1px solid #aaa; +} +.box_info dl:nth-child(odd) > * { background: #eee; } +.box_info dl:nth-child(even) > * { background: #fff; } +.box_info dl > * { margin: 0; } + +ul.toplevel { list-style: none; padding-left: 0; font-size: 1.1em; } +.index_inline_list { padding-left: 0; font-size: 1.1em; } + +.index_inline_list li { + list-style: none; + display: inline-block; + padding: 0 12px; + line-height: 30px; + margin-bottom: 5px; +} + +dl.constants { margin-left: 10px; } +dl.constants dt { font-weight: bold; font-size: 1.1em; margin-bottom: 5px; } +dl.constants.compact dt { display: inline-block; font-weight: normal } +dl.constants dd { width: 75%; white-space: pre; font-family: monospace; margin-bottom: 18px; } +dl.constants .docstring .note:first-child { margin-top: 5px; } + +.summary_desc { + margin-left: 32px; + display: block; + font-family: sans-serif; + font-size: 1.1em; + margin-top: 8px; + line-height: 1.5145em; + margin-bottom: 0.8em; +} +.summary_desc tt { font-size: 0.9em; } +dl.constants .note { padding: 2px 6px; padding-right: 12px; margin-top: 6px; } +dl.constants .docstring { margin-left: 32px; font-size: 0.9em; font-weight: normal; } +dl.constants .tags { padding-left: 32px; font-size: 0.9em; line-height: 0.8em; } +dl.constants .discussion *:first-child { margin-top: 0; } +dl.constants .discussion *:last-child { margin-bottom: 0; } + +.method_details { border-top: 1px dotted #ccc; margin-top: 25px; padding-top: 0; } +.method_details.first { border: 0; margin-top: 5px; } +.method_details.first h3.signature { margin-top: 1em; } +p.signature, h3.signature { + font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace; + padding: 6px 10px; margin-top: 1em; + background: #E8F4FF; border: 1px solid #d8d8e5; border-radius: 5px; +} +p.signature tt, +h3.signature tt { font-family: Monaco, Consolas, Courier, monospace; } +p.signature .overload, +h3.signature .overload { display: block; } +p.signature .extras, +h3.signature .extras { font-weight: normal; font-family: sans-serif; color: #444; font-size: 1em; } +p.signature .not_defined_here, +h3.signature .not_defined_here, +p.signature .aliases, +h3.signature .aliases { display: block; font-weight: normal; font-size: 0.9em; font-family: sans-serif; margin-top: 0px; color: #555; } +p.signature .aliases .names, +h3.signature .aliases .names { font-family: Monaco, Consolas, Courier, monospace; font-weight: bold; color: #000; font-size: 1.2em; } + +.tags .tag_title { font-size: 1.05em; margin-bottom: 0; font-weight: bold; } +.tags .tag_title tt { color: initial; padding: initial; background: initial; } +.tags ul { margin-top: 5px; padding-left: 30px; list-style: square; } +.tags ul li { margin-bottom: 3px; } +.tags ul .name { font-family: monospace; font-weight: bold; } +.tags ul .note { padding: 3px 6px; } +.tags { margin-bottom: 12px; } + +.tags .examples .tag_title { margin-bottom: 10px; font-weight: bold; } +.tags .examples .inline p { padding: 0; margin: 0; font-weight: bold; font-size: 1em; } +.tags .examples .inline p:before { content: "▸"; font-size: 1em; margin-right: 5px; } + +.tags .overload .overload_item { list-style: none; margin-bottom: 25px; } +.tags .overload .overload_item .signature { + padding: 2px 8px; + background: #F1F8FF; border: 1px solid #d8d8e5; border-radius: 3px; +} +.tags .overload .signature { margin-left: -15px; font-family: monospace; display: block; font-size: 1.1em; } +.tags .overload .docstring { margin-top: 15px; } + +.defines { display: none; } + +#method_missing_details .notice.this { position: relative; top: -8px; color: #888; padding: 0; margin: 0; } + +.showSource { font-size: 0.9em; } +.showSource a, .showSource a:visited { text-decoration: none; color: #666; } + +#content a, #content a:visited { text-decoration: none; color: #05a; } +#content a:hover { background: #ffffa5; } + +ul.summary { + list-style: none; + font-family: monospace; + font-size: 1em; + line-height: 1.5em; + padding-left: 0px; +} +ul.summary a, ul.summary a:visited { + text-decoration: none; font-size: 1.1em; +} +ul.summary li { margin-bottom: 5px; } +.summary_signature { padding: 4px 8px; background: #f8f8f8; border: 1px solid #f0f0f0; border-radius: 5px; } +.summary_signature:hover { background: #CFEBFF; border-color: #A4CCDA; cursor: pointer; } +.summary_signature.deprecated { background: #ffe5e5; border-color: #e9dada; } +ul.summary.compact li { display: inline-block; margin: 0px 5px 0px 0px; line-height: 2.6em;} +ul.summary.compact .summary_signature { padding: 5px 7px; padding-right: 4px; } +#content .summary_signature:hover a, +#content .summary_signature:hover a:visited { + background: transparent; + color: #049; +} + +p.inherited a { font-family: monospace; font-size: 0.9em; } +p.inherited { word-spacing: 5px; font-size: 1.2em; } + +p.children { font-size: 1.2em; } +p.children a { font-size: 0.9em; } +p.children strong { font-size: 0.8em; } +p.children strong.modules { padding-left: 5px; } + +ul.fullTree { display: none; padding-left: 0; list-style: none; margin-left: 0; margin-bottom: 10px; } +ul.fullTree ul { margin-left: 0; padding-left: 0; list-style: none; } +ul.fullTree li { text-align: center; padding-top: 18px; padding-bottom: 12px; background: url(data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAHtJREFUeNqMzrEJAkEURdGzuhgZbSoYWcAWoBVsB4JgZAGmphsZCZYzTQgWNCYrDN9RvMmHx+X916SUBFbo8CzD1idXrLErw1mQttgXtyrOcQ/Ny5p4Qh+2XqLYYazsPWNTiuMkRxa4vcV+evuNAUOLIx5+c2hyzv7hNQC67Q+/HHmlEwAAAABJRU5ErkJggg==) no-repeat top center; } +ul.fullTree li:first-child { padding-top: 0; background: transparent; } +ul.fullTree li:last-child { padding-bottom: 0; } +.showAll ul.fullTree { display: block; } +.showAll .inheritName { display: none; } + +#search { position: absolute; right: 12px; top: 0px; z-index: 9000; } +#search a { + display: block; float: left; + padding: 4px 8px; text-decoration: none; color: #05a; fill: #05a; + border: 1px solid #d8d8e5; + border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; + background: #F1F8FF; + box-shadow: -1px 1px 3px #ddd; +} +#search a:hover { background: #f5faff; color: #06b; fill: #06b; } +#search a.active { + background: #568; padding-bottom: 20px; color: #fff; fill: #fff; + border: 1px solid #457; + border-top-left-radius: 5px; border-top-right-radius: 5px; +} +#search a.inactive { color: #999; fill: #999; } +.inheritanceTree, .toggleDefines { + float: right; + border-left: 1px solid #aaa; + position: absolute; top: 0; right: 0; + height: 100%; + background: #f6f6f6; + padding: 5px; + min-width: 55px; + text-align: center; +} + +#menu { font-size: 1.3em; color: #bbb; } +#menu .title, #menu a { font-size: 0.7em; } +#menu .title a { font-size: 1em; } +#menu .title { color: #555; } +#menu a, #menu a:visited { color: #333; text-decoration: none; border-bottom: 1px dotted #bbd; } +#menu a:hover { color: #05a; } + +#footer { margin-top: 15px; border-top: 1px solid #ccc; text-align: center; padding: 7px 0; color: #999; } +#footer a, #footer a:visited { color: #444; text-decoration: none; border-bottom: 1px dotted #bbd; } +#footer a:hover { color: #05a; } + +#listing ul.alpha { font-size: 1.1em; } +#listing ul.alpha { margin: 0; padding: 0; padding-bottom: 10px; list-style: none; } +#listing ul.alpha li.letter { font-size: 1.4em; padding-bottom: 10px; } +#listing ul.alpha ul { margin: 0; padding-left: 15px; } +#listing ul small { color: #666; font-size: 0.7em; } + +li.r1 { background: #f0f0f0; } +li.r2 { background: #fafafa; } + +#content ul.summary li.deprecated .summary_signature a, +#content ul.summary li.deprecated .summary_signature a:visited { text-decoration: line-through; font-style: italic; } + +#toc { + position: relative; + float: right; + overflow-x: auto; + right: -3px; + margin-left: 20px; + margin-bottom: 20px; + padding: 20px; padding-right: 30px; + max-width: 300px; + z-index: 5000; + background: #fefefe; + border: 1px solid #ddd; + box-shadow: -2px 2px 6px #bbb; +} +#toc .title { margin: 0; } +#toc ol { padding-left: 1.8em; } +#toc li { font-size: 1.1em; line-height: 1.7em; } +#toc > ol > li { font-size: 1.1em; font-weight: bold; } +#toc ol > li > ol { font-size: 0.9em; } +#toc ol ol > li > ol { padding-left: 2.3em; } +#toc ol + li { margin-top: 0.3em; } +#toc.hidden { padding: 10px; background: #fefefe; box-shadow: none; } +#toc.hidden:hover { background: #fafafa; } +#filecontents h1 + #toc.nofloat { margin-top: 0; } +@media (max-width: 560px) { + #toc { + margin-left: 0; + margin-top: 16px; + float: none; + max-width: none; + } +} + +/* syntax highlighting */ +.source_code { display: none; padding: 3px 8px; border-left: 8px solid #ddd; margin-top: 5px; } +#filecontents pre.code, .docstring pre.code, .source_code pre { font-family: monospace; } +#filecontents pre.code, .docstring pre.code { display: block; } +.source_code .lines { padding-right: 12px; color: #555; text-align: right; } +#filecontents pre.code, .docstring pre.code, +.tags pre.example { + padding: 9px 14px; + margin-top: 4px; + border: 1px solid #e1e1e8; + background: #f7f7f9; + border-radius: 4px; + font-size: 1em; + overflow-x: auto; + line-height: 1.2em; +} +pre.code { color: #000; tab-size: 2; } +pre.code .info.file { color: #555; } +pre.code .val { color: #036A07; } +pre.code .tstring_content, +pre.code .heredoc_beg, pre.code .heredoc_end, +pre.code .qwords_beg, pre.code .qwords_end, pre.code .qwords_sep, +pre.code .words_beg, pre.code .words_end, pre.code .words_sep, +pre.code .qsymbols_beg, pre.code .qsymbols_end, pre.code .qsymbols_sep, +pre.code .symbols_beg, pre.code .symbols_end, pre.code .symbols_sep, +pre.code .tstring, pre.code .dstring { color: #036A07; } +pre.code .fid, pre.code .rubyid_new, pre.code .rubyid_to_s, +pre.code .rubyid_to_sym, pre.code .rubyid_to_f, +pre.code .dot + pre.code .id, +pre.code .rubyid_to_i pre.code .rubyid_each { color: #0085FF; } +pre.code .comment { color: #0066FF; } +pre.code .const, pre.code .constant { color: #585CF6; } +pre.code .label, +pre.code .symbol { color: #C5060B; } +pre.code .kw, +pre.code .rubyid_require, +pre.code .rubyid_extend, +pre.code .rubyid_include { color: #0000FF; } +pre.code .ivar { color: #318495; } +pre.code .gvar, +pre.code .rubyid_backref, +pre.code .rubyid_nth_ref { color: #6D79DE; } +pre.code .regexp, .dregexp { color: #036A07; } +pre.code a { border-bottom: 1px dotted #bbf; } +/* inline code */ +*:not(pre) > code { + padding: 1px 3px 1px 3px; + border: 1px solid #E1E1E8; + background: #F7F7F9; + border-radius: 4px; +} + +/* Color fix for links */ +#content .summary_desc pre.code .id > .object_link a, /* identifier */ +#content .docstring pre.code .id > .object_link a { color: #0085FF; } +#content .summary_desc pre.code .const > .object_link a, /* constant */ +#content .docstring pre.code .const > .object_link a { color: #585CF6; } diff --git a/docs/file.CHANGELOG.html b/docs/file.CHANGELOG.html new file mode 100644 index 0000000..ab5c985 --- /dev/null +++ b/docs/file.CHANGELOG.html @@ -0,0 +1,319 @@ + + + + + + + File: CHANGELOG + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Changelog

    + +

    SemVer 2.0.0 Keep-A-Changelog 1.0.0

    + +

    All notable changes to this project will be documented in this file.

    + +

    The format is based on Keep a Changelog,
    +and this project adheres to Semantic Versioning,
    +and yes, platform and engine support are part of the public API.
    +Please file a bug if you notice a violation of semantic versioning.

    + +

    Unreleased

    +

    Added

    +

    Changed

    +

    Deprecated

    +

    Removed

    +

    Fixed

    +

    Security

    + +

    +1.1.8 2025-05-06

    +
      +
    • TAG: 1.1.8 +
    • +
    • COVERAGE: 100.00% – 118/118 lines in 8 files
    • +
    • BRANCH COVERAGE: 100.00% – 4/4 branches in 8 files
    • +
    • 84.62% documented +

      Added

      +
    • +
    • CITATION.cff (@pboling)
    • +
    • Cryptographically signed with new 20-year cert (@pboling) +
        +
      • expires 2045-04-29
      • +
      +
    • +
    • Improved documentation (@pboling)
    • +
    • Addressed entire REEK list (@pboling)
    • +
    • GitLab CI, as an addition to existing GHA (@pboling)
    • +
    + +

    +1.1.7 2025-04-15

    +
      +
    • TAG: 1.1.7 +
    • +
    • Line Coverage: 100.0% (117 / 117)
    • +
    • Branch Coverage: 100.0% (4 / 4)
    • +
    • 76.92% documented +

      Added

      +
    • +
    • Support for Epoch Semantic Versioning (@pboling) +
        +
      • +extend VersionGem::Epoch in your library’s MyLib::Version module
      • +
      +
    • +
    • Support for JRuby 10 (@pboling)
    • +
    • More documentation (@pboling) +

      Removed

      +
    • +
    • Ruby 2.2 removed from CI, though technically still supported +
        +
      • can’t run directly in GHA anymore
      • +
      +
    • +
    + +

    +1.1.6 2025-02-24

    +
      +
    • TAG: 1.1.6 +
    • +
    • Line Coverage: 100.0% (77 / 77)
    • +
    • Branch Coverage: 100.0% (2 / 2)
    • +
    • 77.78% documented +

      Added

      +
    • +
    • Support for JRuby 9.1, 9.2, 9.3, 9.4, and head (@pboling)
    • +
    • Support for Truffle Ruby 22.3, 23.0, 23.1, 24.1, and head (@pboling)
    • +
    • Evergreen current latest engine release workflow (@pboling) +
        +
      • Runs ruby, truffleruby, and jruby, always latest release
      • +
      +
    • +
    • Improved developer experience for contributors (@pboling)
    • +
    • More documentation (@pboling)
    • +
    • Switch to stone_checksums for checksum generation (@pboling) +

      Changed

      +
    • +
    • Code of Conduct updated - Contributor Covenant v2.0 => v2.1 (@pboling)
    • +
    + +

    +1.1.5 2025-02-22

    +
      +
    • TAG: 1.1.5 +
    • +
    • Line Coverage: 100.0% (77 / 77)
    • +
    • Branch Coverage: 100.0% (2 / 2)
    • +
    • 77.78% documented +

      Added

      +
    • +
    • Document approach to get code coverage on your gem’s version.rb file (@pboling)
    • +
    • More documentation, and yard task for documentation (@pboling)
    • +
    • Documentation of Ruby version and SemVer support (@pboling) +

      Fixed

      +
    • +
    • +#3 - Allow packaging without signing (@pboling) +
        +
      • to support secure linux distros which have alternate means of signing packages within their package managers
      • +
      +
    • +
    • Code coverage tracking (@pboling)
    • +
    • Documentation of usage in gemspec via Kernel.load (@pboling)
    • +
    • Improved gemspec config (@pboling)
    • +
    + +

    +1.1.4 2024-03-21

    +
      +
    • TAG: 1.1.4 +

      Added

      +
    • +
    • Ruby 3.3 to CI (@pboling) +

      Fixed

      +
    • +
    • Remove the executable bit from non-executable files (@Fryguy)
    • +
    + +

    +1.1.3 2023-06-05

    +
      +
    • TAG: 1.1.3 +

      Added

      +
    • +
    • More test coverage (now 100% 🎉) (@pboling)
    • +
    • Improved documentation (now 77% 🎉) (@pboling)
    • +
    • Gemfile context pattern (@pboling)
    • +
    • Improved linting (via rubocop-lts) (@pboling)
    • +
    • More robust GHA config (@pboling)
    • +
    • (dev) Dependencies (@pboling) +
        +
      • yard-junk
      • +
      • redcarpet
      • +
      • pry, IRB alternative
      • +
      • pry-suite
      • +
      • debase, for IDE debugging
      • +
      +
    • +
    • (dev) Rake task for rubocop_gradual (@pboling) +

      Fixed

      +
    • +
    • (dev) yard documentation task (@pboling) +

      Removed

      +
    • +
    • Formally drop Ruby 2.2 support +
        +
      • Ruby 2.2 was already de facto minimum version supported, which is why this wasn’t a 2.0 release.
      • +
      +
    • +
    + +

    +1.1.2 - 2023-03-17

    +
      +
    • TAG: 1.1.2 +

      Added

      +
    • +
    • +VersionGem::Ruby to help library CI integration against many different versions of Ruby (@pboling) +
        +
      • Experimental, optional, require (not loaded by default, which is why this can be in a patch)
      • +
      +
    • +
    • Spec coverage is now 100%, lines and branches, including the fabled version.rb (@pboling)
    • +
    • Full RBS Signatures (@pboling)
    • +
    + +

    +1.1.1 - 2022-09-19

    +
      +
    • TAG: 1.1.1 +

      Added

      +
    • +
    • Alternatives section to README.md (@pboling)
    • +
    • Signing cert for gem releases (@pboling)
    • +
    • Mailing List and other metadata URIs (@pboling)
    • +
    • Checksums for released gems (@pboling) +

      Changed

      +
    • +
    • SECURITY.md policy (@pboling)
    • +
    • +
+ + + + + + + +
Version methods are now memoized ( =) on initial call for performance (@pboling)
+ +
  • Gem releases are now cryptographically signed (@pboling)
  • + + +

    +1.1.0 - 2022-06-24

    +
      +
    • TAG: 1.1.0 +

      Added

      +
    • +
    • RSpec Matchers and Shared Example (@pboling) +

      Fixed

      +
    • +
    • +to_a uses same type casting as major, minor, patch, and pre (@pboling)
    • +
    + +

    +1.0.2 - 2022-06-23

    +
      +
    • TAG: 1.0.2 +

      Added

      +
    • +
    • Delay loading of library code until after code coverage tool is loaded (@pboling)
    • +
    + +

    +1.0.1 - 2022-06-23

    +
      +
    • TAG: 1.0.1 +

      Added

      +
    • +
    • CI Build improvements (@pboling)
    • +
    • Code coverage reporting (@pboling)
    • +
    • Documentation improvements (@pboling)
    • +
    • Badges! (@pboling)
    • +
    + +

    +1.0.0 - 2022-06-21

    +
      +
    • TAG: 1.0.0 +

      Added

      +
    • +
    • Initial release, with basic version parsing API (@pboling)
    • +
    + + + + + + + + \ No newline at end of file diff --git a/docs/file.CITATION.html b/docs/file.CITATION.html new file mode 100644 index 0000000..3e60561 --- /dev/null +++ b/docs/file.CITATION.html @@ -0,0 +1,92 @@ + + + + + + + File: CITATION + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    cff-version: 1.2.0
    +title: version_gem
    +message: >-
    + If you use this work and you want to cite it,
    + then you can use the metadata from this file.
    +type: software
    +authors:

    +
      +
    • given-names: Peter Hurn
      +family-names: Boling
      +email: peter@railsbling.com
      +affiliation: railsbling.com
      +orcid: ‘https://orcid.org/0009-0008-8519-441X’
      +identifiers:
    • +
    • type: url
      +value: ‘https://github.com/ruby-oauth/version_gem’
      +description: version_gem
      +repository-code: ‘https://github.com/ruby-oauth/version_gem’
      +abstract: >-
      + version_gem
      +license: See license file
    • +
    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.CODE_OF_CONDUCT.html b/docs/file.CODE_OF_CONDUCT.html new file mode 100644 index 0000000..dc14b58 --- /dev/null +++ b/docs/file.CODE_OF_CONDUCT.html @@ -0,0 +1,201 @@ + + + + + + + File: CODE_OF_CONDUCT + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Contributor Covenant Code of Conduct

    + +

    Our Pledge

    + +

    We as members, contributors, and leaders pledge to make participation in our
    +community a harassment-free experience for everyone, regardless of age, body
    +size, visible or invisible disability, ethnicity, sex characteristics, gender
    +identity and expression, level of experience, education, socio-economic status,
    +nationality, personal appearance, race, caste, color, religion, or sexual
    +identity and orientation.

    + +

    We pledge to act and interact in ways that contribute to an open, welcoming,
    +diverse, inclusive, and healthy community.

    + +

    Our Standards

    + +

    Examples of behavior that contributes to a positive environment for our
    +community include:

    + +
      +
    • Demonstrating empathy and kindness toward other people
    • +
    • Being respectful of differing opinions, viewpoints, and experiences
    • +
    • Giving and gracefully accepting constructive feedback
    • +
    • Accepting responsibility and apologizing to those affected by our mistakes,
      +and learning from the experience
    • +
    • Focusing on what is best not just for us as individuals, but for the overall
      +community
    • +
    + +

    Examples of unacceptable behavior include:

    + +
      +
    • The use of sexualized language or imagery, and sexual attention or advances of
      +any kind
    • +
    • Trolling, insulting or derogatory comments, and personal or political attacks
    • +
    • Public or private harassment
    • +
    • Publishing others’ private information, such as a physical or email address,
      +without their explicit permission
    • +
    • Other conduct which could reasonably be considered inappropriate in a
      +professional setting
    • +
    + +

    Enforcement Responsibilities

    + +

    Community leaders are responsible for clarifying and enforcing our standards of
    +acceptable behavior and will take appropriate and fair corrective action in
    +response to any behavior that they deem inappropriate, threatening, offensive,
    +or harmful.

    + +

    Community leaders have the right and responsibility to remove, edit, or reject
    +comments, commits, code, wiki edits, issues, and other contributions that are
    +not aligned to this Code of Conduct, and will communicate reasons for moderation
    +decisions when appropriate.

    + +

    Scope

    + +

    This Code of Conduct applies within all community spaces, and also applies when
    +an individual is officially representing the community in public spaces.
    +Examples of representing our community include using an official email address,
    +posting via an official social media account, or acting as an appointed
    +representative at an online or offline event.

    + +

    Enforcement

    + +

    Instances of abusive, harassing, or otherwise unacceptable behavior may be
    +reported to the community leaders responsible for enforcement at
    +Contact Maintainer.
    +All complaints will be reviewed and investigated promptly and fairly.

    + +

    All community leaders are obligated to respect the privacy and security of the
    +reporter of any incident.

    + +

    Enforcement Guidelines

    + +

    Community leaders will follow these Community Impact Guidelines in determining
    +the consequences for any action they deem in violation of this Code of Conduct:

    + +

    1. Correction

    + +

    Community Impact: Use of inappropriate language or other behavior deemed
    +unprofessional or unwelcome in the community.

    + +

    Consequence: A private, written warning from community leaders, providing
    +clarity around the nature of the violation and an explanation of why the
    +behavior was inappropriate. A public apology may be requested.

    + +

    2. Warning

    + +

    Community Impact: A violation through a single incident or series of
    +actions.

    + +

    Consequence: A warning with consequences for continued behavior. No
    +interaction with the people involved, including unsolicited interaction with
    +those enforcing the Code of Conduct, for a specified period of time. This
    +includes avoiding interactions in community spaces as well as external channels
    +like social media. Violating these terms may lead to a temporary or permanent
    +ban.

    + +

    3. Temporary Ban

    + +

    Community Impact: A serious violation of community standards, including
    +sustained inappropriate behavior.

    + +

    Consequence: A temporary ban from any sort of interaction or public
    +communication with the community for a specified period of time. No public or
    +private interaction with the people involved, including unsolicited interaction
    +with those enforcing the Code of Conduct, is allowed during this period.
    +Violating these terms may lead to a permanent ban.

    + +

    4. Permanent Ban

    + +

    Community Impact: Demonstrating a pattern of violation of community
    +standards, including sustained inappropriate behavior, harassment of an
    +individual, or aggression toward or disparagement of classes of individuals.

    + +

    Consequence: A permanent ban from any sort of public interaction within the
    +community.

    + +

    Attribution

    + +

    This Code of Conduct is adapted from the Contributor Covenant,
    +version 2.1, available at
    +https://www.contributor-covenant.org/version/2/1/code_of_conduct.html.

    + +

    Community Impact Guidelines were inspired by
    +Mozilla’s code of conduct enforcement ladder.

    + +

    For answers to common questions about this code of conduct, see the FAQ at
    +https://www.contributor-covenant.org/faq. Translations are available at
    +https://www.contributor-covenant.org/translations.

    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.CONTRIBUTING.html b/docs/file.CONTRIBUTING.html new file mode 100644 index 0000000..612a778 --- /dev/null +++ b/docs/file.CONTRIBUTING.html @@ -0,0 +1,285 @@ + + + + + + + File: CONTRIBUTING + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Contributing

    + +

    Bug reports and pull requests are welcome on CodeBerg, GitLab, or GitHub.
    +This project should be a safe, welcoming space for collaboration, so contributors agree to adhere to
    +the code of conduct.

    + +

    To submit a patch, please fork the project, create a patch with tests, and send a pull request.
    +Post a message to the google group if you want to.

    + +

    Remember to Keep A Changelog if you make changes.

    + +

    Help out!

    + +

    Take a look at the reek list which is the file called REEK and find something to improve.

    + +

    Follow these instructions:

    + +
      +
    1. Fork the repository
    2. +
    3. Create a feature branch (git checkout -b my-new-feature)
    4. +
    5. Make some fixes.
    6. +
    7. Commit changes (git commit -am 'Added some feature')
    8. +
    9. Push to the branch (git push origin my-new-feature)
    10. +
    11. Make sure to add tests for it. This is important, so it doesn’t break in a future release.
    12. +
    13. Create new Pull Request.
    14. +
    + +

    Environment Variables for Local Development

    + +

    Below are the primary environment variables recognized by stone_checksums (and its integrated tools). Unless otherwise noted, set boolean values to the string “true” to enable.

    + +

    General/runtime

    +
      +
    • DEBUG: Enable extra internal logging for this library (default: false)
    • +
    • REQUIRE_BENCH: Enable require_bench to profile requires (default: false)
    • +
    • CI: When set to true, adjusts default rake tasks toward CI behavior
    • +
    + +

    Coverage (kettle-soup-cover / SimpleCov)

    +
      +
    • K_SOUP_COV_DO: Enable coverage collection (default: true in .envrc)
    • +
    • K_SOUP_COV_FORMATTERS: Comma-separated list of formatters (html, xml, rcov, lcov, json, tty)
    • +
    • K_SOUP_COV_MIN_LINE: Minimum line coverage threshold (integer, e.g., 100)
    • +
    • K_SOUP_COV_MIN_BRANCH: Minimum branch coverage threshold (integer, e.g., 100)
    • +
    • K_SOUP_COV_MIN_HARD: Fail the run if thresholds are not met (true/false)
    • +
    • K_SOUP_COV_MULTI_FORMATTERS: Enable multiple formatters at once (true/false)
    • +
    • K_SOUP_COV_OPEN_BIN: Path to browser opener for HTML (empty disables auto-open)
    • +
    • MAX_ROWS: Limit console output rows for simplecov-console (e.g., 1)
      +Tip: When running a single spec file locally, you may want K_SOUP_COV_MIN_HARD=false to avoid failing thresholds for a partial run.
    • +
    + +

    GitHub API and CI helpers

    +
      +
    • GITHUB_TOKEN or GH_TOKEN: Token used by ci:act and release workflow checks to query GitHub Actions status at higher rate limits
    • +
    + +

    Releasing and signing

    +
      +
    • SKIP_GEM_SIGNING: If set, skip gem signing during build/release
    • +
    • GEM_CERT_USER: Username for selecting your public cert in certs/<USER>.pem (defaults to $USER)
    • +
    • SOURCE_DATE_EPOCH: Reproducible build timestamp. kettle-release will set this automatically for the session.
    • +
    + +

    Git hooks and commit message helpers (exe/kettle-commit-msg)

    +
      +
    • GIT_HOOK_BRANCH_VALIDATE: Branch name validation mode (e.g., jira) or false to disable
    • +
    • GIT_HOOK_FOOTER_APPEND: Append a footer to commit messages when goalie allows (true/false)
    • +
    • GIT_HOOK_FOOTER_SENTINEL: Required when footer append is enabled — a unique first-line sentinel to prevent duplicates
    • +
    • GIT_HOOK_FOOTER_APPEND_DEBUG: Extra debug output in the footer template (true/false)
    • +
    + +

    For a quick starting point, this repository’s .envrc shows sane defaults, and .env.local can override them locally.

    + +

    Appraisals

    + +

    From time to time the appraisal2 gemfiles in gemfiles/ will need to be updated.
    +They are created and updated with the commands:

    + +
    bin/rake appraisal:update
    +
    + +

    When adding an appraisal to CI, check the runner tool cache to see which runner to use.

    + +

    The Reek List

    + +

    Take a look at the reek list which is the file called REEK and find something to improve.

    + +

    To refresh the reek list:

    + +
    bundle exec reek > REEK
    +
    + +

    Run Tests

    + +

    To run all tests

    + +
    bundle exec rake test
    +
    + +

    Spec organization (required)

    + +
      +
    • For each class or module under lib/, keep all of its unit tests in a single spec file under spec/ that mirrors the path and file name (e.g., specs for lib/version_gem/release_cli.rb live in spec/version_gem/release_cli_spec.rb).
    • +
    • Do not create ad-hoc “_more” or split spec files for the same class/module. Consolidate all unit tests into the main spec file for that class/module.
    • +
    • Only integration scenarios that intentionally span multiple classes belong in spec/integration/.
    • +
    + +

    Lint It

    + +

    Run all the default tasks, which includes running the gradually autocorrecting linter, rubocop-gradual.

    + +
    bundle exec rake
    +
    + +

    Or just run the linter.

    + +
    bundle exec rake rubocop_gradual:autocorrect
    +
    + +

    For more detailed information about using RuboCop in this project, please see the RUBOCOP.md guide. This project uses rubocop_gradual instead of vanilla RuboCop, which requires specific commands for checking violations.

    + +

    Important: Do not add inline RuboCop disables

    + +

    Never add # rubocop:disable ... / # rubocop:enable ... comments to code or specs (except when following the few existing rubocop:disable patterns for a rule already being disabled elsewhere in the code). Instead:

    + +
      +
    • Prefer configuration-based exclusions when a rule should not apply to certain paths or files (e.g., via .rubocop.yml).
    • +
    • When a violation is temporary and you plan to fix it later, record it in .rubocop_gradual.lock using the gradual workflow: +
        +
      • +bundle exec rake rubocop_gradual:autocorrect (preferred)
      • +
      • +bundle exec rake rubocop_gradual:force_update (only when you cannot fix the violations immediately)
      • +
      +
    • +
    + +

    As a general rule, fix style issues rather than ignoring them. For example, our specs should follow RSpec conventions like using described_class for the class under test.

    + +

    Contributors

    + +

    Your picture could be here!

    + +

    Contributors

    + +

    Made with contributors-img.

    + +

    Also see GitLab Contributors: https://gitlab.com/ruby-oauth/version_gem/-/graphs/main

    + +

    For Maintainers

    + +

    One-time, Per-maintainer, Setup

    + +

    IMPORTANT: To sign a build,
    +a public key for signing gems will need to be picked up by the line in the
    +gemspec defining the spec.cert_chain (check the relevant ENV variables there).
    +All releases to RubyGems.org are signed releases.
    +See: RubyGems Security Guide

    + +

    NOTE: To build without signing the gem set SKIP_GEM_SIGNING to any value in the environment.

    + +

    To release a new version:

    + +

    Automated process

    + +

    Run bundle exec kettle-release.

    + +

    Manual process

    + +
      +
    1. Run bin/setup && bin/rake as a “test, coverage, & linting” sanity check
    2. +
    3. Update the version number in version.rb, and ensure CHANGELOG.md reflects changes
    4. +
    5. Run bin/setup && bin/rake again as a secondary check, and to update Gemfile.lock +
    6. +
    7. Run git commit -am "🔖 Prepare release v<VERSION>" to commit the changes
    8. +
    9. Run git push to trigger the final CI pipeline before release, and merge PRs + +
    10. +
    11. Run export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME +
    12. +
    13. Run git checkout $GIT_TRUNK_BRANCH_NAME +
    14. +
    15. Run git pull origin $GIT_TRUNK_BRANCH_NAME to ensure latest trunk code
    16. +
    17. Optional for older Bundler (< 2.7.0): Set SOURCE_DATE_EPOCH so rake build and rake release use the same timestamp and generate the same checksums +
        +
      • If your Bundler is >= 2.7.0, you can skip this; builds are reproducible by default.
      • +
      • Run export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH +
      • +
      • If the echo above has no output, then it didn’t work.
      • +
      • Note: zsh/datetime module is needed, if running zsh.
      • +
      • In older versions of bash you can use date +%s instead, i.e. export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH +
      • +
      +
    18. +
    19. Run bundle exec rake build +
    20. +
    21. Run bin/gem_checksums (more context 1, 2)
      +to create SHA-256 and SHA-512 checksums. This functionality is provided by the stone_checksums
      +gem. +
        +
      • The script automatically commits but does not push the checksums
      • +
      +
    22. +
    23. Sanity check the SHA256, comparing with the output from the bin/gem_checksums command: +
        +
      • sha256sum pkg/<gem name>-<version>.gem
      • +
      +
    24. +
    25. Run bundle exec rake release which will create a git tag for the version,
      +push git commits and tags, and push the .gem file to rubygems.org +
    26. +
    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.FUNDING.html b/docs/file.FUNDING.html new file mode 100644 index 0000000..7b4cd85 --- /dev/null +++ b/docs/file.FUNDING.html @@ -0,0 +1,114 @@ + + + + + + + File: FUNDING + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +
    + +

    Official Discord 👉️ Live Chat on Discord

    + +

    Many paths lead to being a sponsor or a backer of this project. Are you on such a path?

    + +

    OpenCollective Backers OpenCollective Sponsors Sponsor Me on Github Liberapay Goal Progress Donate on PayPal

    + +

    Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

    + + + +

    🤑 Request for Help

    + +

    Maintainers have teeth and need to pay their dentists.
    +After getting laid off in an RIF in March and filled with many dozens of rejections,
    +I’m now spending ~60+ hours a week building open source tools.
    +I’m hoping to be able to pay for my kids’ health insurance this month,
    +so if you value the work I am doing, I need your support.
    +Please consider sponsoring me or the project.

    + +

    To join the community or get help 👇️ Join the Discord.

    + +

    Live Chat on Discord

    + +

    To say “thanks for maintaining such a great tool” ☝️ Join the Discord or 👇️ send money.

    + +

    Sponsor ruby-oauth/version_gem on Open Source Collective 💌 Sponsor me on GitHub Sponsors 💌 Sponsor me on Liberapay 💌 Donate on PayPal

    + +

    Another Way to Support Open Source Software

    + +
    +

    How wonderful it is that nobody need wait a single moment before starting to improve the world.

    +—Anne Frank

    +
    + +

    I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).

    + +

    If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in bundle fund.

    + +

    I’m developing a new library, floss_funding, designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.

    + +

    Floss-Funding.dev: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags

    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html new file mode 100644 index 0000000..9e60082 --- /dev/null +++ b/docs/file.LICENSE.html @@ -0,0 +1,70 @@ + + + + + + + File: LICENSE + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +
    The MIT License (MIT)

    Copyright (c) 2022 - 2025 Peter Boling

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in
    all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    THE SOFTWARE.
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.README.html b/docs/file.README.html new file mode 100644 index 0000000..7410fc7 --- /dev/null +++ b/docs/file.README.html @@ -0,0 +1,754 @@ + + + + + + + File: README + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0 ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 version_gem Logo by Aboling0, CC BY-SA 4.0

    + +

    🔖 VersionGem

    + +

    Version GitHub tag (latest SemVer) License: MIT Downloads Rank Open Source Helpers CodeCov Test Coverage Coveralls Test Coverage QLTY Test Coverage QLTY Maintainability CI Heads CI Current CI Truffle Ruby CI JRuby Deps Locked Deps Unlocked CI Supported CI Legacy CI Unsupported CI Ancient CI Test Coverage CI Style CodeQL

    + +

    If ☝️ ci_badges.map(&:color).detect { it != "green"} let me know, as I may have missed the discord notification.

    + +
    + +

    OTOH, if ci_badges.map(&:color).all? { it == "green"} 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.

    + +

    OpenCollective Backers OpenCollective Sponsors Sponsor Me on Github Liberapay Goal Progress Donate on PayPal Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

    + +

    🌻 Synopsis

    + +

    Give your next library an introspectable Version module without breaking your Gemspec.

    + +
    MyLib::Version.to_s # => "1.2.3.rc3"
    +MyLib::Version.major # => 1
    +MyLib::Version.minor # => 2
    +MyLib::Version.patch # => 3
    +MyLib::Version.pre # => "rc3"
    +MyLib::Version.to_a # => [1, 2, 3, "rc3"]
    +MyLib::Version.to_h # => { major: 1, minor: 2, patch: 3, pre: "rc3" }
    +
    + +

    This library was extracted from the gem oauth2.

    + +

    This gem has no runtime dependencies.

    + +

    🧐 Alternatives

    + +

    This gem has a very niche purpose, which is:

    + +
      +
    1. providing introspection of a Version module based on a VERSION constant string within it,
    2. +
    3. while not interfering with gemspec parsing where the VERSION string is traditionally used,
    4. +
    5. allowing 100% test coverage of Ruby code, including the Version module.
    6. +
    + +

    As proof in the pudding, this gem achieves 100% test coverage for lines and branches,
    +all 118 and 4 of them, respectively; coverage enabled in part by patterns from this library.
    +You can make it happen for your library too!

    + +

    If this isn’t precisely your use case you may be better off looking at
    +versionaire, a wonderful, performant, well-maintained,
    +gem from the Alchemists, or version_sorter from GitHub.

    + +

    For more discussion about this see issue #2

    + +

    💡 Info you can shake a stick at

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Tokens to Remember +Gem name Gem namespace +
    Works with JRuby +JRuby 9.1 Compat JRuby 9.2 Compat JRuby 9.3 Compat
    JRuby 9.4 Compat JRuby 10.0 Compat JRuby HEAD Compat +
    Works with Truffle Ruby +Truffle Ruby 22.3 Compat Truffle Ruby 23.0 Compat
    Truffle Ruby 23.1 Compat Truffle Ruby 24.1 Compat +
    Works with MRI Ruby 3 +Ruby 3.0 Compat Ruby 3.1 Compat Ruby 3.2 Compat Ruby 3.3 Compat Ruby 3.4 Compat Ruby HEAD Compat +
    Works with MRI Ruby 2 +Ruby 2.2 Compat
    Ruby 2.3 Compat Ruby 2.4 Compat Ruby 2.5 Compat Ruby 2.6 Compat Ruby 2.7 Compat +
    Source +Source on GitLab.com Source on CodeBerg.org Source on Github.com The best SHA: dQw4w9WgXcQ! +
    Documentation +Current release on RubyDoc.info YARD on Galtzo.com Maintainer Blog Wiki +
    Compliance +License: MIT 📄ilo-declaration-img Security Policy Contributor Covenant 2.1 SemVer 2.0.0 +
    Style +Enforced Code Style Linter Keep-A-Changelog 1.0.0 Gitmoji Commits Compatibility appraised by: appraisal2 +
    Support +Live Chat on Discord Get help from me on Upwork Get help from me on Codementor +
    Maintainer 🎖️ +Follow Me on LinkedIn Follow Me on Ruby.Social Follow Me on Bluesky Contact Maintainer My technical writing +
    +... 💖 +Find Me on WellFound: Find Me on CrunchBase My LinkTree More About Me 🧊 🐙 🛖 🧪 +
    + +

    Compatibility

    + +

    Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby.

    + + + + + + + + + + + + + + +
    🚚 Amazing test matrix was brought to you by🔎 appraisal2 🔎
    👟 Check it out!github.com/appraisal-rb/appraisal2
    + +

    Federated DVCS

    + +
    + Find this repo on other forges (Coming soon!) + +| Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | +|-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| +| 🧪 [ruby-oauth/version_gem on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ | +| 🧊 [ruby-oauth/version_gem on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ | +| 🐙 [ruby-oauth/version_gem on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | [💚][gh-discussions] | +| 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] | + +
    + +

    Enterprise Support Tidelift +

    + +

    Available as part of the Tidelift Subscription.

    + +
    + Need enterprise-level guarantees? + +The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. + +[![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift] + +- 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies +- 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar] +- 💡Tidelift pays maintainers to maintain the software you depend on!
    📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers + +Alternatively: + +- [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] +- [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] +- [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] + +
    + +

    ✨ Installation

    + +

    Install the gem and add to the application’s Gemfile by executing:

    + +
    bundle add version_gem
    +
    + +

    If bundler is not being used to manage dependencies, install the gem by executing:

    + +
    gem install version_gem
    +
    + +

    🔒 Secure Installation

    + +
    + For Medium or High Security Installations + +This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by +[stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with +by following the instructions below. + +Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate: + +```console +gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem) +``` + +You only need to do that once. Then proceed to install with: + +```console +gem install version_gem -P HighSecurity +``` + +The `HighSecurity` trust profile will verify signed gems, and not allow the installation of unsigned dependencies. + +If you want to up your security game full-time: + +```console +bundle config set --global trust-policy MediumSecurity +``` + +`MediumSecurity` instead of `HighSecurity` is necessary if not all the gems you use are signed. + +NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine. + +
    + +

    ⚙️ Configuration

    + +

    In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

    + +
    module MyLib
    +  VERSION = "0.1.0"
    +end
    +
    + +

    Change it to a nested Version namespace (the one implied by the path => namespace convention):

    + +
    module MyLib
    +  module Version
    +    VERSION = "0.1.0"
    +  end
    +end
    +
    + +

    Now add the following near the top of the file the manages requiring external libraries.
    +Using the same example of bundle gem my_lib, this would be lib/my_lib.rb.

    + +
    require "version_gem"
    +
    + +

    Then, add the following wherever you want in the same file (recommend the bottom).

    + +
    MyLib::Version.class_eval do
    +  extend VersionGem::Basic
    +end
    +
    + +

    🔧 Basic Usage

    + +

    Now you have some version introspection methods available:

    + +
    MyLib::Version.to_s # => "0.1.0"
    +MyLib::Version.major # => 0
    +MyLib::Version.minor # => 1
    +MyLib::Version.patch # => 0
    +MyLib::Version.pre # => ""
    +MyLib::Version.to_a # => [0, 1, 0]
    +MyLib::Version.to_h # => { major: 0, minor: 1, patch: 0, pre: "" }
    +
    + +

    Side benefit #1

    + +

    You can reference the version from your gemspec, keeping the version string DRY,
    +and still get accurate code coverage!

    + +
    # Get the GEMFILE_VERSION without *require* "my_gem/version", for code coverage accuracy
    +# See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-2630782358
    +# Kernel.load because load is overloaded in RubyGems during gemspec evaluation
    +Kernel.load("lib/my_gem/version.rb")
    +gem_version = MyGem::Version::VERSION
    +MyGem::Version.send(:remove_const, :VERSION)
    +
    +Gem::Specification.new do |spec|
    +  # ...
    +  spec.version = gem_version
    +end
    +
    + +

    Side benefit #2

    + +

    Your version.rb file now abides the Ruby convention of directory / path matching the namespace / class!

    + +

    Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

    + +

    In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

    + +
    module MyLib
    +  VERSION = "0.1.0"
    +end
    +
    + +

    Change it to a nested Version namespace (the one implied by the path => namespace convention):

    + +
    module MyLib
    +  module Version
    +    VERSION = "0.1.0"
    +  end
    +end
    +
    + +

    The Epoch and Major versions are derived from the formula:

    + +
    {EPOCH * 1000 + MAJOR}.MINOR.PATCH
    +
    + +

    This will start your library with the following version segments:

    + +
      +
    • epoch = 0
    • +
    • major = 0
    • +
    • minor = 1
    • +
    • patch = 0
    • +
    • pre = nil
    • +
    + +

    And the segments are defined as:

    + +
    EPOCH: Increment when you make significant or groundbreaking changes.
    +MAJOR: Increment when you make minor incompatible API changes.
    +MINOR: Increment when you add functionality in a backwards-compatible manner.
    +PATCH: Increment when you make backwards-compatible bug fixes.
    +
    + +

    Therefore, if you set your version number to:

    + +
    VERSION = "27016.42.86-pre.7"
    +
    + +

    You will get the following version segments:

    + +
    {
    +  epoch: 27,
    +  major: 16,
    +  minor: 42,
    +  patch: 86,
    +  pre: "pre-7",
    +}
    +
    + +

    Now add the following near the top of the file the manages requiring external libraries.
    +Using the same example of bundle gem my_lib, this would be lib/my_lib.rb.

    + +
    require "version_gem"
    +
    + +

    Then, add the following wherever you want in the same file (recommend the bottom).

    + +
    MyLib::Version.class_eval do
    +  extend VersionGem::Epoch
    +end
    +
    + +

    And now you have some version introspection methods available:

    + +
    MyLib::Version.to_s # => "1024.3.8"
    +MyLib::Version.epoch # => 1
    +MyLib::Version.major # => 24
    +MyLib::Version.minor # => 3
    +MyLib::Version.patch # => 8
    +MyLib::Version.pre # => ""
    +MyLib::Version.to_a # => [1, 24, 3, 8]
    +MyLib::Version.to_h # => { epoch: 1, major: 24, minor: 3, patch: 8, pre: "" }
    +
    + +

    Usage with Zeitwerk

    + +

    The pattern of version.rb breaking the ruby convention of directory / path matching the namespace / class
    +is so entrenched that the zeitwerk library has a special carve-out for it. 🥺
    +RubyGems using this “bad is actually good” pattern are encouraged to use Zeitwerk.for_gem.

    + +

    Do not do that ^ if you use this gem.

    + +

    Simple Zeitwerk Example

    + +

    Create a gem like this (keeping with the MyLib theme):

    + +
    bundle gem my_lib
    +
    + +

    Then following the usage instructions above, you edit your primary namespace file @ lib/my_lib.rb,
    +but inject the Zeitwerk loader.

    + +
    # frozen_string_literal: true
    +
    +require_relative "my_lib/version"
    +
    +module MyLib
    +  class Error < StandardError; end
    +  # Your code goes here...
    +end
    +
    +loader = Zeitwerk::Loader.new
    +loader.tag = File.basename(__FILE__, ".rb")
    +loader.push_dir("lib/my_lib", namespace: MyLib)
    +loader.setup # ready!
    +loader.eager_load(force: true) # optional!
    +
    +MyLib::Version.class_eval do
    +  extend VersionGem::Basic
    +end
    +
    + +

    Complex Zeitwerk Example

    + +

    Maybe you would like to contribute one?

    + +

    Query Ruby Version (as of version 1.1.2)

    + +

    In Continuous Integration environments for libraries that run against many versions of Ruby,
    +I often need to configure things discretely per Ruby version, and doing so forced me to repeat
    +a significant amount of boilerplate code across each project.

    + +

    Thus VersionGem::Ruby was born. It has the two optimized methods I always need:

    + +
    engine = "ruby"
    +version = "2.7.7"
    +gte_minimum_version?(version, engine)  # Is the current version of Ruby greater than or equal to some minimum?
    +
    +major = 3
    +minor = 2
    +actual_minor_version?(major, minor, engine) # Is the current version of Ruby precisely a specific minor version of Ruby?
    +
    + +

    Version::Ruby is not loaded by default. If you want to use it, you must require it as:

    +
    require "version_gem/ruby"
    +
    + +

    Normally I do this in my spec/spec_helper.rb, and/or .simplecov files.
    +Occasionally in my Rakefile.

    + +

    Caveat

    + +

    This design keeps your version.rb file compatible with the way gemspec files use them.
    +This means that the introspection is not available within the gemspec.
    +The enhancement from this gem is only available at runtime.

    + +

    RSpec Matchers

    + +

    In spec_helper.rb:

    +
    require "version_gem/rspec"
    +
    + +

    Then you can write a test like:

    + +
    RSpec.describe(MyLib::Version) do
    +  it_behaves_like "a Version module", described_class
    +end
    +
    +# Or, if you want to write your own, here is the á la carte menu:
    +RSpec.describe(MyLib::Version) do
    +  it "is a Version module" do
    +    expect(described_class).is_a?(Module)
    +    expect(described_class).to(have_version_constant)
    +    expect(described_class).to(have_version_as_string)
    +    expect(described_class.to_s).to(be_a(String))
    +    expect(described_class).to(have_major_as_integer)
    +    expect(described_class).to(have_epoch_as_integer)
    +    expect(described_class).to(have_minor_as_integer)
    +    expect(described_class).to(have_patch_as_integer)
    +    expect(described_class).to(have_pre_as_nil_or_string)
    +    # This would be %i[epoch major minor patch pre] for epoch version schemes
    +    expect(described_class.to_h.keys).to(match_array(%i[major minor patch pre]))
    +    expect(described_class.to_a).to(be_a(Array))
    +  end
    +end
    +
    +

    🦷 FLOSS Funding

    + +

    While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding.
    +Raising a monthly budget of… “dollars” would make the project more sustainable.

    + +

    We welcome both individual and corporate sponsors! We also offer a
    +wide array of funding channels to account for your preferences
    +(although currently Open Collective is our preferred funding platform).

    + +

    If you’re working in a company that’s making significant use of ruby-oauth tools we’d
    +appreciate it if you suggest to your company to become a ruby-oauth sponsor.

    + +

    You can support the development of ruby-oauth tools via
    +GitHub Sponsors,
    +Liberapay,
    +PayPal,
    +Open Collective
    +and Tidelift.

    + + + + + + + + + + + + +
    📍 NOTE
    If doing a sponsorship in the form of donation is problematic for your company
    from an accounting standpoint, we’d recommend the use of Tidelift,
    where you can get a support-like subscription instead.
    + +

    Open Collective for Individuals

    + + +

    No backers yet. Be the first!
    +

    + +

    Support us with a monthly donation and help us continue our activities. [Become a backer]

    + +

    Open Collective for Organizations

    + + +

    No sponsors yet. Be the first!
    +

    + +

    Become a sponsor and get your logo on our README on GitHub with a link to your site. [Become a sponsor]

    + +

    Another way to support open-source

    + +
    +

    How wonderful it is that nobody need wait a single moment before starting to improve the world.

    +—Anne Frank

    +
    + +

    I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).

    + +

    If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in bundle fund.

    + +

    I’m developing a new library, floss_funding, designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.

    + +

    Floss-Funding.dev: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags

    + +

    OpenCollective Backers OpenCollective Sponsors Sponsor Me on Github Liberapay Goal Progress Donate on PayPal Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

    + +

    🔐 Security

    + +

    See SECURITY.md.

    + +

    🤝 Contributing

    + +

    If you need some ideas of where to help, you could work on adding more code coverage,
    +or if it is already 💯 (see below) check reek, issues, or PRs,
    +or use the gem and think about how it could be better.

    + +

    We Keep A Changelog so if you make changes, remember to update it.

    + +

    See CONTRIBUTING.md for more detailed instructions.

    + +

    🚀 Release Instructions

    + +

    See CONTRIBUTING.md.

    + +

    Code Coverage

    + +

    Coverage Graph

    + +

    Coveralls Test Coverage

    + +

    QLTY Test Coverage

    + +

    🪇 Code of Conduct

    + +

    Everyone interacting with this project’s codebases, issue trackers,
    +chat rooms and mailing lists agrees to follow the Contributor Covenant 2.1.

    + +

    🌈 Contributors

    + +

    Contributors

    + +

    Made with contributors-img.

    + +

    Also see GitLab Contributors: https://gitlab.com/ruby-oauth/version_gem/-/graphs/main

    + +
    + ⭐️ Star History + + + + + + Star History Chart + + + +
    + +

    📌 Versioning

    + +

    This Library adheres to Semantic Versioning 2.0.0.
    +Violations of this scheme should be reported as bugs.
    +Specifically, if a minor or patch version is released that breaks backward compatibility,
    +a new version should be immediately released that restores compatibility.
    +Breaking changes to the public API will only be introduced with new major versions.

    + +
    +

    dropping support for a platform is both obviously and objectively a breaking change

    +—Jordan Harband (@ljharb, maintainer of SemVer) in SemVer issue 716

    +
    + +

    I understand that policy doesn’t work universally (“exceptions to every rule!”),
    +but it is the policy here.
    +As such, in many cases it is good to specify a dependency on this library using
    +the Pessimistic Version Constraint with two digits of precision.

    + +

    For example:

    + +
    spec.add_dependency("version_gem", "~> 1.0")
    +
    + +
    +📌 Is "Platform Support" part of the public API? More details inside. + +SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms +is a *breaking change* to an API. +It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. + +To get a better understanding of how SemVer is intended to work over a project's lifetime, +read this article from the creator of SemVer: + +- ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred] + +
    + +

    See CHANGELOG.md for a list of releases.

    + +

    📄 License

    + +

    The gem is available as open source under the terms of
    +the MIT License License: MIT.
    +See LICENSE.txt for the official Copyright Notice.

    + + + + + +

    🤑 A request for help

    + +

    Maintainers have teeth and need to pay their dentists.
    +After getting laid off in an RIF in March and filled with many dozens of rejections,
    +I’m now spending ~60+ hours a week building open source tools.
    +I’m hoping to be able to pay for my kids’ health insurance this month,
    +so if you value the work I am doing, I need your support.
    +Please consider sponsoring me or the project.

    + +

    To join the community or get help 👇️ Join the Discord.

    + +

    Live Chat on Discord

    + +

    To say “thanks for maintaining such a great tool” ☝️ Join the Discord or 👇️ send money.

    + +

    Sponsor ruby-oauth/version_gem on Open Source Collective 💌 Sponsor me on GitHub Sponsors 💌 Sponsor me on Liberapay 💌 Donate on PayPal

    + +

    Please give the project a star ⭐ ♥.

    + +

    Thanks for RTFM. ☺️

    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.REEK.html b/docs/file.REEK.html new file mode 100644 index 0000000..2898fcb --- /dev/null +++ b/docs/file.REEK.html @@ -0,0 +1,71 @@ + + + + + + + File: REEK + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +
    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.RUBOCOP.html b/docs/file.RUBOCOP.html new file mode 100644 index 0000000..4a0cf06 --- /dev/null +++ b/docs/file.RUBOCOP.html @@ -0,0 +1,171 @@ + + + + + + + File: RUBOCOP + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    RuboCop Usage Guide

    + +

    Overview

    + +

    A tale of two RuboCop plugin gems.

    + +

    RuboCop Gradual

    + +

    This project uses rubocop_gradual instead of vanilla RuboCop for code style checking. The rubocop_gradual tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file.

    + +

    RuboCop LTS

    + +

    This project uses rubocop-lts to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2.
    +RuboCop rules are meticulously configured by the rubocop-lts family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more.

    + +

    Checking RuboCop Violations

    + +

    To check for RuboCop violations in this project, always use:

    + +
    bundle exec rake rubocop_gradual:check
    +
    + +

    Do not use the standard RuboCop commands like:

    +
      +
    • bundle exec rubocop
    • +
    • rubocop
    • +
    + +

    Understanding the Lock File

    + +

    The .rubocop_gradual.lock file tracks all current RuboCop violations in the project. This allows the team to:

    + +
      +
    1. Prevent new violations while gradually fixing existing ones
    2. +
    3. Track progress on code style improvements
    4. +
    5. Ensure CI builds don’t fail due to pre-existing violations
    6. +
    + +

    Common Commands

    + +
      +
    • +Check violations +
        +
      • bundle exec rake rubocop_gradual
      • +
      • bundle exec rake rubocop_gradual:check
      • +
      +
    • +
    • +(Safe) Autocorrect violations, and update lockfile if no new violations +
        +
      • bundle exec rake rubocop_gradual:autocorrect
      • +
      +
    • +
    • +Force update the lock file (w/o autocorrect) to match violations present in code +
        +
      • bundle exec rake rubocop_gradual:force_update
      • +
      +
    • +
    + +

    Workflow

    + +
      +
    1. Before submitting a PR, run bundle exec rake rubocop_gradual:autocorrect
      +a. or just the default bundle exec rake, as autocorrection is a pre-requisite of the default task.
    2. +
    3. If there are new violations, either: +
        +
      • Fix them in your code
      • +
      • Run bundle exec rake rubocop_gradual:force_update to update the lock file (only for violations you can’t fix immediately)
      • +
      +
    4. +
    5. Commit the updated .rubocop_gradual.lock file along with your changes
    6. +
    + +

    Never add inline RuboCop disables

    + +

    Do not add inline rubocop:disable / rubocop:enable comments anywhere in the codebase (including specs, except when following the few existing rubocop:disable patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways:

    + +
      +
    • Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in .rubocop.yml) to exclude a rule for a path or file pattern when it makes sense project-wide.
    • +
    • Temporary exceptions while improving code: record the current violations in .rubocop_gradual.lock via the gradual workflow: +
        +
      • +bundle exec rake rubocop_gradual:autocorrect (preferred; will autocorrect what it can and update the lock only if no new violations were introduced)
      • +
      • If needed, bundle exec rake rubocop_gradual:force_update (as a last resort when you cannot fix the newly reported violations immediately)
      • +
      +
    • +
    + +

    In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect described_class to be used in specs that target a specific class under test.

    + +

    Benefits of rubocop_gradual

    + +
      +
    • Allows incremental adoption of code style rules
    • +
    • Prevents CI failures due to pre-existing violations
    • +
    • Provides a clear record of code style debt
    • +
    • Enables focused efforts on improving code quality over time
    • +
    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html new file mode 100644 index 0000000..3fb09b4 --- /dev/null +++ b/docs/file.SECURITY.html @@ -0,0 +1,101 @@ + + + + + + + File: SECURITY + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Security Policy

    + +

    Supported Versions

    + + + + + + + + + + + + + + +
    VersionSupported
    1.latest
    + +

    Security contact information

    + +

    To report a security vulnerability, please use the
    +Tidelift security contact.
    +Tidelift will coordinate the fix and disclosure.

    + +

    Additional Support

    + +

    If you are interested in support for versions older than the latest release,
    +please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
    +or find other sponsorship links in the README.

    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.all_formatters.html b/docs/file.all_formatters.html new file mode 100644 index 0000000..c4b8f48 --- /dev/null +++ b/docs/file.all_formatters.html @@ -0,0 +1,71 @@ + + + + + + + File: all_formatters + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    ALL_FORMATTERS: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.api.html b/docs/file.api.html new file mode 100644 index 0000000..d47d0ac --- /dev/null +++ b/docs/file.api.html @@ -0,0 +1,102 @@ + + + + + + + File: api + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    module VersionGem
    + module Api
    + @_to_a: Array[String]

    + +
    @major: Integer
    +
    +@minor: Integer
    +
    +@patch: Integer
    +
    +@pre: String?
    +
    +@to_a: Array
    +
    +@to_h: Hash
    +
    +def major: () -> Integer
    +
    +def minor: () -> Integer
    +
    +def patch: () -> Integer
    +
    +def pre: () -> String?
    +
    +def to_a: () -> Array
    +
    +def to_h: () -> Hash
    +
    +private
    +
    +def _to_a: () -> Array[String]   end end
    +
    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.basic.html b/docs/file.basic.html new file mode 100644 index 0000000..25e7593 --- /dev/null +++ b/docs/file.basic.html @@ -0,0 +1,75 @@ + + + + + + + File: basic + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    module VersionGem
    + module Basic
    + def self.extended: () -> void
    + end
    +end

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.debug.html b/docs/file.debug.html new file mode 100644 index 0000000..018f39c --- /dev/null +++ b/docs/file.debug.html @@ -0,0 +1,71 @@ + + + + + + + File: debug + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    DEBUG: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.debug_ide.html b/docs/file.debug_ide.html new file mode 100644 index 0000000..f511218 --- /dev/null +++ b/docs/file.debug_ide.html @@ -0,0 +1,71 @@ + + + + + + + File: debug_ide + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    DEBUG_IDE: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.debug_jruby.html b/docs/file.debug_jruby.html new file mode 100644 index 0000000..0dc2de8 --- /dev/null +++ b/docs/file.debug_jruby.html @@ -0,0 +1,71 @@ + + + + + + + File: debug_jruby + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    DEBUG_JRUBY: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.debugging.html b/docs/file.debugging.html new file mode 100644 index 0000000..b83e70b --- /dev/null +++ b/docs/file.debugging.html @@ -0,0 +1,71 @@ + + + + + + + File: debugging + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    DEBUGGING: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.ruby.html b/docs/file.ruby.html new file mode 100644 index 0000000..3e7bee4 --- /dev/null +++ b/docs/file.ruby.html @@ -0,0 +1,78 @@ + + + + + + + File: ruby + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    module VersionGem
    + module Ruby
    + RUBY_VER: Gem::Version

    + +
    def actual_minor_version?: () -> bool
    +
    +def gte_minimum_version?: () -> bool   end end
    +
    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.run_coverage.html b/docs/file.run_coverage.html new file mode 100644 index 0000000..d852f41 --- /dev/null +++ b/docs/file.run_coverage.html @@ -0,0 +1,71 @@ + + + + + + + File: run_coverage + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    RUN_COVERAGE: bool

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version.html b/docs/file.version.html new file mode 100644 index 0000000..de4f9b3 --- /dev/null +++ b/docs/file.version.html @@ -0,0 +1,75 @@ + + + + + + + File: version + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    module VersionGem
    + module Version
    + VERSION: String
    + end
    +end

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.1.gem.html b/docs/file.version_gem-1.1.1.gem.html new file mode 100644 index 0000000..9c6886a --- /dev/null +++ b/docs/file.version_gem-1.1.1.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.1.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    3b94b064e5337201992893e5b6fd96664f70925671313b46bcc2a0d412e4030810f0b7737777a264de55352e1b3e678fd48760a353c611403c50323b3dfd7304

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.2.gem.html b/docs/file.version_gem-1.1.2.gem.html new file mode 100644 index 0000000..a06ee68 --- /dev/null +++ b/docs/file.version_gem-1.1.2.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.2.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    b0143de89d8f110b0d778826a885c2248b7d4df0af1be4396442dcefa8168ac946a8d0aa0bfa7e4aee43218a0f0e611da39f1da8cd2b7c6bdc035808f712268f

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.3.gem.html b/docs/file.version_gem-1.1.3.gem.html new file mode 100644 index 0000000..cd1a4d2 --- /dev/null +++ b/docs/file.version_gem-1.1.3.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.3.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    e5512174a81a06c3cb9d9a8a18fd51155ffc500e8995dcca86280aed3ceb83c0da8511bbe4fa329038680050482ade5500adf64647327657ed74e94bca89ca80

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.4.gem.html b/docs/file.version_gem-1.1.4.gem.html new file mode 100644 index 0000000..602efa9 --- /dev/null +++ b/docs/file.version_gem-1.1.4.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.4.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    f26122ec619e518eba3625d699568037db0dd219c14fa5c10099a1ca01d2eb76571d2932d1ec42a941dd0c47ce47875316ba95f363720c1da88f7c6d9907c4ec

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.5.gem.html b/docs/file.version_gem-1.1.5.gem.html new file mode 100644 index 0000000..72442e4 --- /dev/null +++ b/docs/file.version_gem-1.1.5.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.5.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    a9f9e01b634e69439a704f35713b3107fda0a5172718f1e9c4b90be31ba961f64ef428db159be7add1369159e786171960847c697b5264c745eb659dd735dbef

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.6.gem.html b/docs/file.version_gem-1.1.6.gem.html new file mode 100644 index 0000000..202b53e --- /dev/null +++ b/docs/file.version_gem-1.1.6.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.6.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    48f8681b01e99fe94707863504f86fc515f4d74708625cf258718f04a71d69ea9414bf7af06310b2074f33b6324af6d98b95c81606c9814773271cedf928313d

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.7.gem.html b/docs/file.version_gem-1.1.7.gem.html new file mode 100644 index 0000000..698f8bb --- /dev/null +++ b/docs/file.version_gem-1.1.7.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.7.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    678ff1d4ad48afef4651c0f7593bb39b44135a5316f3364c816d7c2a9deb24b69b87cb5cf1e97bbbe683beb8d2a88bffa26fd9b8c9471bfbfddb558c103d2f53

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem-1.1.8.gem.html b/docs/file.version_gem-1.1.8.gem.html new file mode 100644 index 0000000..7807ddc --- /dev/null +++ b/docs/file.version_gem-1.1.8.gem.html @@ -0,0 +1,71 @@ + + + + + + + File: version_gem-1.1.8.gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    605cf987cda863f1eb7a8a2f24945eb668d892b0fe5ceb8237d2cb8a725e4315c050f877152a7699b21ebb06a88c209b9174b803b26b3ba7414e31ab89f9d4f0

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file.version_gem.html b/docs/file.version_gem.html new file mode 100644 index 0000000..f039e4c --- /dev/null +++ b/docs/file.version_gem.html @@ -0,0 +1,74 @@ + + + + + + + File: version_gem + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    module VersionGem
    + VERSION: String
    + # See the writing guide of rbs: https://github.com/ruby/rbs#guides
    +end

    +
    + + + +
    + + \ No newline at end of file diff --git a/docs/file_list.html b/docs/file_list.html new file mode 100644 index 0000000..dbc8ddb --- /dev/null +++ b/docs/file_list.html @@ -0,0 +1,239 @@ + + + + + + + + + + + + + + + + + + File List + + + +
    +
    +

    File List

    + + + +
    + + +
    + + diff --git a/docs/frames.html b/docs/frames.html new file mode 100644 index 0000000..6586005 --- /dev/null +++ b/docs/frames.html @@ -0,0 +1,22 @@ + + + + + Documentation by YARD 0.9.37 + + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..cb4c819 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,754 @@ + + + + + + + File: README + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
    + + +

    Galtzo FLOSS Logo by Aboling0, CC BY-SA 4.0 ruby-lang Logo, Yukihiro Matsumoto, Ruby Visual Identity Team, CC BY-SA 2.5 version_gem Logo by Aboling0, CC BY-SA 4.0

    + +

    🔖 VersionGem

    + +

    Version GitHub tag (latest SemVer) License: MIT Downloads Rank Open Source Helpers CodeCov Test Coverage Coveralls Test Coverage QLTY Test Coverage QLTY Maintainability CI Heads CI Current CI Truffle Ruby CI JRuby Deps Locked Deps Unlocked CI Supported CI Legacy CI Unsupported CI Ancient CI Test Coverage CI Style CodeQL

    + +

    If ☝️ ci_badges.map(&:color).detect { it != "green"} let me know, as I may have missed the discord notification.

    + +
    + +

    OTOH, if ci_badges.map(&:color).all? { it == "green"} 👇️ send money so I can do more of this. FLOSS maintenance is now my full-time job.

    + +

    OpenCollective Backers OpenCollective Sponsors Sponsor Me on Github Liberapay Goal Progress Donate on PayPal Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

    + +

    🌻 Synopsis

    + +

    Give your next library an introspectable Version module without breaking your Gemspec.

    + +
    MyLib::Version.to_s # => "1.2.3.rc3"
    +MyLib::Version.major # => 1
    +MyLib::Version.minor # => 2
    +MyLib::Version.patch # => 3
    +MyLib::Version.pre # => "rc3"
    +MyLib::Version.to_a # => [1, 2, 3, "rc3"]
    +MyLib::Version.to_h # => { major: 1, minor: 2, patch: 3, pre: "rc3" }
    +
    + +

    This library was extracted from the gem oauth2.

    + +

    This gem has no runtime dependencies.

    + +

    🧐 Alternatives

    + +

    This gem has a very niche purpose, which is:

    + +
      +
    1. providing introspection of a Version module based on a VERSION constant string within it,
    2. +
    3. while not interfering with gemspec parsing where the VERSION string is traditionally used,
    4. +
    5. allowing 100% test coverage of Ruby code, including the Version module.
    6. +
    + +

    As proof in the pudding, this gem achieves 100% test coverage for lines and branches,
    +all 118 and 4 of them, respectively; coverage enabled in part by patterns from this library.
    +You can make it happen for your library too!

    + +

    If this isn’t precisely your use case you may be better off looking at
    +versionaire, a wonderful, performant, well-maintained,
    +gem from the Alchemists, or version_sorter from GitHub.

    + +

    For more discussion about this see issue #2

    + +

    💡 Info you can shake a stick at

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Tokens to Remember +Gem name Gem namespace +
    Works with JRuby +JRuby 9.1 Compat JRuby 9.2 Compat JRuby 9.3 Compat
    JRuby 9.4 Compat JRuby 10.0 Compat JRuby HEAD Compat +
    Works with Truffle Ruby +Truffle Ruby 22.3 Compat Truffle Ruby 23.0 Compat
    Truffle Ruby 23.1 Compat Truffle Ruby 24.1 Compat +
    Works with MRI Ruby 3 +Ruby 3.0 Compat Ruby 3.1 Compat Ruby 3.2 Compat Ruby 3.3 Compat Ruby 3.4 Compat Ruby HEAD Compat +
    Works with MRI Ruby 2 +Ruby 2.2 Compat
    Ruby 2.3 Compat Ruby 2.4 Compat Ruby 2.5 Compat Ruby 2.6 Compat Ruby 2.7 Compat +
    Source +Source on GitLab.com Source on CodeBerg.org Source on Github.com The best SHA: dQw4w9WgXcQ! +
    Documentation +Current release on RubyDoc.info YARD on Galtzo.com Maintainer Blog Wiki +
    Compliance +License: MIT 📄ilo-declaration-img Security Policy Contributor Covenant 2.1 SemVer 2.0.0 +
    Style +Enforced Code Style Linter Keep-A-Changelog 1.0.0 Gitmoji Commits Compatibility appraised by: appraisal2 +
    Support +Live Chat on Discord Get help from me on Upwork Get help from me on Codementor +
    Maintainer 🎖️ +Follow Me on LinkedIn Follow Me on Ruby.Social Follow Me on Bluesky Contact Maintainer My technical writing +
    +... 💖 +Find Me on WellFound: Find Me on CrunchBase My LinkTree More About Me 🧊 🐙 🛖 🧪 +
    + +

    Compatibility

    + +

    Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby.

    + + + + + + + + + + + + + + +
    🚚 Amazing test matrix was brought to you by🔎 appraisal2 🔎
    👟 Check it out!github.com/appraisal-rb/appraisal2
    + +

    Federated DVCS

    + +
    + Find this repo on other forges (Coming soon!) + +| Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | +|-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| +| 🧪 [ruby-oauth/version_gem on GitLab][📜src-gl] | The Truth | [💚][🤝gl-issues] | [💚][🤝gl-pulls] | [💚][📜wiki] | 🏀 Tiny Matrix | ➖ | +| 🧊 [ruby-oauth/version_gem on CodeBerg][📜src-cb] | An Ethical Mirror ([Donate][🤝cb-donate]) | [💚][🤝cb-issues] | [💚][🤝cb-pulls] | ➖ | ⭕️ No Matrix | ➖ | +| 🐙 [ruby-oauth/version_gem on GitHub][📜src-gh] | Another Mirror | [💚][🤝gh-issues] | [💚][🤝gh-pulls] | ➖ | 💯 Full Matrix | [💚][gh-discussions] | +| 🎮️ [Discord Server][✉️discord-invite] | [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] | [Let's][✉️discord-invite] | [talk][✉️discord-invite] | [about][✉️discord-invite] | [this][✉️discord-invite] | [library!][✉️discord-invite] | + +
    + +

    Enterprise Support Tidelift +

    + +

    Available as part of the Tidelift Subscription.

    + +
    + Need enterprise-level guarantees? + +The maintainers of this and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. + +[![Get help from me on Tidelift][🏙️entsup-tidelift-img]][🏙️entsup-tidelift] + +- 💡Subscribe for support guarantees covering _all_ your FLOSS dependencies +- 💡Tidelift is part of [Sonar][🏙️entsup-tidelift-sonar] +- 💡Tidelift pays maintainers to maintain the software you depend on!
    📊`@`Pointy Haired Boss: An [enterprise support][🏙️entsup-tidelift] subscription is "[never gonna let you down][🧮kloc]", and *supports* open source maintainers + +Alternatively: + +- [![Live Chat on Discord][✉️discord-invite-img-ftb]][✉️discord-invite] +- [![Get help from me on Upwork][👨🏼‍🏫expsup-upwork-img]][👨🏼‍🏫expsup-upwork] +- [![Get help from me on Codementor][👨🏼‍🏫expsup-codementor-img]][👨🏼‍🏫expsup-codementor] + +
    + +

    ✨ Installation

    + +

    Install the gem and add to the application’s Gemfile by executing:

    + +
    bundle add version_gem
    +
    + +

    If bundler is not being used to manage dependencies, install the gem by executing:

    + +
    gem install version_gem
    +
    + +

    🔒 Secure Installation

    + +
    + For Medium or High Security Installations + +This gem is cryptographically signed, and has verifiable [SHA-256 and SHA-512][💎SHA_checksums] checksums by +[stone_checksums][💎stone_checksums]. Be sure the gem you install hasn’t been tampered with +by following the instructions below. + +Add my public key (if you haven’t already, expires 2045-04-29) as a trusted certificate: + +```console +gem cert --add <(curl -Ls https://raw.github.com/galtzo-floss/certs/main/pboling.pem) +``` + +You only need to do that once. Then proceed to install with: + +```console +gem install version_gem -P HighSecurity +``` + +The `HighSecurity` trust profile will verify signed gems, and not allow the installation of unsigned dependencies. + +If you want to up your security game full-time: + +```console +bundle config set --global trust-policy MediumSecurity +``` + +`MediumSecurity` instead of `HighSecurity` is necessary if not all the gems you use are signed. + +NOTE: Be prepared to track down certs for signed gems and add them the same way you added mine. + +
    + +

    ⚙️ Configuration

    + +

    In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

    + +
    module MyLib
    +  VERSION = "0.1.0"
    +end
    +
    + +

    Change it to a nested Version namespace (the one implied by the path => namespace convention):

    + +
    module MyLib
    +  module Version
    +    VERSION = "0.1.0"
    +  end
    +end
    +
    + +

    Now add the following near the top of the file the manages requiring external libraries.
    +Using the same example of bundle gem my_lib, this would be lib/my_lib.rb.

    + +
    require "version_gem"
    +
    + +

    Then, add the following wherever you want in the same file (recommend the bottom).

    + +
    MyLib::Version.class_eval do
    +  extend VersionGem::Basic
    +end
    +
    + +

    🔧 Basic Usage

    + +

    Now you have some version introspection methods available:

    + +
    MyLib::Version.to_s # => "0.1.0"
    +MyLib::Version.major # => 0
    +MyLib::Version.minor # => 1
    +MyLib::Version.patch # => 0
    +MyLib::Version.pre # => ""
    +MyLib::Version.to_a # => [0, 1, 0]
    +MyLib::Version.to_h # => { major: 0, minor: 1, patch: 0, pre: "" }
    +
    + +

    Side benefit #1

    + +

    You can reference the version from your gemspec, keeping the version string DRY,
    +and still get accurate code coverage!

    + +
    # Get the GEMFILE_VERSION without *require* "my_gem/version", for code coverage accuracy
    +# See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-2630782358
    +# Kernel.load because load is overloaded in RubyGems during gemspec evaluation
    +Kernel.load("lib/my_gem/version.rb")
    +gem_version = MyGem::Version::VERSION
    +MyGem::Version.send(:remove_const, :VERSION)
    +
    +Gem::Specification.new do |spec|
    +  # ...
    +  spec.version = gem_version
    +end
    +
    + +

    Side benefit #2

    + +

    Your version.rb file now abides the Ruby convention of directory / path matching the namespace / class!

    + +

    Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

    + +

    In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

    + +
    module MyLib
    +  VERSION = "0.1.0"
    +end
    +
    + +

    Change it to a nested Version namespace (the one implied by the path => namespace convention):

    + +
    module MyLib
    +  module Version
    +    VERSION = "0.1.0"
    +  end
    +end
    +
    + +

    The Epoch and Major versions are derived from the formula:

    + +
    {EPOCH * 1000 + MAJOR}.MINOR.PATCH
    +
    + +

    This will start your library with the following version segments:

    + +
      +
    • epoch = 0
    • +
    • major = 0
    • +
    • minor = 1
    • +
    • patch = 0
    • +
    • pre = nil
    • +
    + +

    And the segments are defined as:

    + +
    EPOCH: Increment when you make significant or groundbreaking changes.
    +MAJOR: Increment when you make minor incompatible API changes.
    +MINOR: Increment when you add functionality in a backwards-compatible manner.
    +PATCH: Increment when you make backwards-compatible bug fixes.
    +
    + +

    Therefore, if you set your version number to:

    + +
    VERSION = "27016.42.86-pre.7"
    +
    + +

    You will get the following version segments:

    + +
    {
    +  epoch: 27,
    +  major: 16,
    +  minor: 42,
    +  patch: 86,
    +  pre: "pre-7",
    +}
    +
    + +

    Now add the following near the top of the file the manages requiring external libraries.
    +Using the same example of bundle gem my_lib, this would be lib/my_lib.rb.

    + +
    require "version_gem"
    +
    + +

    Then, add the following wherever you want in the same file (recommend the bottom).

    + +
    MyLib::Version.class_eval do
    +  extend VersionGem::Epoch
    +end
    +
    + +

    And now you have some version introspection methods available:

    + +
    MyLib::Version.to_s # => "1024.3.8"
    +MyLib::Version.epoch # => 1
    +MyLib::Version.major # => 24
    +MyLib::Version.minor # => 3
    +MyLib::Version.patch # => 8
    +MyLib::Version.pre # => ""
    +MyLib::Version.to_a # => [1, 24, 3, 8]
    +MyLib::Version.to_h # => { epoch: 1, major: 24, minor: 3, patch: 8, pre: "" }
    +
    + +

    Usage with Zeitwerk

    + +

    The pattern of version.rb breaking the ruby convention of directory / path matching the namespace / class
    +is so entrenched that the zeitwerk library has a special carve-out for it. 🥺
    +RubyGems using this “bad is actually good” pattern are encouraged to use Zeitwerk.for_gem.

    + +

    Do not do that ^ if you use this gem.

    + +

    Simple Zeitwerk Example

    + +

    Create a gem like this (keeping with the MyLib theme):

    + +
    bundle gem my_lib
    +
    + +

    Then following the usage instructions above, you edit your primary namespace file @ lib/my_lib.rb,
    +but inject the Zeitwerk loader.

    + +
    # frozen_string_literal: true
    +
    +require_relative "my_lib/version"
    +
    +module MyLib
    +  class Error < StandardError; end
    +  # Your code goes here...
    +end
    +
    +loader = Zeitwerk::Loader.new
    +loader.tag = File.basename(__FILE__, ".rb")
    +loader.push_dir("lib/my_lib", namespace: MyLib)
    +loader.setup # ready!
    +loader.eager_load(force: true) # optional!
    +
    +MyLib::Version.class_eval do
    +  extend VersionGem::Basic
    +end
    +
    + +

    Complex Zeitwerk Example

    + +

    Maybe you would like to contribute one?

    + +

    Query Ruby Version (as of version 1.1.2)

    + +

    In Continuous Integration environments for libraries that run against many versions of Ruby,
    +I often need to configure things discretely per Ruby version, and doing so forced me to repeat
    +a significant amount of boilerplate code across each project.

    + +

    Thus VersionGem::Ruby was born. It has the two optimized methods I always need:

    + +
    engine = "ruby"
    +version = "2.7.7"
    +gte_minimum_version?(version, engine)  # Is the current version of Ruby greater than or equal to some minimum?
    +
    +major = 3
    +minor = 2
    +actual_minor_version?(major, minor, engine) # Is the current version of Ruby precisely a specific minor version of Ruby?
    +
    + +

    Version::Ruby is not loaded by default. If you want to use it, you must require it as:

    +
    require "version_gem/ruby"
    +
    + +

    Normally I do this in my spec/spec_helper.rb, and/or .simplecov files.
    +Occasionally in my Rakefile.

    + +

    Caveat

    + +

    This design keeps your version.rb file compatible with the way gemspec files use them.
    +This means that the introspection is not available within the gemspec.
    +The enhancement from this gem is only available at runtime.

    + +

    RSpec Matchers

    + +

    In spec_helper.rb:

    +
    require "version_gem/rspec"
    +
    + +

    Then you can write a test like:

    + +
    RSpec.describe(MyLib::Version) do
    +  it_behaves_like "a Version module", described_class
    +end
    +
    +# Or, if you want to write your own, here is the á la carte menu:
    +RSpec.describe(MyLib::Version) do
    +  it "is a Version module" do
    +    expect(described_class).is_a?(Module)
    +    expect(described_class).to(have_version_constant)
    +    expect(described_class).to(have_version_as_string)
    +    expect(described_class.to_s).to(be_a(String))
    +    expect(described_class).to(have_major_as_integer)
    +    expect(described_class).to(have_epoch_as_integer)
    +    expect(described_class).to(have_minor_as_integer)
    +    expect(described_class).to(have_patch_as_integer)
    +    expect(described_class).to(have_pre_as_nil_or_string)
    +    # This would be %i[epoch major minor patch pre] for epoch version schemes
    +    expect(described_class.to_h.keys).to(match_array(%i[major minor patch pre]))
    +    expect(described_class.to_a).to(be_a(Array))
    +  end
    +end
    +
    +

    🦷 FLOSS Funding

    + +

    While ruby-oauth tools are free software and will always be, the project would benefit immensely from some funding.
    +Raising a monthly budget of… “dollars” would make the project more sustainable.

    + +

    We welcome both individual and corporate sponsors! We also offer a
    +wide array of funding channels to account for your preferences
    +(although currently Open Collective is our preferred funding platform).

    + +

    If you’re working in a company that’s making significant use of ruby-oauth tools we’d
    +appreciate it if you suggest to your company to become a ruby-oauth sponsor.

    + +

    You can support the development of ruby-oauth tools via
    +GitHub Sponsors,
    +Liberapay,
    +PayPal,
    +Open Collective
    +and Tidelift.

    + + + + + + + + + + + + +
    📍 NOTE
    If doing a sponsorship in the form of donation is problematic for your company
    from an accounting standpoint, we’d recommend the use of Tidelift,
    where you can get a support-like subscription instead.
    + +

    Open Collective for Individuals

    + + +

    No backers yet. Be the first!
    +

    + +

    Support us with a monthly donation and help us continue our activities. [Become a backer]

    + +

    Open Collective for Organizations

    + + +

    No sponsors yet. Be the first!
    +

    + +

    Become a sponsor and get your logo on our README on GitHub with a link to your site. [Become a sponsor]

    + +

    Another way to support open-source

    + +
    +

    How wonderful it is that nobody need wait a single moment before starting to improve the world.

    +—Anne Frank

    +
    + +

    I’m driven by a passion to foster a thriving open-source community – a space where people can tackle complex problems, no matter how small. Revitalizing libraries that have fallen into disrepair, and building new libraries focused on solving real-world challenges, are my passions — totaling 79 hours of FLOSS coding over just the past seven days, a pretty regular week for me. I was recently affected by layoffs, and the tech jobs market is unwelcoming. I’m reaching out here because your support would significantly aid my efforts to provide for my family, and my farm (11 🐔 chickens, 2 🐶 dogs, 3 🐰 rabbits, 8 🐈‍ cats).

    + +

    If you work at a company that uses my work, please encourage them to support me as a corporate sponsor. My work on gems you use might show up in bundle fund.

    + +

    I’m developing a new library, floss_funding, designed to empower open-source developers like myself to get paid for the work we do, in a sustainable way. Please give it a look.

    + +

    Floss-Funding.dev: 👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing. 💡 Easily disabled nags

    + +

    OpenCollective Backers OpenCollective Sponsors Sponsor Me on Github Liberapay Goal Progress Donate on PayPal Buy me a coffee Donate on Polar Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

    + +

    🔐 Security

    + +

    See SECURITY.md.

    + +

    🤝 Contributing

    + +

    If you need some ideas of where to help, you could work on adding more code coverage,
    +or if it is already 💯 (see below) check reek, issues, or PRs,
    +or use the gem and think about how it could be better.

    + +

    We Keep A Changelog so if you make changes, remember to update it.

    + +

    See CONTRIBUTING.md for more detailed instructions.

    + +

    🚀 Release Instructions

    + +

    See CONTRIBUTING.md.

    + +

    Code Coverage

    + +

    Coverage Graph

    + +

    Coveralls Test Coverage

    + +

    QLTY Test Coverage

    + +

    🪇 Code of Conduct

    + +

    Everyone interacting with this project’s codebases, issue trackers,
    +chat rooms and mailing lists agrees to follow the Contributor Covenant 2.1.

    + +

    🌈 Contributors

    + +

    Contributors

    + +

    Made with contributors-img.

    + +

    Also see GitLab Contributors: https://gitlab.com/ruby-oauth/version_gem/-/graphs/main

    + +
    + ⭐️ Star History + + + + + + Star History Chart + + + +
    + +

    📌 Versioning

    + +

    This Library adheres to Semantic Versioning 2.0.0.
    +Violations of this scheme should be reported as bugs.
    +Specifically, if a minor or patch version is released that breaks backward compatibility,
    +a new version should be immediately released that restores compatibility.
    +Breaking changes to the public API will only be introduced with new major versions.

    + +
    +

    dropping support for a platform is both obviously and objectively a breaking change

    +—Jordan Harband (@ljharb, maintainer of SemVer) in SemVer issue 716

    +
    + +

    I understand that policy doesn’t work universally (“exceptions to every rule!”),
    +but it is the policy here.
    +As such, in many cases it is good to specify a dependency on this library using
    +the Pessimistic Version Constraint with two digits of precision.

    + +

    For example:

    + +
    spec.add_dependency("version_gem", "~> 1.0")
    +
    + +
    +📌 Is "Platform Support" part of the public API? More details inside. + +SemVer should, IMO, but doesn't explicitly, say that dropping support for specific Platforms +is a *breaking change* to an API. +It is obvious to many, but not all, and since the spec is silent, the bike shedding is endless. + +To get a better understanding of how SemVer is intended to work over a project's lifetime, +read this article from the creator of SemVer: + +- ["Major Version Numbers are Not Sacred"][📌major-versions-not-sacred] + +
    + +

    See CHANGELOG.md for a list of releases.

    + +

    📄 License

    + +

    The gem is available as open source under the terms of
    +the MIT License License: MIT.
    +See LICENSE.txt for the official Copyright Notice.

    + + + + + +

    🤑 A request for help

    + +

    Maintainers have teeth and need to pay their dentists.
    +After getting laid off in an RIF in March and filled with many dozens of rejections,
    +I’m now spending ~60+ hours a week building open source tools.
    +I’m hoping to be able to pay for my kids’ health insurance this month,
    +so if you value the work I am doing, I need your support.
    +Please consider sponsoring me or the project.

    + +

    To join the community or get help 👇️ Join the Discord.

    + +

    Live Chat on Discord

    + +

    To say “thanks for maintaining such a great tool” ☝️ Join the Discord or 👇️ send money.

    + +

    Sponsor ruby-oauth/version_gem on Open Source Collective 💌 Sponsor me on GitHub Sponsors 💌 Sponsor me on Liberapay 💌 Donate on PayPal

    + +

    Please give the project a star ⭐ ♥.

    + +

    Thanks for RTFM. ☺️

    + +
    + + + +
    + + \ No newline at end of file diff --git a/docs/js/app.js b/docs/js/app.js new file mode 100644 index 0000000..b5610ef --- /dev/null +++ b/docs/js/app.js @@ -0,0 +1,344 @@ +(function () { + var localStorage = {}, + sessionStorage = {}; + try { + localStorage = window.localStorage; + } catch (e) {} + try { + sessionStorage = window.sessionStorage; + } catch (e) {} + + function createSourceLinks() { + $(".method_details_list .source_code").before( + "[View source]" + ); + $(".toggleSource").toggle( + function () { + $(this).parent().nextAll(".source_code").slideDown(100); + $(this).text("Hide source"); + }, + function () { + $(this).parent().nextAll(".source_code").slideUp(100); + $(this).text("View source"); + } + ); + } + + function createDefineLinks() { + var tHeight = 0; + $(".defines").after(" more..."); + $(".toggleDefines").toggle( + function () { + tHeight = $(this).parent().prev().height(); + $(this).prev().css("display", "inline"); + $(this).parent().prev().height($(this).parent().height()); + $(this).text("(less)"); + }, + function () { + $(this).prev().hide(); + $(this).parent().prev().height(tHeight); + $(this).text("more..."); + } + ); + } + + function createFullTreeLinks() { + var tHeight = 0; + $(".inheritanceTree").toggle( + function () { + tHeight = $(this).parent().prev().height(); + $(this).parent().toggleClass("showAll"); + $(this).text("(hide)"); + $(this).parent().prev().height($(this).parent().height()); + }, + function () { + $(this).parent().toggleClass("showAll"); + $(this).parent().prev().height(tHeight); + $(this).text("show all"); + } + ); + } + + function searchFrameButtons() { + $(".full_list_link").click(function () { + toggleSearchFrame(this, $(this).attr("href")); + return false; + }); + window.addEventListener("message", function (e) { + if (e.data === "navEscape") { + $("#nav").slideUp(100); + $("#search a").removeClass("active inactive"); + $(window).focus(); + } + }); + + $(window).resize(function () { + if ($("#search:visible").length === 0) { + $("#nav").removeAttr("style"); + $("#search a").removeClass("active inactive"); + $(window).focus(); + } + }); + } + + function toggleSearchFrame(id, link) { + var frame = $("#nav"); + $("#search a").removeClass("active").addClass("inactive"); + if (frame.attr("src") === link && frame.css("display") !== "none") { + frame.slideUp(100); + $("#search a").removeClass("active inactive"); + } else { + $(id).addClass("active").removeClass("inactive"); + if (frame.attr("src") !== link) frame.attr("src", link); + frame.slideDown(100); + } + } + + function linkSummaries() { + $(".summary_signature").click(function () { + document.location = $(this).find("a").attr("href"); + }); + } + + function summaryToggle() { + $(".summary_toggle").click(function (e) { + e.preventDefault(); + localStorage.summaryCollapsed = $(this).text(); + $(".summary_toggle").each(function () { + $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); + var next = $(this).parent().parent().nextAll("ul.summary").first(); + if (next.hasClass("compact")) { + next.toggle(); + next.nextAll("ul.summary").first().toggle(); + } else if (next.hasClass("summary")) { + var list = $('
      '); + list.html(next.html()); + list.find(".summary_desc, .note").remove(); + list.find("a").each(function () { + $(this).html($(this).find("strong").html()); + $(this).parent().html($(this)[0].outerHTML); + }); + next.before(list); + next.toggle(); + } + }); + return false; + }); + if (localStorage.summaryCollapsed == "collapse") { + $(".summary_toggle").first().click(); + } else { + localStorage.summaryCollapsed = "expand"; + } + } + + function constantSummaryToggle() { + $(".constants_summary_toggle").click(function (e) { + e.preventDefault(); + localStorage.summaryCollapsed = $(this).text(); + $(".constants_summary_toggle").each(function () { + $(this).text($(this).text() == "collapse" ? "expand" : "collapse"); + var next = $(this).parent().parent().nextAll("dl.constants").first(); + if (next.hasClass("compact")) { + next.toggle(); + next.nextAll("dl.constants").first().toggle(); + } else if (next.hasClass("constants")) { + var list = $('
      '); + list.html(next.html()); + list.find("dt").each(function () { + $(this).addClass("summary_signature"); + $(this).text($(this).text().split("=")[0]); + if ($(this).has(".deprecated").length) { + $(this).addClass("deprecated"); + } + }); + // Add the value of the constant as "Tooltip" to the summary object + list.find("pre.code").each(function () { + console.log($(this).parent()); + var dt_element = $(this).parent().prev(); + var tooltip = $(this).text(); + if (dt_element.hasClass("deprecated")) { + tooltip = "Deprecated. " + tooltip; + } + dt_element.attr("title", tooltip); + }); + list.find(".docstring, .tags, dd").remove(); + next.before(list); + next.toggle(); + } + }); + return false; + }); + if (localStorage.summaryCollapsed == "collapse") { + $(".constants_summary_toggle").first().click(); + } else { + localStorage.summaryCollapsed = "expand"; + } + } + + function generateTOC() { + if ($("#filecontents").length === 0) return; + var _toc = $('
        '); + var show = false; + var toc = _toc; + var counter = 0; + var tags = ["h2", "h3", "h4", "h5", "h6"]; + var i; + var curli; + if ($("#filecontents h1").length > 1) tags.unshift("h1"); + for (i = 0; i < tags.length; i++) { + tags[i] = "#filecontents " + tags[i]; + } + var lastTag = parseInt(tags[0][1], 10); + $(tags.join(", ")).each(function () { + if ($(this).parents(".method_details .docstring").length != 0) return; + if (this.id == "filecontents") return; + show = true; + var thisTag = parseInt(this.tagName[1], 10); + if (this.id.length === 0) { + var proposedId = $(this).attr("toc-id"); + if (typeof proposedId != "undefined") this.id = proposedId; + else { + var proposedId = $(this) + .text() + .replace(/[^a-z0-9-]/gi, "_"); + if ($("#" + proposedId).length > 0) { + proposedId += counter; + counter++; + } + this.id = proposedId; + } + } + if (thisTag > lastTag) { + for (i = 0; i < thisTag - lastTag; i++) { + if (typeof curli == "undefined") { + curli = $("
      1. "); + toc.append(curli); + } + toc = $("
          "); + curli.append(toc); + curli = undefined; + } + } + if (thisTag < lastTag) { + for (i = 0; i < lastTag - thisTag; i++) { + toc = toc.parent(); + toc = toc.parent(); + } + } + var title = $(this).attr("toc-title"); + if (typeof title == "undefined") title = $(this).text(); + curli = $('
        1. ' + title + "
        2. "); + toc.append(curli); + lastTag = thisTag; + }); + if (!show) return; + html = + ''; + $("#content").prepend(html); + $("#toc").append(_toc); + $("#toc .hide_toc").toggle( + function () { + $("#toc .top").slideUp("fast"); + $("#toc").toggleClass("hidden"); + $("#toc .title small").toggle(); + }, + function () { + $("#toc .top").slideDown("fast"); + $("#toc").toggleClass("hidden"); + $("#toc .title small").toggle(); + } + ); + } + + function navResizeFn(e) { + if (e.which !== 1) { + navResizeFnStop(); + return; + } + + sessionStorage.navWidth = e.pageX.toString(); + $(".nav_wrap").css("width", e.pageX); + $(".nav_wrap").css("-ms-flex", "inherit"); + } + + function navResizeFnStop() { + $(window).unbind("mousemove", navResizeFn); + window.removeEventListener("message", navMessageFn, false); + } + + function navMessageFn(e) { + if (e.data.action === "mousemove") navResizeFn(e.data.event); + if (e.data.action === "mouseup") navResizeFnStop(); + } + + function navResizer() { + $("#resizer").mousedown(function (e) { + e.preventDefault(); + $(window).mousemove(navResizeFn); + window.addEventListener("message", navMessageFn, false); + }); + $(window).mouseup(navResizeFnStop); + + if (sessionStorage.navWidth) { + navResizeFn({ which: 1, pageX: parseInt(sessionStorage.navWidth, 10) }); + } + } + + function navExpander() { + if (typeof pathId === "undefined") return; + var done = false, + timer = setTimeout(postMessage, 500); + function postMessage() { + if (done) return; + clearTimeout(timer); + var opts = { action: "expand", path: pathId }; + document.getElementById("nav").contentWindow.postMessage(opts, "*"); + done = true; + } + + window.addEventListener( + "message", + function (event) { + if (event.data === "navReady") postMessage(); + return false; + }, + false + ); + } + + function mainFocus() { + var hash = window.location.hash; + if (hash !== "" && $(hash)[0]) { + $(hash)[0].scrollIntoView(); + } + + setTimeout(function () { + $("#main").focus(); + }, 10); + } + + function navigationChange() { + // This works around the broken anchor navigation with the YARD template. + window.onpopstate = function () { + var hash = window.location.hash; + if (hash !== "" && $(hash)[0]) { + $(hash)[0].scrollIntoView(); + } + }; + } + + $(document).ready(function () { + navResizer(); + navExpander(); + createSourceLinks(); + createDefineLinks(); + createFullTreeLinks(); + searchFrameButtons(); + linkSummaries(); + summaryToggle(); + constantSummaryToggle(); + generateTOC(); + mainFocus(); + navigationChange(); + }); +})(); diff --git a/docs/js/full_list.js b/docs/js/full_list.js new file mode 100644 index 0000000..12bba48 --- /dev/null +++ b/docs/js/full_list.js @@ -0,0 +1,242 @@ +(function() { + +var $clicked = $(null); +var searchTimeout = null; +var searchCache = []; +var caseSensitiveMatch = false; +var ignoreKeyCodeMin = 8; +var ignoreKeyCodeMax = 46; +var commandKey = 91; + +RegExp.escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); +} + +function escapeShortcut() { + $(document).keydown(function(evt) { + if (evt.which == 27) { + window.parent.postMessage('navEscape', '*'); + } + }); +} + +function navResizer() { + $(window).mousemove(function(e) { + window.parent.postMessage({ + action: 'mousemove', event: {pageX: e.pageX, which: e.which} + }, '*'); + }).mouseup(function(e) { + window.parent.postMessage({action: 'mouseup'}, '*'); + }); + window.parent.postMessage("navReady", "*"); +} + +function clearSearchTimeout() { + clearTimeout(searchTimeout); + searchTimeout = null; +} + +function enableLinks() { + // load the target page in the parent window + $('#full_list li').on('click', function(evt) { + $('#full_list li').removeClass('clicked'); + $clicked = $(this); + $clicked.addClass('clicked'); + evt.stopPropagation(); + + if (evt.target.tagName === 'A') return true; + + var elem = $clicked.find('> .item .object_link a')[0]; + var e = evt.originalEvent; + var newEvent = new MouseEvent(evt.originalEvent.type); + newEvent.initMouseEvent(e.type, e.canBubble, e.cancelable, e.view, e.detail, e.screenX, e.screenY, e.clientX, e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.button, e.relatedTarget); + elem.dispatchEvent(newEvent); + evt.preventDefault(); + return false; + }); +} + +function enableToggles() { + // show/hide nested classes on toggle click + $('#full_list a.toggle').on('click', function(evt) { + evt.stopPropagation(); + evt.preventDefault(); + $(this).parent().parent().toggleClass('collapsed'); + $(this).attr('aria-expanded', function (i, attr) { + return attr == 'true' ? 'false' : 'true' + }); + highlight(); + }); + + // navigation of nested classes using keyboard + $('#full_list a.toggle').on('keypress',function(evt) { + // enter key is pressed + if (evt.which == 13) { + evt.stopPropagation(); + evt.preventDefault(); + $(this).parent().parent().toggleClass('collapsed'); + $(this).attr('aria-expanded', function (i, attr) { + return attr == 'true' ? 'false' : 'true' + }); + highlight(); + } + }); +} + +function populateSearchCache() { + $('#full_list li .item').each(function() { + var $node = $(this); + var $link = $node.find('.object_link a'); + if ($link.length > 0) { + searchCache.push({ + node: $node, + link: $link, + name: $link.text(), + fullName: $link.attr('title').split(' ')[0] + }); + } + }); +} + +function enableSearch() { + $('#search input').keyup(function(event) { + if (ignoredKeyPress(event)) return; + if (this.value === "") { + clearSearch(); + } else { + performSearch(this.value); + } + }); + + $('#full_list').after(""); +} + +function ignoredKeyPress(event) { + if ( + (event.keyCode > ignoreKeyCodeMin && event.keyCode < ignoreKeyCodeMax) || + (event.keyCode == commandKey) + ) { + return true; + } else { + return false; + } +} + +function clearSearch() { + clearSearchTimeout(); + $('#full_list .found').removeClass('found').each(function() { + var $link = $(this).find('.object_link a'); + $link.text($link.text()); + }); + $('#full_list, #content').removeClass('insearch'); + $clicked.parents().removeClass('collapsed'); + highlight(); +} + +function performSearch(searchString) { + clearSearchTimeout(); + $('#full_list, #content').addClass('insearch'); + $('#noresults').text('').hide(); + partialSearch(searchString, 0); +} + +function partialSearch(searchString, offset) { + var lastRowClass = ''; + var i = null; + for (i = offset; i < Math.min(offset + 50, searchCache.length); i++) { + var item = searchCache[i]; + var searchName = (searchString.indexOf('::') != -1 ? item.fullName : item.name); + var matchString = buildMatchString(searchString); + var matchRegexp = new RegExp(matchString, caseSensitiveMatch ? "" : "i"); + if (searchName.match(matchRegexp) == null) { + item.node.removeClass('found'); + item.link.text(item.link.text()); + } + else { + item.node.addClass('found'); + item.node.removeClass(lastRowClass).addClass(lastRowClass == 'r1' ? 'r2' : 'r1'); + lastRowClass = item.node.hasClass('r1') ? 'r1' : 'r2'; + item.link.html(item.name.replace(matchRegexp, "$&")); + } + } + if(i == searchCache.length) { + searchDone(); + } else { + searchTimeout = setTimeout(function() { + partialSearch(searchString, i); + }, 0); + } +} + +function searchDone() { + searchTimeout = null; + highlight(); + var found = $('#full_list li:visible').size(); + if (found === 0) { + $('#noresults').text('No results were found.'); + } else { + // This is read out to screen readers + $('#noresults').text('There are ' + found + ' results.'); + } + $('#noresults').show(); + $('#content').removeClass('insearch'); +} + +function buildMatchString(searchString, event) { + caseSensitiveMatch = searchString.match(/[A-Z]/) != null; + var regexSearchString = RegExp.escape(searchString); + if (caseSensitiveMatch) { + regexSearchString += "|" + + $.map(searchString.split(''), function(e) { return RegExp.escape(e); }). + join('.+?'); + } + return regexSearchString; +} + +function highlight() { + $('#full_list li:visible').each(function(n) { + $(this).removeClass('even odd').addClass(n % 2 == 0 ? 'odd' : 'even'); + }); +} + +/** + * Expands the tree to the target element and its immediate + * children. + */ +function expandTo(path) { + var $target = $(document.getElementById('object_' + path)); + $target.addClass('clicked'); + $target.removeClass('collapsed'); + $target.parentsUntil('#full_list', 'li').removeClass('collapsed'); + + $target.find('a.toggle').attr('aria-expanded', 'true') + $target.parentsUntil('#full_list', 'li').each(function(i, el) { + $(el).find('> div > a.toggle').attr('aria-expanded', 'true'); + }); + + if($target[0]) { + window.scrollTo(window.scrollX, $target.offset().top - 250); + highlight(); + } +} + +function windowEvents(event) { + var msg = event.data; + if (msg.action === "expand") { + expandTo(msg.path); + } + return false; +} + +window.addEventListener("message", windowEvents, false); + +$(document).ready(function() { + escapeShortcut(); + navResizer(); + enableLinks(); + enableToggles(); + populateSearchCache(); + enableSearch(); +}); + +})(); diff --git a/docs/js/jquery.js b/docs/js/jquery.js new file mode 100644 index 0000000..198b3ff --- /dev/null +++ b/docs/js/jquery.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
          a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
          "+""+"
          ",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
          t
          ",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
          ",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

          ";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
          ";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
          ","
          "],thead:[1,"","
          "],tr:[2,"","
          "],td:[3,"","
          "],col:[2,"","
          "],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
          ","
          "]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
          ").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/docs/method_list.html b/docs/method_list.html new file mode 100644 index 0000000..a89d552 --- /dev/null +++ b/docs/method_list.html @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + Method List + + + +
          +
          +

          Method List

          + + + +
          + +
            + + +
          • +
            + actual_minor_version? + VersionGem::Ruby +
            +
          • + + +
          • +
            + #epoch + VersionGem::Epoch::OverloadApiForEpoch +
            +
          • + + +
          • +
            + extended + VersionGem::Basic +
            +
          • + + +
          • +
            + extended + VersionGem::Epoch +
            +
          • + + +
          • +
            + gte_minimum_version? + VersionGem::Ruby +
            +
          • + + +
          • +
            + #major + VersionGem::Api +
            +
          • + + +
          • +
            + #major + VersionGem::Epoch::OverloadApiForEpoch +
            +
          • + + +
          • +
            + #minor + VersionGem::Api +
            +
          • + + +
          • +
            + #patch + VersionGem::Api +
            +
          • + + +
          • +
            + #pre + VersionGem::Api +
            +
          • + + +
          • +
            + #to_a + VersionGem::Api +
            +
          • + + +
          • +
            + #to_a + VersionGem::Epoch::OverloadApiForEpoch +
            +
          • + + +
          • +
            + #to_h + VersionGem::Api +
            +
          • + + +
          • +
            + #to_h + VersionGem::Epoch::OverloadApiForEpoch +
            +
          • + + +
          • +
            + #to_s + VersionGem::Api +
            +
          • + + + +
          +
          + + diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html new file mode 100644 index 0000000..81ea99c --- /dev/null +++ b/docs/top-level-namespace.html @@ -0,0 +1,110 @@ + + + + + + + Top Level Namespace + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
          + + +

          Top Level Namespace + + + +

          +
          + + + + + + + + + + + +
          + +

          Defined Under Namespace

          +

          + + + Modules: VersionGem + + + + +

          + + + + + + + + + +
          + + + +
          + + \ No newline at end of file From 28ddc2dea46bd8c7507eacbbcddea83b710e2465 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 02:57:40 -0600 Subject: [PATCH 11/29] =?UTF-8?q?=F0=9F=9A=A8=20Linting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .rubocop_gradual.lock | 3 --- REEK | 1 - 2 files changed, 4 deletions(-) diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock index 5b59ae6..c5ecc01 100644 --- a/.rubocop_gradual.lock +++ b/.rubocop_gradual.lock @@ -1,8 +1,5 @@ { "bin/bundle:4041706560": [ [67, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] - ], - "version_gem.gemspec:2595774114": [ - [4, 6, 12, "Gemspec/RubyVersionGlobalsUsage: Do not use `RUBY_VERSION` in gemspec file.", 31296028] ] } diff --git a/REEK b/REEK index a33f1c1..e69de29 100644 --- a/REEK +++ b/REEK @@ -1 +0,0 @@ -0 total warnings From 1712ebf7abff0f48707e181d0194dcaf0831f94a Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 03:03:37 -0600 Subject: [PATCH 12/29] =?UTF-8?q?=F0=9F=93=9D=20CHANGELOG.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84139d3..fd9b4a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,10 @@ Please file a bug if you notice a violation of semantic versioning. ## [Unreleased] ### Added +- re-templated gem using kettle-dev + - new binstubs for changelog, readme, commit message, & release management + - new CI workflows + - enhanced project documentation - More RBS types - docs site: https://version-gem.galtzo.com ### Changed From c06ee5b23773613ecc7c4be8af5b66c59eb72595 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 03:19:33 -0600 Subject: [PATCH 13/29] =?UTF-8?q?=F0=9F=91=B7=20appraisal2=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gemfiles/audit.gemfile | 4 +--- gemfiles/coverage.gemfile | 4 +++- gemfiles/current.gemfile | 2 +- gemfiles/head.gemfile | 3 ++- gemfiles/ruby_2_3.gemfile | 2 +- gemfiles/ruby_2_4.gemfile | 2 +- gemfiles/ruby_2_5.gemfile | 2 +- gemfiles/ruby_2_6.gemfile | 2 +- gemfiles/ruby_2_7.gemfile | 2 +- gemfiles/ruby_3_0.gemfile | 2 +- gemfiles/ruby_3_1.gemfile | 2 +- gemfiles/ruby_3_2.gemfile | 2 +- gemfiles/ruby_3_3.gemfile | 2 +- gemfiles/style.gemfile | 2 +- gemfiles/unlocked_deps.gemfile | 13 +++++++++++++ 15 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 gemfiles/unlocked_deps.gemfile diff --git a/gemfiles/audit.gemfile b/gemfiles/audit.gemfile index b93d318..bbf20a8 100644 --- a/gemfiles/audit.gemfile +++ b/gemfiles/audit.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" @@ -6,5 +6,3 @@ gem "mutex_m", "~> 0.2" gem "stringio", "~> 3.0" gemspec path: "../" - -eval_gemfile("modular/audit.gemfile") diff --git a/gemfiles/coverage.gemfile b/gemfiles/coverage.gemfile index ec3037b..263e4d3 100644 --- a/gemfiles/coverage.gemfile +++ b/gemfiles/coverage.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" @@ -8,3 +8,5 @@ gem "stringio", "~> 3.0" gemspec path: "../" eval_gemfile("modular/coverage.gemfile") + +eval_gemfile("modular/optional.gemfile") diff --git a/gemfiles/current.gemfile b/gemfiles/current.gemfile index 49b0671..8e8e7e8 100644 --- a/gemfiles/current.gemfile +++ b/gemfiles/current.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/head.gemfile b/gemfiles/head.gemfile index 49b0671..2842673 100644 --- a/gemfiles/head.gemfile +++ b/gemfiles/head.gemfile @@ -1,8 +1,9 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" gem "mutex_m", ">= 0.2" gem "stringio", ">= 3.0" +gem "benchmark", "~> 0.4", ">= 0.4.1" gemspec path: "../" diff --git a/gemfiles/ruby_2_3.gemfile b/gemfiles/ruby_2_3.gemfile index 095e660..0ac28b9 100644 --- a/gemfiles/ruby_2_3.gemfile +++ b/gemfiles/ruby_2_3.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_2_4.gemfile b/gemfiles/ruby_2_4.gemfile index 095e660..0ac28b9 100644 --- a/gemfiles/ruby_2_4.gemfile +++ b/gemfiles/ruby_2_4.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_2_5.gemfile b/gemfiles/ruby_2_5.gemfile index 095e660..0ac28b9 100644 --- a/gemfiles/ruby_2_5.gemfile +++ b/gemfiles/ruby_2_5.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_2_6.gemfile b/gemfiles/ruby_2_6.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_2_6.gemfile +++ b/gemfiles/ruby_2_6.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_2_7.gemfile b/gemfiles/ruby_2_7.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_2_7.gemfile +++ b/gemfiles/ruby_2_7.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_3_0.gemfile b/gemfiles/ruby_3_0.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_3_0.gemfile +++ b/gemfiles/ruby_3_0.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_3_1.gemfile b/gemfiles/ruby_3_1.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_3_1.gemfile +++ b/gemfiles/ruby_3_1.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_3_2.gemfile b/gemfiles/ruby_3_2.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_3_2.gemfile +++ b/gemfiles/ruby_3_2.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/ruby_3_3.gemfile b/gemfiles/ruby_3_3.gemfile index ed1eb63..bbf20a8 100644 --- a/gemfiles/ruby_3_3.gemfile +++ b/gemfiles/ruby_3_3.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/style.gemfile b/gemfiles/style.gemfile index f75762c..bd9f436 100644 --- a/gemfiles/style.gemfile +++ b/gemfiles/style.gemfile @@ -1,4 +1,4 @@ -# This file was generated by Appraisal +# This file was generated by Appraisal2 source "https://rubygems.org" diff --git a/gemfiles/unlocked_deps.gemfile b/gemfiles/unlocked_deps.gemfile new file mode 100644 index 0000000..dd71998 --- /dev/null +++ b/gemfiles/unlocked_deps.gemfile @@ -0,0 +1,13 @@ +# This file was generated by Appraisal2 + +source "https://rubygems.org" + +gemspec path: "../" + +eval_gemfile("modular/coverage.gemfile") + +eval_gemfile("modular/documentation.gemfile") + +eval_gemfile("modular/style.gemfile") + +eval_gemfile("modular/optional.gemfile") From 8fad16848f2cf25c4e8ead264d19de19d65f390d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 14:29:36 -0600 Subject: [PATCH 14/29] =?UTF-8?q?=F0=9F=94=A5=20Remove=20unused=20appraisa?= =?UTF-8?q?l=20gemfile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gemfiles/ruby_2_2.gemfile | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 gemfiles/ruby_2_2.gemfile diff --git a/gemfiles/ruby_2_2.gemfile b/gemfiles/ruby_2_2.gemfile deleted file mode 100644 index 095e660..0000000 --- a/gemfiles/ruby_2_2.gemfile +++ /dev/null @@ -1,5 +0,0 @@ -# This file was generated by Appraisal - -source "https://rubygems.org" - -gemspec path: "../" From 5f47199f4f22c136447ffca0a58008a94bf0dc33 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 14:30:09 -0600 Subject: [PATCH 15/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.0.27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/version_gem.iml | 4 ++-- Gemfile.lock | 7 +++---- version_gem.gemspec | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml index 6954010..baf0708 100644 --- a/.idea/version_gem.iml +++ b/.idea/version_gem.iml @@ -40,7 +40,7 @@ - + @@ -86,7 +86,7 @@ - + diff --git a/Gemfile.lock b/Gemfile.lock index 9f49bcf..25b2c99 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.0.26) + kettle-dev (1.0.27) appraisal2 (~> 3.0) bundler-audit (~> 0.9.2) gitmoji-regex (~> 1.0, >= 1.0.3) @@ -92,7 +92,6 @@ GEM rspec-pending_for ruby-progressbar (~> 1.13) stone_checksums (~> 1.0, >= 1.0.2) - version_gem (~> 1.1, >= 1.1.8) kettle-soup-cover (1.0.10) simplecov (~> 0.22) simplecov-cobertura (~> 3.0) @@ -222,7 +221,7 @@ GEM rubocop-rake (0.7.1) lint_roller (~> 1.1) rubocop (>= 1.72.1) - rubocop-rspec (3.6.0) + rubocop-rspec (3.7.0) lint_roller (~> 1.1) rubocop (~> 1.72, >= 1.72.1) rubocop-ruby2_2 (2.0.5) @@ -309,7 +308,7 @@ DEPENDENCIES benchmark (~> 0.4, >= 0.4.1) debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) - kettle-dev (~> 1.0, >= 1.0.26) + kettle-dev (~> 1.0, >= 1.0.27) kettle-soup-cover (~> 1.0, >= 1.0.10) kramdown (~> 2.5, >= 2.5.1) kramdown-parser-gfm (~> 1.1) diff --git a/version_gem.gemspec b/version_gem.gemspec index d788b06..99c5a73 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,5 +112,5 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.26") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.27") # ruby >= 2.3.0 end From 6ef6cc720ad4fa9f4a3b66e9b99b417f578ebf5b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Mon, 1 Sep 2025 18:46:00 -0600 Subject: [PATCH 16/29] =?UTF-8?q?=F0=9F=8E=A8=20Template=20bootstrap=20by?= =?UTF-8?q?=20kettle-dev-setup=20v1.0.27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 9 +++++++++ Rakefile | 2 +- bin/kettle-dev-setup | 16 ++++++++++++++++ bin/kramdown | 16 ++++++++++++++++ bin/nokogiri | 16 ++++++++++++++++ bin/rbs | 16 ++++++++++++++++ version_gem.gemspec | 24 ++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 bin/kettle-dev-setup create mode 100644 bin/kramdown create mode 100644 bin/nokogiri create mode 100644 bin/rbs diff --git a/Gemfile.lock b/Gemfile.lock index 25b2c99..31fddd0 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -305,22 +305,31 @@ PLATFORMS x86_64-linux DEPENDENCIES + appraisal2 (~> 3.0) benchmark (~> 0.4, >= 0.4.1) + bundler-audit (~> 0.9.2) debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) + gitmoji-regex (~> 1.0, >= 1.0.3) kettle-dev (~> 1.0, >= 1.0.27) kettle-soup-cover (~> 1.0, >= 1.0.10) + kettle-test (~> 1.0) kramdown (~> 2.5, >= 2.5.1) kramdown-parser-gfm (~> 1.1) pry (~> 0.14) + rake (~> 13.0) rdoc (~> 6.11) reek (~> 6.5) + require_bench (~> 1.0, >= 1.0.4) + rspec-pending_for rubocop-lts (~> 8.0) rubocop-on-rbs (~> 1.8) rubocop-packaging (~> 0.6, >= 0.6.0) rubocop-rspec (~> 3.6) rubocop-ruby2_2 + ruby-progressbar (~> 1.13) standard (>= 1.50) + stone_checksums (~> 1.0, >= 1.0.2) version_gem! yard (~> 0.9, >= 0.9.37) yard-junk (~> 0.0, >= 0.0.10)! diff --git a/Rakefile b/Rakefile index e225475..0f97a18 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ # frozen_string_literal: true -# kettle-dev Rakefile v1.0.25 - 2025-08-31 +# kettle-dev Rakefile v1.0.27 - 2025-09-01 # Ruby 2.3 (Safe Navigation) or higher required # # MIT License (see License.txt) diff --git a/bin/kettle-dev-setup b/bin/kettle-dev-setup new file mode 100644 index 0000000..276319a --- /dev/null +++ b/bin/kettle-dev-setup @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-dev-setup' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-dev-setup") diff --git a/bin/kramdown b/bin/kramdown new file mode 100644 index 0000000..547fd06 --- /dev/null +++ b/bin/kramdown @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kramdown' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kramdown", "kramdown") diff --git a/bin/nokogiri b/bin/nokogiri new file mode 100644 index 0000000..8b72331 --- /dev/null +++ b/bin/nokogiri @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'nokogiri' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("nokogiri", "nokogiri") diff --git a/bin/rbs b/bin/rbs new file mode 100644 index 0000000..ffc95a0 --- /dev/null +++ b/bin/rbs @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'rbs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("rbs", "rbs") diff --git a/version_gem.gemspec b/version_gem.gemspec index 99c5a73..3f1d30d 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -113,4 +113,28 @@ Gem::Specification.new do |spec| # Dev, Test, & Release Tasks spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.27") # ruby >= 2.3.0 + spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 + + spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0 + + spec.add_development_dependency("require_bench", "~> 1.0", ">= 1.0.4") # ruby >= 2.2.0 + + spec.add_development_dependency("appraisal2", "~> 3.0") # ruby >= 1.8.7, for testing against multiple versions of dependencies + + spec.add_development_dependency("kettle-test", "~> 1.0") # ruby >= 2.3 + + spec.add_development_dependency("rspec-pending_for") # ruby >= 2.3, used to skip specs on incompatible Rubies + + spec.add_development_dependency("ruby-progressbar", "~> 1.13") # ruby >= 0 + + spec.add_development_dependency("stone_checksums", "~> 1.0", ">= 1.0.2") # ruby >= 2.2.0 + + # spec.add_development_dependency("erb", ">= 2.2") # ruby >= 2.3.0, not SemVer, old rubies get dropped in a patch. + + spec.add_development_dependency("gitmoji-regex", "~> 1.0", ">= 1.0.3") # ruby >= 2.3.0 + + # spec.add_development_dependency("vcr", ">= 4") # 6.0 claims to support ruby >= 2.3, but fails on ruby 2.4 + + # spec.add_development_dependency("webmock", ">= 3") # Last version to support ruby >= 2.3 + end From 50a861ff813df920ce3fa242162da68a58100e19 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 00:32:01 -0600 Subject: [PATCH 17/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 12 ++---------- version_gem.gemspec | 2 +- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 31fddd0..67cd1a4 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,16 +82,8 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.0.27) - appraisal2 (~> 3.0) - bundler-audit (~> 0.9.2) - gitmoji-regex (~> 1.0, >= 1.0.3) - kettle-test (~> 1.0) + kettle-dev (1.1.0) rake (~> 13.0) - require_bench (~> 1.0, >= 1.0.4) - rspec-pending_for - ruby-progressbar (~> 1.13) - stone_checksums (~> 1.0, >= 1.0.2) kettle-soup-cover (1.0.10) simplecov (~> 0.22) simplecov-cobertura (~> 3.0) @@ -311,7 +303,7 @@ DEPENDENCIES debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) gitmoji-regex (~> 1.0, >= 1.0.3) - kettle-dev (~> 1.0, >= 1.0.27) + kettle-dev (~> 1.0, >= 1.1) kettle-soup-cover (~> 1.0, >= 1.0.10) kettle-test (~> 1.0) kramdown (~> 2.5, >= 2.5.1) diff --git a/version_gem.gemspec b/version_gem.gemspec index 3f1d30d..b1ec21a 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,7 +112,7 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.0.27") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.1") # ruby >= 2.3.0 spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0 From d17bbdbacb9e0e2c8cd78346005b68ff9e579f51 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 00:32:13 -0600 Subject: [PATCH 18/29] =?UTF-8?q?=F0=9F=8E=A8=20Template=20bootstrap=20by?= =?UTF-8?q?=20kettle-dev-setup=20v1.1.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 0f97a18..3dd71b0 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ # frozen_string_literal: true -# kettle-dev Rakefile v1.0.27 - 2025-09-01 +# kettle-dev Rakefile v1.1.0 - 2025-09-02 # Ruby 2.3 (Safe Navigation) or higher required # # MIT License (see License.txt) From 570266b0a9ef98492d1cd21cba91591b79fa842b Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 01:37:30 -0600 Subject: [PATCH 19/29] =?UTF-8?q?=F0=9F=93=9D=20Heading=20levels=20alignme?= =?UTF-8?q?nt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 65bb416..f815327 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ This library was extracted from the gem _[oauth2](https://gitlab.com/oauth-xx/oa This gem has no runtime dependencies. -## 🧐 Alternatives +### 🧐 Alternatives This gem has a very niche purpose, which is: @@ -240,7 +240,7 @@ end Your `version.rb` file now abides the Ruby convention of directory / path matching the namespace / class! -## Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7) +### Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7) In the standard `bundle gem my_lib` code you get the following in `lib/my_lib/version.rb`: From 3819831b35887cb158b3166ace691c5a5751b009 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 01:37:59 -0600 Subject: [PATCH 20/29] =?UTF-8?q?=F0=9F=94=A7=20Simplecov=20config?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .simplecov | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.simplecov b/.simplecov index af5bd1c..9fafdfe 100644 --- a/.simplecov +++ b/.simplecov @@ -4,4 +4,8 @@ require "kettle/soup/cover/config" # It is controlled by ENV variables, which are set in .envrc and loaded via `direnv allow` # If the values for minimum coverage need to change, they should be changed both there, # and in 2 places in .github/workflows/coverage.yml. -SimpleCov.start +SimpleCov.start do + track_files "lib/**/*.rb" + track_files "lib/**/*.rake" + track_files "exe/*.rb" +end From 31cbc36fecbf2e29f2804972b9be8527e2fd6c81 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 01:47:39 -0600 Subject: [PATCH 21/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/version_gem.iml | 2 +- Gemfile.lock | 4 ++-- version_gem.gemspec | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml index baf0708..2defb7f 100644 --- a/.idea/version_gem.iml +++ b/.idea/version_gem.iml @@ -40,7 +40,7 @@ - + diff --git a/Gemfile.lock b/Gemfile.lock index 67cd1a4..15f6d0f 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.1.0) + kettle-dev (1.1.1) rake (~> 13.0) kettle-soup-cover (1.0.10) simplecov (~> 0.22) @@ -303,7 +303,7 @@ DEPENDENCIES debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) gitmoji-regex (~> 1.0, >= 1.0.3) - kettle-dev (~> 1.0, >= 1.1) + kettle-dev (~> 1.1, >= 1.1.1) kettle-soup-cover (~> 1.0, >= 1.0.10) kettle-test (~> 1.0) kramdown (~> 2.5, >= 2.5.1) diff --git a/version_gem.gemspec b/version_gem.gemspec index b1ec21a..f1b3238 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,7 +112,7 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.0", ">= 1.1") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.1") # ruby >= 2.3.0 spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0 From 727343c3c9d6a74688a29d056154082c5b2eee43 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 01:47:46 -0600 Subject: [PATCH 22/29] =?UTF-8?q?=F0=9F=8E=A8=20Template=20bootstrap=20by?= =?UTF-8?q?=20kettle-dev-setup=20v1.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index 3dd71b0..002f728 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ # frozen_string_literal: true -# kettle-dev Rakefile v1.1.0 - 2025-09-02 +# kettle-dev Rakefile v1.1.1 - 2025-09-02 # Ruby 2.3 (Safe Navigation) or higher required # # MIT License (see License.txt) From 11c49f7d8d776756d6095e1bbb98267005d20bb9 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 02:05:04 -0600 Subject: [PATCH 23/29] =?UTF-8?q?=F0=9F=8E=A8=20Updated=20gem=20template?= =?UTF-8?q?=20w/=20kettle-dev=20v1.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 53 +++++++++++++++++++++++++++++++++++++-------- CHANGELOG.md | 52 ++++++++++++++++++++++---------------------- CONTRIBUTING.md | 6 ++--- version_gem.gemspec | 34 ++++++++++++++++++++++++----- 4 files changed, 101 insertions(+), 44 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 67c1b3b..a324e16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,28 +12,63 @@ #include: # - template: Security/SAST.gitlab-ci.yml +default: + image: ruby + variables: + BUNDLE_INSTALL_FLAGS: "--quiet --jobs=$(nproc) --retry=3" + BUNDLE_FROZEN: "false" # No lockfile! + BUNDLE_GEMFILE: Appraisal.root.gemfile K_SOUP_COV_DEBUG: true K_SOUP_COV_DO: true K_SOUP_COV_HARD: true K_SOUP_COV_MIN_BRANCH: 100 K_SOUP_COV_MIN_LINE: 100 K_SOUP_COV_VERBOSE: true - K_SOUP_COV_FORMATTERS: "html,rcov,lcov,json,tty" + K_SOUP_COV_FORMATTERS: "tty" K_SOUP_COV_MULTI_FORMATTERS: true K_SOUP_COV_COMMAND_NAME: "RSpec Coverage" -default: - image: ruby:3.4.3 +workflow: + rules: + # For merge requests, create a pipeline. + - if: '$CI_MERGE_REQUEST_IID' + # For the ` main ` branch, create a pipeline (this includes on schedules, pushes, merges, etc.). + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' + # For tags, create a pipeline. + - if: '$CI_COMMIT_TAG' - before_script: - - gem update --silent --system +.current_ruby_template: ¤t_ruby_template + image: ruby:${RUBY_VERSION} + stage: test + script: + # || true so we don't fail here, because it'll probably work even if the gem update fails + - gem update --system > /dev/null 2>&1 || true - mkdir -p vendor/bundle - bundle config set path 'vendor/bundle' - chmod +t -R vendor/bundle - chmod o-w -R vendor/bundle - - bundle install --jobs 4 --retry 3 + # Setup appraisal2 + - bundle install + # Bundle a specific appraisal + - bundle exec appraisal unlocked_deps bundle install + # Light smoke test + - bundle exec appraisal unlocked_deps bin/rake --tasks + # Run tests, skipping those that won't work in CI + - > + bundle exec appraisal unlocked_deps \ + bin/rspec spec \ + --tag \~ci_skip \ + --format progress \ + --format RspecJunitFormatter -run_tests: - script: - - bundle exec rake + cache: + key: ${CI_JOB_IMAGE} + paths: + - vendor/ruby + +current-ruby: + <<: *current_ruby_template + parallel: + matrix: + - RUBY_VERSION: ["3.2", "3.3", "3.4"] diff --git a/CHANGELOG.md b/CHANGELOG.md index fd9b4a9..5b8649f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,7 +84,7 @@ Please file a bug if you notice a violation of semantic versioning. - More documentation, and yard task for documentation (@pboling) - Documentation of Ruby version and SemVer support (@pboling) ### Fixed -- [#3](https://gitlab.com/oauth-xx/version_gem/-/issues/3) - Allow packaging without signing (@pboling) +- [#3](https://gitlab.com/ruby-oauth/version_gem/-/issues/3) - Allow packaging without signing (@pboling) - to support secure linux distros which have alternate means of signing packages within their package managers - Code coverage tracking (@pboling) - Documentation of usage in gemspec via `Kernel.load` (@pboling) @@ -163,28 +163,28 @@ Please file a bug if you notice a violation of semantic versioning. ### Added - Initial release, with basic version parsing API (@pboling) -[Unreleased]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.8...main -[1.1.8]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.7...v1.1.8 -[1.1.8t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.8 -[1.1.7]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.6...v1.1.7 -[1.1.7t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.7 -[1.1.6]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.5...v1.1.6 -[1.1.6t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.6 -[1.1.5]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.4...v1.1.5 -[1.1.5t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.5 -[1.1.4]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.3...v1.1.4 -[1.1.4t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.4 -[1.1.3]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.2...v1.1.3 -[1.1.3t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.3 -[1.1.2]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.1...v1.1.2 -[1.1.2t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.2 -[1.1.1]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.0...v1.1.1 -[1.1.1t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.1 -[1.1.0]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.0.2...v1.1.0 -[1.1.0t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.1.0 -[1.0.2]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.0.1...v1.0.2 -[1.0.2t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.0.2 -[1.0.1]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.0.0...v1.0.1 -[1.0.1t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.0.1 -[1.0.0]: https://gitlab.com/oauth-xx/version_gem/-/compare/a3055964517c159bf214712940982034b75264be...v1.0.0 -[1.0.0t]: https://gitlab.com/oauth-xx/version_gem/-/tags/v1.0.0 +[Unreleased]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.8...main +[1.1.8]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.7...v1.1.8 +[1.1.8t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.8 +[1.1.7]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.6...v1.1.7 +[1.1.7t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.7 +[1.1.6]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.5...v1.1.6 +[1.1.6t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.6 +[1.1.5]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.4...v1.1.5 +[1.1.5t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.5 +[1.1.4]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.3...v1.1.4 +[1.1.4t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.4 +[1.1.3]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.2...v1.1.3 +[1.1.3t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.3 +[1.1.2]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.1...v1.1.2 +[1.1.2t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.2 +[1.1.1]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.1.0...v1.1.1 +[1.1.1t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.1 +[1.1.0]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.0.2...v1.1.0 +[1.1.0t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.1.0 +[1.0.2]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.0.1...v1.0.2 +[1.0.2t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.0.2 +[1.0.1]: https://gitlab.com/ruby-oauth/version_gem/-/compare/v1.0.0...v1.0.1 +[1.0.1t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.0.1 +[1.0.0]: https://gitlab.com/ruby-oauth/version_gem/-/compare/a3055964517c159bf214712940982034b75264be...v1.0.0 +[1.0.0t]: https://gitlab.com/ruby-oauth/version_gem/-/tags/v1.0.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 73fd4ce..9b9f3a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,6 @@ This project should be a safe, welcoming space for collaboration, so contributor the [code of conduct][🤝conduct]. To submit a patch, please fork the project, create a patch with tests, and send a pull request. -Post a message to the [google group][⛳mail-list] if you want to. Remember to [![Keep A Changelog][📗keep-changelog-img]][📗keep-changelog] if you make changes. @@ -147,7 +146,9 @@ NOTE: To build without signing the gem set `SKIP_GEM_SIGNING` to any value in th #### Automated process -Run `bundle exec kettle-release`. +1. Update version.rb to contian the correct version-to-be-released. +2. Run `bundle exec kettle-changelog`. +3. Run `bundle exec kettle-release`. #### Manual process @@ -176,7 +177,6 @@ Run `bundle exec kettle-release`. 13. Run `bundle exec rake release` which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org][💎rubygems] -[⛳mail-list]: http://groups.google.com/group/oauth-ruby [📜src-gl]: https://gitlab.com/ruby-oauth/version_gem/ [📜src-cb]: https://codeberg.org/ruby-oauth/version_gem [📜src-gh]: https://github.com/ruby-oauth/version_gem diff --git a/version_gem.gemspec b/version_gem.gemspec index f1b3238..c486fb1 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -113,28 +113,50 @@ Gem::Specification.new do |spec| # Dev, Test, & Release Tasks spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.1") # ruby >= 2.3.0 + + # Security spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 + # Tasks spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2.0 + # Debugging spec.add_development_dependency("require_bench", "~> 1.0", ">= 1.0.4") # ruby >= 2.2.0 + # Testing spec.add_development_dependency("appraisal2", "~> 3.0") # ruby >= 1.8.7, for testing against multiple versions of dependencies - spec.add_development_dependency("kettle-test", "~> 1.0") # ruby >= 2.3 - spec.add_development_dependency("rspec-pending_for") # ruby >= 2.3, used to skip specs on incompatible Rubies + # Releasing spec.add_development_dependency("ruby-progressbar", "~> 1.13") # ruby >= 0 - spec.add_development_dependency("stone_checksums", "~> 1.0", ">= 1.0.2") # ruby >= 2.2.0 - # spec.add_development_dependency("erb", ">= 2.2") # ruby >= 2.3.0, not SemVer, old rubies get dropped in a patch. + # Git integration (optional) + # The 'git' gem is optional; version_gem falls back to shelling out to `git` if it is not present. + # The current release of the git gem depends on activesupport, which makes it too heavy to depend on directly + # spec.add_dependency("git", ">= 1.19.1") # ruby >= 2.3 + # Development tasks + # The cake is a lie. erb v2.2, the oldest release on RubyGems.org, was never compatible with Ruby 2.3. + # This means we have no choice but to use the erb that shipped with Ruby 2.3 + # /opt/hostedtoolcache/Ruby/2.3.8/x64/lib/ruby/gems/2.3.0/gems/erb-2.2.2/lib/erb.rb:670:in `prepare_trim_mode': undefined method `match?' for "-":String (NoMethodError) + # spec.add_development_dependency("erb", ">= 2.2") # ruby >= 2.3.0, not SemVer, old rubies get dropped in a patch. spec.add_development_dependency("gitmoji-regex", "~> 1.0", ">= 1.0.3") # ruby >= 2.3.0 + # HTTP recording for deterministic specs + # It seems that somehow just having a newer version of appraisal installed breaks + # Ruby 2.3 and 2.4 even if their bundle specifies an older version, + # and as a result it can only be a dependency in the appraisals. + # | An error occurred while loading spec_helper. + # | Failure/Error: require "vcr" + # | + # | NoMethodError: + # | undefined method `delete_prefix' for "CONTENT_LENGTH":String + # | # ./spec/config/vcr.rb:3:in `require' + # | # ./spec/config/vcr.rb:3:in `' + # | # ./spec/spec_helper.rb:8:in `require_relative' + # | # ./spec/spec_helper.rb:8:in `' # spec.add_development_dependency("vcr", ">= 4") # 6.0 claims to support ruby >= 2.3, but fails on ruby 2.4 - # spec.add_development_dependency("webmock", ">= 3") # Last version to support ruby >= 2.3 - end From 3b55f83317bb1cc6815c5b24fc8d3ef8372e1c82 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 02:08:14 -0600 Subject: [PATCH 24/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20rspec-pending=5Ffor?= =?UTF-8?q?=200.0.17?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 2 +- version_gem.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 15f6d0f..cd75798 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -313,7 +313,7 @@ DEPENDENCIES rdoc (~> 6.11) reek (~> 6.5) require_bench (~> 1.0, >= 1.0.4) - rspec-pending_for + rspec-pending_for (~> 0.0, >= 0.0.17) rubocop-lts (~> 8.0) rubocop-on-rbs (~> 1.8) rubocop-packaging (~> 0.6, >= 0.6.0) diff --git a/version_gem.gemspec b/version_gem.gemspec index c486fb1..6ff3d5c 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -126,7 +126,7 @@ Gem::Specification.new do |spec| # Testing spec.add_development_dependency("appraisal2", "~> 3.0") # ruby >= 1.8.7, for testing against multiple versions of dependencies spec.add_development_dependency("kettle-test", "~> 1.0") # ruby >= 2.3 - spec.add_development_dependency("rspec-pending_for") # ruby >= 2.3, used to skip specs on incompatible Rubies + spec.add_development_dependency("rspec-pending_for", "~> 0.0", ">= 0.0.17") # ruby >= 2.3, used to skip specs on incompatible Rubies # Releasing spec.add_development_dependency("ruby-progressbar", "~> 1.13") # ruby >= 0 From 470e5a765ec2724df80b812628203565d8aae384 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 05:43:09 -0600 Subject: [PATCH 25/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - binstubs --- .idea/version_gem.iml | 2 +- Gemfile.lock | 4 ++-- bin/kettle-dvcs | 16 ++++++++++++++++ version_gem.gemspec | 2 +- 4 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 bin/kettle-dvcs diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml index 2defb7f..10d8646 100644 --- a/.idea/version_gem.iml +++ b/.idea/version_gem.iml @@ -40,7 +40,7 @@ - + diff --git a/Gemfile.lock b/Gemfile.lock index cd75798..3e64e78 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.1.1) + kettle-dev (1.1.2) rake (~> 13.0) kettle-soup-cover (1.0.10) simplecov (~> 0.22) @@ -303,7 +303,7 @@ DEPENDENCIES debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) gitmoji-regex (~> 1.0, >= 1.0.3) - kettle-dev (~> 1.1, >= 1.1.1) + kettle-dev (~> 1.1, >= 1.1.2) kettle-soup-cover (~> 1.0, >= 1.0.10) kettle-test (~> 1.0) kramdown (~> 2.5, >= 2.5.1) diff --git a/bin/kettle-dvcs b/bin/kettle-dvcs new file mode 100644 index 0000000..b572d48 --- /dev/null +++ b/bin/kettle-dvcs @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'kettle-dvcs' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "rubygems" +require "bundler/setup" + +load Gem.bin_path("kettle-dev", "kettle-dvcs") diff --git a/version_gem.gemspec b/version_gem.gemspec index 6ff3d5c..5973b33 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,7 +112,7 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.1") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.2") # ruby >= 2.3.0 # Security spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 From 6ce721a1610d74e99f67393fc344ca87a4859b49 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 05:49:28 -0600 Subject: [PATCH 26/29] =?UTF-8?q?=F0=9F=8E=A8=20Updated=20gem=20template?= =?UTF-8?q?=20w/=20kettle-dev=20v1.1.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .envrc | 4 +- .gitignore | 1 + .rubocop.yml | 3 + CHANGELOG.md | 2 +- CONTRIBUTING.md | 7 +- Rakefile | 2 +- docs/VersionGem.html | 2 +- docs/VersionGem/Api.html | 2 +- docs/VersionGem/Basic.html | 2 +- docs/VersionGem/Epoch.html | 2 +- .../VersionGem/Epoch/OverloadApiForEpoch.html | 2 +- docs/VersionGem/Error.html | 2 +- docs/VersionGem/Ruby.html | 2 +- docs/VersionGem/Version.html | 2 +- docs/_index.html | 8 +- docs/file.CHANGELOG.html | 78 ++++++++------- docs/file.CITATION.html | 2 +- docs/file.CODE_OF_CONDUCT.html | 2 +- docs/file.CONTRIBUTING.html | 18 ++-- docs/file.FUNDING.html | 2 +- docs/file.LICENSE.html | 2 +- docs/file.README.html | 6 +- docs/file.REEK.html | 2 +- docs/file.RUBOCOP.html | 2 +- docs/file.SECURITY.html | 2 +- docs/file.all_formatters.html | 2 +- docs/file.api.html | 26 ++--- docs/file.basic.html | 2 +- docs/file.debug.html | 2 +- docs/file.debug_ide.html | 2 +- docs/file.debug_jruby.html | 2 +- docs/file.debugging.html | 2 +- docs/file.epoch.html | 95 +++++++++++++++++++ docs/file.error.html | 74 +++++++++++++++ docs/file.ruby.html | 10 +- docs/file.run_coverage.html | 2 +- docs/file.version.html | 11 ++- docs/file.version_gem-1.1.1.gem.html | 2 +- docs/file.version_gem-1.1.2.gem.html | 2 +- docs/file.version_gem-1.1.3.gem.html | 2 +- docs/file.version_gem-1.1.4.gem.html | 2 +- docs/file.version_gem-1.1.5.gem.html | 2 +- docs/file.version_gem-1.1.6.gem.html | 2 +- docs/file.version_gem-1.1.7.gem.html | 2 +- docs/file.version_gem-1.1.8.gem.html | 2 +- docs/file.version_gem.html | 4 +- docs/file_list.html | 10 ++ docs/index.html | 6 +- docs/top-level-namespace.html | 2 +- 49 files changed, 316 insertions(+), 111 deletions(-) create mode 100644 docs/file.epoch.html create mode 100644 docs/file.error.html diff --git a/.envrc b/.envrc index 661b35f..6b06e0a 100644 --- a/.envrc +++ b/.envrc @@ -21,8 +21,8 @@ export K_SOUP_COV_DO=true # Means you want code coverage export K_SOUP_COV_COMMAND_NAME="Test Coverage" # Available formats are html, xml, rcov, lcov, json, tty export K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty" -export K_SOUP_COV_MIN_BRANCH=100 # Means you want to enforce X% branch coverage -export K_SOUP_COV_MIN_LINE=100 # Means you want to enforce X% line coverage +export K_SOUP_COV_MIN_BRANCH=78 # Means you want to enforce X% branch coverage +export K_SOUP_COV_MIN_LINE=97 # Means you want to enforce X% line coverage export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met export K_SOUP_COV_MULTI_FORMATTERS=true export K_SOUP_COV_OPEN_BIN= # Means don't try to open coverage results in browser diff --git a/.gitignore b/.gitignore index 83000f2..5fb6e27 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ Appraisal.*.gemfile.lock /coverage/ /spec/reports/ /results/ +.output.txt # Documentation /.yardoc/ diff --git a/.rubocop.yml b/.rubocop.yml index 9dad2b7..7e881a6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -14,3 +14,6 @@ RSpec/ExampleLength: RSpec/MultipleExpectations: Enabled: false + +RSpec/NestedGroups: + Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b8649f..645e109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ Please file a bug if you notice a violation of semantic versioning. ## [Unreleased] ### Added -- re-templated gem using kettle-dev +- re-templated gem using kettle-dev v1.1.2 - new binstubs for changelog, readme, commit message, & release management - new CI workflows - enhanced project documentation diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b9f3a6..1db9d02 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -89,9 +89,10 @@ bundle exec rake test ### Spec organization (required) -- For each class or module under `lib/`, keep all of its unit tests in a single spec file under `spec/` that mirrors the path and file name (e.g., specs for `lib/version_gem/release_cli.rb` live in `spec/version_gem/release_cli_spec.rb`). -- Do not create ad-hoc "_more" or split spec files for the same class/module. Consolidate all unit tests into the main spec file for that class/module. -- Only integration scenarios that intentionally span multiple classes belong in `spec/integration/`. +- One spec file per class/module. For each class or module under `lib/`, keep all of its unit tests in a single spec file under `spec/` that mirrors the path and file name exactly: `lib/version_gem/release_cli.rb` -> `spec/version_gem/release_cli_spec.rb`. +- Never add a second spec file for the same class/module. Examples of disallowed names: `*_more_spec.rb`, `*_extra_spec.rb`, `*_status_spec.rb`, or any other suffix that still targets the same class. If you find yourself wanting a second file, merge those examples into the canonical spec file for that class/module. +- Exception: Integration specs that intentionally span multiple classes. Place these under `spec/integration/` (or a clearly named integration folder), and do not directly mirror a single class. Name them after the scenario, not a class. +- Migration note: If a duplicate spec file exists, move all examples into the canonical file and delete the duplicate. Do not leave stubs or empty files behind. ## Lint It diff --git a/Rakefile b/Rakefile index 002f728..342b54e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ # frozen_string_literal: true -# kettle-dev Rakefile v1.1.1 - 2025-09-02 +# kettle-dev Rakefile v1.1.2 - 2025-09-02 # Ruby 2.3 (Safe Navigation) or higher required # # MIT License (see License.txt) diff --git a/docs/VersionGem.html b/docs/VersionGem.html index c742b07..18b8d04 100644 --- a/docs/VersionGem.html +++ b/docs/VersionGem.html @@ -119,7 +119,7 @@

          Overview

          diff --git a/docs/VersionGem/Api.html b/docs/VersionGem/Api.html index 41987c7..f51d666 100644 --- a/docs/VersionGem/Api.html +++ b/docs/VersionGem/Api.html @@ -664,7 +664,7 @@

          diff --git a/docs/VersionGem/Basic.html b/docs/VersionGem/Basic.html index d0a8324..3c45ee3 100644 --- a/docs/VersionGem/Basic.html +++ b/docs/VersionGem/Basic.html @@ -202,7 +202,7 @@

          diff --git a/docs/VersionGem/Epoch.html b/docs/VersionGem/Epoch.html index a5c01a5..37887cf 100644 --- a/docs/VersionGem/Epoch.html +++ b/docs/VersionGem/Epoch.html @@ -231,7 +231,7 @@

          diff --git a/docs/VersionGem/Epoch/OverloadApiForEpoch.html b/docs/VersionGem/Epoch/OverloadApiForEpoch.html index 1a0f1bd..1f4d0b4 100644 --- a/docs/VersionGem/Epoch/OverloadApiForEpoch.html +++ b/docs/VersionGem/Epoch/OverloadApiForEpoch.html @@ -444,7 +444,7 @@

          diff --git a/docs/VersionGem/Error.html b/docs/VersionGem/Error.html index 60e6225..5d524e7 100644 --- a/docs/VersionGem/Error.html +++ b/docs/VersionGem/Error.html @@ -124,7 +124,7 @@

          Overview

          diff --git a/docs/VersionGem/Ruby.html b/docs/VersionGem/Ruby.html index 8d8a731..df59027 100644 --- a/docs/VersionGem/Ruby.html +++ b/docs/VersionGem/Ruby.html @@ -296,7 +296,7 @@

          diff --git a/docs/VersionGem/Version.html b/docs/VersionGem/Version.html index 2c24bba..51fcc4d 100644 --- a/docs/VersionGem/Version.html +++ b/docs/VersionGem/Version.html @@ -111,7 +111,7 @@

          diff --git a/docs/_index.html b/docs/_index.html index 287ac27..be41251 100644 --- a/docs/_index.html +++ b/docs/_index.html @@ -162,6 +162,12 @@

          File Listing

        3. basic
        4. +
        5. epoch
        6. + + +
        7. error
        8. + +
        9. ruby
        10. @@ -294,7 +300,7 @@

          Namespace Listing A-Z

          diff --git a/docs/file.CHANGELOG.html b/docs/file.CHANGELOG.html index ab5c985..c15550f 100644 --- a/docs/file.CHANGELOG.html +++ b/docs/file.CHANGELOG.html @@ -68,18 +68,32 @@ and yes, platform and engine support are part of the public API.
          Please file a bug if you notice a violation of semantic versioning.

          -

          Unreleased

          +

          Unreleased

          Added

          -

          Changed

          -

          Deprecated

          -

          Removed

          -

          Fixed

          -

          Security

          +
            +
          • re-templated gem using kettle-dev v1.1.2 +
              +
            • new binstubs for changelog, readme, commit message, & release management
            • +
            • new CI workflows
            • +
            • enhanced project documentation
            • +
            +
          • +
          • More RBS types
          • +
          • docs site: https://version-gem.galtzo.com +

            Changed

            +

            Deprecated

            +

            Removed

            +

            Fixed

            +
          • +
          • RBS types are more accurate +

            Security

            +
          • +

          -1.1.8 2025-05-06

          +1.1.8 2025-05-06
            -
          • TAG: 1.1.8 +
          • TAG: 1.1.8
          • COVERAGE: 100.00% – 118/118 lines in 8 files
          • BRANCH COVERAGE: 100.00% – 4/4 branches in 8 files
          • @@ -98,9 +112,9 @@

            Added

          -1.1.7 2025-04-15

          +1.1.7 2025-04-15
            -
          • TAG: 1.1.7 +
          • TAG: 1.1.7
          • Line Coverage: 100.0% (117 / 117)
          • Branch Coverage: 100.0% (4 / 4)
          • @@ -125,9 +139,9 @@

            Removed

          -1.1.6 2025-02-24

          +1.1.6 2025-02-24
            -
          • TAG: 1.1.6 +
          • TAG: 1.1.6
          • Line Coverage: 100.0% (77 / 77)
          • Branch Coverage: 100.0% (2 / 2)
          • @@ -150,9 +164,9 @@

            Changed

          -1.1.5 2025-02-22

          +1.1.5 2025-02-22
            -
          • TAG: 1.1.5 +
          • TAG: 1.1.5
          • Line Coverage: 100.0% (77 / 77)
          • Branch Coverage: 100.0% (2 / 2)
          • @@ -165,7 +179,7 @@

            Added

            Fixed

          • -#3 - Allow packaging without signing (@pboling) +#3 - Allow packaging without signing (@pboling)
            • to support secure linux distros which have alternate means of signing packages within their package managers
            @@ -176,9 +190,9 @@

            Fixed

          -1.1.4 2024-03-21

          +1.1.4 2024-03-21
            -
          • TAG: 1.1.4 +
          • TAG: 1.1.4

            Added

          • Ruby 3.3 to CI (@pboling) @@ -188,9 +202,9 @@

            Fixed

          -1.1.3 2023-06-05

          +1.1.3 2023-06-05
            -
          • TAG: 1.1.3 +
          • TAG: 1.1.3

            Added

          • More test coverage (now 100% 🎉) (@pboling)
          • @@ -221,9 +235,9 @@

            Removed

          -1.1.2 - 2023-03-17

          +1.1.2 - 2023-03-17
            -
          • TAG: 1.1.2 +
          • TAG: 1.1.2

            Added

          • @@ -237,9 +251,9 @@

            Added

          -1.1.1 - 2022-09-19

          +1.1.1 - 2022-09-19
            -
          • TAG: 1.1.1 +
          • TAG: 1.1.1

            Added

          • Alternatives section to README.md (@pboling)
          • @@ -264,9 +278,9 @@

            Changed

          -1.1.0 - 2022-06-24

          +1.1.0 - 2022-06-24
            -
          • TAG: 1.1.0 +
          • TAG: 1.1.0

            Added

          • RSpec Matchers and Shared Example (@pboling) @@ -277,18 +291,18 @@

            Fixed

          -1.0.2 - 2022-06-23

          +1.0.2 - 2022-06-23
            -
          • TAG: 1.0.2 +
          • TAG: 1.0.2

            Added

          • Delay loading of library code until after code coverage tool is loaded (@pboling)

          -1.0.1 - 2022-06-23

          +1.0.1 - 2022-06-23
            -
          • TAG: 1.0.1 +
          • TAG: 1.0.1

            Added

          • CI Build improvements (@pboling)
          • @@ -298,9 +312,9 @@

            Added

          -1.0.0 - 2022-06-21

          +1.0.0 - 2022-06-21
            -
          • TAG: 1.0.0 +
          • TAG: 1.0.0

            Added

          • Initial release, with basic version parsing API (@pboling)
          • @@ -309,7 +323,7 @@

            Added

            diff --git a/docs/file.CITATION.html b/docs/file.CITATION.html index 3e60561..140ca61 100644 --- a/docs/file.CITATION.html +++ b/docs/file.CITATION.html @@ -82,7 +82,7 @@ diff --git a/docs/file.CODE_OF_CONDUCT.html b/docs/file.CODE_OF_CONDUCT.html index dc14b58..453e2c6 100644 --- a/docs/file.CODE_OF_CONDUCT.html +++ b/docs/file.CODE_OF_CONDUCT.html @@ -191,7 +191,7 @@

            Attribution

            diff --git a/docs/file.CONTRIBUTING.html b/docs/file.CONTRIBUTING.html index 612a778..985e536 100644 --- a/docs/file.CONTRIBUTING.html +++ b/docs/file.CONTRIBUTING.html @@ -63,8 +63,7 @@ This project should be a safe, welcoming space for collaboration, so contributors agree to adhere to
            the code of conduct.

            -

            To submit a patch, please fork the project, create a patch with tests, and send a pull request.
            -Post a message to the google group if you want to.

            +

            To submit a patch, please fork the project, create a patch with tests, and send a pull request.

            Remember to Keep A Changelog if you make changes.

            @@ -159,9 +158,10 @@

            Run Tests

            Spec organization (required)

              -
            • For each class or module under lib/, keep all of its unit tests in a single spec file under spec/ that mirrors the path and file name (e.g., specs for lib/version_gem/release_cli.rb live in spec/version_gem/release_cli_spec.rb).
            • -
            • Do not create ad-hoc “_more” or split spec files for the same class/module. Consolidate all unit tests into the main spec file for that class/module.
            • -
            • Only integration scenarios that intentionally span multiple classes belong in spec/integration/.
            • +
            • One spec file per class/module. For each class or module under lib/, keep all of its unit tests in a single spec file under spec/ that mirrors the path and file name exactly: lib/version_gem/release_cli.rb -> spec/version_gem/release_cli_spec.rb.
            • +
            • Never add a second spec file for the same class/module. Examples of disallowed names: *_more_spec.rb, *_extra_spec.rb, *_status_spec.rb, or any other suffix that still targets the same class. If you find yourself wanting a second file, merge those examples into the canonical spec file for that class/module.
            • +
            • Exception: Integration specs that intentionally span multiple classes. Place these under spec/integration/ (or a clearly named integration folder), and do not directly mirror a single class. Name them after the scenario, not a class.
            • +
            • Migration note: If a duplicate spec file exists, move all examples into the canonical file and delete the duplicate. Do not leave stubs or empty files behind.

            Lint It

            @@ -222,7 +222,11 @@

            To release a new version:

            Automated process

            -

            Run bundle exec kettle-release.

            +
              +
            1. Update version.rb to contian the correct version-to-be-released.
            2. +
            3. Run bundle exec kettle-changelog.
            4. +
            5. Run bundle exec kettle-release.
            6. +

            Manual process

            @@ -275,7 +279,7 @@

            Manual process

            diff --git a/docs/file.FUNDING.html b/docs/file.FUNDING.html index 7b4cd85..7bb3824 100644 --- a/docs/file.FUNDING.html +++ b/docs/file.FUNDING.html @@ -104,7 +104,7 @@

            Another Way to Support Open diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html index 9e60082..1f5c68a 100644 --- a/docs/file.LICENSE.html +++ b/docs/file.LICENSE.html @@ -60,7 +60,7 @@
            The MIT License (MIT)

            Copyright (c) 2022 - 2025 Peter Boling

            Permission is hereby granted, free of charge, to any person obtaining a copy
            of this software and associated documentation files (the "Software"), to deal
            in the Software without restriction, including without limitation the rights
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
            copies of the Software, and to permit persons to whom the Software is
            furnished to do so, subject to the following conditions:

            The above copyright notice and this permission notice shall be included in
            all copies or substantial portions of the Software.

            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
            THE SOFTWARE.
            diff --git a/docs/file.README.html b/docs/file.README.html index 7410fc7..6744435 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -88,7 +88,7 @@

            🌻 Synopsis

            This gem has no runtime dependencies.

            -

            🧐 Alternatives

            +

            🧐 Alternatives

            This gem has a very niche purpose, which is:

            @@ -360,7 +360,7 @@

            Side benefit #2

            Your version.rb file now abides the Ruby convention of directory / path matching the namespace / class!

            -

            Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

            +

            Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

            In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

            @@ -744,7 +744,7 @@

            Please give the project a star ⭐ ♥ diff --git a/docs/file.REEK.html b/docs/file.REEK.html index 2898fcb..bf88265 100644 --- a/docs/file.REEK.html +++ b/docs/file.REEK.html @@ -61,7 +61,7 @@ diff --git a/docs/file.RUBOCOP.html b/docs/file.RUBOCOP.html index 4a0cf06..61de8ce 100644 --- a/docs/file.RUBOCOP.html +++ b/docs/file.RUBOCOP.html @@ -161,7 +161,7 @@

            Benefits of rubocop_gradual

            diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html index 3fb09b4..ec361d0 100644 --- a/docs/file.SECURITY.html +++ b/docs/file.SECURITY.html @@ -91,7 +91,7 @@

            Additional Support

            diff --git a/docs/file.all_formatters.html b/docs/file.all_formatters.html index c4b8f48..de421da 100644 --- a/docs/file.all_formatters.html +++ b/docs/file.all_formatters.html @@ -61,7 +61,7 @@ diff --git a/docs/file.api.html b/docs/file.api.html index d47d0ac..f18a42b 100644 --- a/docs/file.api.html +++ b/docs/file.api.html @@ -59,31 +59,25 @@

            module VersionGem
            module Api
            + # Internal memoized version string segments
            @_to_a: Array[String]

            -
            @major: Integer
            -
            +
            # Memoized components
            +@major: Integer
             @minor: Integer
            -
             @patch: Integer
            -
             @pre: String?
            +@to_a: Array[Integer | String | nil]
            +@to_h: Hash[Symbol, (Integer | String | nil)]
             
            -@to_a: Array
            -
            -@to_h: Hash
            -
            +# Public API
            +def to_s: () -> String
             def major: () -> Integer
            -
             def minor: () -> Integer
            -
             def patch: () -> Integer
            -
             def pre: () -> String?
            -
            -def to_a: () -> Array
            -
            -def to_h: () -> Hash
            +def to_a: () -> Array[Integer | String | nil]
            +def to_h: () -> Hash[Symbol, (Integer | String | nil)]
             
             private
             
            @@ -92,7 +86,7 @@
             
            diff --git a/docs/file.basic.html b/docs/file.basic.html index 25e7593..a35e4b3 100644 --- a/docs/file.basic.html +++ b/docs/file.basic.html @@ -65,7 +65,7 @@ diff --git a/docs/file.debug.html b/docs/file.debug.html index 018f39c..1432828 100644 --- a/docs/file.debug.html +++ b/docs/file.debug.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debug_ide.html b/docs/file.debug_ide.html index f511218..4e309f5 100644 --- a/docs/file.debug_ide.html +++ b/docs/file.debug_ide.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debug_jruby.html b/docs/file.debug_jruby.html index 0dc2de8..522534f 100644 --- a/docs/file.debug_jruby.html +++ b/docs/file.debug_jruby.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debugging.html b/docs/file.debugging.html index b83e70b..b52da8a 100644 --- a/docs/file.debugging.html +++ b/docs/file.debugging.html @@ -61,7 +61,7 @@ diff --git a/docs/file.epoch.html b/docs/file.epoch.html new file mode 100644 index 0000000..b073a21 --- /dev/null +++ b/docs/file.epoch.html @@ -0,0 +1,95 @@ + + + + + + + File: epoch + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
            + + +

            module VersionGem
            + module Epoch
            + EPOCH_SIZE: Integer

            + +
            # Hook used when this module is extended
            +def self.extended: (untyped) -> void
            +
            +module OverloadApiForEpoch
            +  # The epoch component (derived)
            +  def epoch: () -> Integer
            +
            +  # Override of Api#major returning the derived major component
            +  def major: () -> Integer
            +
            +  # Hash representation including epoch
            +  def to_h: () -> Hash[Symbol, (Integer | String | nil)]
            +
            +  # Array of components [epoch, major, minor, patch, pre]
            +  def to_a: () -> Array[Integer | String | nil]
            +
            +  private
            +
            +  def _major: () -> Integer
            +end   end end
            +
            +
            + + + +
            + + \ No newline at end of file diff --git a/docs/file.error.html b/docs/file.error.html new file mode 100644 index 0000000..14844f5 --- /dev/null +++ b/docs/file.error.html @@ -0,0 +1,74 @@ + + + + + + + File: error + + — Documentation by YARD 0.9.37 + + + + + + + + + + + + + + + + + + + +
            + + +

            module VersionGem
            + class Error < ::RuntimeError
            + end
            +end

            +
            + + + +
            + + \ No newline at end of file diff --git a/docs/file.ruby.html b/docs/file.ruby.html index 3e7bee4..b144755 100644 --- a/docs/file.ruby.html +++ b/docs/file.ruby.html @@ -59,16 +59,18 @@

            module VersionGem
            module Ruby
            - RUBY_VER: Gem::Version

            + RUBY_VER: ::Gem::Version

            -
            def actual_minor_version?: () -> bool
            +
            # Check if the current Ruby version is >= given version for the engine
            +def self.gte_minimum_version?: (String, ?String) -> bool
             
            -def gte_minimum_version?: () -> bool   end end
            +# Check if the current Ruby MAJOR.MINOR equals the given values for the engine
            +def self.actual_minor_version?: ((Integer | String), (Integer | String), ?String) -> bool   end end
             
            diff --git a/docs/file.run_coverage.html b/docs/file.run_coverage.html index d852f41..4e9a9fb 100644 --- a/docs/file.run_coverage.html +++ b/docs/file.run_coverage.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version.html b/docs/file.version.html index de4f9b3..7bc5913 100644 --- a/docs/file.version.html +++ b/docs/file.version.html @@ -59,13 +59,16 @@

            module VersionGem
            module Version
            - VERSION: String
            - end
            -end

            + VERSION: String

            + +
            # At runtime this module is extended with Basic via class_eval in lib/version_gem.rb
            +# Declare the intended extension so class methods are available in typing
            +extend VersionGem::Basic   end end
            +
            diff --git a/docs/file.version_gem-1.1.1.gem.html b/docs/file.version_gem-1.1.1.gem.html index 9c6886a..5dd2f25 100644 --- a/docs/file.version_gem-1.1.1.gem.html +++ b/docs/file.version_gem-1.1.1.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.2.gem.html b/docs/file.version_gem-1.1.2.gem.html index a06ee68..f64715b 100644 --- a/docs/file.version_gem-1.1.2.gem.html +++ b/docs/file.version_gem-1.1.2.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.3.gem.html b/docs/file.version_gem-1.1.3.gem.html index cd1a4d2..0dbabe8 100644 --- a/docs/file.version_gem-1.1.3.gem.html +++ b/docs/file.version_gem-1.1.3.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.4.gem.html b/docs/file.version_gem-1.1.4.gem.html index 602efa9..9df74c0 100644 --- a/docs/file.version_gem-1.1.4.gem.html +++ b/docs/file.version_gem-1.1.4.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.5.gem.html b/docs/file.version_gem-1.1.5.gem.html index 72442e4..7f18d4e 100644 --- a/docs/file.version_gem-1.1.5.gem.html +++ b/docs/file.version_gem-1.1.5.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.6.gem.html b/docs/file.version_gem-1.1.6.gem.html index 202b53e..b04eff5 100644 --- a/docs/file.version_gem-1.1.6.gem.html +++ b/docs/file.version_gem-1.1.6.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.7.gem.html b/docs/file.version_gem-1.1.7.gem.html index 698f8bb..fa9a1ea 100644 --- a/docs/file.version_gem-1.1.7.gem.html +++ b/docs/file.version_gem-1.1.7.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.8.gem.html b/docs/file.version_gem-1.1.8.gem.html index 7807ddc..f98ec26 100644 --- a/docs/file.version_gem-1.1.8.gem.html +++ b/docs/file.version_gem-1.1.8.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem.html b/docs/file.version_gem.html index f039e4c..10836ae 100644 --- a/docs/file.version_gem.html +++ b/docs/file.version_gem.html @@ -58,13 +58,11 @@

            module VersionGem
            - VERSION: String
            - # See the writing guide of rbs: https://github.com/ruby/rbs#guides
            end

            diff --git a/docs/file_list.html b/docs/file_list.html index dbc8ddb..2008ba2 100644 --- a/docs/file_list.html +++ b/docs/file_list.html @@ -217,6 +217,16 @@

            File List

            +
          • + +
          • + + +
          • + +
          • + +
          • diff --git a/docs/index.html b/docs/index.html index cb4c819..71e4cb5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -88,7 +88,7 @@

            🌻 Synopsis

            This gem has no runtime dependencies.

            -

            🧐 Alternatives

            +

            🧐 Alternatives

            This gem has a very niche purpose, which is:

            @@ -360,7 +360,7 @@

            Side benefit #2

            Your version.rb file now abides the Ruby convention of directory / path matching the namespace / class!

            -

            Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

            +

            Epoch Usage (Epoch Semantic Versioning, as of version 1.1.7)

            In the standard bundle gem my_lib code you get the following in lib/my_lib/version.rb:

            @@ -744,7 +744,7 @@

            Please give the project a star ⭐ ♥ diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html index 81ea99c..47ddddb 100644 --- a/docs/top-level-namespace.html +++ b/docs/top-level-namespace.html @@ -100,7 +100,7 @@

            Defined Under Namespace

            From b4e624da4ee8403446b78578a25ba23075155002 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 06:08:02 -0600 Subject: [PATCH 27/29] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20kettle-dev=20v1.1.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/version_gem.iml | 2 +- Gemfile.lock | 4 ++-- version_gem.gemspec | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.idea/version_gem.iml b/.idea/version_gem.iml index 10d8646..f76d4b5 100644 --- a/.idea/version_gem.iml +++ b/.idea/version_gem.iml @@ -40,7 +40,7 @@ - + diff --git a/Gemfile.lock b/Gemfile.lock index 3e64e78..daf28c4 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -82,7 +82,7 @@ GEM rdoc (>= 4.0.0) reline (>= 0.4.2) json (2.13.2) - kettle-dev (1.1.2) + kettle-dev (1.1.3) rake (~> 13.0) kettle-soup-cover (1.0.10) simplecov (~> 0.22) @@ -303,7 +303,7 @@ DEPENDENCIES debug (>= 1.0.0) gem_bench (~> 2.0, >= 2.0.5) gitmoji-regex (~> 1.0, >= 1.0.3) - kettle-dev (~> 1.1, >= 1.1.2) + kettle-dev (~> 1.1, >= 1.1.3) kettle-soup-cover (~> 1.0, >= 1.0.10) kettle-test (~> 1.0) kramdown (~> 2.5, >= 2.5.1) diff --git a/version_gem.gemspec b/version_gem.gemspec index 5973b33..ee08278 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -112,7 +112,7 @@ Gem::Specification.new do |spec| # and preferably a modular one (see gemfiles/modular/*.gemfile). # Dev, Test, & Release Tasks - spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.2") # ruby >= 2.3.0 + spec.add_development_dependency("kettle-dev", "~> 1.1", ">= 1.1.3") # ruby >= 2.3.0 # Security spec.add_development_dependency("bundler-audit", "~> 0.9.2") # ruby >= 2.0.0 From d166a93e0d9c9550179535cb47d9f0cb3594458d Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 06:32:07 -0600 Subject: [PATCH 28/29] =?UTF-8?q?=F0=9F=93=9D=20kettle-dvcs=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/VersionGem.html | 2 +- docs/VersionGem/Api.html | 2 +- docs/VersionGem/Basic.html | 2 +- docs/VersionGem/Epoch.html | 2 +- docs/VersionGem/Epoch/OverloadApiForEpoch.html | 2 +- docs/VersionGem/Error.html | 2 +- docs/VersionGem/Ruby.html | 2 +- docs/VersionGem/Version.html | 2 +- docs/_index.html | 2 +- docs/file.CHANGELOG.html | 2 +- docs/file.CITATION.html | 2 +- docs/file.CODE_OF_CONDUCT.html | 2 +- docs/file.CONTRIBUTING.html | 2 +- docs/file.FUNDING.html | 2 +- docs/file.LICENSE.html | 2 +- docs/file.README.html | 4 ++-- docs/file.REEK.html | 2 +- docs/file.RUBOCOP.html | 2 +- docs/file.SECURITY.html | 2 +- docs/file.all_formatters.html | 2 +- docs/file.api.html | 2 +- docs/file.basic.html | 2 +- docs/file.debug.html | 2 +- docs/file.debug_ide.html | 2 +- docs/file.debug_jruby.html | 2 +- docs/file.debugging.html | 2 +- docs/file.epoch.html | 2 +- docs/file.error.html | 2 +- docs/file.ruby.html | 2 +- docs/file.run_coverage.html | 2 +- docs/file.version.html | 2 +- docs/file.version_gem-1.1.1.gem.html | 2 +- docs/file.version_gem-1.1.2.gem.html | 2 +- docs/file.version_gem-1.1.3.gem.html | 2 +- docs/file.version_gem-1.1.4.gem.html | 2 +- docs/file.version_gem-1.1.5.gem.html | 2 +- docs/file.version_gem-1.1.6.gem.html | 2 +- docs/file.version_gem-1.1.7.gem.html | 2 +- docs/file.version_gem-1.1.8.gem.html | 2 +- docs/file.version_gem.html | 2 +- docs/index.html | 4 ++-- docs/top-level-namespace.html | 2 +- 43 files changed, 45 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index f815327..dd03238 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ Compatible with MRI Ruby 2.3+, and concordant releases of JRuby, and TruffleRuby ### Federated DVCS
            - Find this repo on other forges (Coming soon!) + Find this repo on other forges | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| diff --git a/docs/VersionGem.html b/docs/VersionGem.html index 18b8d04..1dc582e 100644 --- a/docs/VersionGem.html +++ b/docs/VersionGem.html @@ -119,7 +119,7 @@

            Overview

            diff --git a/docs/VersionGem/Api.html b/docs/VersionGem/Api.html index f51d666..64f0822 100644 --- a/docs/VersionGem/Api.html +++ b/docs/VersionGem/Api.html @@ -664,7 +664,7 @@

            diff --git a/docs/VersionGem/Basic.html b/docs/VersionGem/Basic.html index 3c45ee3..d2b0cca 100644 --- a/docs/VersionGem/Basic.html +++ b/docs/VersionGem/Basic.html @@ -202,7 +202,7 @@

            diff --git a/docs/VersionGem/Epoch.html b/docs/VersionGem/Epoch.html index 37887cf..0b65bc7 100644 --- a/docs/VersionGem/Epoch.html +++ b/docs/VersionGem/Epoch.html @@ -231,7 +231,7 @@

            diff --git a/docs/VersionGem/Epoch/OverloadApiForEpoch.html b/docs/VersionGem/Epoch/OverloadApiForEpoch.html index 1f4d0b4..a025930 100644 --- a/docs/VersionGem/Epoch/OverloadApiForEpoch.html +++ b/docs/VersionGem/Epoch/OverloadApiForEpoch.html @@ -444,7 +444,7 @@

            diff --git a/docs/VersionGem/Error.html b/docs/VersionGem/Error.html index 5d524e7..1a0ec55 100644 --- a/docs/VersionGem/Error.html +++ b/docs/VersionGem/Error.html @@ -124,7 +124,7 @@

            Overview

            diff --git a/docs/VersionGem/Ruby.html b/docs/VersionGem/Ruby.html index df59027..520756c 100644 --- a/docs/VersionGem/Ruby.html +++ b/docs/VersionGem/Ruby.html @@ -296,7 +296,7 @@

            diff --git a/docs/VersionGem/Version.html b/docs/VersionGem/Version.html index 51fcc4d..683159b 100644 --- a/docs/VersionGem/Version.html +++ b/docs/VersionGem/Version.html @@ -111,7 +111,7 @@

            diff --git a/docs/_index.html b/docs/_index.html index be41251..c1d2b36 100644 --- a/docs/_index.html +++ b/docs/_index.html @@ -300,7 +300,7 @@

            Namespace Listing A-Z

            diff --git a/docs/file.CHANGELOG.html b/docs/file.CHANGELOG.html index c15550f..bbf68ca 100644 --- a/docs/file.CHANGELOG.html +++ b/docs/file.CHANGELOG.html @@ -323,7 +323,7 @@

            Added

            diff --git a/docs/file.CITATION.html b/docs/file.CITATION.html index 140ca61..6d848f6 100644 --- a/docs/file.CITATION.html +++ b/docs/file.CITATION.html @@ -82,7 +82,7 @@ diff --git a/docs/file.CODE_OF_CONDUCT.html b/docs/file.CODE_OF_CONDUCT.html index 453e2c6..4da2dda 100644 --- a/docs/file.CODE_OF_CONDUCT.html +++ b/docs/file.CODE_OF_CONDUCT.html @@ -191,7 +191,7 @@

            Attribution

            diff --git a/docs/file.CONTRIBUTING.html b/docs/file.CONTRIBUTING.html index 985e536..a3ece5a 100644 --- a/docs/file.CONTRIBUTING.html +++ b/docs/file.CONTRIBUTING.html @@ -279,7 +279,7 @@

            Manual process

            diff --git a/docs/file.FUNDING.html b/docs/file.FUNDING.html index 7bb3824..e5e87a6 100644 --- a/docs/file.FUNDING.html +++ b/docs/file.FUNDING.html @@ -104,7 +104,7 @@

            Another Way to Support Open diff --git a/docs/file.LICENSE.html b/docs/file.LICENSE.html index 1f5c68a..ac3be0d 100644 --- a/docs/file.LICENSE.html +++ b/docs/file.LICENSE.html @@ -60,7 +60,7 @@
            The MIT License (MIT)

            Copyright (c) 2022 - 2025 Peter Boling

            Permission is hereby granted, free of charge, to any person obtaining a copy
            of this software and associated documentation files (the "Software"), to deal
            in the Software without restriction, including without limitation the rights
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
            copies of the Software, and to permit persons to whom the Software is
            furnished to do so, subject to the following conditions:

            The above copyright notice and this permission notice shall be included in
            all copies or substantial portions of the Software.

            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
            THE SOFTWARE.
            diff --git a/docs/file.README.html b/docs/file.README.html index 6744435..7f06799 100644 --- a/docs/file.README.html +++ b/docs/file.README.html @@ -212,7 +212,7 @@

            Compatibility

            Federated DVCS

            - Find this repo on other forges (Coming soon!) + Find this repo on other forges | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| @@ -744,7 +744,7 @@

            Please give the project a star ⭐ ♥ diff --git a/docs/file.REEK.html b/docs/file.REEK.html index bf88265..3e55193 100644 --- a/docs/file.REEK.html +++ b/docs/file.REEK.html @@ -61,7 +61,7 @@ diff --git a/docs/file.RUBOCOP.html b/docs/file.RUBOCOP.html index 61de8ce..d9a544e 100644 --- a/docs/file.RUBOCOP.html +++ b/docs/file.RUBOCOP.html @@ -161,7 +161,7 @@

            Benefits of rubocop_gradual

            diff --git a/docs/file.SECURITY.html b/docs/file.SECURITY.html index ec361d0..5e3de7d 100644 --- a/docs/file.SECURITY.html +++ b/docs/file.SECURITY.html @@ -91,7 +91,7 @@

            Additional Support

            diff --git a/docs/file.all_formatters.html b/docs/file.all_formatters.html index de421da..c0ec5c8 100644 --- a/docs/file.all_formatters.html +++ b/docs/file.all_formatters.html @@ -61,7 +61,7 @@ diff --git a/docs/file.api.html b/docs/file.api.html index f18a42b..22b4cb3 100644 --- a/docs/file.api.html +++ b/docs/file.api.html @@ -86,7 +86,7 @@ diff --git a/docs/file.basic.html b/docs/file.basic.html index a35e4b3..c81ce20 100644 --- a/docs/file.basic.html +++ b/docs/file.basic.html @@ -65,7 +65,7 @@ diff --git a/docs/file.debug.html b/docs/file.debug.html index 1432828..3a5b6ff 100644 --- a/docs/file.debug.html +++ b/docs/file.debug.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debug_ide.html b/docs/file.debug_ide.html index 4e309f5..708d739 100644 --- a/docs/file.debug_ide.html +++ b/docs/file.debug_ide.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debug_jruby.html b/docs/file.debug_jruby.html index 522534f..55ec6b4 100644 --- a/docs/file.debug_jruby.html +++ b/docs/file.debug_jruby.html @@ -61,7 +61,7 @@ diff --git a/docs/file.debugging.html b/docs/file.debugging.html index b52da8a..ff25d7e 100644 --- a/docs/file.debugging.html +++ b/docs/file.debugging.html @@ -61,7 +61,7 @@ diff --git a/docs/file.epoch.html b/docs/file.epoch.html index b073a21..fcf2d6e 100644 --- a/docs/file.epoch.html +++ b/docs/file.epoch.html @@ -85,7 +85,7 @@ diff --git a/docs/file.error.html b/docs/file.error.html index 14844f5..c523b02 100644 --- a/docs/file.error.html +++ b/docs/file.error.html @@ -64,7 +64,7 @@ diff --git a/docs/file.ruby.html b/docs/file.ruby.html index b144755..d277902 100644 --- a/docs/file.ruby.html +++ b/docs/file.ruby.html @@ -70,7 +70,7 @@ diff --git a/docs/file.run_coverage.html b/docs/file.run_coverage.html index 4e9a9fb..747f4f4 100644 --- a/docs/file.run_coverage.html +++ b/docs/file.run_coverage.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version.html b/docs/file.version.html index 7bc5913..7ff0ad3 100644 --- a/docs/file.version.html +++ b/docs/file.version.html @@ -68,7 +68,7 @@ diff --git a/docs/file.version_gem-1.1.1.gem.html b/docs/file.version_gem-1.1.1.gem.html index 5dd2f25..f3b4973 100644 --- a/docs/file.version_gem-1.1.1.gem.html +++ b/docs/file.version_gem-1.1.1.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.2.gem.html b/docs/file.version_gem-1.1.2.gem.html index f64715b..3f7049b 100644 --- a/docs/file.version_gem-1.1.2.gem.html +++ b/docs/file.version_gem-1.1.2.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.3.gem.html b/docs/file.version_gem-1.1.3.gem.html index 0dbabe8..a5c44c2 100644 --- a/docs/file.version_gem-1.1.3.gem.html +++ b/docs/file.version_gem-1.1.3.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.4.gem.html b/docs/file.version_gem-1.1.4.gem.html index 9df74c0..dfe7e33 100644 --- a/docs/file.version_gem-1.1.4.gem.html +++ b/docs/file.version_gem-1.1.4.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.5.gem.html b/docs/file.version_gem-1.1.5.gem.html index 7f18d4e..30356fa 100644 --- a/docs/file.version_gem-1.1.5.gem.html +++ b/docs/file.version_gem-1.1.5.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.6.gem.html b/docs/file.version_gem-1.1.6.gem.html index b04eff5..3ce3ca4 100644 --- a/docs/file.version_gem-1.1.6.gem.html +++ b/docs/file.version_gem-1.1.6.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.7.gem.html b/docs/file.version_gem-1.1.7.gem.html index fa9a1ea..0c3b215 100644 --- a/docs/file.version_gem-1.1.7.gem.html +++ b/docs/file.version_gem-1.1.7.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem-1.1.8.gem.html b/docs/file.version_gem-1.1.8.gem.html index f98ec26..875b09b 100644 --- a/docs/file.version_gem-1.1.8.gem.html +++ b/docs/file.version_gem-1.1.8.gem.html @@ -61,7 +61,7 @@ diff --git a/docs/file.version_gem.html b/docs/file.version_gem.html index 10836ae..0d83da9 100644 --- a/docs/file.version_gem.html +++ b/docs/file.version_gem.html @@ -62,7 +62,7 @@ diff --git a/docs/index.html b/docs/index.html index 71e4cb5..d1efe5f 100644 --- a/docs/index.html +++ b/docs/index.html @@ -212,7 +212,7 @@

            Compatibility

            Federated DVCS

            - Find this repo on other forges (Coming soon!) + Find this repo on other forges | Federated [DVCS][💎d-in-dvcs] Repository | Status | Issues | PRs | Wiki | CI | Discussions | |-------------------------------------------------|-----------------------------------------------------------------------|---------------------------|--------------------------|---------------------------|--------------------------|------------------------------| @@ -744,7 +744,7 @@

            Please give the project a star ⭐ ♥ diff --git a/docs/top-level-namespace.html b/docs/top-level-namespace.html index 47ddddb..946cee6 100644 --- a/docs/top-level-namespace.html +++ b/docs/top-level-namespace.html @@ -100,7 +100,7 @@

            Defined Under Namespace

            From fba039f780e7bcc33ebc62d101f0077d4ad7eed1 Mon Sep 17 00:00:00 2001 From: "Peter H. Boling" Date: Tue, 2 Sep 2025 06:37:48 -0600 Subject: [PATCH 29/29] =?UTF-8?q?=F0=9F=90=9B=20Oops,=20lol.=20version=5Fg?= =?UTF-8?q?em=20ate=20itself.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Gemfile.lock | 1 - version_gem.gemspec | 3 --- 2 files changed, 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index daf28c4..9827834 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -14,7 +14,6 @@ PATH remote: . specs: version_gem (1.1.8) - version_gem (~> 1.1, >= 1.1.8) GEM remote: https://rubygems.org/ diff --git a/version_gem.gemspec b/version_gem.gemspec index ee08278..0070502 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -94,9 +94,6 @@ Gem::Specification.new do |spec| # files listed are relative paths from bindir above. spec.executables = [] - # Utilities - spec.add_dependency("version_gem", "~> 1.1", ">= 1.1.8") # ruby >= 2.2.0 - # NOTE: It is preferable to list development dependencies in the gemspec due to increased # visibility and discoverability on RubyGems.org. # However, development dependencies in gemspec will install on