diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index bb41341..7d26064 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,13 +1,13 @@ # These are supported funding model platforms +buy_me_a_coffee: pboling +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry github: [pboling] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: galtzo # Replace with a single Patreon username -open_collective: # Replace with a single Open Collective username +issuehunt: pboling # Replace with a single IssueHunt username ko_fi: pboling # Replace with a single Ko-fi username -tidelift: rubygems/version_gem # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: pboling # Replace with a single Liberapay username -issuehunt: pboling # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +open_collective: # Replace with a single Open Collective username +patreon: galtzo # Replace with a single Patreon username +polar: pboling +thanks_dev: gh/pboling +tidelift: rubygems/version_gem # Replace with a single Tidelift platform-name/package-name e.g., npm/babel diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index 68f6acb..e6f8f92 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -1,16 +1,16 @@ -name: Code Coverage +name: Ruby - Coverage env: - CI_CODECOV: true - COVER_ALL: true + K_SOUP_COV_MIN_BRANCH: 82 + K_SOUP_COV_MIN_LINE: 94 + K_SOUP_COV_MIN_HARD: true on: push: branches: - 'main' - - '*-maintenance' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -19,50 +19,57 @@ 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. - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: test: name: Specs with Coverage - Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + CI_CODECOV: true + COVER_ALL: true + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} strategy: - fail-fast: false matrix: - experimental: [false] rubygems: - latest bundler: - latest + gemfile: + - coverage ruby: - - "2.7" + - '3.1' - runs-on: ubuntu-latest - continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: - - uses: amancevice/setup-code-climate@v0 - name: CodeClimate Install - if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always() + - name: CodeClimate Install + uses: amancevice/setup-code-climate@v1 + if: ${{ github.event_name != 'pull_request' }} with: - cc_test_reporter_id: ${{ secrets.CC_TEST_REPORTER_ID }} + cc_test_reporter_id: "${{ secrets.CC_TEST_REPORTER_ID }}" - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Ruby & Bundle uses: ruby/setup-ruby@v1 with: - ruby-version: ${{ matrix.ruby }} - rubygems: ${{ matrix.rubygems }} - bundler: ${{ matrix.bundler }} + ruby-version: "${{ matrix.ruby }}" + rubygems: "${{ matrix.rubygems }}" + bundler: "${{ matrix.bundler }}" bundler-cache: true - name: CodeClimate Pre-build Notification run: cc-test-reporter before-build - if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always() + if: ${{ github.event_name != 'pull_request' }} continue-on-error: ${{ matrix.experimental != 'false' }} - name: Run tests @@ -70,26 +77,27 @@ jobs: - name: CodeClimate Post-build Notification run: cc-test-reporter after-build - if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always() + if: ${{ github.event_name != 'pull_request' }} continue-on-error: ${{ matrix.experimental != 'false' }} - name: Code Coverage Summary Report - uses: irongut/CodeCoverageSummary@v1.2.0 + uses: irongut/CodeCoverageSummary@v1.3.0 + if: ${{ github.event_name == 'pull_request' }} with: filename: ./coverage/coverage.xml badge: true fail_below_min: true format: markdown - hide_branch_rate: true + hide_branch_rate: false hide_complexity: true indicators: true output: both - thresholds: '86 88' + thresholds: '93 82' continue-on-error: ${{ matrix.experimental != 'false' }} - name: Add Coverage PR Comment uses: marocchino/sticky-pull-request-comment@v2 - if: matrix.ruby == '2.7' && always() + if: ${{ github.event_name == 'pull_request' }} with: recreate: true path: code-coverage-results.md @@ -97,18 +105,6 @@ jobs: - name: Coveralls uses: coverallsapp/github-action@master - if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always() with: - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: "${{ secrets.GITHUB_TOKEN }}" continue-on-error: ${{ matrix.experimental != 'false' }} - -# Using the codecov gem instead. -# - name: CodeCov -# uses: codecov/codecov-action@v2 -# if: matrix.ruby == '2.7' && github.event_name != 'pull_request' && always() -# with: -# files: ./coverage/coverage.xml -# flags: unittests -# name: codecov-upload -# fail_ci_if_error: true -# continue-on-error: ${{ matrix.experimental != 'false' }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..5545cd2 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v2 diff --git a/.github/workflows/heads.yml b/.github/workflows/heads.yml index 9aae8e2..46d151f 100644 --- a/.github/workflows/heads.yml +++ b/.github/workflows/heads.yml @@ -1,11 +1,14 @@ -name: Ruby HEAD Support +name: Ruby Heads Matrix + +env: + K_SOUP_COV_DO: false on: push: branches: - 'main' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -14,39 +17,48 @@ 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. - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: test: - name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} + name: Specs - Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} strategy: - fail-fast: false + fail-fast: true matrix: - experimental: [true] rubygems: - latest bundler: - latest + gemfile: + - vanilla ruby: - # rubocop supports JRuby, but I can't get it to work on jruby-head (and the problem might be in JRuby!) - "ruby-head" + # TODO: Use rspec-pending_for to exempt (and document) truffleruby-head from specific tests that are failing + # - truffleruby-head - runs-on: ubuntu-latest - continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: Setup Ruby & Bundle uses: ruby/setup-ruby@v1 with: - ruby-version: ${{ matrix.ruby }} - rubygems: ${{ matrix.rubygems }} - bundler: ${{ matrix.bundler }} + ruby-version: "${{ matrix.ruby }}" + rubygems: "${{ matrix.rubygems }}" + bundler: "${{ matrix.bundler }}" bundler-cache: true + - name: Run tests run: bundle exec rake test diff --git a/.github/workflows/legacy.yml b/.github/workflows/legacy.yml index 4e2cd45..b170f78 100644 --- a/.github/workflows/legacy.yml +++ b/.github/workflows/legacy.yml @@ -4,9 +4,8 @@ on: push: branches: - 'main' - - '*-maintenance' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -25,6 +24,8 @@ jobs: test: name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile strategy: fail-fast: false matrix: @@ -33,11 +34,14 @@ jobs: - "2.7.11" bundler: - none + gemfile: + - vanilla ruby: + - "3.0" + - "2.7" - "2.6" - "2.5" - "2.4" - - "2.3" runs-on: ubuntu-20.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 5317639..4896968 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -1,12 +1,15 @@ -name: Code Style Checks +# RuboCop Gradual isn't able to parse something in this repo. +# Not sure what exactly, and reported here: +# https://github.com/skryukov/rubocop-gradual/issues/12 +# As a result this workflow must allow failure. +name: Ruby - Style on: push: branches: - 'main' - - '*-maintenance' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -15,18 +18,26 @@ on: jobs: rubocop: - name: Rubocop - if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + name: RuboCop strategy: fail-fast: false matrix: - experimental: [false] + experimental: [true] + rubygems: + - latest + bundler: + - latest + gemfile: + - style ruby: - - "2.2" - runs-on: ubuntu-20.04 + - "3.2" + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Ruby & Bundle uses: ruby/setup-ruby@v1 with: @@ -34,5 +45,5 @@ jobs: rubygems: ${{ matrix.rubygems }} bundler: ${{ matrix.bundler }} bundler-cache: true - - name: Run Rubocop - run: bundle exec rubocop -DES + - name: Run RuboCop + run: bundle exec rake rubocop_gradual:check diff --git a/.github/workflows/supported.yml b/.github/workflows/supported.yml index e5343c1..a470846 100644 --- a/.github/workflows/supported.yml +++ b/.github/workflows/supported.yml @@ -1,12 +1,14 @@ -name: Current Ruby Support +name: Ruby Current Matrix + +env: + K_SOUP_COV_DO: false on: push: branches: - 'main' - - '*-maintenance' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -15,40 +17,49 @@ 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. - group: ${{ github.workflow }}-${{ github.ref }} + group: "${{ github.workflow }}-${{ github.ref }}" cancel-in-progress: true jobs: test: - name: Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} + name: Specs - Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile + runs-on: ubuntu-latest + continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} strategy: - fail-fast: false matrix: - experimental: [false] rubygems: - latest bundler: - latest + gemfile: + - vanilla ruby: - - "2.7" - - "3.0" - - "3.1" + #- '3.1' - 3.1 tests are run by coverage.yml + - '3.2' + - '3.3' + # TODO: Use rspec-pending_for to exempt (and document) truffleruby from specific tests that are failing + # - truffleruby - runs-on: ubuntu-latest - continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 + - name: Setup Ruby & Bundle uses: ruby/setup-ruby@v1 with: - ruby-version: ${{ matrix.ruby }} - rubygems: ${{ matrix.rubygems }} - bundler: ${{ matrix.bundler }} + ruby-version: "${{ matrix.ruby }}" + rubygems: "${{ matrix.rubygems }}" + bundler: "${{ matrix.bundler }}" bundler-cache: true + - name: Run tests run: bundle exec rake test diff --git a/.github/workflows/unsupported.yml b/.github/workflows/unsupported.yml index 56989f9..a6cb849 100644 --- a/.github/workflows/unsupported.yml +++ b/.github/workflows/unsupported.yml @@ -1,12 +1,14 @@ name: Unofficial Support +env: + K_SOUP_COV_DO: false + on: push: branches: - 'main' - - '*-maintenance' - - '*-dev' - '*-stable' + - '*-dev' tags: - '!*' # Do not execute on tags pull_request: @@ -18,25 +20,29 @@ on: # 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 + group: "${{ github.workflow }}-${{ github.ref }}" + cancel-in-progress: false jobs: test: - name: Specs - Ruby ${{ matrix.ruby }} ${{ matrix.name_extra || '' }} + name: Ruby ${{ matrix.ruby }} ${{matrix.gemfile}} ${{ matrix.name_extra || '' }} if: "!contains(github.event.commits[0].message, '[ci skip]') && !contains(github.event.commits[0].message, '[skip ci]')" + env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps + BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile strategy: fail-fast: false matrix: - experimental: [false] + experimental: [true] + gemfile: + - vanilla ruby: - - "2.2" + - "2.3" runs-on: ubuntu-20.04 continue-on-error: ${{ matrix.experimental || endsWith(matrix.ruby, 'head') }} steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Ruby & Bundle uses: ruby/setup-ruby@v1 with: diff --git a/.gitignore b/.gitignore index f2d16f1..1d9ee31 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ /.idea/ *.gem +gemfiles/*.gemfile.lock \ No newline at end of file diff --git a/.rubocop.yml b/.rubocop.yml index d7b8b52..6de99cd 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,15 +1,2 @@ -inherit_from: .rubocop_todo.yml - inherit_gem: - rubocop-lts: rubocop-lts.yml - -Metrics/BlockLength: - ExcludedMethods: - - context - - describe - - it - - shared_context - - shared_examples - - shared_examples_for - - namespace - - draw + rubocop-lts: config/rubygem_rspec.yml diff --git a/.rubocop_gradual.lock b/.rubocop_gradual.lock new file mode 100644 index 0000000..e2f1cad --- /dev/null +++ b/.rubocop_gradual.lock @@ -0,0 +1,20 @@ +{ + "bin/bundle:4041706560": [ + [67, 5, 20, "ThreadSafety/ClassInstanceVariable: Avoid class instance variables.", 2485198147] + ], + "bin/checksums:2906467651": [ + [12, 28, 2, "Lint/Syntax: unexpected token error\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5858765], + [14, 18, 2, "Lint/Syntax: unexpected token error\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5858765], + [20, 1, 4, "Lint/Syntax: unexpected token kELSE\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 2087423834], + [33, 1, 3, "Lint/Syntax: unexpected token kEND\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 193405706], + [45, 11, 2, "Lint/Syntax: unexpected token tLSHFT\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 5859461], + [46, 21, 1, "Lint/Syntax: unexpected token tSTAR\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177551], + [47, 17, 1, "Lint/Syntax: unexpected token tSTRING_BEG\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177543], + [53, 9, 3, "Lint/Syntax: unexpected token tCONSTANT\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 193466585], + [54, 14, 3, "Lint/Syntax: unexpected token tCONSTANT\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 193467647], + [54, 21, 1, "Lint/Syntax: unexpected token tCOLON\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177567], + [55, 21, 1, "Lint/Syntax: unexpected token tCOLON\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 177567], + [56, 22, 4, "Lint/Syntax: unexpected token tCONSTANT\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 2089414472], + [57, 22, 4, "Lint/Syntax: unexpected token tCONSTANT\n(Using Ruby 2.2 parser; configure using `TargetRubyVersion` parameter, under `AllCops`)", 2089414472] + ] +} diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml deleted file mode 100644 index b9c8271..0000000 --- a/.rubocop_todo.yml +++ /dev/null @@ -1,46 +0,0 @@ -# This configuration was generated by -# `rubocop --auto-gen-config` -# on 2023-03-17 05:51:32 -0600 using RuboCop version 0.68.1. -# The point is for the user to remove these configuration records -# one by one as the offenses are removed from the code base. -# Note that changes in the inspected code, or installation of new -# versions of RuboCop, may require this file to be generated again. - -# Offense count: 1 -Metrics/AbcSize: - Max: 17 - -# Offense count: 1 -Metrics/CyclomaticComplexity: - Max: 8 - -# Offense count: 1 -# Configuration parameters: CountComments, ExcludedMethods. -Metrics/MethodLength: - Max: 11 - -# Offense count: 1 -Metrics/PerceivedComplexity: - Max: 8 - -# Offense count: 2 -# Configuration parameters: EnforcedStyle. -# SupportedStyles: inline, group -Style/AccessModifierDeclarations: - Exclude: - - 'lib/version_gem/ruby.rb' - -# Offense count: 2 -Style/Documentation: - Exclude: - - 'spec/**/*' - - 'test/**/*' - - 'lib/version_gem.rb' - - 'lib/version_gem/api.rb' - -# Offense count: 32 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. -# URISchemes: http, https -Metrics/LineLength: - Max: 198 diff --git a/.simplecov b/.simplecov index e5b2083..bfe90c0 100644 --- a/.simplecov +++ b/.simplecov @@ -1,31 +1,3 @@ -# frozen_string_literal: true +require "kettle/soup/cover/config" -# To get coverage -# On Local, default (HTML) output, it just works, coverage is turned on: -# bundle exec rspec spec -# On Local, all output formats: -# COVER_ALL=true bundle exec rspec spec -# -# On CI, all output formats, the ENV variables CI is always set, -# and COVER_ALL, and CI_CODECOV, are set in the coverage.yml workflow only, -# so coverage only runs in that workflow, and outputs all formats. -# - -if RUN_COVERAGE - SimpleCov.start do - enable_coverage :branch - primary_coverage :branch - add_filter "spec" - track_files "lib/**/*.rb" - - if ALL_FORMATTERS - command_name "#{ENV["GITHUB_WORKFLOW"]} Job #{ENV["GITHUB_RUN_ID"]}:#{ENV["GITHUB_RUN_NUMBER"]}" - else - formatter SimpleCov::Formatter::HTMLFormatter - end - - minimum_coverage(100) - end -else - puts "Not running coverage on #{RUBY_ENGINE} #{RUBY_VERSION}" -end +SimpleCov.start diff --git a/.tool-versions b/.tool-versions index 33a8789..c1c77c3 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 2.7.7 +ruby 3.2.3 diff --git a/.yardopts b/.yardopts new file mode 100644 index 0000000..f9cf06c --- /dev/null +++ b/.yardopts @@ -0,0 +1 @@ +--plugin junk diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cbe457..d38e29b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed ### Removed +## [1.1.4] 2024-03-21 ([tag][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]) +### 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.2t]) ### Added - `VersionGem::Ruby` to help library CI integration against many different versions of Ruby (@pboling) @@ -49,7 +75,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial release, with basic version parsing API (@pboling) -[Unreleased]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.2...HEAD +[Unreleased]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.4...HEAD +[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/oauth2/-/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/oauth2/-/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/oauth2/-/tags/v1.1.2 [1.1.1]: https://gitlab.com/oauth-xx/version_gem/-/compare/v1.1.0...v1.1.1 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f2abe4..d042fda 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,47 @@ ## 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 +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]. + +## Release + +To release a new version: + +1. Run `bin/setup && bin/rake` as a tests, coverage, & linting sanity check +2. Update the version number in `version.rb` +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 + a. NOTE: Remember to [check the build][🧪build]! +6. Run `git checkout main` (Or whichever branch is considered `trunk`, e.g. `master`) +7. Run `git pull origin main` to ensure you will release the latest trunk code. +8. Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use same timestamp, and generate same checksums + a. Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS` (you'll need the zsh/datetime module, if running zsh) +9. Run `bundle exec rake build` +10. Run [`bin/checksums`](https://github.com/rubygems/guides/pull/325) to create SHA-256 and SHA-512 checksums + a. Checksums will be committed automatically by the script, but not pushed +11. 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] + +NOTE: You will need to have a public key in `certs/`, and list your cert in the +`gemspec`, in order to sign the new release. +See: [RubyGems Security Guide][🔒️rubygems-security-guide] + +## Contributors + +[![Contributors](https://contrib.rocks/image?repo=oauth-xx/version_gem)][🖐contributors] + +Made with [contributors-img][🖐contrib-rocks]. + +Also see GitLab Contributors: [https://gitlab.com/oauth-xx/version_gem/-/graphs/main][🚎contributors] + +## Contributing + Bug reports and pull requests are welcome on GitLab 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 the [code of conduct][conduct]. @@ -27,14 +69,17 @@ See: [RubyGems Security Guide][rubygems-security-guide] ## Contributors -See: [https://gitlab.com/oauth-xx/version_gem/-/graphs/main][🚎contributors] [comment]: <> (Following links are used by README, CONTRIBUTING) -[conduct]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/CODE_OF_CONDUCT.md [🚎contributors]: https://gitlab.com/oauth-xx/version_gem/-/graphs/main [⛳mail-list]: http://groups.google.com/group/oauth-ruby [🚎src-main]: https://gitlab.com/oauth-xx/version_gem -[🏘chat]: https://gitter.im/oauth-xx/version_gem -[rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems -[rubygems]: https://rubygems.org +[🧪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 +[🖐contrib-rocks]: https://contrib.rocks +[🖐contributors]: https://github.com/oauth-xx/version_gem/graphs/contributors +[💎rubygems]: https://rubygems.org +[🔒️rubygems-security-guide]: https://guides.rubygems.org/security/#building-gems +[🚎src-main]: https://github.com/oauth-xx/version_gem diff --git a/Gemfile b/Gemfile index 122c787..d51e535 100644 --- a/Gemfile +++ b/Gemfile @@ -1,37 +1,22 @@ # frozen_string_literal: true -source 'https://rubygems.org' - -# Specify your gem's dependencies in gitmoji-regex.gemspec -gemspec +source "https://rubygems.org" git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } +git_source(:gitlab) { |repo_name| "https://gitlab.com/#{repo_name}" } -gem 'rake', '~> 13.0' - -gem 'rspec', '~> 3.0' - -ruby_version = Gem::Version.new(RUBY_VERSION) -minimum_version = ->(version, engine = 'ruby') { ruby_version >= Gem::Version.new(version) && RUBY_ENGINE == engine } -coverage = minimum_version.call('2.6') -debugging = minimum_version.call('2.7') +# Include dependencies from .gemspec +gemspec -platforms :mri do - if coverage - gem 'codecov', '~> 0.6' # For CodeCov - gem 'simplecov', '~> 0.21', require: false - gem 'simplecov-cobertura' # XML for Jenkins - gem 'simplecov-json' # For CodeClimate - gem 'simplecov-lcov', '~> 0.8', require: false - end - if debugging - # Add `byebug` to your code where you want to drop to REPL - gem 'byebug' - gem 'pry-byebug' - end +platform :mri do + # Debugging + gem "byebug", ">= 11" end -platforms :jruby do - # Add `binding.pry` to your code where you want to drop to REPL - gem 'pry-debugger-jruby' -end +# Coverage +gem "kettle-soup-cover", "~> 1.0", ">= 1.0.2" + +# Linting +gem "rubocop-lts", "~> 8.1", ">= 8.1.1" # Linting for Ruby >= 2.2 +gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" +gem "rubocop-rspec", "~> 2.10" diff --git a/Gemfile.lock b/Gemfile.lock index e5dec12..7f9b886 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,101 +1,167 @@ PATH remote: . specs: - version_gem (1.1.2) + version_gem (1.1.4) GEM remote: https://rubygems.org/ specs: + ansi (1.5.0) ast (2.4.2) byebug (11.1.3) - codecov (0.6.0) - simplecov (>= 0.15, < 0.22) coderay (1.1.3) - diff-lcs (1.5.0) - docile (1.4.0) - jaro_winkler (1.5.4) - json (2.6.3) - method_source (1.0.0) - parallel (1.22.1) - parser (3.2.1.1) + diff-lcs (1.5.1) + diffy (3.4.3) + docile (1.4.1) + json (2.9.1) + kettle-soup-cover (1.0.4) + simplecov (~> 0.22) + simplecov-cobertura (~> 2.1) + simplecov-console (~> 0.9, >= 0.9.1) + simplecov-html (~> 0.12) + simplecov-lcov (~> 0.8) + simplecov-rcov (~> 0.3, >= 0.3.3) + simplecov_json_formatter (~> 0.1, >= 0.1.4) + version_gem (~> 1.1, >= 1.1.4) + language_server-protocol (3.17.0.3) + lint_roller (1.1.0) + method_source (1.1.0) + parallel (1.26.3) + parser (3.3.7.0) ast (~> 2.4.1) - pry (0.14.2) + racc + pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) - pry-byebug (3.10.1) - byebug (~> 11.0) - pry (>= 0.13, < 0.15) + racc (1.8.1) rainbow (3.1.1) - rake (13.0.6) - rexml (3.2.5) - rspec (3.12.0) - rspec-core (~> 3.12.0) - rspec-expectations (~> 3.12.0) - rspec-mocks (~> 3.12.0) - rspec-block_is_expected (1.0.2) - rspec-core - rspec-core (3.12.1) - rspec-support (~> 3.12.0) - rspec-expectations (3.12.2) + rake (13.2.1) + regexp_parser (2.10.0) + rexml (3.4.0) + rspec (3.13.0) + 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.2) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-mocks (3.12.4) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.12.0) - rspec-support (3.12.0) - rubocop (0.68.1) - jaro_winkler (~> 1.5.1) + rspec-support (~> 3.13.0) + rspec-support (3.13.2) + rubocop (1.70.0) + json (~> 2.3) + language_server-protocol (>= 3.17.0) parallel (~> 1.10) - parser (>= 2.5, != 2.5.1.1) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.36.2, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 1.6) - rubocop-lts (8.0.2) - rubocop-ruby2_2 (~> 1.0.4) - rubocop-performance (1.3.0) - rubocop (>= 0.68.0) - rubocop-rspec (1.41.0) - rubocop (>= 0.68.1) - rubocop-ruby2_2 (1.0.4) - rubocop (= 0.68.1) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.37.0) + parser (>= 3.3.1.0) + rubocop-capybara (2.21.0) + rubocop (~> 1.41) + rubocop-factory_bot (2.26.1) + rubocop (~> 1.61) + rubocop-gradual (0.3.6) + diff-lcs (>= 1.2.0, < 2.0) + diffy (~> 3.0) + parallel (~> 1.10) + rainbow (>= 2.2.2, < 4.0) + rubocop (~> 1.0) + rubocop-lts (8.1.1) + rubocop-ruby2_2 (>= 2.0.3, < 3) + standard-rubocop-lts (>= 1.0.3, < 3) + version_gem (>= 1.1.2, < 3) + rubocop-md (1.2.4) + rubocop (>= 1.45) + rubocop-packaging (0.5.2) + rubocop (>= 1.33, < 2.0) + rubocop-performance (1.23.1) + rubocop (>= 1.48.1, < 2.0) + rubocop-ast (>= 1.31.1, < 2.0) + rubocop-rake (0.6.0) + rubocop (~> 1.0) + rubocop-rspec (2.31.0) + rubocop (~> 1.40) + rubocop-capybara (~> 2.17) + rubocop-factory_bot (~> 2.22) + rubocop-rspec_rails (~> 2.28) + rubocop-rspec_rails (2.29.1) + rubocop (~> 1.61) + rubocop-ruby2_2 (2.0.5) + rubocop-gradual (~> 0.3, >= 0.3.1) + rubocop-md (~> 1.2) + rubocop-rake (~> 0.6) + rubocop-shopify (~> 2.14) + 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.15.1) + rubocop (~> 1.51) + rubocop-thread_safety (0.6.0) + rubocop (>= 1.48.1) ruby-progressbar (1.13.0) - simplecov (0.21.2) + simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) simplecov-cobertura (2.1.0) rexml simplecov (~> 0.19) - simplecov-html (0.12.3) - simplecov-json (0.2.3) - json + simplecov-console (0.9.2) + ansi simplecov + terminal-table + simplecov-html (0.13.1) simplecov-lcov (0.8.0) + simplecov-rcov (0.3.7) + simplecov (>= 0.4.1) simplecov_json_formatter (0.1.4) - unicode-display_width (1.5.0) + standard (1.44.0) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.70.0) + standard-custom (~> 1.0.0) + standard-performance (~> 1.6) + standard-custom (1.0.2) + lint_roller (~> 1.0) + rubocop (~> 1.50) + standard-performance (1.6.0) + lint_roller (~> 1.1) + rubocop-performance (~> 1.23.0) + standard-rubocop-lts (1.0.10) + rspec-block_is_expected (~> 1.0, >= 1.0.5) + standard (>= 1.35.1, < 2) + standard-custom (>= 1.0.2, < 2) + standard-performance (>= 1.3.1, < 2) + version_gem (>= 1.1.4, < 3) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.6.0) PLATFORMS arm64-darwin-22 + arm64-darwin-24 x86_64-darwin-19 x86_64-linux DEPENDENCIES - byebug - codecov (~> 0.6) - pry - pry-byebug - pry-debugger-jruby + byebug (>= 11) + kettle-soup-cover (~> 1.0, >= 1.0.2) + pry (~> 0.14) rake (~> 13.0) - rspec (~> 3.0) - rspec-block_is_expected - rubocop-lts (~> 8.0, >= 8.0.2) - rubocop-performance - rubocop-rspec - simplecov (~> 0.21) - simplecov-cobertura - simplecov-json - simplecov-lcov (~> 0.8) + rspec (~> 3.12) + rspec-block_is_expected (~> 1.0) + rubocop-lts (~> 8.1, >= 8.1.1) + rubocop-packaging (~> 0.5, >= 0.5.2) + rubocop-rspec (~> 2.10) version_gem! BUNDLED WITH - 2.4.8 + 2.6.3 diff --git a/README.md b/README.md index 585d2fe..59489ad 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,31 @@ This gem has a very niche purpose, which is: 2. while not interfering with `gemspec` parsing where the `VERSION` string is traditionally used. If this isn't **precisely** your use case you may be better off looking at -[`versionaire`](https://www.alchemists.io/projects/versionaire), a wonderful, performant, well-maintained, -gem from the Alchemists, or [`version_sorter`](https://rubygems.org/gems/version_sorter) from GitHub. +_[versionaire](https://www.alchemists.io/projects/versionaire)_, a wonderful, performant, well-maintained, +gem from the Alchemists, or _[version_sorter](https://rubygems.org/gems/version_sorter)_ from GitHub. For more discussion about this [see issue #2](https://gitlab.com/oauth-xx/version_gem/-/issues/2) +----- + +
+ +[![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] +[![Sponsor Me on Github][🖇sponsor-img]][🖇sponsor] + +Buy me coffee donation button + + +Patreon donate button + + +
+ +[⛳liberapay-img]: https://img.shields.io/liberapay/patrons/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 + ## Still here? Give your next library an introspectable `Version` module without breaking your Gemspec. @@ -27,7 +47,7 @@ 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 library was extracted from the gem _[oauth2](https://gitlab.com/oauth-xx/oauth2)_. This gem has no runtime dependencies. @@ -58,15 +78,15 @@ appended indicators: ♻️ - URL needs to be updated from SAAS integration. Find / Replace is insufficient. --> -| | Project | bundle add version_gem | -|:----|--------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| 1️⃣ | name, license, docs, standards | [![RubyGems.org][⛳️name-img]][⛳️gem] [![License: MIT][🖇src-license-img]][🖇src-license] [![RubyDoc.info][🚎yard-img]][🚎yard] [![SemVer 2.0.0][🧮semver-img]][🧮semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] | -| 2️⃣ | version & activity | [![Gem Version][⛳️version-img]][⛳️gem] [![Total Downloads][🖇DL-total-img]][⛳️gem] [![Download Rank][🏘DL-rank-img]][⛳️gem] [![Source Code][🚎src-main-img]][🚎src-main] [![Open PRs][🖐prs-o-img]][🖐prs-o] [![Closed PRs][🧮prs-c-img]][🧮prs-c] | -| 3️⃣ | maintanence & linting | [![Maintainability][⛳cclim-maint-img♻️]][⛳cclim-maint] [![Helpers][🖇triage-help-img]][🖇triage-help] [![Depfu][🏘depfu-img♻️]][🏘depfu♻️] [![Contributors][🚎contributors-img]][🚎contributors] [![Style][🖐style-wf-img]][🖐style-wf] [![Kloc Roll][🧮kloc-img]][🧮kloc] | -| 4️⃣ | testing | [![Supported][🏘sup-wf-img]][🏘sup-wf] [![Heads][🚎heads-wf-img]][🚎heads-wf] [![Unofficial Support][🖐uns-wf-img]][🖐uns-wf] | -| 5️⃣ | coverage & security | [![CodeClimate][⛳cclim-cov-img♻️]][⛳cclim-cov] [![CodeCov][🖇codecov-img♻️]][🖇codecov] [![Coveralls][🏘coveralls-img]][🏘coveralls] [![Security Policy][🚎sec-pol-img]][🚎sec-pol] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Code Coverage][🧮cov-wf-img]][🧮cov-wf] | -| 6️⃣ | resources | [![Get help on Codementor][🖇codementor-img]][🖇codementor] [![Chat][🏘chat-img]][🏘chat] [![Blog][🚎blog-img]][🚎blog] [![Wiki][🖐wiki-img]][🖐wiki] | -| 7️⃣ | spread 💖 | [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] [![Sponsor Me][🖇sponsor-img]][🖇sponsor] [![Tweet @ Peter][🏘tweet-img]][🏘tweet] [🌏][aboutme] [👼][angelme] [💻][coderme] | +| | Project | bundle add version_gem | +|:----|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| 1️⃣ | name, license, docs, standards | [![RubyGems.org][⛳️name-img]][⛳️gem] [![License: MIT][🖇src-license-img]][🖇src-license] [![RubyDoc.info][🚎yard-img]][🚎yard] [![SemVer 2.0.0][🧮semver-img]][🧮semver] [![Keep-A-Changelog 1.0.0][📗keep-changelog-img]][📗keep-changelog] | +| 2️⃣ | version & activity | [![Gem Version][⛳️version-img]][⛳️gem] [![Total Downloads][🖇DL-total-img]][⛳️gem] [![Download Rank][🏘DL-rank-img]][⛳️gem] [![Source Code][🚎src-main-img]][🚎src-main] [![Open PRs][🖐prs-o-img]][🖐prs-o] [![Closed PRs][🧮prs-c-img]][🧮prs-c] | +| 3️⃣ | maintenance & linting | [![Maintainability][⛳cclim-maint-img♻️]][⛳cclim-maint] [![Helpers][🖇triage-help-img]][🖇triage-help] [![Depfu][🏘depfu-img♻️]][🏘depfu♻️] [![Contributors][🚎contributors-img]][🚎contributors] [![Style][🖐style-wf-img]][🖐style-wf] [![Kloc Roll][🧮kloc-img]][🧮kloc] | +| 4️⃣ | testing | [![Supported][🏘sup-wf-img]][🏘sup-wf] [![Heads][🚎heads-wf-img]][🚎heads-wf] [![Unofficial Support][🖐uns-wf-img]][🖐uns-wf] | +| 5️⃣ | coverage & security | [![CodeClimate][⛳cclim-cov-img♻️]][⛳cclim-cov] [![CodeCov][🖇codecov-img♻️]][🖇codecov] [![Coveralls][🏘coveralls-img]][🏘coveralls] [![Security Policy][🚎sec-pol-img]][🚎sec-pol] [![CodeQL][🖐codeQL-img]][🖐codeQL] [![Code Coverage][🧮cov-wf-img]][🧮cov-wf] | +| 6️⃣ | resources | [![Get help on Codementor][🖇codementor-img]][🖇codementor] [![Chat][🏘chat-img]][🏘chat] [![Blog][🚎blog-img]][🚎blog] [![Wiki][🖐wiki-img]][🖐wiki] | +| 7️⃣ | spread 💖 | [![Liberapay Patrons][⛳liberapay-img]][⛳liberapay] [![Sponsor Me][🖇sponsor-img]][🖇sponsor] [![Tweet @ Peter][🏘tweet-img]][🏘tweet] [🌏][aboutme] [👼][angelme] [💻][coderme] | + [⛳cclim-maint]: https://codeclimate.com/github/pboling/version_gem/maintainability [⛳cclim-maint-img♻️]: https://api.codeclimate.com/v1/badges/b504d61c4ed1d46aec02/maintainability [🖇triage-help]: https://www.codetriage.com/pboling/version_gem @@ -217,11 +237,71 @@ MyLib::Version.to_a # => [0, 1, 0] MyLib::Version.to_h # => { major: 0, minor: 1, patch: 0, pre: "" } ``` -### Side benefit +### Side benefit #1 + +You can reference the DRY version from your gemspec, *and* still get accurate code coverage! + +```ruby +# Get the GEMFILE_VERSION without *require* "my_gem/version", for code coverage accuracy +# See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-825171399 +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! -#### Query Ruby Version (as of version 1.2.0) +### Zietwerk + +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): + +```shell +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. + +```ruby +# 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 + + +#### 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 @@ -230,7 +310,7 @@ a significant amount of boilerplate code across each project. Thus `VersionGem::Ruby` was born. It has the two optimized methods I always need: ```ruby -engine = 'ruby' +engine = "ruby" version = "2.7.7" gte_minimum_version?(version, engine) # Is the current version of Ruby greater than or equal to some minimum? @@ -257,29 +337,29 @@ The enhancement from this gem is only available at runtime. In `spec_helper.rb`: ```ruby -require 'version_gem/rspec' +require "version_gem/rspec" ``` Then you can write a test like: ```ruby -RSpec.describe MyLib::Version do - it_behaves_like 'a Version module', described_class +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 a la carte menu: -RSpec.describe MyLib::Version do +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_minor_as_integer - expect(described_class).to have_patch_as_integer - expect(described_class).to have_pre_as_nil_or_string - expect(described_class.to_h.keys).to match_array(%i[major minor patch pre]) - expect(described_class.to_a).to be_a(Array) + 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_minor_as_integer) + expect(described_class).to(have_patch_as_integer) + expect(described_class).to(have_pre_as_nil_or_string) + 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 ``` @@ -325,57 +405,39 @@ the [Pessimistic Version Constraint][pvc] with two digits of precision. For example: ```ruby -spec.add_dependency "version_gem", "~> 1.1" +spec.add_dependency("version_gem", "~> 1.1") ``` ## Security See [SECURITY.md](https://gitlab.com/oauth-xx/version_gem/-/blob/main/SECURITY.md). +[aboutme]: https://about.me/peter.boling +[actions]: https://github.com/oauth-xx/version_gem/actions +[angelme]: https://angel.co/peter-boling +[blogpage]: http://www.railsbling.com/tags/version_gem/ +[codecov_coverage]: https://codecov.io/gh/oauth-xx/version_gem +[code_triage]: https://www.codetriage.com/oauth-xx/version_gem +[chat]: https://gitter.im/oauth-xx/version_gem?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge +[climate_coverage]: https://codeclimate.com/github/oauth-xx/version_gem/test_coverage +[climate_maintainability]: https://codeclimate.com/github/oauth-xx/version_gem/maintainability [copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year - [conduct]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/CODE_OF_CONDUCT.md - [contributing]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/CONTRIBUTING.md - -[security]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/SECURITY.md - -[license]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/LICENSE.txt - +[devto]: https://dev.to/galtzo +[documentation]: https://rubydoc.info/github/oauth-xx/version_gem/main +[followme]: https://img.shields.io/twitter/follow/galtzo.svg?style=social&label=Follow +[gh_sponsors]: https://github.com/sponsors/pboling +[issues]: https://github.com/oauth-xx/version_gem/issues +[liberapay_donate]: https://liberapay.com/pboling/donate +[license]: LICENSE.txt [license-ref]: https://opensource.org/licenses/MIT - +[license-img]: https://img.shields.io/badge/License-MIT-green.svg +[peterboling]: http://www.peterboling.com [pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint - -[aboutme]: https://about.me/peter.boling - -[angelme]: https://angel.co/peter-boling - -[coderme]:http://coderwall.com/pboling - -[followme-img]: https://img.shields.io/twitter/follow/galtzo.svg?style=social&label=Follow - -[tweetme]: http://twitter.com/galtzo - -[source]: https://gitlab.com/oauth-xx/version_gem/ - -[actions]: https://github.com/oauth-xx/version_gem/actions - -[issues]: https://gitlab.com/oauth-xx/version_gem/-/issues - -[climate_maintainability]: https://codeclimate.com/github/pboling/version_gem/maintainability - -[climate_coverage]: https://codeclimate.com/github/pboling/version_gem/test_coverage - -[codecov_coverage]: https://codecov.io/gh/pboling/version_gem - -[code_triage]: https://www.codetriage.com/pboling/version_gem - -[blogpage]: http://www.railsbling.com/tags/version_gem/ - +[railsbling]: http://www.railsbling.com [rubygems]: https://rubygems.org/gems/version_gem - -[maintenancee_policy]: https://guides.rubyonrails.org/maintenance_policy.html#security-issues - -[liberapay_donate]: https://liberapay.com/pboling/donate - -[gh_sponsors]: https://github.com/sponsors/pboling +[security]: https://gitlab.com/oauth-xx/version_gem/-/blob/main/SECURITY.md +[semver]: http://semver.org/ +[source]: https://gitlab.com/oauth-xx/version_gem +[tweetme]: http://twitter.com/galtzo diff --git a/Rakefile b/Rakefile index cea63e1..b86bec3 100644 --- a/Rakefile +++ b/Rakefile @@ -1,22 +1,47 @@ # frozen_string_literal: true -%w[ - bundler/gem_tasks - rake/testtask - rspec/core/rake_task -].each { |f| require f } - -RSpec::Core::RakeTask.new(:spec) -desc 'alias spec => test' +require "bundler/gem_tasks" + +defaults = [] + +begin + require "rspec/core/rake_task" + RSpec::Core::RakeTask.new(:spec) + defaults << :spec +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 "alias test task to spec" task test: :spec begin - require 'rubocop/rake_task' - RuboCop::RakeTask.new + require "yard" + + YARD::Rake::YardocTask.new do |t| + t.files = [ + # Splats (alphabetical) + "lib/**/*.rb", + ] + end + defaults << :yard +rescue LoadError + task(:yard) do + warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") + end +end + +begin + require "rubocop/lts" + + Rubocop::Lts.install_tasks + defaults << :rubocop_gradual rescue LoadError - task :rubocop do - warn "RuboCop is disabled on #{RUBY_ENGINE} #{RUBY_VERSION}" + task(:rubocop_gradual) do + warn("NOTE: rubocop-lts isn't installed, or is disabled for #{RUBY_VERSION} in the current environment") end end -task default: %i[spec rubocop] +task default: defaults diff --git a/bin/bundle b/bin/bundle index 3c58bc4..00a1186 100755 --- a/bin/bundle +++ b/bin/bundle @@ -8,7 +8,7 @@ # this file is here to facilitate running it. # -require 'rubygems' +require "rubygems" m = Module.new do module_function @@ -18,18 +18,18 @@ m = Module.new do end def env_var_version - ENV.fetch('BUNDLER_VERSION', nil) + ENV.fetch("BUNDLER_VERSION", nil) end def cli_arg_version return unless invoked_as_script? # don't want to hijack other binstubs - return unless 'update'.start_with?(ARGV.first || ' ') # must be running `bundle update` + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` bundler_version = nil update_index = nil ARGV.each_with_index do |a, i| bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN - next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o bundler_version = Regexp.last_match(1) update_index = i @@ -38,16 +38,16 @@ m = Module.new do end def gemfile - gemfile = ENV.fetch('BUNDLE_GEMFILE', nil) + gemfile = ENV.fetch("BUNDLE_GEMFILE", nil) return gemfile if gemfile && !gemfile.empty? - File.expand_path('../Gemfile', __dir__) + File.expand_path("../Gemfile", __dir__) end def lockfile lockfile = case File.basename(gemfile) - when 'gems.rb' then gemfile.sub(/\.rb$/, gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) else "#{gemfile}.lock" end File.expand_path(lockfile) @@ -57,16 +57,18 @@ m = Module.new do return unless File.file?(lockfile) lockfile_contents = File.read(lockfile) - return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o Regexp.last_match(1) end + # rubocop:disable ThreadSafety/InstanceVariableInClassMethod def bundler_requirement @bundler_requirement ||= env_var_version || cli_arg_version || bundler_requirement_for(lockfile_version) end + # rubocop:enable ThreadSafety/InstanceVariableInClassMethod def bundler_requirement_for(version) return "#{Gem::Requirement.default}.a" unless version @@ -75,32 +77,32 @@ m = Module.new do requirement = bundler_version_gemsion.approximate_recommendation - return requirement unless Gem.rubygems_version < Gem::Version.new('2.7.0') + return requirement if Gem.rubygems_version >= Gem::Version.new("2.7.0") - requirement += '.a' if bundler_version_gemsion.prerelease? + requirement += ".a" if bundler_version_gemsion.prerelease? requirement end def load_bundler! - ENV['BUNDLE_GEMFILE'] ||= gemfile + ENV["BUNDLE_GEMFILE"] ||= gemfile activate_bundler end def activate_bundler gem_error = activation_error_handling do - gem 'bundler', bundler_requirement + gem("bundler", bundler_requirement) end return if gem_error.nil? require_error = activation_error_handling do - require 'bundler/version' + require "bundler/version" end return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) - warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" - exit 42 + warn("Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`") + exit(42) end def activation_error_handling @@ -113,4 +115,4 @@ end m.load_bundler! -load Gem.bin_path('bundler', 'bundle') if m.invoked_as_script? +load Gem.bin_path("bundler", "bundle") if m.invoked_as_script? diff --git a/bin/checksum b/bin/checksum deleted file mode 100755 index a596f85..0000000 --- a/bin/checksum +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -require 'digest/sha2' -gems = Dir['*.gem'] -puts "Found: #{gems.inspect}" -raise 'No Gems' if gems.length.zero? -raise 'Too Many Gems' if gems.length > 1 - -built_gem_path = gems.first -checksum512 = Digest::SHA512.new.hexdigest(File.read(built_gem_path)) -checksum512_path = "checksums/#{built_gem_path}.sha512" -File.write(checksum512_path, checksum512) - -checksum256 = Digest::SHA256.new.hexdigest(File.read(built_gem_path)) -checksum256_path = "checksums/#{built_gem_path}.sha256" -File.write(checksum256_path, checksum256) - -puts "You must now git add and commit '#{checksum256_path}' and '#{checksum512_path}'" diff --git a/bin/checksums b/bin/checksums new file mode 100755 index 0000000..5498152 --- /dev/null +++ b/bin/checksums @@ -0,0 +1,67 @@ +#!/usr/bin/env ruby + +# Script from https://github.com/rubygems/guides/pull/325 +require "digest/sha2" + +# Final clause of Regex `(?=\.gem)` is a positive lookahead assertion +# See: https://learnbyexample.github.io/Ruby_Regexp/lookarounds.html#positive-lookarounds +# Used to pattern match against a gem package name, which always ends with .gem. +# The positive lookahead ensures it is present, and prevents it from being captured. +VERSION_REGEX = /((\d+\.\d+\.\d+)([-.][0-9A-Za-z-]+)*)(?=\.gem)/ + +gem_path_parts = ARGV.first&.split("/") + +if gem_path_parts&.any? + gem_name = gem_path_parts.last + gem_pkg = File.join(gem_path_parts) + puts "Looking for: #{gem_pkg.inspect}" + gems = Dir[gem_pkg] + puts "Found: #{gems.inspect}" +else + gem_pkgs = File.join("pkg", "*.gem") + puts "Looking for: #{gem_pkgs.inspect}" + gems = Dir[gem_pkgs] + raise "Unable to find gems #{gem_pkgs}" if gems.empty? + + # Sort by newest last + # [ "my_gem-2.3.9.gem", "my_gem-2.3.11.pre.alpha.4.gem", "my_gem-2.3.15.gem", ... ] + gems.sort_by! { |gem| Gem::Version.new(gem[VERSION_REGEX]) } + gem_pkg = gems.last + gem_path_parts = gem_pkg.split("/") + gem_name = gem_path_parts.last + puts "Found: #{gems.length} gems; latest is #{gem_name}" +end + +checksum512 = Digest::SHA512.new.hexdigest(File.read(gem_pkg)) +checksum512_path = "checksums/#{gem_name}.sha512" +File.write(checksum512_path, checksum512) + +checksum256 = Digest::SHA256.new.hexdigest(File.read(gem_pkg)) +checksum256_path = "checksums/#{gem_name}.sha256" +File.write(checksum256_path, checksum256) + +version = gem_name[VERSION_REGEX] + +git_cmd = <<~GIT_MSG + git add checksums/* && \ + git commit -m "🔒️ Checksums for v#{version}" +GIT_MSG + +puts <<~RESULTS + [ GEM: #{gem_name} ] + [ VERSION: #{version} ] + [ GEM PKG LOCATION: #{gem_pkg} ] + [ CHECKSUM SHA-256: #{checksum256} ] + [ CHECKSUM SHA-512: #{checksum512} ] + [ CHECKSUM SHA-256 PATH: #{checksum256_path} ] + [ CHECKSUM SHA-512 PATH: #{checksum512_path} ] + + ... Running ... + + #{git_cmd} +RESULTS + +# This will replace the current process with the git process, and exit. +# Any command placed after this will not be run: +# See: https://www.akshaykhot.com/call-shell-commands-in-ruby +exec(git_cmd) diff --git a/bin/console b/bin/console index 668f28d..fb09256 100755 --- a/bin/console +++ b/bin/console @@ -1,8 +1,8 @@ #!/usr/bin/env ruby # frozen_string_literal: true -require 'bundler/setup' -require 'version_gem' +require "bundler/setup" +require "version_gem" # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. @@ -11,5 +11,5 @@ require 'version_gem' # require "pry" # Pry.start -require 'irb' +require "irb" IRB.start(__FILE__) diff --git a/bin/rake b/bin/rake index 5f615c2..4eb7d7b 100755 --- a/bin/rake +++ b/bin/rake @@ -8,12 +8,12 @@ # this file is here to facilitate running it. # -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -bundle_binstub = File.expand_path('bundle', __dir__) +bundle_binstub = File.expand_path("bundle", __dir__) if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + 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. @@ -21,7 +21,7 @@ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this end end -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -load Gem.bin_path('rake', 'rake') +load Gem.bin_path("rake", "rake") diff --git a/bin/rspec b/bin/rspec index d3f4959..cb53ebe 100755 --- a/bin/rspec +++ b/bin/rspec @@ -8,12 +8,12 @@ # this file is here to facilitate running it. # -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -bundle_binstub = File.expand_path('bundle', __dir__) +bundle_binstub = File.expand_path("bundle", __dir__) if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + 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. @@ -21,7 +21,7 @@ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this end end -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -load Gem.bin_path('rspec-core', 'rspec') +load Gem.bin_path("rspec-core", "rspec") diff --git a/bin/rubocop b/bin/rubocop index cc105e8..f8c5cfb 100755 --- a/bin/rubocop +++ b/bin/rubocop @@ -8,12 +8,12 @@ # this file is here to facilitate running it. # -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) -bundle_binstub = File.expand_path('bundle', __dir__) +bundle_binstub = File.expand_path("bundle", __dir__) if File.file?(bundle_binstub) - if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/ + if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300)) load(bundle_binstub) else abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. @@ -21,7 +21,7 @@ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this end end -require 'rubygems' -require 'bundler/setup' +require "rubygems" +require "bundler/setup" -load Gem.bin_path('rubocop', 'rubocop') +load Gem.bin_path("rubocop", "rubocop") diff --git a/certs/pboling.pem b/certs/pboling.pem index f11daea..3344386 100644 --- a/certs/pboling.pem +++ b/certs/pboling.pem @@ -1,27 +1,27 @@ -----BEGIN CERTIFICATE----- MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW -A2NvbTAeFw0yMjA5MTgyMzEyMzBaFw0yMzA5MTgyMzEyMzBaMEMxFTATBgNVBAMM +A2NvbTAeFw0yMzA5MjAxNzMwMjhaFw0yNDA5MTkxNzMwMjhaMEMxFTATBgNVBAMM DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy -LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA2Dn1GM3W -8K2/rvN1zz+06bQMcxD16ZKTihVwi7Pb1v3T98rM4Omnxohm3s+CwpDWGeiB9pj6 -0I/CTce0e4e3s8GKJSOrg93veImPSoH2PfsMsRsuB8wtqyiOCjLbF5o6S29x87r0 -LA5EawH+Lh4xqrkkPjdffsmLk7TaCig/vlmNvnzxXKBdey/X/aEJZXzzBiWRfVdh -O1fmMbVKyieGv9HK7+pLotIoT08bjDv8NP6V7zZslwQRqW27bQc6cqC2LGIbTYO3 -3jt1kQxfMWmhOictS6SzG9VtKSrXf0L4Neq0Gh7CLBZBvJFWJYZPfb92YNITDbd8 -emPOAQlXXNMN4mMXsEqtEhCPZRMnmwO+fOk/cC4AyglKi9lnQugCQoFV1XDMZST/ -CYbzdQyadOdPDInTntG6V+Uw51d2QGXZ6PDDfrx9+toc/3sl5h68rCUGgE6Q3jPz -srinqmBsxv2vTpmd4FjmiAtEnwH5/ooLpQYL8UdAjEoeysxS3AwIh+5dAgMBAAGj -fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQWU6D156a2cle+ -lb5RBfvVXlxTwjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG +LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA+a9UvHo3 +84k96WgU5Kk5HB+cLZs/modjorsTfqY67MJF5nNvAoqcKTUBW4uG+Zpfnm3jaDO5 +GxhJEIZWfndYzycHT2KMVQ1uTP82ba8ZaKrPlPIafkbui3mdds47qsmqHiblKERg +U532lkwfqHDlJwE7OBZQ59EwWWLynlT/yAUHpOBbqIuHKUxdpmBI+sIjrZcD1e05 +WmjkO6fwIdC5oM757aoPxIgXD587VOViH11Vkm2doskj4T8yONtwVHlcrrhJ9Bzd +/zdp6vEn7GZQrABvpOlqwWxQ72ZnFhJe/RJZf6CXOPOh69Ai0QKYl2a1sYuCJKS3 +nsBnxXJINEEznjR7rZjNUmYD+CZqfjzgPqedRxTlASe7iA4w7xZOqMDzcuhNwcUQ +tMEH6BTktxKP3jXZPXRfHCf6s+HRVb6vezAonTBVyydf5Xp5VwWkd6cwm+2BzHl5 +7kc/3lLxKMcsyEUprAsk8LdHohwZdC267l+RS++AP6Cz6x+nB3oGob19AgMBAAGj +fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQCSSas60GqqMjt +xR7LoY1gucEvtzAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD -ggGBAJ4SqhPlgUiLYIrphGXIaxXScHyvx4kixuvdrwhI4VoQV2qXvO7R6ZjOXVwX -f/z84BWPiTZ8lzThPbt1UV/BGwkvLw9I4RjOdzvUz3J42j9Ly6q63isall07bo3F -QWe/OBvIMBF1IbjC3q5vKPg4rq8+TkNRJNoE86U2gfR+PkW3jYYs9uiy0GloHDCP -k5xgaj0vSL0Uy5mTOPdk3K6a/sUGZyYniWK05zdhIi956ynhfGaFO988FFdVw5Jq -LHtXfIpAU8F7ES04syZSslxOluw7VlcSKyRdVIr737J92ZTduppB4PRGSKRgBsWV -hXTahRE72Kyw53Q7FAuzF3v102WxAAQ7BuMjW+MyCUT75fwPm3W4ELPL8HYkNGE7 -2oA5CPghFitRnvYS3GNrDG+9bNiRMEskeaBYwZ9UgReBQIwGYVj7LZk3UhiAsn44 -gwGrEXGQGDZ0NIgBcmvMOqlXjkGQwQvugKycJ024z89+fz2332vdZIKTrSxJrXGk -4/bR9A== +ggGBAMl9ifcw5p+PdvB7dCPoNKoVdp/2LbC9ztETHuYL2gUMJB6UoS3o9c/piSuR +V3ZMQaijmNu6ms1bWAtJ66LjmYrVflJtf9yp31Kierr9LpisMSUx2qbMOHGa8d2Z +vCUWPF8E9Cg0mP3GAyZ6qql8jDh/anUKeksPXqJvNxNPDu2DVYsa/IWdl96whzS4 +Bl7SwB1E7agps40UcshCSKaVDOU0M+XN6SrnJMElnBic+KSAkBkVFbzS0BE4ODZM +BgE6nYzQ05qhuvbE+oGdACTlemNtDDWCh0uw+7x0q2PocGIDU5zsPn/WNTkCXPmB +CHGvqDNWq4M7ncTKAaS2XExgyb7uPdq9fKiOW8nmH+zCiGzJXzBWwZlKf7L4Ht9E +a3f0e5C+zvee9Z5Ng9ciyfav9/fcXgYt5MjoBv27THr5XfBhgOCIHSYW2tqJmWKi +KuxrfYrN+9HvMdm+nZ6TypmKftHY3Gj+/uu+g8Icm/zrvTWAEE0mcJOkfrIoNPJb +pF8dMA== -----END CERTIFICATE----- diff --git a/checksums/version_gem-1.1.3.gem.sha256 b/checksums/version_gem-1.1.3.gem.sha256 new file mode 100644 index 0000000..cc08ec5 --- /dev/null +++ b/checksums/version_gem-1.1.3.gem.sha256 @@ -0,0 +1 @@ +7550b80b1c04510c9d6fd5b621da572759a2968a0111108045aa92a15344c8db \ No newline at end of file diff --git a/checksums/version_gem-1.1.3.gem.sha512 b/checksums/version_gem-1.1.3.gem.sha512 new file mode 100644 index 0000000..412bbb1 --- /dev/null +++ b/checksums/version_gem-1.1.3.gem.sha512 @@ -0,0 +1 @@ +e5512174a81a06c3cb9d9a8a18fd51155ffc500e8995dcca86280aed3ceb83c0da8511bbe4fa329038680050482ade5500adf64647327657ed74e94bca89ca80 \ No newline at end of file diff --git a/checksums/version_gem-1.1.4.gem.sha256 b/checksums/version_gem-1.1.4.gem.sha256 new file mode 100644 index 0000000..59f588e --- /dev/null +++ b/checksums/version_gem-1.1.4.gem.sha256 @@ -0,0 +1 @@ +dbc9374806b46c2e4c2766295fb520d3b108c3668c4f9ab78239c7b2e6285cec \ No newline at end of file diff --git a/checksums/version_gem-1.1.4.gem.sha512 b/checksums/version_gem-1.1.4.gem.sha512 new file mode 100644 index 0000000..cedcb42 --- /dev/null +++ b/checksums/version_gem-1.1.4.gem.sha512 @@ -0,0 +1 @@ +f26122ec619e518eba3625d699568037db0dd219c14fa5c10099a1ca01d2eb76571d2932d1ec42a941dd0c47ce47875316ba95f363720c1da88f7c6d9907c4ec \ No newline at end of file diff --git a/gemfiles/coverage.gemfile b/gemfiles/coverage.gemfile new file mode 100644 index 0000000..e8f3763 --- /dev/null +++ b/gemfiles/coverage.gemfile @@ -0,0 +1,10 @@ +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +source "https://rubygems.org" + +# Root Gemfile is only for local development only. It is not loaded on CI. +# On CI we only need the gemspecs' dependencies (including development dependencies). +# Exceptions, if any, will be found in gemfiles/*.gemfile +gem "kettle-soup-cover", "~> 1.0", ">= 1.0.2" + +gemspec path: "../" diff --git a/gemfiles/style.gemfile b/gemfiles/style.gemfile new file mode 100644 index 0000000..62f7175 --- /dev/null +++ b/gemfiles/style.gemfile @@ -0,0 +1,12 @@ +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +source "https://rubygems.org" + +# Root Gemfile is only for local development only. It is not loaded on CI. +# On CI we only need the gemspecs' dependencies (including development dependencies). +# Exceptions, if any, will be found in gemfiles/*.gemfile +gem "rubocop-lts", "~> 14.1", ">= 14.1.1" +gem "rubocop-packaging", "~> 0.5", ">= 0.5.2" +gem "rubocop-rspec", "~> 2.10" + +gemspec path: "../" diff --git a/gemfiles/vanilla.gemfile b/gemfiles/vanilla.gemfile new file mode 100644 index 0000000..b45c4e8 --- /dev/null +++ b/gemfiles/vanilla.gemfile @@ -0,0 +1,9 @@ +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } + +source "https://rubygems.org" + +# Root Gemfile is only for local development only. It is not loaded on CI. +# On CI we only need the gemspecs' dependencies (including development dependencies). +# Exceptions, if any, will be found in gemfiles/*.gemfile + +gemspec path: "../" diff --git a/lib/version_gem.rb b/lib/version_gem.rb index 9f54647..5749edf 100644 --- a/lib/version_gem.rb +++ b/lib/version_gem.rb @@ -1,8 +1,9 @@ # frozen_string_literal: true -require_relative 'version_gem/version' -require_relative 'version_gem/basic' +require_relative "version_gem/version" +require_relative "version_gem/basic" +# Namespace of this library module VersionGem end diff --git a/lib/version_gem/api.rb b/lib/version_gem/api.rb index e228c93..8a0c1cd 100644 --- a/lib/version_gem/api.rb +++ b/lib/version_gem/api.rb @@ -1,4 +1,7 @@ +# frozen_string_literal: true + module VersionGem + # Public API of this library module Api # The version number as a string # @@ -43,7 +46,7 @@ def to_h major: major, minor: minor, patch: patch, - pre: pre + pre: pre, } end @@ -60,7 +63,7 @@ def to_a # # @return [Array] def _to_a - @_to_a = self::VERSION.split('.') + @_to_a = self::VERSION.split(".") end end end diff --git a/lib/version_gem/basic.rb b/lib/version_gem/basic.rb index 14e7a00..c9d2ec6 100644 --- a/lib/version_gem/basic.rb +++ b/lib/version_gem/basic.rb @@ -1,15 +1,17 @@ # frozen_string_literal: true -require_relative 'error' -require_relative 'api' +require_relative "error" +require_relative "api" module VersionGem # This is a very *basic* version parser. Others could be built based on this pattern! module Basic - def self.extended(base) - raise Error, "VERSION must be defined before 'extend #{name}'" unless defined?(base::VERSION) + class << self + def extended(base) + raise Error, "VERSION must be defined before 'extend #{name}'" unless defined?(base::VERSION) - base.extend Api + base.extend(Api) + end end end end diff --git a/lib/version_gem/error.rb b/lib/version_gem/error.rb index 4bdf60e..ad478b4 100644 --- a/lib/version_gem/error.rb +++ b/lib/version_gem/error.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module VersionGem class Error < RuntimeError; end end diff --git a/lib/version_gem/rspec.rb b/lib/version_gem/rspec.rb index 79f556c..62a53d1 100644 --- a/lib/version_gem/rspec.rb +++ b/lib/version_gem/rspec.rb @@ -1,54 +1,54 @@ # frozen_string_literal: true -RSpec::Matchers.define :have_version_constant do +RSpec::Matchers.define(:have_version_constant) do match do |version_mod| version_mod.const_defined?(:VERSION, false) end end -RSpec::Matchers.define :have_version_as_string do +RSpec::Matchers.define(:have_version_as_string) do match do |version_mod| !version_mod::VERSION.nil? && version_mod::VERSION.is_a?(String) end end -RSpec::Matchers.define :have_major_as_integer do +RSpec::Matchers.define(:have_major_as_integer) do match do |version_mod| version_mod.major.is_a?(Integer) end end -RSpec::Matchers.define :have_minor_as_integer do +RSpec::Matchers.define(:have_minor_as_integer) do match do |version_mod| version_mod.minor.is_a?(Integer) end end -RSpec::Matchers.define :have_patch_as_integer do +RSpec::Matchers.define(:have_patch_as_integer) do match do |version_mod| version_mod.patch.is_a?(Integer) end end -RSpec::Matchers.define :have_pre_as_nil_or_string do +RSpec::Matchers.define(:have_pre_as_nil_or_string) do match do |version_mod| version_mod.pre.nil? || version_mod.pre.is_a?(String) end end -RSpec.shared_examples_for 'a Version module' do |version_mod| - it 'is introspectable' do - aggregate_failures 'introspectable api' do +RSpec.shared_examples_for("a Version module") do |version_mod| + it "is introspectable" do + aggregate_failures "introspectable api" do expect(version_mod).is_a?(Module) - expect(version_mod).to have_version_constant - expect(version_mod).to have_version_as_string - expect(version_mod.to_s).to be_a(String) - expect(version_mod).to have_major_as_integer - expect(version_mod).to have_minor_as_integer - expect(version_mod).to have_patch_as_integer - expect(version_mod).to have_pre_as_nil_or_string - expect(version_mod.to_h.keys).to match_array(%i[major minor patch pre]) - expect(version_mod.to_a).to be_a(Array) + expect(version_mod).to(have_version_constant) + expect(version_mod).to(have_version_as_string) + expect(version_mod.to_s).to(be_a(String)) + expect(version_mod).to(have_major_as_integer) + expect(version_mod).to(have_minor_as_integer) + expect(version_mod).to(have_patch_as_integer) + expect(version_mod).to(have_pre_as_nil_or_string) + expect(version_mod.to_h.keys).to(match_array(%i[major minor patch pre])) + expect(version_mod.to_a).to(be_a(Array)) end end end diff --git a/lib/version_gem/ruby.rb b/lib/version_gem/ruby.rb index f0a67f5..0bf9574 100644 --- a/lib/version_gem/ruby.rb +++ b/lib/version_gem/ruby.rb @@ -1,14 +1,16 @@ +# frozen_string_literal: true + module VersionGem # Helpers for library CI integration against many different versions of Ruby module Ruby RUBY_VER = ::Gem::Version.new(RUBY_VERSION) - def gte_minimum_version?(version, engine = 'ruby') + def gte_minimum_version?(version, engine = "ruby") RUBY_VER >= ::Gem::Version.new(version) && ::RUBY_ENGINE == engine end module_function :gte_minimum_version? - def actual_minor_version?(major, minor, engine = 'ruby') + def actual_minor_version?(major, minor, engine = "ruby") major.to_i == RUBY_VER.segments[0] && minor.to_i == RUBY_VER.segments[1] && ::RUBY_ENGINE == engine diff --git a/lib/version_gem/version.rb b/lib/version_gem/version.rb index cbd55ea..c99aa3b 100644 --- a/lib/version_gem/version.rb +++ b/lib/version_gem/version.rb @@ -2,7 +2,7 @@ module VersionGem module Version - VERSION = '1.1.2'.freeze + VERSION = "1.1.4" # This would work in this gem, but not in external libraries, # because version files are loaded in Gemspecs before bundler # has a chance to load dependencies. diff --git a/sig/debug_ide.rbs b/sig/debug_ide.rbs new file mode 100644 index 0000000..df62ef1 --- /dev/null +++ b/sig/debug_ide.rbs @@ -0,0 +1 @@ +DEBUG_IDE: bool diff --git a/sig/debug_jruby.rbs b/sig/debug_jruby.rbs new file mode 100644 index 0000000..8ba0b4c --- /dev/null +++ b/sig/debug_jruby.rbs @@ -0,0 +1 @@ +DEBUG_JRUBY: bool diff --git a/sig/debugging.rbs b/sig/debugging.rbs new file mode 100644 index 0000000..ca05e2f --- /dev/null +++ b/sig/debugging.rbs @@ -0,0 +1 @@ +DEBUGGING: bool diff --git a/spec/config/rspec/rspec_block_is_expected.rb b/spec/config/rspec/rspec_block_is_expected.rb new file mode 100644 index 0000000..8e0cb09 --- /dev/null +++ b/spec/config/rspec/rspec_block_is_expected.rb @@ -0,0 +1,5 @@ +require "rspec/block_is_expected" + +# This breaks RSpec v2, which may be used to run transpec. +# So allow it to be turned off. +require "rspec/block_is_expected/matchers/not" unless ENV["TRANSPEC"] == "true" diff --git a/spec/config/rspec/rspec_core.rb b/spec/config/rspec/rspec_core.rb index 7ee4005..0d02f5f 100644 --- a/spec/config/rspec/rspec_core.rb +++ b/spec/config/rspec/rspec_core.rb @@ -2,12 +2,12 @@ RSpec.configure do |config| # Enable flags like --only-failures and --next-failure - config.example_status_persistence_file_path = '.rspec_status' + config.example_status_persistence_file_path = ".rspec_status" # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! - config.expect_with :rspec do |c| + config.expect_with(:rspec) do |c| c.syntax = :expect end end diff --git a/spec/helpers/under_test.rb b/spec/helpers/under_test.rb new file mode 100644 index 0000000..42433b0 --- /dev/null +++ b/spec/helpers/under_test.rb @@ -0,0 +1,5 @@ +# If your version file will be required by a gemspec, do not do this, instead follow README.md#usage +module UnderTest + VERSION = "12.34.56.pre-78" + extend VersionGem::Api +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 055f2b6..dcacb4f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,54 +1,53 @@ # frozen_string_literal: true -# external gems -require 'rspec/block_is_expected' - -# RSpec Helpers from this gem -require 'version_gem/rspec' -# Ruby Helpers from this gem (use load because we want line coverage) -load 'version_gem/ruby.rb' +begin + # This does not require "simplecov", + # because that has a side-effect of running `.simplecov` + require "kettle-soup-cover" +rescue LoadError + puts "Not running code coverage" +end -# RSpec Configs -require 'config/rspec/rspec_core' +DEBUG = ENV.fetch("DEBUG", nil) == "true" +DEBUG_IDE = ENV.fetch("DEBUG_IDE", "false") == "true" -DEBUG = ENV['DEBUG'] == 'true' +# Ruby Helpers from this gem. +# - Not requiring because we want line coverage +# - Not loading because we don't want to manage the constant re-definition +module VersionGem + # Helpers for library CI integration against many different versions of Ruby + module Faux + RUBY_VER = ::Gem::Version.new(RUBY_VERSION) -debugging = VersionGem::Ruby.gte_minimum_version?('2.7') && DEBUG -RUN_COVERAGE = VersionGem::Ruby.gte_minimum_version?('2.6') && (ENV['COVER_ALL'] || ENV['CI_CODECOV'] || ENV['CI'].nil?) -ALL_FORMATTERS = VersionGem::Ruby.actual_minor_version?(2, 7) && (ENV['COVER_ALL'] || ENV['CI_CODECOV'] || ENV['CI']) -VersionGem::Ruby.send(:remove_const, :RUBY_VER) + def gte_minimum_version?(version, engine = "ruby") + RUBY_VER >= ::Gem::Version.new(version) && ::RUBY_ENGINE == engine + end + module_function :gte_minimum_version? -if DEBUG - if debugging - require 'byebug' - elsif minimum_version.call('2.7', 'jruby') - require 'pry-debugger-jruby' + def actual_minor_version?(major, minor, engine = "ruby") + major.to_i == RUBY_VER.segments[0] && + minor.to_i == RUBY_VER.segments[1] && + ::RUBY_ENGINE == engine + end + module_function :actual_minor_version? end end -if RUN_COVERAGE - require 'simplecov' # Config file `.simplecov` is run immediately when simplecov loads - require 'codecov' - require 'simplecov-json' - require 'simplecov-lcov' - require 'simplecov-cobertura' - # This will override any formatter set in .simplecov - if ALL_FORMATTERS - SimpleCov::Formatter::LcovFormatter.config do |c| - c.report_with_single_file = true - c.single_report_path = 'coverage/lcov.info' - end +# RSpec Helpers from this gem +require "version_gem/rspec" - SimpleCov.formatters = [ - SimpleCov::Formatter::HTMLFormatter, - SimpleCov::Formatter::CoberturaFormatter, # XML for Jenkins - SimpleCov::Formatter::LcovFormatter, - SimpleCov::Formatter::JSONFormatter, # For CodeClimate - SimpleCov::Formatter::Codecov # For CodeCov - ] - end -else - puts "Not running coverage on #{RUBY_ENGINE} #{RUBY_VERSION}" -end +# RSpec Configs +require_relative "config/rspec/rspec_core" +require_relative "config/rspec/rspec_block_is_expected" + +# RSpec Helpers which do not depend on gem internals +# NONE + +# Last thing before this gem is code coverage: +require "simplecov" if defined?(Kettle) && Kettle::Soup::Cover::DO_COV + +# This gem +require "version_gem" -require 'version_gem' +# RSpec Helpers which depend on gem internals +require_relative "helpers/under_test" diff --git a/spec/version_gem/api_spec.rb b/spec/version_gem/api_spec.rb index 8163288..38f9d54 100644 --- a/spec/version_gem/api_spec.rb +++ b/spec/version_gem/api_spec.rb @@ -1,44 +1,37 @@ # frozen_string_literal: true -# If your version file will be required by a gemspec, do not do this, instead follow README.md#usage -module UnderTest - VERSION = '12.34.56.pre-78'.freeze - extend VersionGem::Api -end +RSpec.describe(VersionGem::Api) do + context "when under test" do + subject(:under_test) { UnderTest } -RSpec.describe UnderTest do - it_behaves_like 'a Version module', described_class + it_behaves_like "a Version module", UnderTest - it 'is greater than 0.1.0' do - expect(Gem::Version.new(described_class) > Gem::Version.new('0.1.0')).to be(true) - end + it "is greater than 0.1.0" do + expect(Gem::Version.new(under_test) > Gem::Version.new("0.1.0")).to(be(true)) + end - it 'major version is an integer' do - expect(described_class.major).to eq(12) - end + it "major version is an integer" do + expect(under_test.major).to(eq(12)) + end - it 'minor version is an integer' do - expect(described_class.minor).to eq(34) - end + it "minor version is an integer" do + expect(under_test.minor).to(eq(34)) + end - it 'patch version is an integer' do - expect(described_class.patch).to eq(56) - end + it "patch version is an integer" do + expect(under_test.patch).to(eq(56)) + end - it 'pre version is an string' do - expect(described_class.pre).to eq('pre-78') - end + it "pre version is an string" do + expect(under_test.pre).to(eq("pre-78")) + end - it 'returns a Hash' do - expect(described_class.to_h).to eq( - major: 12, - minor: 34, - patch: 56, - pre: 'pre-78' - ) - end + it "returns a Hash" do + expect(under_test.to_h).to(eq(major: 12, minor: 34, patch: 56, pre: "pre-78")) + end - it 'returns an Array' do - expect(described_class.to_a).to eq([12, 34, 56, 'pre-78']) + it "returns an Array" do + expect(under_test.to_a).to(eq([12, 34, 56, "pre-78"])) + end end end diff --git a/spec/version_gem/basic_spec.rb b/spec/version_gem/basic_spec.rb index d58b30b..c55bd9c 100644 --- a/spec/version_gem/basic_spec.rb +++ b/spec/version_gem/basic_spec.rb @@ -2,12 +2,12 @@ # If your version file will be required by a gemspec, do not do this, instead follow README.md#usage -RSpec.describe VersionGem::Basic do - it 'raises when no VERSION' do +RSpec.describe(VersionGem::Basic) do + it "raises when no VERSION" do expect do Module.new do extend VersionGem::Basic end - end.to raise_error(VersionGem::Error, "VERSION must be defined before 'extend VersionGem::Basic'") + end.to(raise_error(VersionGem::Error, "VERSION must be defined before 'extend VersionGem::Basic'")) end end diff --git a/spec/version_gem/error_spec.rb b/spec/version_gem/error_spec.rb index 07d0c4c..f33e104 100644 --- a/spec/version_gem/error_spec.rb +++ b/spec/version_gem/error_spec.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true -RSpec.describe VersionGem::Error do - it 'is a standard error' do +RSpec.describe(VersionGem::Error) do + it "is a standard error" do expect(described_class).is_a?(StandardError) end - it 'can be raised' do - expect { raise(described_class, 'moo') }.to raise_error(described_class, 'moo') + describe "raise" do + subject(:raising) { raise(described_class, "moo") } + + it "can be raised" do + block_is_expected.to raise_error(described_class, "moo") + end end end diff --git a/spec/version_gem/ruby_spec.rb b/spec/version_gem/ruby_spec.rb index 65babd5..ed5cc0d 100644 --- a/spec/version_gem/ruby_spec.rb +++ b/spec/version_gem/ruby_spec.rb @@ -1,48 +1,50 @@ # frozen_string_literal: true # Not loaded by the gem by default, so loaded here: -require 'version_gem/ruby' +require "version_gem/ruby" -RSpec.describe VersionGem::Ruby do - it 'is a module' do +RSpec.describe(VersionGem::Ruby) do + let(:engine) { "ruby" } + + it "is a module" do expect(described_class).is_a?(Module) end - let(:engine) { 'ruby' } - - describe '#gte_minimum_version?' do - let(:version) { ::RUBY_VERSION } - + describe "#gte_minimum_version?" do subject(:gte_minimum_version) { described_class.gte_minimum_version?(version, engine) } - it 'returns true when current ruby greater than minimum' do - expect(gte_minimum_version).to eq(true) + let(:version) { RUBY_VERSION } + + it "returns true when current ruby greater than minimum" do + expect(gte_minimum_version).to(be(true)) end - context 'when not gte minimum' do - let(:version) { '99.0.0' } - it 'returns false when current ruby not greater than minimum' do - expect(gte_minimum_version).to eq(false) + context "when not gte minimum" do + let(:version) { "99.0.0" } + + it "returns false when current ruby not greater than minimum" do + expect(gte_minimum_version).to(be(false)) end end end - describe '#actual_minor_version?' do - let(:major) { '1' } - let(:minor) { '8' } - + describe "#actual_minor_version?" do subject(:actual_minor_version) { described_class.actual_minor_version?(major, minor, engine) } - it 'returns false when actual ruby not same' do - expect(actual_minor_version).to eq(false) + let(:major) { "1" } + let(:minor) { "8" } + + it "returns false when actual ruby not same" do + expect(actual_minor_version).to(be(false)) end - context 'when actual' do + context "when actual" do let(:ruby_ver) { VersionGem::Ruby::RUBY_VER } let(:major) { ruby_ver.segments[0] } let(:minor) { ruby_ver.segments[1] } - it 'returns true' do - expect(actual_minor_version).to eq(true) + + it "returns true" do + expect(actual_minor_version).to(be(true)) end end end diff --git a/spec/version_gem/version_spec.rb b/spec/version_gem/version_spec.rb index c19a98a..507ed6b 100644 --- a/spec/version_gem/version_spec.rb +++ b/spec/version_gem/version_spec.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true -RSpec.describe VersionGem::Version do - it_behaves_like 'a Version module', described_class +RSpec.describe(VersionGem::Version) do + it_behaves_like "a Version module", described_class - it 'is greater than 0.1.0' do - expect(Gem::Version.new(described_class) > Gem::Version.new('0.1.0')).to be(true) + it "is greater than 0.1.0" do + expect(Gem::Version.new(described_class) > Gem::Version.new("0.1.0")).to(be(true)) end - it 'is greater than 1.0.0' do - expect(Gem::Version.new(described_class) > Gem::Version.new('1.0.0')).to be(true) + it "is greater than 1.0.0" do + expect(Gem::Version.new(described_class) > Gem::Version.new("1.0.0")).to(be(true)) end end diff --git a/spec/version_gem_spec.rb b/spec/version_gem_spec.rb index 6a7dfda..55b0c06 100644 --- a/spec/version_gem_spec.rb +++ b/spec/version_gem_spec.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -RSpec.describe VersionGem do - it 'is a module' do +RSpec.describe(VersionGem) do + it "is a module" do expect(described_class).is_a?(Module) end - it 'extends Version with Basic' do + it "extends Version with Basic" do expect(described_class::Version).is_a?(VersionGem::Basic) end end diff --git a/version_gem.gemspec b/version_gem.gemspec index aa662ac..fb3c2f5 100644 --- a/version_gem.gemspec +++ b/version_gem.gemspec @@ -2,64 +2,59 @@ # Get the GEMFILE_VERSION without *require* "my_gem/version", for code coverage accuracy # See: https://github.com/simplecov-ruby/simplecov/issues/557#issuecomment-825171399 -load 'lib/version_gem/version.rb' +load "lib/version_gem/version.rb" gem_version = VersionGem::Version::VERSION VersionGem::Version.send(:remove_const, :VERSION) Gem::Specification.new do |spec| - spec.cert_chain = ['certs/pboling.pem'] - spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $PROGRAM_NAME =~ /gem\z/ + spec.cert_chain = ["certs/pboling.pem"] + spec.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $PROGRAM_NAME.end_with?("gem") - spec.name = 'version_gem' + spec.name = "version_gem" spec.version = gem_version - spec.authors = ['Peter Boling'] - spec.email = ['peter.boling@gmail.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.required_ruby_version = '>= 2.2' - - spec.metadata['homepage_uri'] = spec.homepage - 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['mailing_list_uri'] = 'https://groups.google.com/g/oauth-ruby' - spec.metadata['funding_uri'] = 'https://liberapay.com/pboling' - spec.metadata['rubygems_mfa_required'] = 'true' + spec.authors = ["Peter Boling"] + spec.email = ["peter.boling@gmail.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.required_ruby_version = ">= 2.2" + + spec.metadata["homepage_uri"] = spec.homepage + 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["mailing_list_uri"] = "https://groups.google.com/g/oauth-ruby" + spec.metadata["funding_uri"] = "https://liberapay.com/pboling" + spec.metadata["rubygems_mfa_required"] = "true" spec.files = Dir[ - 'lib/**/*', - 'CHANGELOG.md', - 'CODE_OF_CONDUCT.md', - 'CONTRIBUTING.md', - 'LICENSE.txt', - 'README.md', - 'SECURITY.md', + "lib/**/*", + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE.txt", + "README.md", + "SECURITY.md", ] - spec.require_paths = ['lib'] + spec.require_paths = ["lib"] # Tests - spec.add_development_dependency 'rspec' - spec.add_development_dependency 'rspec-block_is_expected' + spec.add_development_dependency("rspec", "~> 3.12") # ruby >= 0 + spec.add_development_dependency("rspec-block_is_expected", "~> 1.0") # ruby >= 1.8.7 # Development Tasks - spec.add_development_dependency 'rake' + spec.add_development_dependency("rake", "~> 13.0") # ruby >= 2.2 - # Debugger - spec.add_development_dependency 'pry' + # Dev Console - Binding.pry - Irb replacement + spec.add_development_dependency("pry", "~> 0.14") # ruby >= 2.0 - # Linting - rubocop-lts v8 is a rubocop wrapper for Ruby >= 2.2, + # Linting - rubocop-lts v10 is a rubocop wrapper for Ruby >= 2.3, # and should only be bumped when dropping old Ruby support - # see: https://dev.to/pboling/rubocop-lts-1e31 - spec.add_development_dependency 'rubocop-lts', ['~> 8.0', '>= 8.0.2'] - - # Lint RSpec code - spec.add_development_dependency 'rubocop-rspec' - - # Add performance linting - spec.add_development_dependency 'rubocop-performance' + # 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'] end