Class: GemKit::Release::Project
- Inherits:
-
Object
- Object
- GemKit::Release::Project
- Defined in:
- lib/gem_kit/release/project.rb
Overview
What the tooling needs to know about the project it is running in.
Almost all of it is already declared in the project's .gemspec — name,
version, and (through require_relative) where the version constant
lives. So the normal case is no configuration at all: point it at a
directory and it works out the rest.
project = GemKit::Release::Project.detect
project.name # => "brute"
project.version # => Gem::Version.new("4.1.0")
project.version_file # => ".../lib/brute/version.rb"
Anything that cannot be inferred is an override:
GemKit::Release.configure do |config|
config.changelog = "HISTORY.md"
config.test_command = "bin/test"
end
Defined Under Namespace
Classes: Ambiguous, Config, NotFound
Instance Attribute Summary collapse
-
#config ⇒ Object
readonly
Returns the value of attribute config.
-
#gemspec_path ⇒ Object
readonly
Returns the value of attribute gemspec_path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
Class Method Summary collapse
-
.detect(dir = Dir.pwd, name: nil, config: GemKit::Release.config) ⇒ Object
namepicks one gem out of a repository that holds several — matched against the gemspec's filename, so--gem gem_kitfinds gem_kit.gemspec and not gem_kit-release.gemspec.
Instance Method Summary collapse
-
#changelog_path ⇒ Object
One changelog per gem.
- #changelog_writer ⇒ Object
- #default_changelog ⇒ Object
-
#initialize(gemspec_path, config: GemKit::Release.config) ⇒ Project
constructor
A new instance of Project.
-
#load! ⇒ Object
Load the library, so Deprecate's registry reflects this project.
- #lockfile_path ⇒ Object
- #multi_gem? ⇒ Boolean
- #name ⇒ Object
-
#next_major_version ⇒ Object
The next major version — the usual deadline for a deprecation.
-
#require_path ⇒ Object
What to require so that deprecation declarations register themselves.
-
#self_locked? ⇒ Boolean
A Gemfile that says
gemspecorpath: "."puts this gem in its own bundle, and the lockfile then records this gem's version. -
#siblings ⇒ Object
Every gemspec beside this one, this one included.
-
#spec ⇒ Object
The evaluated gemspec.
-
#tag_prefix ⇒ Object
v1.2.3says which version but not which gem, which is fine until a repository holds two of them at the same version. - #test_command ⇒ Object
- #version ⇒ Object
-
#version_file ⇒ Object
lib/gem_kit/release/version.rb for "gem_kit-release", lib/brute/version.rb for "brute" — the convention every
bundle gemproject follows. -
#version_template ⇒ Object
An ERB template beside the version file, if the project generates it.
Constructor Details
#initialize(gemspec_path, config: GemKit::Release.config) ⇒ Project
Returns a new instance of Project.
63 64 65 66 67 |
# File 'lib/gem_kit/release/project.rb', line 63 def initialize(gemspec_path, config: GemKit::Release.config) @gemspec_path = File.(gemspec_path) @root = File.dirname(@gemspec_path) @config = config end |
Instance Attribute Details
#config ⇒ Object (readonly)
Returns the value of attribute config.
61 62 63 |
# File 'lib/gem_kit/release/project.rb', line 61 def config @config end |
#gemspec_path ⇒ Object (readonly)
Returns the value of attribute gemspec_path.
61 62 63 |
# File 'lib/gem_kit/release/project.rb', line 61 def gemspec_path @gemspec_path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
61 62 63 |
# File 'lib/gem_kit/release/project.rb', line 61 def root @root end |
Class Method Details
.detect(dir = Dir.pwd, name: nil, config: GemKit::Release.config) ⇒ Object
name picks one gem out of a repository that holds several — matched
against the gemspec's filename, so --gem gem_kit finds
gem_kit.gemspec and not gem_kit-release.gemspec.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/gem_kit/release/project.rb', line 39 def self.detect(dir = Dir.pwd, name: nil, config: GemKit::Release.config) gemspecs = Dir[File.join(dir, "*.gemspec")].sort raise NotFound, "no .gemspec in #{dir}" if gemspecs.empty? if name match = gemspecs.find { |path| File.basename(path, ".gemspec") == name } raise NotFound, "no #{name}.gemspec in #{dir}" if match.nil? return new(match, config: config) end # Silently picking the first would mean bumping the wrong gem's version # and only finding out on release. if gemspecs.size > 1 names = gemspecs.map { |path| File.basename(path, ".gemspec") } raise Ambiguous, "#{gemspecs.size} gemspecs in #{dir} (#{names.join(", ")}); " \ "name one with --gem" end new(gemspecs.first, config: config) end |
Instance Method Details
#changelog_path ⇒ Object
One changelog per gem. A shared file cannot work: the release gate asks whether the version being cut is the topmost released section, and two gems interleaved in one file means the older one never is — so the second gem could never be released.
100 101 102 |
# File 'lib/gem_kit/release/project.rb', line 100 def changelog_path File.(config.changelog || default_changelog, root) end |
#changelog_writer ⇒ Object
160 |
# File 'lib/gem_kit/release/project.rb', line 160 def changelog_writer = config.changelog_writer || "claude" |
#default_changelog ⇒ Object
104 105 106 |
# File 'lib/gem_kit/release/project.rb', line 104 def default_changelog multi_gem? ? "CHANGELOG-#{name}.md" : "CHANGELOG.md" end |
#load! ⇒ Object
Load the library, so Deprecate's registry reflects this project.
148 149 150 151 152 153 154 155 156 |
# File 'lib/gem_kit/release/project.rb', line 148 def load! $LOAD_PATH.unshift(File.join(root, "lib")) unless $LOAD_PATH.include?(File.join(root, "lib")) require require_path true rescue LoadError => error warn "gem_kit-release: could not require #{require_path.inspect} (#{error.});" \ " deprecations will not be detected" false end |
#lockfile_path ⇒ Object
108 109 110 |
# File 'lib/gem_kit/release/project.rb', line 108 def lockfile_path File.join(root, "Gemfile.lock") end |
#multi_gem? ⇒ Boolean
94 |
# File 'lib/gem_kit/release/project.rb', line 94 def multi_gem? = siblings > 1 |
#name ⇒ Object
76 |
# File 'lib/gem_kit/release/project.rb', line 76 def name = spec.name |
#next_major_version ⇒ Object
The next major version — the usual deadline for a deprecation. Written "5.0" rather than "5": it reads as a version in prose and in a declaration, and Gem::Version treats the two as equal anyway.
83 84 85 |
# File 'lib/gem_kit/release/project.rb', line 83 def next_major_version "#{version.segments.first.to_i + 1}.0" end |
#require_path ⇒ Object
What to require so that deprecation declarations register themselves. "gem_kit-release" -> "gem_kit/release".
143 144 145 |
# File 'lib/gem_kit/release/project.rb', line 143 def require_path config.require_path || name.tr("-", "/") end |
#self_locked? ⇒ Boolean
A Gemfile that says gemspec or path: "." puts this gem in its own
bundle, and the lockfile then records this gem's version. Bumping
without relocking leaves the two disagreeing — which bundler reports as
"the gemspecs for path gems changed", and refuses outright under
frozen mode, as bundlerEnv sets.
117 118 119 120 121 |
# File 'lib/gem_kit/release/project.rb', line 117 def self_locked? return false unless File.exist?(lockfile_path) File.read(lockfile_path).match?(/^\s{4}#{Regexp.escape(name)} \(\d/) end |
#siblings ⇒ Object
Every gemspec beside this one, this one included. A repository with more than one releases each gem on its own schedule, and several things below have to know that.
90 91 92 |
# File 'lib/gem_kit/release/project.rb', line 90 def siblings @siblings ||= Dir[File.join(root, "*.gemspec")].size end |
#spec ⇒ Object
The evaluated gemspec. Loaded from the project root, because a gemspec typically require_relative's its own version file.
71 72 73 74 |
# File 'lib/gem_kit/release/project.rb', line 71 def spec @spec ||= Dir.chdir(root) { Gem::Specification.load(gemspec_path) } or raise NotFound, "could not load #{gemspec_path}" end |
#tag_prefix ⇒ Object
v1.2.3 says which version but not which gem, which is fine until a
repository holds two of them at the same version.
125 126 127 |
# File 'lib/gem_kit/release/project.rb', line 125 def tag_prefix multi_gem? ? "#{name}-v" : "v" end |
#test_command ⇒ Object
158 |
# File 'lib/gem_kit/release/project.rb', line 158 def test_command = config.test_command || "bin/test" |
#version ⇒ Object
78 |
# File 'lib/gem_kit/release/project.rb', line 78 def version = Gem::Version.new(spec.version.to_s) |
#version_file ⇒ Object
lib/gem_kit/release/version.rb for "gem_kit-release", lib/brute/version.rb
for "brute" — the convention every bundle gem project follows.
131 132 133 |
# File 'lib/gem_kit/release/project.rb', line 131 def version_file File.(config.version_file || File.join("lib", *name.split("-"), "version.rb"), root) end |
#version_template ⇒ Object
An ERB template beside the version file, if the project generates it.
136 137 138 139 |
# File 'lib/gem_kit/release/project.rb', line 136 def version_template candidate = "#{version_file}.erb" candidate if File.exist?(candidate) end |