inquirex-tools 0.8.0 → 0.9.4

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.
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "colored2"
4
+ require_relative "workspace"
5
+
6
+ module Inquirex
7
+ module Tools
8
+ # Publishes every package in the family by running each one's own
9
+ # `just publish` in its own directory.
10
+ #
11
+ # How a package reaches its registry stays that package's business: the
12
+ # gems build a .gem and `gem push` it, the npm packages run bun or yarn.
13
+ # This class only decides the order, supplies the one thing a package
14
+ # cannot work out for itself — a fresh 2FA code — and stops at the first
15
+ # failure.
16
+ #
17
+ # **A TOTP is single-use.** Reading 1Password once per gem inside a
18
+ # 30-second window returns the same six digits every time, and RubyGems
19
+ # rejects the second push as a replay. So a code is read per gem and the
20
+ # run waits for it to actually rotate before moving on, which is why
21
+ # publishing four gems takes minutes rather than seconds. The npm packages
22
+ # read their own code and are called with no argument.
23
+ #
24
+ # Order comes from {Workspace::LOCKSTEP}, so adding a package to the family
25
+ # adds it to the release. That order puts the core gem first, which matters:
26
+ # inquirex-llm and inquirex-tty depend on it and cannot resolve until it is
27
+ # on RubyGems.
28
+ #
29
+ # @example Preview a release without touching a registry
30
+ # Inquirex::Tools::Publisher.new.call(dry_run: true)
31
+ class Publisher
32
+ # How long to wait for a TOTP to rotate before giving up and using what
33
+ # 1Password last returned. Codes rotate every 30 seconds; 90 covers a
34
+ # window boundary landing badly without hanging a release indefinitely.
35
+ ROTATE_TIMEOUT = 90
36
+
37
+ # Seconds between polls of 1Password while waiting for a new code.
38
+ ROTATE_INTERVAL = 2
39
+
40
+ # Shells out with the child's stdout and stderr left attached, so a
41
+ # failing package's own output is what the operator sees.
42
+ DEFAULT_RUNNER = lambda { |dir, argv|
43
+ Dir.chdir(dir) { system("just", *argv) }
44
+ }
45
+
46
+ # Reads the current RubyGems TOTP. `op` resolves the account from
47
+ # OP_ACCOUNT, which `just publish-all` exports by decrypting
48
+ # .env.encrypted. Returns nil when unavailable, so a release without
49
+ # 1Password degrades to `gem push` prompting rather than failing.
50
+ DEFAULT_OTP_READER = lambda {
51
+ ref = "op://open-source-repos/ruby-gems/one-time password?attribute=otp"
52
+ code = `op read #{ref.inspect} 2>/dev/null`.strip
53
+ code.empty? ? nil : code
54
+ }
55
+
56
+ # @param workspace [Workspace] the ecosystem checkout to publish from
57
+ # @param out [IO] where report output goes
58
+ # @param runner [#call] invoked with (dir, argv) to run a command; the
59
+ # default shells out. Injected so specs can assert what would run
60
+ # without publishing anything.
61
+ # @param otp_reader [#call] returns the current 2FA code, or nil
62
+ def initialize(workspace: Workspace.new,
63
+ out: $stdout,
64
+ runner: DEFAULT_RUNNER,
65
+ otp_reader: DEFAULT_OTP_READER)
66
+ @workspace = workspace
67
+ @out = out
68
+ @runner = runner
69
+ @otp_reader = otp_reader
70
+ end
71
+
72
+ # Publishes every lockstep package, or prints what it would publish.
73
+ #
74
+ # @param dry_run [Boolean] print the commands and run nothing
75
+ # @param args [Array<String>] extra arguments forwarded verbatim to each
76
+ # package's `just publish`
77
+ # @return [Boolean] true when every package published (or was printed)
78
+ def call(dry_run: false, args: [])
79
+ out.puts(dry_run ? "DRY RUN — these commands would run, in this order:" : "Publishing the family:")
80
+
81
+ last_otp = nil
82
+ Workspace::LOCKSTEP.each do |name, kind|
83
+ dir = File.join(workspace.root, name)
84
+ raise Error, "no checkout for #{name} at #{dir}" unless Dir.exist?(dir)
85
+
86
+ argv = ["publish", *args]
87
+ if dry_run
88
+ row(name, kind, "just #{argv.join(" ")}")
89
+ next
90
+ end
91
+
92
+ # Only the gems take a code: each npm package reads its own.
93
+ if kind == :gem
94
+ last_otp = fresh_otp(last_otp)
95
+ argv += [last_otp] if last_otp
96
+ end
97
+
98
+ out.puts
99
+ out.puts "━━ #{name} (#{kind}) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
100
+ return false unless run(name, dir, argv)
101
+ end
102
+
103
+ out.puts
104
+ out.puts(dry_run ? "Nothing was published." : "Published every package.".green)
105
+ true
106
+ end
107
+
108
+ private
109
+
110
+ # @return [Workspace] the ecosystem checkout being published
111
+ attr_reader :workspace
112
+
113
+ # @return [IO] where report output goes
114
+ attr_reader :out
115
+
116
+ # @return [#call] command runner
117
+ attr_reader :runner
118
+
119
+ # @return [#call] source of 2FA codes
120
+ attr_reader :otp_reader
121
+
122
+ # @return [Boolean] whether the package published cleanly
123
+ def run(name, dir, argv)
124
+ return true if runner.call(dir, argv)
125
+
126
+ out.puts
127
+ out.puts "#{"ERROR".bold.red}: #{name} failed `just #{argv.first}` — stopping here."
128
+ out.puts "Publishing is irreversible, so the packages after #{name} were left alone."
129
+ false
130
+ end
131
+
132
+ # Blocks until 1Password returns a code that has not already been spent.
133
+ #
134
+ # @param last [String, nil] the code the previous gem used
135
+ # @return [String, nil] a fresh code, or nil when 1Password is unavailable
136
+ def fresh_otp(last)
137
+ waited = 0
138
+ loop do
139
+ code = otp_reader.call
140
+ return nil if code.nil?
141
+ return code if code != last
142
+ return code if waited >= ROTATE_TIMEOUT
143
+
144
+ out.puts " waiting for the 2FA code to rotate…" if waited.zero?
145
+ sleep ROTATE_INTERVAL
146
+ waited += ROTATE_INTERVAL
147
+ end
148
+ end
149
+
150
+ # Pads before colorizing: an ANSI escape is several characters wide to
151
+ # `format` and zero columns wide on screen, so colorizing first left the
152
+ # table ragged by exactly the length of the escape codes.
153
+ #
154
+ # @return [void]
155
+ def row(name, kind, detail)
156
+ out.puts " #{name.ljust(18).yellow} #{kind.to_s.ljust(4).cyan} #{detail}"
157
+ end
158
+ end
159
+ end
160
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Inquirex
4
4
  module Tools
5
- VERSION = "0.8.0"
5
+ VERSION = "0.9.4"
6
6
  end
7
7
  end
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "colored2"
4
+ require "rubygems/version"
5
+ require_relative "workspace"
6
+
7
+ module Inquirex
8
+ module Tools
9
+ # Moves every lockstep package to one version, then proves each one still
10
+ # builds — the write half of the pair whose read half is {VersionChecker}.
11
+ #
12
+ # The family shares a serialization format, so a version that identifies
13
+ # one package identifies all of them. Bumping is therefore all-or-nothing:
14
+ # there is no supported way to move a single package.
15
+ #
16
+ # Writing a version and verifying it are one command on purpose. A version
17
+ # written but never checked is the failure this is meant to prevent: the
18
+ # number says the family agrees while one package no longer passes its own
19
+ # suite.
20
+ #
21
+ # @example Move the family to 0.9.2 and check every package
22
+ # Inquirex::Tools::VersionBumper.new.call("0.9.2") # => false if any check fails
23
+ class VersionBumper
24
+ # A version must be exactly MAJOR.MINOR.PATCH — no prereleases, because
25
+ # the npm packages and the gems would spell them differently.
26
+ SEMVER_RE = /\A\d+\.\d+\.\d+\z/
27
+
28
+ # Prefix for the refusal messages. This command's only feedback is what
29
+ # it prints, so the word carries weight.
30
+ ERROR = "ERROR"
31
+
32
+ # What each package is verified with. One recipe for gems and npm
33
+ # packages alike — every repo's justfile defines it, which is the point
34
+ # of having a justfile in each.
35
+ CHECK = %w[just check-all].freeze
36
+
37
+ # Rule across the report, sized to the rows.
38
+ RULE = ("—" * 52).freeze
39
+
40
+ # @param workspace [Workspace] the ecosystem checkout to rewrite
41
+ # @param out [IO] where report output goes
42
+ def initialize(workspace: Workspace.new, out: $stdout)
43
+ @workspace = workspace
44
+ @out = out
45
+ end
46
+
47
+ # Rewrites every lockstep package to the target version, then runs each
48
+ # package's own `just check-all`.
49
+ #
50
+ # Refuses to move backwards: a version already published cannot be
51
+ # reissued, so the target must be at least the highest current value.
52
+ #
53
+ # @param version [String] target, MAJOR.MINOR.PATCH
54
+ # @param verify [Boolean] run `just check-all` per package afterwards
55
+ # @return [Boolean] true when every package was written and checked
56
+ def call(version, verify: true)
57
+ return false unless valid?(version)
58
+
59
+ out.puts "Setting all lockstep packages to #{version} 🚨:"
60
+ each_package { |name, kind| write(name, kind, version) }
61
+ return true unless verify
62
+
63
+ out.puts
64
+ out.puts "Verifying each package with `#{CHECK.join(" ")}`:"
65
+ results = each_package { |name, _kind| check(name) }
66
+ report(results)
67
+ end
68
+
69
+ private
70
+
71
+ # @return [Workspace] the ecosystem checkout being rewritten
72
+ attr_reader :workspace
73
+
74
+ # @return [IO] where report output goes
75
+ attr_reader :out
76
+
77
+ # The one place the package list is walked, so adding a package changes
78
+ # nothing here.
79
+ #
80
+ # @yieldparam name [String] package name
81
+ # @yieldparam kind [Symbol] :gem or :npm
82
+ # @return [Hash{String => Object}] name => whatever the block returned
83
+ def each_package
84
+ Workspace::LOCKSTEP.to_h { |name, kind| [name, yield(name, kind)] }
85
+ end
86
+
87
+ # @return [void]
88
+ def write(name, kind, version)
89
+ workspace.write_version(name, version, kind)
90
+ row(name, kind.to_s.cyan, version.green)
91
+ end
92
+
93
+ # Runs one package's checks in its own directory.
94
+ #
95
+ # A package with no justfile is reported and skipped rather than failed:
96
+ # the fixture used by the specs has none, and a repo that has not grown
97
+ # one yet should not make a legitimate bump look broken.
98
+ #
99
+ # @param name [String] package name
100
+ # @return [Boolean, nil] pass/fail, or nil when skipped
101
+ def check(name)
102
+ dir = File.join(workspace.root, name)
103
+ passed = Dir.chdir(dir) do
104
+ row(name, "running #{CHECK.join(" ")} in ".yellow, dir)
105
+ out.puts RULE
106
+ system("git fetch")
107
+ system("test -n $(git status --porcelain) && { git stash -u; echo 'Stashing locally modified files...'; }")
108
+ system("git pull origin main")
109
+ system("git fetch --tags")
110
+ system("git rebase origin/main")
111
+ unless File.exist?(File.join(dir, "justfile"))
112
+ row(name, "skip".yellow, "no justfile".yellow)
113
+ return nil
114
+ end
115
+ row(name, "Pulled in #{name}, current version is #{system("just version")}", dir)
116
+ system(*CHECK)
117
+ end
118
+ row(name, passed ? "[ OK ]".on.green : "[ 🅧 ]".on_red, dir)
119
+ passed
120
+ end
121
+
122
+ # The single formatting site for every line of the report.
123
+ #
124
+ # `format`, never `printf`: printf writes straight to $stdout and returns
125
+ # nil, so an injected out would receive one blank line per package while
126
+ # the real output went elsewhere.
127
+ #
128
+ # @return [void]
129
+ def row(name, state, detail)
130
+ out.puts format(" → %<name>-24s %<state>-6s %<detail>s", name: name.yellow, state:, detail:)
131
+ end
132
+
133
+ # @param results [Hash{String => Boolean, nil}] per-package check outcome
134
+ # @return [Boolean] true when nothing failed
135
+ def report(results)
136
+ failed = results.select { |_name, passed| passed == false }.keys
137
+ out.puts RULE
138
+ if failed.empty?
139
+ out.puts "OK: every package checked out".green
140
+ true
141
+ else
142
+ out.puts "#{ERROR.bold.red}: #{failed.join(", ")} failed `#{CHECK.join(" ")}`"
143
+ false
144
+ end
145
+ end
146
+
147
+ # Whether the target is well-formed and moves the family forward.
148
+ # Reports the reason it does not, since this is the CLI's only feedback.
149
+ #
150
+ # @param version [String] proposed target
151
+ # @return [Boolean]
152
+ def valid?(version)
153
+ unless SEMVER_RE.match?(version.to_s)
154
+ out.puts "#{ERROR.bold.red}: #{version.inspect} is not MAJOR.MINOR.PATCH"
155
+ return false
156
+ end
157
+
158
+ highest = workspace.versions.values.compact.max_by { Gem::Version.new(it) }
159
+ if highest && Gem::Version.new(highest) > Gem::Version.new(version)
160
+ out.puts "#{ERROR.bold.red}: #{version} is below the highest existing " \
161
+ "version (#{highest}) — versions only go forward"
162
+ return false
163
+ end
164
+
165
+ true
166
+ end
167
+ end
168
+ end
169
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "colored2"
4
+ require_relative "workspace"
5
+
6
+ module Inquirex
7
+ module Tools
8
+ # Reports version parity across the lockstep packages.
9
+ #
10
+ # Read-only by construction: nothing here writes a version file. Bumping is
11
+ # {VersionBumper}'s job. The split means a check can be run anywhere — CI, a
12
+ # dirty tree, a colleague's checkout — with no chance of editing something,
13
+ # and the two behaviours no longer share a flag that decides which happens.
14
+ #
15
+ # @example Check for drift
16
+ # Inquirex::Tools::VersionChecker.new.call # => false when versions differ
17
+ class VersionChecker
18
+ # @param workspace [Workspace] the ecosystem checkout to inspect
19
+ # @param out [IO] where report output goes
20
+ def initialize(workspace: Workspace.new, out: $stdout)
21
+ @workspace = workspace
22
+ @out = out
23
+ end
24
+
25
+ # Prints the current state of every lockstep package.
26
+ #
27
+ # @return [Boolean] true when all packages agree on one version
28
+ def call
29
+ versions = workspace.versions
30
+ print_table(versions)
31
+ verdict(versions)
32
+ end
33
+
34
+ # Parity plus git readiness: clean tree, on main, tagged at the version.
35
+ #
36
+ # @return [Boolean] true when every package could be published now
37
+ def preflight
38
+ ok = call
39
+ target = workspace.versions.values.compact.uniq.first
40
+ out.puts
41
+ out.puts "Release readiness:"
42
+
43
+ Workspace::LOCKSTEP.each_key do |name|
44
+ problems = readiness_problems(name, target)
45
+ out.puts format(" %<name>-16s %<state>s", name: name, state: problems.empty? ? "ready".bright_green : problems.join(", ").red)
46
+ ok &&= problems.empty?
47
+ end
48
+
49
+ out.puts
50
+ out.puts ok ? "ALL READY — publish with `gem push` / `npm publish`" : "NOT READY — resolve the above"
51
+ ok
52
+ end
53
+
54
+ private
55
+
56
+ # @return [Workspace] the ecosystem checkout being inspected
57
+ attr_reader :workspace
58
+
59
+ # @return [IO] where report output goes
60
+ attr_reader :out
61
+
62
+ # @param versions [Hash{String => String, nil}]
63
+ # @return [void]
64
+ def print_table(versions)
65
+ versions.each do |name, version|
66
+ # format, not printf: printf writes straight to $stdout and returns
67
+ # nil, so the injected out saw one blank line per package and the
68
+ # real table bypassed it entirely.
69
+ out.puts format(" → %<name>-30s %<kind>5s %<version>6s",
70
+ name: name.to_s.yellow,
71
+ kind: Workspace::LOCKSTEP[name].to_s.cyan,
72
+ version: (version || "MISSING").to_s.green)
73
+ end
74
+ end
75
+
76
+ # @param versions [Hash{String => String, nil}]
77
+ # @return [Boolean] true when every package agrees on one version
78
+ def verdict(versions)
79
+ out.puts "——————————————————————————————————"
80
+ distinct = versions.values.compact.uniq
81
+ if versions.value?(nil)
82
+ out.puts "DRIFT: a version could not be read (MISSING above)".red
83
+ false
84
+ elsif distinct.one?
85
+ out.puts "OK: all #{versions.size} at #{distinct.first}".green
86
+ true
87
+ else
88
+ out.puts "DRIFT: #{distinct.sort.join(", ")} — run `inquirex versions-bump <version>`".yellow
89
+ false
90
+ end
91
+ end
92
+
93
+ # Why a package is not publishable right now.
94
+ #
95
+ # @param name [String] package name
96
+ # @param target [String, nil] the version its tag must match
97
+ # @return [Array<String>] empty when ready
98
+ def readiness_problems(name, target)
99
+ state = workspace.git_state(name)
100
+ return ["no git checkout"] if state[:clean].nil?
101
+
102
+ problems = []
103
+ problems << "DIRTY" unless state[:clean]
104
+ problems << "on #{state[:branch]}" unless state[:branch] == "main"
105
+ problems << "untagged" unless state[:tags].any? { |tag| tag.delete_prefix("v") == target }
106
+ problems
107
+ end
108
+ end
109
+ end
110
+ end
@@ -11,34 +11,34 @@ module Inquirex
11
11
  # walking up from the working directory looking for the sibling checkouts,
12
12
  # or taken from INQUIREX_ROOT.
13
13
  class Workspace
14
- # Packages that must always carry the same version. They share one
15
- # serialization format — the gem defines the DSL and emits step JSON,
16
- # inquirex-js renders it, inquirex-webui prints it back to DSL,
17
- # inquirex-llm extends the vocabulary, and inquirex-tools is the tooling
18
- # that ships alongside them. A verb present in one and absent in another
19
- # does not fail loudly; it drops data.
14
+ # Every package in the family, all carrying the same version. They share
15
+ # one serialization format — the gem defines the DSL and emits step JSON,
16
+ # inquirex-widget (npm; formerly @kigster/inquirex-js) renders it,
17
+ # inquirex-webui prints it back to DSL, inquirex-llm extends the
18
+ # vocabulary, inquirex-tty walks a flow in the terminal, and
19
+ # inquirex-tools is the tooling that ships alongside them. A verb present
20
+ # in one and absent in another does not fail loudly; it drops data.
20
21
  #
21
- # `inquirex-tty` is deliberately absent: a developer tool outside the
22
- # wire contract, versioned on its own cadence.
22
+ # Nothing is excluded. One version number across the whole family means
23
+ # "which combination has this bug?" is a lookup rather than an
24
+ # investigation.
23
25
  LOCKSTEP = {
24
- "inquirex" => :gem,
25
- "inquirex-llm" => :gem,
26
- "inquirex-tools" => :gem,
27
- "inquirex-js" => :npm,
28
- "inquirex-webui" => :npm
26
+ "inquirex" => :gem,
27
+ "inquirex-llm" => :gem,
28
+ "inquirex-tools" => :gem,
29
+ "inquirex-tty" => :gem,
30
+ "inquirex-widget" => :npm,
31
+ "inquirex-webui" => :npm
29
32
  }.freeze
30
33
 
31
- # Excluded from lockstep, documented so the omission reads as deliberate.
32
- EXCLUDED = %w[inquirex-tty].freeze
33
-
34
34
  # Repositories that carry a generated CHANGELOG.md but are not versioned
35
35
  # in lockstep.
36
- CHANGELOG_ONLY = %w[inquirex-tty qualified-at].freeze
36
+ CHANGELOG_ONLY = %w[qualified-at].freeze
37
37
 
38
38
  GEM_VERSION_RE = /VERSION\s*=\s*"([^"]+)"/
39
39
 
40
40
  # Directories whose presence identifies the ecosystem root.
41
- MARKERS = %w[inquirex inquirex-js].freeze
41
+ MARKERS = %w[inquirex inquirex-widget].freeze
42
42
 
43
43
  # @return [String] absolute path to the ecosystem root
44
44
  attr_reader :root
@@ -92,18 +92,21 @@ module Inquirex
92
92
  #
93
93
  # @param name [String] package name
94
94
  # @param version [String] new version
95
+ # @param kind [Symbol] :gem or :npm — which version line to rewrite.
96
+ # Passed by the caller rather than looked up here so a caller that
97
+ # already knows the kind does not pay for a second lookup.
95
98
  # @return [void]
96
- def write_version(name, version)
99
+ def write_version(name, version, kind)
97
100
  file = version_file(name)
98
101
  raise Error, "no version file for #{name}" unless file
99
102
 
100
103
  src = File.read(file)
101
- updated =
102
- if LOCKSTEP[name] == :gem
103
- src.sub(GEM_VERSION_RE, %(VERSION = "#{version}"))
104
- else
105
- src.sub(/"version":\s*"[^"]*"/, %("version": "#{version}"))
106
- end
104
+ updated = case kind
105
+ when :gem
106
+ src.sub(GEM_VERSION_RE, %(VERSION = "#{version}"))
107
+ when :npm
108
+ src.sub(/"version":\s*"[^"]*"/, %("version": "#{version}"))
109
+ end
107
110
  File.write(file, updated)
108
111
  end
109
112
 
@@ -114,9 +117,9 @@ module Inquirex
114
117
  return { clean: nil, branch: nil, tags: [] } unless File.exist?(File.join(dir, ".git"))
115
118
 
116
119
  {
117
- clean: `git -C #{dir} status --porcelain 2>/dev/null`.strip.empty?,
120
+ clean: `git -C #{dir} status --porcelain 2>/dev/null`.strip.empty?,
118
121
  branch: `git -C #{dir} rev-parse --abbrev-ref HEAD 2>/dev/null`.strip,
119
- tags: `git -C #{dir} tag --points-at HEAD 2>/dev/null`.split("\n").map(&:strip).reject(&:empty?)
122
+ tags: `git -C #{dir} tag --points-at HEAD 2>/dev/null`.split("\n").map(&:strip).reject(&:empty?)
120
123
  }
121
124
  end
122
125
 
@@ -2,7 +2,9 @@
2
2
 
3
3
  require_relative "tools/version"
4
4
  require_relative "tools/workspace"
5
- require_relative "tools/versions"
5
+ require_relative "tools/version_checker"
6
+ require_relative "tools/version_bumper"
7
+ require_relative "tools/publisher"
6
8
  require_relative "tools/changelogs"
7
9
 
8
10
  module Inquirex
@@ -17,13 +19,16 @@ module Inquirex
17
19
  # required to have zero runtime dependencies, and nothing added here changes
18
20
  # that, because nothing here is loaded by the runtime gems.
19
21
  #
20
- # Executables:
22
+ # It ships one executable, `inquirex`, with these subcommands:
21
23
  #
22
- # - `inquirex-version` — version parity across the lockstep packages
23
- # - `inquirex-changelogs` — regenerate CHANGELOG.md from merged PRs
24
+ # - `versions-check` — version parity across the lockstep packages
25
+ # - `versions-bump` — move every lockstep package to one version
26
+ # - `publish` — publish every package to RubyGems and npm
27
+ # - `changelogs` — regenerate CHANGELOG.md from merged PRs
28
+ # - `version` — this gem's own version
24
29
  #
25
30
  # @example Check whether the family is releasable
26
- # Inquirex::Tools::Versions.new.preflight # => true when every package is ready
31
+ # Inquirex::Tools::VersionChecker.new.preflight # => true when every package is ready
27
32
  module Tools
28
33
  class Error < StandardError; end
29
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inquirex-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
25
  version: '1.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: colored2
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
26
40
  description: |
27
41
  Ships the `inquirex` command: lockstep version management across the
28
42
  Inquirex gems and npm packages, changelog regeneration, and release
@@ -32,24 +46,38 @@ email:
32
46
  - kigster@gmail.com
33
47
  executables:
34
48
  - inquirex
49
+ - inquirexor
35
50
  extensions: []
36
51
  extra_rdoc_files: []
37
52
  files:
38
53
  - ".DS_Store"
54
+ - ".env.encrypted"
55
+ - ".env.example"
56
+ - ".envrc"
39
57
  - ".github_changelog_generator"
58
+ - ".relaxed_rubocop.yml"
59
+ - ".sops.yaml"
60
+ - ".sopsy.sha"
61
+ - ".sopsy.yml"
40
62
  - CHANGELOG.md
41
63
  - LICENSE.txt
42
64
  - README.md
43
65
  - Rakefile
44
66
  - exe/inquirex
67
+ - exe/inquirexor
68
+ - justfile
45
69
  - lib/inquirex/tools.rb
46
70
  - lib/inquirex/tools/changelogs.rb
47
71
  - lib/inquirex/tools/commands.rb
48
72
  - lib/inquirex/tools/commands/changelogs.rb
73
+ - lib/inquirex/tools/commands/publish.rb
49
74
  - lib/inquirex/tools/commands/version.rb
50
- - lib/inquirex/tools/commands/versions.rb
75
+ - lib/inquirex/tools/commands/versions_bump.rb
76
+ - lib/inquirex/tools/commands/versions_check.rb
77
+ - lib/inquirex/tools/publisher.rb
51
78
  - lib/inquirex/tools/version.rb
52
- - lib/inquirex/tools/versions.rb
79
+ - lib/inquirex/tools/version_bumper.rb
80
+ - lib/inquirex/tools/version_checker.rb
53
81
  - lib/inquirex/tools/workspace.rb
54
82
  - sig/inquirex/tools.rbs
55
83
  homepage: https://github.com/kigster/inquirex-tools