Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 30 additions & 12 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,15 @@ jobs:
# lockfile bump misses the bundler cache and installs a full Rails tree
# from source. Still bounds a hang well under the 6-hour default.
timeout-minutes: 30
name: "rspec - Ruby ${{ matrix.ruby }} / ${{ matrix.gemfile }}"
name: "rspec - Ruby ${{ matrix.ruby }}"
strategy:
fail-fast: false
matrix:
# Covers the supported range from the floor (Ruby 3.2 / Rails 6.1) to
# the current ceiling (Ruby 3.4 / Rails 8.1). Curated pairs avoid
# Ruby/Rails combinations that are not mutually supported.
include:
- { ruby: "3.2", gemfile: rails_6_1 }
- { ruby: "3.2", gemfile: rails_7_1 }
- { ruby: "3.3", gemfile: rails_7_2 }
- { ruby: "3.3", gemfile: rails_8_0 }
- { ruby: "3.4", gemfile: rails_8_0 }
- { ruby: "3.4", gemfile: rails_8_1 }
ruby: ["3.2", "3.3", "3.4", "4.0"]
env:
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
# Rails lives in the gemspec's generator development group. Matcher tests
# prove that the runtime works without installing that dependency tree.
BUNDLE_WITHOUT: generators
steps:
# Both actions track their major tag, so upstream patch releases arrive
# without a commit here. Dependabot opens a PR for each new major.
Expand All @@ -65,6 +58,31 @@ jobs:
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run rspec
run: bundle exec rspec spec/rspec

generators:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
timeout-minutes: 30
name: "generators - Ruby ${{ matrix.ruby }} / ${{ matrix.gemfile }}"
strategy:
fail-fast: false
matrix:
include:
- { ruby: "3.2", gemfile: rails_6_1 }
- { ruby: "3.4", gemfile: rails_8_1 }
env:
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run rspec
run: bundle exec rspec

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ gemfiles/*.gemfile.lock

# local mise tool configuration
mise.toml

# private project roadmap
/ROADMAP.md
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
## [Unreleased]

### Fixed
- Exact arrays enforce full key structure for Hash elements. Extra null-valued keys and missing keys that happen to accept blank values no longer pass inside tuples.
- Nested key checks preserve each key's parent association. Objects with the same nested key names attached to different parents no longer match when the affected values are `null`.
- Regexp schemas require a String value instead of matching `to_s`. Numeric values and `null` no longer satisfy permissive regular expressions.

### Changed
- Removed ActiveSupport blank/present core extensions in favor of a JSON-focused internal helper with the same relevant semantics.
- Runtime dependencies are now only `diffy` and `rspec-expectations`. Rails, Railties, ActiveSupport, and `rspec-rails` are no longer installed for matcher-only consumers. Projects using the optional generators must provide Rails themselves.
- The compatibility matrix tests matcher behavior without Rails on Ruby 3.2, 3.3, 3.4, and 4.0. Separate generator jobs exercise Rails 6.1 and Rails 8.1 at the supported boundaries.
- The README now documents strict key behavior, schema dispatch, errors, array shorthand, supported runtimes, and the fact that this is a general JSON shape matcher rather than a JSON:API implementation.
- CI runs `actions/checkout@v7`, up from v5, alongside `ruby/setup-ruby@v1`. Both track their major tag, so upstream patch releases arrive without a commit here and Dependabot opens a pull request for each new major. Checkout also runs with `persist-credentials: false`: no step needs git credentials, and bundler evaluates gemspec and native-extension code from the branch under test.
- The workflow runs once per change rather than twice. `push` is scoped to `master`, so a branch with an open pull request no longer builds under both events, and a `concurrency` group cancels superseded pull request runs. Runs on `master` are left alone, so every commit there keeps a result.
- `rubocop` and `bundler-audit` share one job definition instead of two byte-identical ones, and every job carries `timeout-minutes: 30` in place of the six-hour default.

### Added
- Top-level Class and Regexp schemas now work for scalar JSON documents, using the same dispatch rules as nested values.
- `match_json_schema` exposes an RSpec description for one-line and documentation formatter output.
- Direct unit coverage for schema matching, traversal, constraints, and the Rails generators; randomized spec ordering; Ruby warnings; and a 90% SimpleCov floor.
- Contributor and security policy documents, included in the packaged gem.
- A weekly `schedule` trigger, so `bundler-audit` reports an advisory published against a lockfile nobody has touched. Only the audit runs on that trigger. `workflow_dispatch` runs it on demand and is also how the cron is re-armed, since GitHub disables scheduled workflows after 60 days without repository activity.

### Removed
- The internal example interface fixture from the packaged library; it now lives under test support.
- Redundant Rails 7.1, 7.2, and 8.0 appraisal files after reducing generator compatibility checks to the supported boundaries.

## [1.6.0] - 2026-09-03

### Fixed
Expand Down
24 changes: 24 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Contributing

Bug reports and pull requests are welcome.

## Setup

Use the Ruby version declared in `.ruby-version` and Bundler 4.0.4:

```sh
gem install bundler -v 4.0.4
bundle install
```

Run the local checks before opening a pull request:

```sh
bundle exec rspec
bundle exec rubocop
bundle exec bundle-audit check --update
```

Matcher changes should include focused examples under `spec/rspec/json_api`. Generator changes should include examples under `spec/generators` and be checked against both appraisal gemfiles.

Keep pull requests focused and explain user-visible behavior changes in `CHANGELOG.md`. By participating, you agree to follow the [code of conduct](CODE_OF_CONDUCT.md).
12 changes: 8 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

# Specify your gem's dependencies in rspec-json_api.gemspec
# Runtime dependencies come from the gemspec.
gemspec

gem "activesupport", ">= 6.1.4.1"
gem "bundler-audit", "~> 0.9"
gem "diffy", "~> 3.4"
gem "rake", "~> 13.2"
gem "rspec-rails", ">= 5.0.2"
gem "rspec", "~> 3.13"
gem "rubocop", "~> 1.65"
gem "simplecov", "~> 0.22"

group :generators do
gem "railties", ">= 6.1.4.1"
gem "rspec-rails", ">= 5.0.2"
end
26 changes: 18 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
PATH
remote: .
specs:
rspec-json_api (1.6.0)
activesupport (>= 6.1.4.1)
rspec-json_api (2.0.0)
diffy (>= 3.4.2)
railties (>= 6.1.4.1)
rspec-rails (>= 5.0.2)
rspec-expectations (~> 3.0)

GEM
remote: https://rubygems.org/
Expand Down Expand Up @@ -51,6 +49,7 @@ GEM
crass (1.0.7)
diff-lcs (1.6.2)
diffy (3.4.4)
docile (1.4.1)
drb (2.2.3)
erb (6.0.7)
erubi (1.13.1)
Expand Down Expand Up @@ -78,7 +77,7 @@ GEM
racc (~> 1.4)
nokogiri (1.19.4-x86_64-linux-gnu)
racc (~> 1.4)
parallel (2.1.0)
parallel (1.28.0)
parser (3.3.12.0)
ast (~> 2.4.1)
racc
Expand Down Expand Up @@ -113,7 +112,7 @@ GEM
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.4.2)
rbs (4.2.0)
rbs (4.1.3)
logger
prism (>= 1.6.0)
tsort
Expand All @@ -125,6 +124,10 @@ GEM
regexp_parser (2.12.0)
reline (0.7.0)
io-console (~> 0.5)
rspec (3.13.2)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
Expand Down Expand Up @@ -158,6 +161,12 @@ GEM
prism (~> 1.7)
ruby-progressbar (1.13.0)
securerandom (0.4.1)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.13.2)
simplecov_json_formatter (0.1.4)
thor (1.5.0)
tsort (0.2.0)
tzinfo (2.0.6)
Expand All @@ -176,13 +185,14 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
activesupport (>= 6.1.4.1)
bundler-audit (~> 0.9)
diffy (~> 3.4)
railties (>= 6.1.4.1)
rake (~> 13.2)
rspec (~> 3.13)
rspec-json_api!
rspec-rails (>= 5.0.2)
rubocop (~> 1.65)
simplecov (~> 0.22)

BUNDLED WITH
4.0.4
Loading