kk-git 0.2.7 → 0.2.9
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 +4 -4
- data/lib/kk/git/commit_message.rb +2 -2
- data/lib/kk/git/git_ops.rb +27 -0
- data/lib/kk/git/rake_tasks.rb +14 -0
- data/lib/kk/git/release.rb +97 -2
- data/lib/kk/git/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cf707ff92a149936ea729095e66789b1af70a80a5519a1b90f262ac9f9bfeaf5
|
|
4
|
+
data.tar.gz: 16527f8e79675fde491dfad46bc3bf853f43755c837364c905bf7e1839fef542
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 47fe99e7a65c3e9eed0f3e6d2fb56ec47dfe2ab77daf775a8706c598e7ed20b7857adaa6256a122c28924fb677954cbf60d3eb6311f319456c914b93d1f69ce2
|
|
7
|
+
data.tar.gz: fb76a7efc708d33ec57b9309db3b79a278b146a47df37159f4acdb39ff7f3920fa14996c9c70b24ed7a68e238d6170953ccd9886b5085b0c5d6cef522cc7d01e
|
|
@@ -315,8 +315,8 @@ module KKGit
|
|
|
315
315
|
return false if path.nil?
|
|
316
316
|
path.start_with?('openspec/') ||
|
|
317
317
|
path.match?(/\AREADME(\..+)?\z/i) ||
|
|
318
|
-
path.match?(/\.(md|mdx|txt)\z/i)
|
|
319
|
-
|
|
318
|
+
path.match?(/\.(md|mdx|txt|csv)\z/i)
|
|
319
|
+
end
|
|
320
320
|
|
|
321
321
|
def self.ci_path?(path)
|
|
322
322
|
return false if path.nil?
|
data/lib/kk/git/git_ops.rb
CHANGED
|
@@ -312,6 +312,18 @@ module KKGit
|
|
|
312
312
|
raise Error, 'Set KK_GIT_YES=1 to confirm this commit'
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
+
def fallback_commit_message(repo_dir: '.')
|
|
316
|
+
inferred = KKGit::CommitMessage.generate(repo_dir: repo_dir, mode: :all).to_s.strip
|
|
317
|
+
return inferred unless inferred.empty?
|
|
318
|
+
|
|
319
|
+
out, _err, ok = run_cmd('git', 'diff', '--cached', '--name-only', chdir: repo_dir)
|
|
320
|
+
names = ok ? out.split("\n").reject(&:empty?) : []
|
|
321
|
+
return 'chore(general): Update project' if names.empty?
|
|
322
|
+
|
|
323
|
+
label = File.basename(names.first)
|
|
324
|
+
names.length == 1 ? "chore(general): Update #{label}" : "chore(general): Update #{names.length} files"
|
|
325
|
+
end
|
|
326
|
+
|
|
315
327
|
def commit_with_message!(message, repo_dir: '.')
|
|
316
328
|
commit_args = amend? ? %w[commit --amend -F] : %w[commit -F]
|
|
317
329
|
|
|
@@ -352,6 +364,17 @@ module KKGit
|
|
|
352
364
|
add_all!(repo_dir: repo_dir)
|
|
353
365
|
ensure_no_sensitive_staged!(repo_dir: repo_dir)
|
|
354
366
|
|
|
367
|
+
# add 后可能已干净:假脏(换行归一化等)或 KK_GIT_ADD_PATHS 未覆盖到变更
|
|
368
|
+
if working_tree_clean?(repo_dir: repo_dir)
|
|
369
|
+
if status(remote: remote_name, branch: branch_name, repo_dir: repo_dir).needs_sync?
|
|
370
|
+
sync_with_remote!(remote_name, branch_name, repo_dir: repo_dir)
|
|
371
|
+
return :synced
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
puts 'No changes to commit or push'
|
|
375
|
+
return :noop
|
|
376
|
+
end
|
|
377
|
+
|
|
355
378
|
message =
|
|
356
379
|
if commit_message_generator
|
|
357
380
|
commit_message_generator.call
|
|
@@ -359,6 +382,10 @@ module KKGit
|
|
|
359
382
|
KKGit::CommitMessage.generate(repo_dir: repo_dir, mode: :all)
|
|
360
383
|
end
|
|
361
384
|
message = message.to_s.strip
|
|
385
|
+
if message.empty?
|
|
386
|
+
message = fallback_commit_message(repo_dir: repo_dir)
|
|
387
|
+
warn "Commit message inference empty; using fallback: #{message}"
|
|
388
|
+
end
|
|
362
389
|
raise Error, 'Could not generate commit message from staged changes' if message.empty?
|
|
363
390
|
|
|
364
391
|
confirm_commit!(message)
|
data/lib/kk/git/rake_tasks.rb
CHANGED
|
@@ -71,6 +71,20 @@ module KKGit
|
|
|
71
71
|
warn e.message
|
|
72
72
|
exit 1
|
|
73
73
|
end
|
|
74
|
+
|
|
75
|
+
desc 'Auto commit/push, then semver tag (SKIP_TAG=1 or KK_GIT_AUTO_TAG=0 to skip)'
|
|
76
|
+
task :auto_commit_push_tag do
|
|
77
|
+
generator = lambda do
|
|
78
|
+
Rake::Task['git:auto_commit'].reenable
|
|
79
|
+
Rake::Task['git:auto_commit'].invoke
|
|
80
|
+
ENV['KK_GIT_COMMIT_MESSAGE'].to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
KKGit::Release.auto_commit_push_and_tag!(commit_message_generator: generator)
|
|
84
|
+
rescue KKGit::GitOps::Error, ArgumentError => e
|
|
85
|
+
warn e.message
|
|
86
|
+
exit 1
|
|
87
|
+
end
|
|
74
88
|
end
|
|
75
89
|
end
|
|
76
90
|
end
|
data/lib/kk/git/release.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module KKGit
|
|
4
|
-
# Semver bump and git tag helpers (maintainer release flow).
|
|
4
|
+
# Semver bump and git tag helpers (maintainer release flow + consumer auto-tag).
|
|
5
5
|
module Release
|
|
6
6
|
VERSION_PATH = File.join(__dir__, 'version.rb').freeze
|
|
7
7
|
|
|
@@ -48,7 +48,7 @@ module KKGit
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def semver_max(*versions)
|
|
51
|
-
versions.compact.
|
|
51
|
+
versions.compact.max
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def tag_exists?(tag, repo_dir: '.')
|
|
@@ -74,6 +74,42 @@ module KKGit
|
|
|
74
74
|
true
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
# Strict repo tags only: vMAJOR.MINOR.PATCH with MAJOR < max_major (skips date tags like v2026.09.23).
|
|
78
|
+
# @return [Array<Array(Integer)>]
|
|
79
|
+
def list_repo_semver_versions(prefix: 'v', repo_dir: '.', max_major: 1999)
|
|
80
|
+
stdout, _stderr, ok = GitOps.run_cmd('git', 'tag', '--list', "#{prefix}*", chdir: repo_dir)
|
|
81
|
+
return [] unless ok
|
|
82
|
+
|
|
83
|
+
stdout.to_s.split("\n").filter_map do |t|
|
|
84
|
+
t = t.strip
|
|
85
|
+
next unless t.start_with?(prefix)
|
|
86
|
+
|
|
87
|
+
ver = parse_semver(t.delete_prefix(prefix))
|
|
88
|
+
next unless ver
|
|
89
|
+
next if ver[0] > max_major
|
|
90
|
+
|
|
91
|
+
ver
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Next tag from git history only (no version.rb / gem VERSION). For product repos.
|
|
96
|
+
# @return [String] e.g. "v1.0.1"
|
|
97
|
+
def next_repo_semver_tag(prefix: nil, bump: nil, repo_dir: '.', default_base: [1, 0, 0], max_major: 1999)
|
|
98
|
+
prefix ||= ENV.fetch('KK_GIT_TAG_PREFIX', 'v')
|
|
99
|
+
bump ||= ENV.fetch('KK_GIT_BUMP', 'patch')
|
|
100
|
+
raise ArgumentError, "bump must be major|minor|patch (got #{bump})" unless %w[major minor patch].include?(bump)
|
|
101
|
+
|
|
102
|
+
base = list_repo_semver_versions(prefix: prefix, repo_dir: repo_dir, max_major: max_major).max || default_base
|
|
103
|
+
version = base
|
|
104
|
+
50.times do
|
|
105
|
+
version = bump_semver(version, bump)
|
|
106
|
+
candidate = "#{prefix}#{semver_to_s(version)}"
|
|
107
|
+
return candidate unless tag_exists?(candidate, repo_dir: repo_dir)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
raise 'Failed to generate next repo semver tag: too many attempts'
|
|
111
|
+
end
|
|
112
|
+
|
|
77
113
|
# @return [Array(String, String)] tag, version
|
|
78
114
|
def next_tag_and_version(prefix: nil, bump: nil, repo_dir: '.')
|
|
79
115
|
prefix ||= ENV.fetch('KK_GIT_TAG_PREFIX', 'v')
|
|
@@ -81,6 +117,7 @@ module KKGit
|
|
|
81
117
|
|
|
82
118
|
latest_tag = latest_semver_tag(prefix: prefix, repo_dir: repo_dir)
|
|
83
119
|
tag_version = latest_tag ? parse_semver(latest_tag.delete_prefix(prefix)) : nil
|
|
120
|
+
# Prefer strict repo tags when gem/file versions would pollute consumer repos.
|
|
84
121
|
file_version = current_version_in_file || parse_semver(KKGit::VERSION)
|
|
85
122
|
|
|
86
123
|
# version.rb already ahead of tags and tag not yet created → release that version
|
|
@@ -109,5 +146,63 @@ module KKGit
|
|
|
109
146
|
out, err, ok = GitOps.run_cmd('git', 'push', push_target, tag, chdir: repo_dir)
|
|
110
147
|
GitOps.ensure_ok!(ok, 'git push tag', stdout: out, stderr: err, repo_dir: repo_dir)
|
|
111
148
|
end
|
|
149
|
+
|
|
150
|
+
def auto_tag_enabled?
|
|
151
|
+
return false if ENV['SKIP_TAG'] == '1'
|
|
152
|
+
|
|
153
|
+
ENV.fetch('KK_GIT_AUTO_TAG', '1') != '0'
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# Commit + push, then create/push a semver tag when a new commit was made.
|
|
157
|
+
#
|
|
158
|
+
# - Product repos: leave bump_gem_version false (uses next_repo_semver_tag).
|
|
159
|
+
# - kk-git itself: bump_gem_version true (updates version.rb before commit).
|
|
160
|
+
#
|
|
161
|
+
# Env: KK_GIT_AUTO_TAG (default 1), SKIP_TAG=1, KK_GIT_BUMP, KK_GIT_TAG_PREFIX
|
|
162
|
+
#
|
|
163
|
+
# @return [Hash] keys :result (Symbol), :tag (String or nil)
|
|
164
|
+
def auto_commit_push_and_tag!(commit_message_generator: nil, repo_dir: '.', bump_gem_version: false)
|
|
165
|
+
GitOps.ensure_in_repo!(repo_dir: repo_dir)
|
|
166
|
+
|
|
167
|
+
head_before, _err, ok = GitOps.run_cmd('git', 'rev-parse', 'HEAD', chdir: repo_dir)
|
|
168
|
+
head_before = ok ? head_before.to_s.strip : ''
|
|
169
|
+
|
|
170
|
+
prepared_tag = nil
|
|
171
|
+
if bump_gem_version && auto_tag_enabled? && !GitOps.working_tree_clean?(repo_dir: repo_dir)
|
|
172
|
+
prepared_tag, new_version = next_tag_and_version(repo_dir: repo_dir)
|
|
173
|
+
bumped = update_version!(new_version)
|
|
174
|
+
puts((bumped ? "Version bumped to #{new_version}" : "Version already #{new_version}") +
|
|
175
|
+
", preparing tag #{prepared_tag}")
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
result = GitOps.auto_commit_push!(
|
|
179
|
+
commit_message_generator: commit_message_generator,
|
|
180
|
+
repo_dir: repo_dir
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
head_after, _err2, ok2 = GitOps.run_cmd('git', 'rev-parse', 'HEAD', chdir: repo_dir)
|
|
184
|
+
head_after = ok2 ? head_after.to_s.strip : ''
|
|
185
|
+
new_commit = result == :committed_and_synced || (head_before != head_after && !head_after.empty?)
|
|
186
|
+
|
|
187
|
+
unless auto_tag_enabled?
|
|
188
|
+
puts 'SKIP_TAG/KK_GIT_AUTO_TAG=0 — not tagging' if ENV['SKIP_TAG'] == '1' || ENV['KK_GIT_AUTO_TAG'] == '0'
|
|
189
|
+
return { result: result, tag: nil }
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
unless new_commit
|
|
193
|
+
puts "No new commit (#{result}) — skip tag"
|
|
194
|
+
return { result: result, tag: nil }
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
tag = prepared_tag || next_repo_semver_tag(repo_dir: repo_dir)
|
|
198
|
+
if tag_exists?(tag, repo_dir: repo_dir)
|
|
199
|
+
puts "Tag #{tag} already exists — skip"
|
|
200
|
+
return { result: result, tag: nil }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
create_and_push_tag!(tag, repo_dir: repo_dir)
|
|
204
|
+
puts "Tagged and pushed #{tag}"
|
|
205
|
+
{ result: result, tag: tag }
|
|
206
|
+
end
|
|
112
207
|
end
|
|
113
208
|
end
|
data/lib/kk/git/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kk-git
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kk
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-11-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Generate Conventional Commits commit messages from current git changes
|
|
14
14
|
(staged/worktree), designed for Rake/script usage.
|