Module: KKGit::Release
- Defined in:
- lib/kk/git/release.rb
Overview
Semver bump and git tag helpers (maintainer release flow).
Constant Summary collapse
- VERSION_PATH =
File.join(__dir__, 'version.rb').freeze
Class Method Summary collapse
- .bump_semver(version, level) ⇒ Object
- .create_and_push_tag!(tag, remote: nil, repo_dir: '.') ⇒ Object
- .current_version_in_file ⇒ Object
- .latest_semver_tag(prefix: 'v', repo_dir: '.') ⇒ Object
-
.next_tag_and_version(prefix: nil, bump: nil, repo_dir: '.') ⇒ Array(String, String)
Tag, version.
- .parse_semver(str) ⇒ Object
- .semver_gt?(a, b) ⇒ Boolean
- .semver_max(*versions) ⇒ Object
- .semver_to_s(version) ⇒ Object
- .tag_exists?(tag, repo_dir: '.') ⇒ Boolean
-
.update_version!(new_version) ⇒ Boolean
True when file was updated.
Class Method Details
.bump_semver(version, level) ⇒ Object
27 28 29 30 31 32 33 34 |
# File 'lib/kk/git/release.rb', line 27 def bump_semver(version, level) major, minor, patch = version case level when 'major' then [major + 1, 0, 0] when 'minor' then [major, minor + 1, 0] else [major, minor, patch + 1] end end |
.create_and_push_tag!(tag, remote: nil, repo_dir: '.') ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/kk/git/release.rb', line 103 def create_and_push_tag!(tag, remote: nil, repo_dir: '.') remote ||= GitOps.remote out, err, ok = GitOps.run_cmd('git', 'tag', '-a', tag, '-m', "Release #{tag}", chdir: repo_dir) GitOps.ensure_ok!(ok, 'git tag', stdout: out, stderr: err, repo_dir: repo_dir) push_target = GitOps.push_target(remote) out, err, ok = GitOps.run_cmd('git', 'push', push_target, tag, chdir: repo_dir) GitOps.ensure_ok!(ok, 'git push tag', stdout: out, stderr: err, repo_dir: repo_dir) end |
.current_version_in_file ⇒ Object
59 60 61 62 63 |
# File 'lib/kk/git/release.rb', line 59 def current_version_in_file content = File.read(VERSION_PATH, mode: 'r:BOM|UTF-8') m = content.match(/VERSION\s*=\s*'([^']*)'/) m ? parse_semver(m[1]) : nil end |
.latest_semver_tag(prefix: 'v', repo_dir: '.') ⇒ Object
10 11 12 13 14 15 16 17 18 |
# File 'lib/kk/git/release.rb', line 10 def latest_semver_tag(prefix: 'v', repo_dir: '.') stdout, _stderr, ok = GitOps.run_cmd( 'git', 'tag', '--list', "#{prefix}[0-9]*.[0-9]*.[0-9]*", '--sort=-v:refname', chdir: repo_dir ) return nil unless ok stdout.to_s.split("\n").first&.strip end |
.next_tag_and_version(prefix: nil, bump: nil, repo_dir: '.') ⇒ Array(String, String)
Returns tag, version.
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/kk/git/release.rb', line 78 def next_tag_and_version(prefix: nil, bump: nil, repo_dir: '.') prefix ||= ENV.fetch('KK_GIT_TAG_PREFIX', 'v') bump ||= ENV.fetch('KK_GIT_BUMP', 'patch') latest_tag = latest_semver_tag(prefix: prefix, repo_dir: repo_dir) tag_version = latest_tag ? parse_semver(latest_tag.delete_prefix(prefix)) : nil file_version = current_version_in_file || parse_semver(KKGit::VERSION) # version.rb already ahead of tags and tag not yet created → release that version if file_version && tag_version && semver_gt?(file_version, tag_version) candidate = "#{prefix}#{semver_to_s(file_version)}" return [candidate, semver_to_s(file_version)] unless tag_exists?(candidate, repo_dir: repo_dir) end base = semver_max(tag_version, file_version) || [0, 1, 0] version = base 50.times do version = bump_semver(version, bump) candidate = "#{prefix}#{semver_to_s(version)}" return [candidate, semver_to_s(version)] unless tag_exists?(candidate, repo_dir: repo_dir) end raise 'Failed to generate next release tag: too many attempts' end |
.parse_semver(str) ⇒ Object
20 21 22 23 24 25 |
# File 'lib/kk/git/release.rb', line 20 def parse_semver(str) m = str.to_s.match(/\A(\d+)\.(\d+)\.(\d+)\z/) return nil unless m [m[1].to_i, m[2].to_i, m[3].to_i] end |
.semver_gt?(a, b) ⇒ Boolean
40 41 42 43 44 45 46 47 48 |
# File 'lib/kk/git/release.rb', line 40 def semver_gt?(a, b) return false if a.nil? || b.nil? a.each_with_index do |part, i| return true if part > b[i] return false if part < b[i] end false end |
.semver_max(*versions) ⇒ Object
50 51 52 |
# File 'lib/kk/git/release.rb', line 50 def semver_max(*versions) versions.compact.max_by { |v| v } end |
.semver_to_s(version) ⇒ Object
36 37 38 |
# File 'lib/kk/git/release.rb', line 36 def semver_to_s(version) "#{version[0]}.#{version[1]}.#{version[2]}" end |
.tag_exists?(tag, repo_dir: '.') ⇒ Boolean
54 55 56 57 |
# File 'lib/kk/git/release.rb', line 54 def tag_exists?(tag, repo_dir: '.') out, _err, ok = GitOps.run_cmd('git', 'tag', '--list', tag, chdir: repo_dir) ok && !out.to_s.strip.empty? end |
.update_version!(new_version) ⇒ Boolean
Returns true when file was updated.
66 67 68 69 70 71 72 73 74 75 |
# File 'lib/kk/git/release.rb', line 66 def update_version!(new_version) content = File.read(VERSION_PATH, mode: 'r:BOM|UTF-8') return false if content.match?(/VERSION\s*=\s*'#{Regexp.escape(new_version)}'/) replaced = content.sub(/VERSION\s*=\s*'[^']*'/, "VERSION = '#{new_version}'") raise "Failed to update version in #{VERSION_PATH}" if replaced == content File.write(VERSION_PATH, replaced) true end |