Skip to content

Commit 652b3ce

Browse files
authored
Merge pull request #6 from MarioRuiz/chore/release-0-12-0
prepare 0.12.0 release: OpenAPI 3.1 support, safety, and tests
2 parents e01d86d + 47f2093 commit 652b3ce

31 files changed

Lines changed: 2309 additions & 556 deletions

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
fail-fast: false
14+
matrix:
15+
ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4']
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Ruby ${{ matrix.ruby-version }}
21+
uses: ruby/setup-ruby@v1
22+
with:
23+
ruby-version: ${{ matrix.ruby-version }}
24+
bundler-cache: true
25+
26+
- name: Run tests
27+
run: bundle exec rake spec
28+
29+
lint:
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
34+
- name: Set up Ruby
35+
uses: ruby/setup-ruby@v1
36+
with:
37+
ruby-version: '3.3'
38+
bundler-cache: true
39+
40+
- name: Run RuboCop
41+
run: bundle exec rubocop

.rubocop.yml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
AllCops:
2+
TargetRubyVersion: 3.0
3+
NewCops: enable
4+
SuggestExtensions: false
5+
Exclude:
6+
- 'spec/fixtures/**/*'
7+
- 'vendor/**/*'
8+
- 'tmp/**/*'
9+
10+
Style/Documentation:
11+
Enabled: false
12+
13+
Style/FrozenStringLiteralComment:
14+
Enabled: true
15+
EnforcedStyle: always
16+
Exclude:
17+
- 'spec/**/*'
18+
- 'Rakefile'
19+
- 'Gemfile'
20+
- 'bin/*'
21+
22+
Metrics/MethodLength:
23+
Max: 400
24+
Exclude:
25+
- 'spec/**/*'
26+
- 'lib/open_api_import/open_api_import.rb'
27+
28+
Metrics/AbcSize:
29+
Max: 500
30+
Exclude:
31+
- 'spec/**/*'
32+
- 'lib/open_api_import/open_api_import.rb'
33+
34+
Metrics/CyclomaticComplexity:
35+
Max: 80
36+
Exclude:
37+
- 'lib/open_api_import/open_api_import.rb'
38+
39+
Metrics/PerceivedComplexity:
40+
Max: 80
41+
Exclude:
42+
- 'lib/open_api_import/open_api_import.rb'
43+
44+
Metrics/BlockLength:
45+
Exclude:
46+
- 'spec/**/*'
47+
- 'Rakefile'
48+
- 'bin/open_api_import'
49+
- 'lib/open_api_import/open_api_import.rb'
50+
- 'lib/open_api_import/get_examples.rb'
51+
52+
Metrics/ClassLength:
53+
Max: 800
54+
55+
Layout/LineLength:
56+
Max: 200
57+
58+
Style/StringLiterals:
59+
EnforcedStyle: double_quotes
60+
61+
Style/StringLiteralsInInterpolation:
62+
EnforcedStyle: double_quotes
63+
64+
Naming/MethodName:
65+
Enabled: false
66+
67+
Naming/MethodParameterName:
68+
Enabled: false
69+
70+
Style/GuardClause:
71+
Enabled: false
72+
73+
Style/Next:
74+
Enabled: false
75+
76+
Style/IfUnlessModifier:
77+
Enabled: false
78+
79+
Style/ConditionalAssignment:
80+
Enabled: false
81+
82+
Style/NegatedIf:
83+
Enabled: false
84+
85+
Style/CaseLikeIf:
86+
Enabled: false
87+
88+
Style/SymbolArray:
89+
Enabled: false
90+
91+
Lint/SuppressedException:
92+
Enabled: false
93+
94+
Style/RescueStandardError:
95+
Enabled: false
96+
97+
Style/OptionalBooleanParameter:
98+
Enabled: false
99+
100+
Metrics/BlockNesting:
101+
Enabled: false
102+
103+
Metrics/ParameterLists:
104+
Enabled: false
105+
106+
Lint/DuplicateBranch:
107+
Enabled: false
108+
109+
Lint/UnreachableLoop:
110+
Enabled: false
111+
112+
Lint/EmptyFile:
113+
Exclude:
114+
- 'spec/open_api_import/utils/open_api_import_utils_spec.rb'
115+
116+
Gemspec/DevelopmentDependencies:
117+
Enabled: false
118+
119+
Gemspec/RequiredRubyVersion:
120+
Enabled: false
121+
122+
Security/Eval:
123+
Exclude:
124+
- 'spec/**/*'

CHANGELOG.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [0.12.0] - 2026-03-17
9+
10+
### Added
11+
- OpenAPI 3.1 support: handles nullable type arrays (`type: ["string", "null"]`) and `examples` keyword (plural)
12+
- `OpenApiImport::ParseError` exception class for parse failures (instead of `exit!`)
13+
- `OpenApiImport::VERSION` constant
14+
- `return_data` option to get generated code as a Hash without writing files
15+
- `--version` / `-v` CLI flag
16+
- `--dry_run` / `-d` CLI flag to preview output without writing files
17+
- GitHub Actions CI workflow (`.github/workflows/ci.yml`) testing Ruby 3.0-3.4
18+
- RuboCop configuration (`.rubocop.yml`)
19+
- Unit tests for all helper modules (`get_examples`, `get_patterns`, `filter`, `get_required_data`, `pretty_hash_symbolized`, `get_data_all_of_bodies`)
20+
- Feature tests for `mock_response`, `silent`, error handling, `return_data`, and OAS 3.1
21+
- `after(:suite)` cleanup in spec_helper to remove generated test artifacts
22+
- `CHANGELOG.md`
23+
24+
### Changed
25+
- **BREAKING**: `exit!` on parse failure replaced with `raise OpenApiImport::ParseError` -- callers should rescue this
26+
- **BREAKING**: Minimum Ruby version raised from 2.7 to 3.0
27+
- `rescue Exception` replaced with `rescue StandardError` throughout (no longer swallows Ctrl-C/OOM)
28+
- `eval()` calls removed -- replaced with safe hash construction and `load` for file validation
29+
- `String` monkey-patching (`snake_case`/`camel_case`) replaced with Ruby refinements (`OpenApiImportStringExt`)
30+
- `include LibOpenApiImport` moved from top-level (global namespace) into `OpenApiImport` class via `extend`
31+
- Shell commands (`rufo`, `ruby -c`) now use `Shellwords.shellescape` for path safety
32+
- `activesupport` constraint relaxed from `~> 6.1` to `>= 6.1, < 8.0` (supports Rails 7)
33+
- `rufo` constraint relaxed from `~> 0.16.1` to `~> 0.16`
34+
- Input data mutations reduced (non-destructive `gsub` instead of `gsub!`, local variables instead of modifying input hashes)
35+
- Repeated `rufo` formatting + syntax check code extracted into `format_and_check_file` helper method
36+
- `kind_of?` standardized to `is_a?`, `.keys.include?` to `.key?`
37+
- Ruby version comparison uses `Gem::Version` instead of string comparison
38+
- Output messages now display relative paths (as provided by the user) instead of expanded absolute paths
39+
40+
### Fixed
41+
- Bug in `get_examples.rb`: `val.include?("'")` was checking hash keys instead of string content
42+
- Array modification during iteration in `get_required_data.rb` (now collects and concatenates after)
43+
- `filter.rb`: nil guard added for nested key access (`result[key] ||= {}`)
44+
- `get_patterns`: simple-type array items (e.g., `{type: "string"}`) now correctly produce `[:'string']` patterns without relying on mutation side-effects from `get_examples`
45+
- `build_example_value`: array types now recurse into items schema instead of returning empty `[]`, restoring type-hinted examples like `["string"]` and `[{...}]`
46+
47+
### Deprecated
48+
- Travis CI configuration (`.travis.yml`) -- superseded by GitHub Actions

Gemfile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
source 'https://rubygems.org'
1+
source "https://rubygems.org"
22

33
group :test do
4-
gem 'rake'
5-
gem 'rspec'
6-
gem 'coveralls_reborn', '~> 0.27.0', require: false
4+
gem "coveralls_reborn", "~> 0.27.0", require: false
5+
gem "rake"
6+
gem "rspec"
77
end
88

99
# Specify your gem's dependencies in mygem.gemspec
10-
gemspec
10+
gemspec

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
# OpenApiImport
22

33
[![Gem Version](https://badge.fury.io/rb/open_api_import.svg)](https://rubygems.org/gems/open_api_import)
4-
[![Build Status](https://travis-ci.com/MarioRuiz/open_api_import.svg?branch=master)](https://github.com/MarioRuiz/open_api_import)
4+
[![CI](https://github.com/MarioRuiz/open_api_import/actions/workflows/ci.yml/badge.svg)](https://github.com/MarioRuiz/open_api_import/actions/workflows/ci.yml)
55
[![Coverage Status](https://coveralls.io/repos/github/MarioRuiz/open_api_import/badge.svg?branch=master)](https://coveralls.io/github/MarioRuiz/open_api_import?branch=master)
66

7-
Import a Swagger or Open API file and create a Ruby Request Hash file including all requests and responses with all the examples. The file can be in JSON or YAML.
7+
Import a Swagger or Open API file (including Open API 3.1) and create a Ruby Request Hash file including all requests and responses with all the examples. The file can be in JSON or YAML.
88

99
The Request Hash will include also the pattern (regular expressions) of the fields, parameters, default values...
1010

@@ -68,6 +68,10 @@ This is the output of the previous run:
6868
- Helper: ./spec/helper.rb
6969
```
7070

71+
## Requirements
72+
73+
- Ruby >= 3.0
74+
7175
## Installation
7276

7377
Install it yourself as:
@@ -102,6 +106,7 @@ More info: https://github.com/MarioRuiz/open_api_import
102106
In case no options supplied:
103107
* It will be used the value of operation_id on snake_case for the name of the methods
104108
* It will be used the first folder of the path to create the module name
109+
-v, --version Display the version
105110
-n, --no_responses if you don't want to add the examples of responses in the resultant file.
106111
-m, --mock Add the first response on the request as mock_response
107112
-p, --path_method it will be used the path and http method to create the method names
@@ -111,6 +116,7 @@ In case no options supplied:
111116
-F, --fixed_module all the requests will be under the module Requests
112117
-s, --silent It will display only errors
113118
-c, --create_constants For required arguments, it will create keyword arguments assigning by default a constant.
119+
-d, --dry_run Preview the generated output without writing files
114120
```
115121

116122

@@ -490,6 +496,23 @@ It will include this on the output file:
490496
...
491497
```
492498

499+
### return_data
500+
501+
Instead of writing files to disk, return a Hash of `{filename => content}`. This is useful for previewing the output or programmatically processing the generated code.
502+
503+
Accepts true or false, by default is false.
504+
505+
```ruby
506+
require 'open_api_import'
507+
508+
result = OpenApiImport.from "./spec/fixtures/v2.0/yaml/petstore-simple.yaml", return_data: true
509+
510+
result.each do |filepath, content|
511+
puts "--- #{filepath} ---"
512+
puts content
513+
end
514+
```
515+
493516
### create_constants
494517

495518
The methods will be generated using keyword arguments and for required arguments, it will create keyword arguments assigning by default a constant.

Rakefile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,15 @@ RSpec::Core::RakeTask.new(:spec) do |t|
44
t.pattern = Dir.glob("spec/**/*_spec.rb")
55
t.rspec_opts = "--format documentation"
66
end
7-
task default: :spec
7+
8+
begin
9+
require "rubocop/rake_task"
10+
RuboCop::RakeTask.new(:rubocop)
11+
rescue LoadError
12+
desc "RuboCop not available"
13+
task :rubocop do
14+
puts "RuboCop is not installed. Run: gem install rubocop"
15+
end
16+
end
17+
18+
task default: [:spec]

bin/open_api_import

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
#!/usr/bin/env ruby
2-
require 'optparse'
3-
require 'open_api_import'
2+
require "optparse"
3+
require "open_api_import"
44

55
options = {
66
name_for_module: :path
77
}
88

99
optparse = OptionParser.new do |opts|
1010
opts.banner = "Usage: open_api_import [open_api_file] [options]\n"
11-
opts.banner+= "Import a Swagger or Open API file and create a Ruby Request Hash file including all requests and responses.\n"
12-
opts.banner+= "More info: https://github.com/MarioRuiz/open_api_import\n\n"
13-
opts.banner+= "In case no options supplied: \n"
14-
opts.banner+= " * It will be used the value of operation_id on snake_case for the name of the methods\n"
15-
opts.banner+= " * It will be used the first folder of the path to create the module name\n"
16-
11+
opts.banner += "Import a Swagger or Open API file and create a Ruby Request Hash file including all requests and responses.\n"
12+
opts.banner += "More info: https://github.com/MarioRuiz/open_api_import\n\n"
13+
opts.banner += "In case no options supplied: \n"
14+
opts.banner += " * It will be used the value of operation_id on snake_case for the name of the methods\n"
15+
opts.banner += " * It will be used the first folder of the path to create the module name\n"
16+
17+
opts.on("-v", "--version", "Display the version") do
18+
puts "open_api_import #{OpenApiImport::VERSION}"
19+
exit
20+
end
21+
1722
opts.on("-n", "--no_responses", "if you don't want to add the examples of responses in the resultant file.") do
1823
options[:include_responses] = false
1924
end
@@ -50,7 +55,9 @@ optparse = OptionParser.new do |opts|
5055
options[:create_constants] = true
5156
end
5257

53-
58+
opts.on("-d", "--dry_run", "Preview the generated output without writing files") do
59+
options[:return_data] = true
60+
end
5461
end
5562

5663
optparse.parse!
@@ -65,9 +72,16 @@ if options.key?(:create_files)
6572
end
6673

6774
filename = ARGV.pop
68-
if filename.to_s==''
75+
if filename.to_s == ""
6976
puts optparse
7077
puts "** Need to specify at least a file to import."
7178
else
72-
OpenApiImport.from filename, **options
79+
result = OpenApiImport.from filename, **options
80+
if options[:return_data] && result.is_a?(Hash)
81+
result.each do |filepath, content|
82+
puts "--- #{filepath} ---"
83+
puts content
84+
puts
85+
end
86+
end
7387
end

lib/open_api_import.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# frozen_string_literal: true
2+
13
require_relative "open_api_import/utils"
24
require_relative "open_api_import/filter"
35
require_relative "open_api_import/pretty_hash_symbolized"
@@ -8,10 +10,8 @@
810
require_relative "open_api_import/get_examples"
911
require_relative "open_api_import/open_api_import"
1012

11-
include LibOpenApiImport
12-
1313
require "oas_parser_reborn"
1414
require "rufo"
1515
require "nice_hash"
1616
require "logger"
17-
17+
require "shellwords"

0 commit comments

Comments
 (0)