bump-cli 0.3.2 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa0bd892b8317be2e6bce1fe83c0d747c6ae989fe3e02c69730479e9c595ba9b
4
- data.tar.gz: '0924e8faa5b4221383c8c3ea0dc80774790666a5568c7180e51ad655a5c9cfcd'
3
+ metadata.gz: a76424c2ad6eed8a8b65caa28e57e26c7efb892b8909a9e6aed60871b9964105
4
+ data.tar.gz: 4f597a0961e36cfb2108409198a11abae798333b49fadf298fbd0f7b332c529a
5
5
  SHA512:
6
- metadata.gz: de9f6fe376a5ebba4144c595004d5b990a10be581a58ca6af116d80ab9cb957cdbe9e03a549ea7ba1b2597f194e38bc5d9b001232beb0675cf152a01ca599021
7
- data.tar.gz: 7fa8848a39ceabc042183cb1d5fe5151f6956f001149a01db4751d02c05793e3a6306695b432fda851dbb88741a20a770bd78ae47fd891765f0ddb395c6099bd
6
+ metadata.gz: bda499aed9b3edfb4600ccd8ede77a65dd6bd98403937f29b714c557e8fb5457f8258d49d55ab5968499c5e10ff67b6a0cd446d3304a5b0ea69afeab20f0e47d
7
+ data.tar.gz: 2fa948728d09d134b552954d12d2f64d3141bf5c0422ffdd95ec853afed861aed0440c4c6a3ff5378025f5788d1ceb535e04c37a12e8b4180441d35b850b499c
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .byebug_history
2
+ .ruby-version
2
3
  /.bundle/
3
4
  /.yardoc
4
5
  /Gemfile.lock
data/README.md CHANGED
@@ -20,27 +20,40 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- By default, `bump-cli` considers files as `yaml` ones. If you work with JSON definitions, you need to specify the format for all the commands using `--format json`.
23
+ Bump tries to identify your file specification and format automatically. You can force it by using the `--specification` option. Here are the supported values:
24
24
 
25
- The doc `id` and `token` used below can be found in your documentation settings page on https://bump.sh. Note that you can replace the options by environments variables: `--id` can be replaced by `BUMP_ID`, and `--token` can by replaced by `BUMP_TOKEN`. This is useful to keep your private token secret.
25
+ * `openapi/v2/json`
26
+ * `openapi/v2/yaml`
27
+ * `openapi/v3/json`
28
+ * `openapi/v3/yaml`
29
+ * `asyncapi/v2/json`
30
+ * `asyncapi/v2/yaml`
31
+
32
+ `doc` and `token` options used below can be found in your documentation settings page on https://bump.sh. Note that you can replace the token option by an environment variable, to keep it secret: `--token` can by replaced by `BUMP_TOKEN`.
26
33
 
27
34
  ### Preview
28
35
 
29
36
  You can preview your documentation by calling the `preview` command. A temporary preview will be created, with a unique URL. This preview will be available for 30 minutes. You don't need any credentials to use this command.
30
37
 
31
- $ bundle exec bump preview path/to/your/openapi.yml
38
+ Preview a documentation:
39
+
40
+ $ bundle exec bump preview path/to/your/file.yml
32
41
 
33
42
  ### Validate
34
43
 
35
- Validate your file against the OpenApi specification.
44
+ Validate your file against its specification:
36
45
 
37
- $ bundle exec bump validate path/to/your/openapi.yml --id DOC_ID --token DOC_TOKEN
46
+ $ bundle exec bump validate path/to/your/file.yml --doc DOC_ID_OR_SLUG --token DOC_TOKEN
38
47
 
39
48
  ### Deploy
40
49
 
41
- Deploy the file as the current version of the documentation.
50
+ Deploy the file as the current version of the documentation:
51
+
52
+ $ bundle exec bump deploy path/to/your/file.yml --doc DOC_ID_OR_SLUG --token DOC_TOKEN
53
+
54
+ Automatically create a documentation inside a hub and deploy it:
42
55
 
43
- $ bundle exec bump deploy path/to/your/openapi.yml --id DOC_ID --token DOC_TOKEN
56
+ $ bundle exec bump deploy path/to/your/file.yml --auto-create --doc DOC_SLUG --hub HUB_ID_OR_SLUG --token HUB_TOKEN
44
57
 
45
58
  ## Development
46
59
 
@@ -26,13 +26,13 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '>= 2.3'
28
28
 
29
- spec.add_dependency "hanami-cli", '~> 0'
30
- spec.add_dependency "http", '~> 3'
29
+ spec.add_dependency "dry-cli", '~> 0'
30
+ spec.add_dependency "http", '>= 3'
31
31
 
32
- spec.add_development_dependency "bundler", "~> 1.15"
33
- spec.add_development_dependency "byebug", "~> 9"
32
+ spec.add_development_dependency "bundler", ">= 1", "< 3"
33
+ spec.add_development_dependency "byebug", "~> 11"
34
34
  spec.add_development_dependency "climate_control", '~> 0'
35
- spec.add_development_dependency "rake", "~> 10.0"
35
+ spec.add_development_dependency "rake", "~> 13"
36
36
  spec.add_development_dependency "rspec", "~> 3"
37
37
  spec.add_development_dependency "webmock", "~> 3"
38
38
  end
@@ -1,5 +1,5 @@
1
1
  require "bump/cli/version"
2
- require "hanami/cli"
2
+ require "dry/cli"
3
3
  require "http"
4
4
 
5
5
  module Bump
@@ -9,11 +9,11 @@ module Bump
9
9
  API_URL = ROOT_URL + API_PATH
10
10
 
11
11
  def call(*args)
12
- Hanami::CLI.new(Commands).call(*args)
12
+ Dry::CLI.new(Commands).call(*args)
13
13
  end
14
14
 
15
15
  module Commands
16
- extend Hanami::CLI::Registry
16
+ extend Dry::CLI::Registry
17
17
  end
18
18
  end
19
19
  end
@@ -1,9 +1,10 @@
1
- require 'open-uri'
1
+ require 'bump/cli/definition'
2
+ require 'bump/cli/uuid'
2
3
 
3
4
  module Bump
4
5
  class CLI
5
6
  module Commands
6
- class Base < Hanami::CLI::Command
7
+ class Base < Dry::CLI::Command
7
8
  USER_AGENT = "bump-cli/#{VERSION}".freeze
8
9
 
9
10
  private
@@ -14,11 +15,64 @@ module Bump
14
15
  .post(url, body: body)
15
16
  end
16
17
 
17
- def body(file, specification)
18
- {
19
- definition: open(file).read,
20
- specification: specification
21
- }
18
+ def body(file, **options)
19
+ deprecation_warning(options)
20
+
21
+ compact(
22
+ {
23
+ definition: prepare_file(file, options),
24
+ specification: options[:specification],
25
+ validation: options[:validation],
26
+ auto_create_documentation: options[:'auto-create']
27
+ }.merge(documentation_or_hub(options))
28
+ )
29
+ end
30
+
31
+ def prepare_file(file, options)
32
+ Definition.new(file, import_external_references: options[:'import-external-references']).prepare
33
+ end
34
+
35
+ def deprecation_warning(options)
36
+ if present?(options[:id])
37
+ puts "[DEPRECATION WARNING] --id option is deprecated. Please use --doc instead."
38
+ end
39
+ end
40
+
41
+ def present?(string)
42
+ !string.nil? && string != ''
43
+ end
44
+
45
+ def compact(hash)
46
+ hash.delete_if { |key, value| value.nil? }
47
+ end
48
+
49
+ def documentation_or_hub(options)
50
+ result = {}
51
+
52
+ result[:documentation_id] = options[:id]
53
+ result[:documentation_id] = options[:doc] if documentation_uuid?(options)
54
+ result[:documentation_slug] = options[:doc] if documentation_slug?(options)
55
+ result[:documentation_name] = options[:'doc-name']
56
+ result[:hub_id] = options[:hub] if hub_uuid?(options)
57
+ result[:hub_slug] = options[:hub] if hub_slug?(options)
58
+
59
+ compact(result)
60
+ end
61
+
62
+ def documentation_uuid?(options)
63
+ Bump::CLI::UUID.valid?(options[:doc])
64
+ end
65
+
66
+ def documentation_slug?(options)
67
+ !options[:doc].nil? && !documentation_uuid?(options)
68
+ end
69
+
70
+ def hub_uuid?(options)
71
+ Bump::CLI::UUID.valid?(options[:hub])
72
+ end
73
+
74
+ def hub_slug?(options)
75
+ !options[:hub].nil? && !hub_uuid?(options)
22
76
  end
23
77
 
24
78
  def with_errors_rescued
@@ -5,17 +5,23 @@ module Bump
5
5
  module Commands
6
6
  class Deploy < Base
7
7
  desc "Create a new version"
8
- argument :file, required: true, desc: "Path or URL to your API documentation file. Only OpenApi 2.0 (Swagger) specification is currently supported."
9
- option :id, default: ENV.fetch("BUMP_ID", ""), desc: "Documentation public id"
10
- option :token, default: ENV.fetch("BUMP_TOKEN", ""), desc: "Documentation private token"
8
+ argument :file, required: true, desc: "Path or URL to your API documentation file. OpenAPI (2.0 to 3.0.2) and AsyncAPI (2.0) specifications are currently supported."
9
+ option :id, default: ENV.fetch("BUMP_ID", ""), desc: "[DEPRECATED] Documentation id. Use `documentation` option instead"
10
+ option :doc, default: ENV.fetch("BUMP_ID", ""), desc: "Documentation id or slug"
11
+ option :'doc-name', desc: "Documentation name. Used with --auto-create flag."
12
+ option :hub, default: ENV.fetch("BUMP_HUB_ID", ""), desc: "Hub id or slug"
13
+ option :token, default: ENV.fetch("BUMP_TOKEN", ""), desc: "Documentation or Hub token"
11
14
  option :specification, desc: "Specification of the definition"
15
+ option :validation, desc: "Validation mode", values: %w(basic strict), default: 'basic'
16
+ option :'auto-create', type: :boolean, default: false, desc: 'Automatically create the documentation if needed (only available with a hub and when specifying a slug for documentation)'
17
+ option :'import-external-references', type: :boolean, default: false, desc: 'Import external $refs (URI or file system) into the specification before sending it to Bump servers'
12
18
 
13
- def call(file:, id:, token:, specification: nil)
19
+ def call(file:, **options)
14
20
  with_errors_rescued do
15
21
  response = post(
16
- url: API_URL + "/docs/#{id}/versions",
17
- body: body(file, specification).to_json,
18
- token: token
22
+ url: API_URL + "/versions",
23
+ body: body(file, options).to_json,
24
+ token: options[:token]
19
25
  )
20
26
 
21
27
  if response.code == 201
@@ -3,14 +3,16 @@ module Bump
3
3
  module Commands
4
4
  class Preview < Base
5
5
  desc "Create a documentation preview for the given file"
6
- argument :file, required: true, desc: "Path or URL to your API documentation file. Only OpenApi 2.0 (Swagger) specification is currently supported."
6
+ argument :file, required: true, desc: "Path or URL to your API documentation file. OpenAPI (2.0 to 3.0.2) and AsyncAPI (2.0) specifications are currently supported."
7
7
  option :specification, desc: "Specification of the definition"
8
+ option :validation, desc: "Validation mode", values: %w(basic strict), default: 'basic'
9
+ option :'import-external-references', type: :boolean, default: false, desc: 'Import external $refs (URI or file system) into the specification before sending it to Bump servers'
8
10
 
9
- def call(file:, specification: nil)
11
+ def call(file:, **options)
10
12
  with_errors_rescued do
11
13
  response = post(
12
14
  url: API_URL + "/previews",
13
- body: body(file, specification).to_json
15
+ body: body(file, options).to_json
14
16
  )
15
17
 
16
18
  if response.code == 201
@@ -5,17 +5,23 @@ module Bump
5
5
  module Commands
6
6
  class Validate < Base
7
7
  desc "Validate a given file against its schema definition"
8
- argument :file, required: true, desc: "Path or URL to your API documentation file. Only OpenApi 2.0 (Swagger) specification is currently supported."
9
- option :id, default: ENV.fetch("BUMP_ID", ""), desc: "Documentation public id"
10
- option :token, default: ENV.fetch("BUMP_TOKEN", ""), desc: "Documentation private token"
8
+ argument :file, required: true, desc: "Path or URL to your API documentation file. OpenAPI (2.0 to 3.0.2) and AsyncAPI (2.0) specifications are currently supported."
9
+ option :id, default: ENV.fetch("BUMP_ID", ""), desc: "[DEPRECATED] Documentation id. Use `documentation` option instead"
10
+ option :doc, default: ENV.fetch("BUMP_ID", ""), desc: "Documentation public id or slug"
11
+ option :'doc-name', desc: "Documentation name. Used with --auto-create flag."
12
+ option :hub, desc: "Hub id or slug"
13
+ option :token, default: ENV.fetch("BUMP_TOKEN", ""), desc: "Documentation or Hub token"
11
14
  option :specification, desc: "Specification of the definition"
15
+ option :validation, desc: "Validation mode", values: %w(basic strict), default: 'basic'
16
+ option :'auto-create', type: :boolean, default: false, desc: 'Automatically create the documentation if needed (only available with a hub and when specifying a slug for documentation)'
17
+ option :'import-external-references', type: :boolean, default: false, desc: 'Import external $refs (URI or file system) into the specification before sending it to Bump servers'
12
18
 
13
- def call(file:, id:, token:, specification: nil)
19
+ def call(file:, **options)
14
20
  with_errors_rescued do
15
21
  response = post(
16
- url: API_URL + "/docs/#{id}/validations",
17
- body: body(file, specification).to_json,
18
- token: token
22
+ url: API_URL + "/validations",
23
+ body: body(file, options).to_json,
24
+ token: options[:token]
19
25
  )
20
26
 
21
27
  if response.code == 200
@@ -0,0 +1,43 @@
1
+ require 'open-uri'
2
+ require 'bump/cli/parser'
3
+ require 'bump/cli/references'
4
+
5
+ module Bump
6
+ class CLI
7
+ class Definition
8
+ def initialize(path, import_external_references: false)
9
+ @path = path
10
+ @import_external_references = import_external_references
11
+ end
12
+
13
+ def prepare
14
+ if !import_external_references
15
+ read_file
16
+ else
17
+ parse_file_and_import_external_references
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :path, :import_external_references
24
+
25
+ def read_file
26
+ open(path).read
27
+ end
28
+
29
+ def parse_file_and_import_external_references
30
+ original_format, definition = parser.load(read_file)
31
+
32
+ references = References.new(definition, base_path: path)
33
+ references.import!
34
+
35
+ parser.dump(references.definition, original_format)
36
+ end
37
+
38
+ def parser
39
+ @parser ||= Parser.new
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,24 @@
1
+ require 'json'
2
+ require 'yaml'
3
+
4
+ module Bump
5
+ class CLI
6
+ class Parser
7
+ def load(content)
8
+ [:json, ::JSON.parse(content)]
9
+ rescue ::JSON::ParserError => e
10
+ [:yaml, ::YAML.safe_load(content, [Date, Time])]
11
+ rescue ::Psych::SyntaxError
12
+ raise 'Invalid format: definition file should be valid YAML or JSON'
13
+ end
14
+
15
+ def dump(definition, format)
16
+ if format == :yaml
17
+ ::YAML.dump(definition)
18
+ else
19
+ ::JSON.dump(definition)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,88 @@
1
+ require 'open-uri'
2
+ require 'pathname'
3
+
4
+ module Bump
5
+ class CLI
6
+ class References
7
+ attr_reader :definition
8
+
9
+ def initialize(definition, base_path: '')
10
+ @definition = definition
11
+ @base_path = cleanup(base_path)
12
+ @processed = false
13
+ @external_references = {}
14
+ end
15
+
16
+ def import!
17
+ if !processed
18
+ @definition = traverse_and_replace_external_references(definition)
19
+ import_references
20
+ @processed = true
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :base_path, :processed, :external_references
27
+
28
+ def traverse_and_replace_external_references(current, parent = nil)
29
+ current.each do |key, value|
30
+ if key == '$ref'
31
+ current[key] = replace_external_reference(value)
32
+ elsif value.is_a?(Hash)
33
+ traverse_and_replace_external_references(value, key)
34
+ end
35
+ end
36
+ end
37
+
38
+ def replace_external_reference(reference)
39
+ if external?(reference)
40
+ if external_references[reference].nil?
41
+ @external_references[reference] = "#{external_references.count + 1}"
42
+ end
43
+
44
+ subpath = reference[/#(.*)$/, 1]
45
+ "#/components/x-imported/#{external_references[reference]}#{ '/' + subpath if !subpath.nil? }"
46
+ else
47
+ reference
48
+ end
49
+ end
50
+
51
+ def import_references
52
+ if external_references.count > 0
53
+ @definition['components'] = {} if @definition['components'].nil?
54
+ @definition['components']['x-imported'] = {} if @definition['components']['x-imported'].nil?
55
+
56
+ external_references.each do |key, value|
57
+ _, @definition['components']['x-imported'][value.to_s] = Parser.new.load(open(prepare_path(key)).read)
58
+ end
59
+ end
60
+ end
61
+
62
+ def prepare_path(key)
63
+ key = key.sub(/#.*/, '')
64
+ if url?(key) || absolute_path?(key)
65
+ key
66
+ else
67
+ base_path + key
68
+ end
69
+ end
70
+
71
+ def external?(reference)
72
+ !reference.start_with?('#')
73
+ end
74
+
75
+ def url?(path)
76
+ path.start_with?('http')
77
+ end
78
+
79
+ def absolute_path?(path)
80
+ path.start_with?('/')
81
+ end
82
+
83
+ def cleanup(path)
84
+ Pathname.new(path).dirname.to_s + Pathname::SEPARATOR_LIST
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,11 @@
1
+ module Bump
2
+ class CLI
3
+ class UUID
4
+ REGEXP = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
5
+
6
+ def self.valid?(string)
7
+ string.to_s =~ REGEXP
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,5 +1,5 @@
1
1
  module Bump
2
2
  class CLI
3
- VERSION = "0.3.2"
3
+ VERSION = "0.6.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bump-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mehdi Lahmam
@@ -9,10 +9,10 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2019-01-17 00:00:00.000000000 Z
12
+ date: 2020-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: hanami-cli
15
+ name: dry-cli
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - "~>"
@@ -29,44 +29,50 @@ dependencies:
29
29
  name: http
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - "~>"
32
+ - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '3'
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - "~>"
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '3'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: bundler
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - "~>"
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '1'
49
+ - - "<"
47
50
  - !ruby/object:Gem::Version
48
- version: '1.15'
51
+ version: '3'
49
52
  type: :development
50
53
  prerelease: false
51
54
  version_requirements: !ruby/object:Gem::Requirement
52
55
  requirements:
53
- - - "~>"
56
+ - - ">="
54
57
  - !ruby/object:Gem::Version
55
- version: '1.15'
58
+ version: '1'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '3'
56
62
  - !ruby/object:Gem::Dependency
57
63
  name: byebug
58
64
  requirement: !ruby/object:Gem::Requirement
59
65
  requirements:
60
66
  - - "~>"
61
67
  - !ruby/object:Gem::Version
62
- version: '9'
68
+ version: '11'
63
69
  type: :development
64
70
  prerelease: false
65
71
  version_requirements: !ruby/object:Gem::Requirement
66
72
  requirements:
67
73
  - - "~>"
68
74
  - !ruby/object:Gem::Version
69
- version: '9'
75
+ version: '11'
70
76
  - !ruby/object:Gem::Dependency
71
77
  name: climate_control
72
78
  requirement: !ruby/object:Gem::Requirement
@@ -87,14 +93,14 @@ dependencies:
87
93
  requirements:
88
94
  - - "~>"
89
95
  - !ruby/object:Gem::Version
90
- version: '10.0'
96
+ version: '13'
91
97
  type: :development
92
98
  prerelease: false
93
99
  version_requirements: !ruby/object:Gem::Requirement
94
100
  requirements:
95
101
  - - "~>"
96
102
  - !ruby/object:Gem::Version
97
- version: '10.0'
103
+ version: '13'
98
104
  - !ruby/object:Gem::Dependency
99
105
  name: rspec
100
106
  requirement: !ruby/object:Gem::Requirement
@@ -149,6 +155,10 @@ files:
149
155
  - lib/bump/cli/commands/deploy.rb
150
156
  - lib/bump/cli/commands/preview.rb
151
157
  - lib/bump/cli/commands/validate.rb
158
+ - lib/bump/cli/definition.rb
159
+ - lib/bump/cli/parser.rb
160
+ - lib/bump/cli/references.rb
161
+ - lib/bump/cli/uuid.rb
152
162
  - lib/bump/cli/version.rb
153
163
  homepage: https://bump.sh
154
164
  licenses: