afterlife 1.8.0 → 1.9.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 +4 -4
- data/.rubocop.yml +23 -2
- data/.ruby-version +1 -1
- data/Gemfile +3 -0
- data/afterlife.gemspec +2 -1
- data/config.ru +2 -3
- data/lib/afterlife/bump/semver.rb +2 -2
- data/lib/afterlife/cdn/cli.rb +1 -0
- data/lib/afterlife/cli.rb +1 -0
- data/lib/afterlife/clickup/cli.rb +15 -2
- data/lib/afterlife/clickup/commit_input_splitter.rb +64 -0
- data/lib/afterlife/clickup/get_ids_from_text.rb +1 -1
- data/lib/afterlife/clickup/next_task_status_decider.rb +46 -0
- data/lib/afterlife/clickup/status_precedence_checker.rb +2 -0
- data/lib/afterlife/clickup/task_revert_detector.rb +30 -0
- data/lib/afterlife/clickup/update_task_status.rb +71 -20
- data/lib/afterlife/config/cli.rb +1 -0
- data/lib/afterlife/config/provider.rb +1 -1
- data/lib/afterlife/deploy/cli.rb +1 -0
- data/lib/afterlife/notify.rb +2 -2
- data/lib/afterlife/propagate/cli.rb +1 -0
- data/lib/afterlife/propagate/propagate_qa_to_sandbox.rb +1 -1
- data/lib/afterlife/release/change_version.rb +1 -1
- data/lib/afterlife/release/cli.rb +1 -1
- data/lib/afterlife/release/create_helper.rb +3 -2
- data/lib/afterlife/release/pre_helper.rb +5 -4
- data/lib/afterlife/repo/config.rb +5 -5
- data/lib/afterlife/version.rb +1 -1
- metadata +21 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ded787195d0197794e9ce63aab421fd0b9f4168208bab96b1cdab4e34f22d955
|
|
4
|
+
data.tar.gz: f9305bba34772dbe134eedad518d67ad371e85a1e8b6f28b25785f54f8737e58
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: decbc189d4fc9e422ab524fdd80adc4234d919542350db532bc04a69a48cdef40220fde5331fb94fa77c1427a59df5d4328f7d454e50d8a8b20d336c239e976b
|
|
7
|
+
data.tar.gz: 394711b68721f95e338b558c51d86581537b6a0ddf7f4dcd31646420cf0a9cebcdfbff60ef2395f4b13acaae1e44856aac5b57b0d690402f46c51b8053a94d81
|
data/.rubocop.yml
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
plugins:
|
|
2
2
|
- rubocop-rspec
|
|
3
3
|
- rubocop-rake
|
|
4
4
|
|
|
5
5
|
AllCops:
|
|
6
6
|
NewCops: enable
|
|
7
|
-
TargetRubyVersion:
|
|
7
|
+
TargetRubyVersion: 3.3
|
|
8
8
|
|
|
9
9
|
Lint/ConstantDefinitionInBlock:
|
|
10
10
|
Enabled: false
|
|
@@ -44,3 +44,24 @@ Layout/AccessModifierIndentation:
|
|
|
44
44
|
|
|
45
45
|
Style/SignalException:
|
|
46
46
|
EnforcedStyle: semantic
|
|
47
|
+
|
|
48
|
+
Metrics/ClassLength:
|
|
49
|
+
Enabled: false
|
|
50
|
+
|
|
51
|
+
Metrics/CyclomaticComplexity:
|
|
52
|
+
Enabled: false
|
|
53
|
+
|
|
54
|
+
Metrics/MethodLength:
|
|
55
|
+
Enabled: false
|
|
56
|
+
|
|
57
|
+
Metrics/ParameterLists:
|
|
58
|
+
Enabled: false
|
|
59
|
+
|
|
60
|
+
Metrics/PerceivedComplexity:
|
|
61
|
+
Enabled: false
|
|
62
|
+
|
|
63
|
+
RSpec/MultipleExpectations:
|
|
64
|
+
Enabled: false
|
|
65
|
+
|
|
66
|
+
RSpec/MultipleMemoizedHelpers:
|
|
67
|
+
Enabled: false
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.
|
|
1
|
+
3.3.5
|
data/Gemfile
CHANGED
data/afterlife.gemspec
CHANGED
|
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
|
10
10
|
|
|
11
11
|
spec.summary = 'Devops utils'
|
|
12
12
|
spec.description = 'Afterlife helps you setup your development environment and deploy code easily'
|
|
13
|
-
spec.required_ruby_version = '>=
|
|
13
|
+
spec.required_ruby_version = '>= 3.3'
|
|
14
14
|
|
|
15
15
|
spec.metadata['source_code_uri'] = 'https://bitbucket.org/volabit/afterlife'
|
|
16
16
|
spec.metadata['changelog_uri'] = 'https://bitbucket.org/volabit/afterlife/src/master/CHANGELOG.md'
|
|
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.require_paths = ['lib']
|
|
30
30
|
|
|
31
31
|
spec.add_dependency 'faraday'
|
|
32
|
+
spec.add_dependency 'ostruct'
|
|
32
33
|
spec.add_dependency 'racc' # rubocop dependency, cannot run `bundle exec rubocop` without it
|
|
33
34
|
spec.add_dependency 'thor'
|
|
34
35
|
spec.add_dependency 'zeitwerk'
|
data/config.ru
CHANGED
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
require 'logger'
|
|
4
4
|
require 'rack/directory'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
logger_file.sync = true
|
|
6
|
+
logger = Logger.new(Afterlife::Cdn.log_path)
|
|
8
7
|
|
|
9
8
|
class AssetHeaders
|
|
10
9
|
def initialize(app)
|
|
@@ -19,7 +18,7 @@ class AssetHeaders
|
|
|
19
18
|
end
|
|
20
19
|
|
|
21
20
|
use AssetHeaders
|
|
22
|
-
use Rack::CommonLogger,
|
|
21
|
+
use Rack::CommonLogger, logger
|
|
23
22
|
run do |env|
|
|
24
23
|
Rack::Directory.new(Afterlife::Cdn.local_path).call(env)
|
|
25
24
|
end
|
|
@@ -6,9 +6,9 @@ module Afterlife
|
|
|
6
6
|
module_function
|
|
7
7
|
|
|
8
8
|
DEFAULT_PRERELEASE_NAME = 'rc'
|
|
9
|
-
VERSION_REGEX = /(\d+\.\d+\.\d+(?:-(?:.+))?)
|
|
9
|
+
VERSION_REGEX = /(\d+\.\d+\.\d+(?:-(?:.+))?)/
|
|
10
10
|
|
|
11
|
-
def calculate_next(part, pre = nil)
|
|
11
|
+
def calculate_next(part, pre = nil)
|
|
12
12
|
x, y, z = release
|
|
13
13
|
case part.to_sym
|
|
14
14
|
when :major
|
data/lib/afterlife/cdn/cli.rb
CHANGED
data/lib/afterlife/cli.rb
CHANGED
|
@@ -37,10 +37,23 @@ module Afterlife
|
|
|
37
37
|
desc: 'Force update status of tasks even if they would not be updated due to status precedence'
|
|
38
38
|
option :dry_run, type: :boolean, default: false, aliases: '-d',
|
|
39
39
|
desc: 'Do not actually update the status of the tasks, just print what would be done'
|
|
40
|
-
|
|
40
|
+
option :cherry_pick, type: :boolean, default: false, aliases: '-c',
|
|
41
|
+
desc: 'Include cherry pick status in the output'
|
|
42
|
+
option :verbose, type: :boolean, default: true, aliases: '-v',
|
|
43
|
+
desc: 'Print skipped tasks'
|
|
44
|
+
option :commits, type: :string,
|
|
45
|
+
desc: 'Commit messages used to detect reverted tasks'
|
|
46
|
+
def update_status(target_status, *task_ids) # rubocop:disable Metrics/AbcSize
|
|
41
47
|
task_ids = $stdin.read.strip.split("\n") if task_ids.empty?
|
|
42
48
|
|
|
43
|
-
UpdateTaskStatus.call(
|
|
49
|
+
UpdateTaskStatus.call(
|
|
50
|
+
task_ids, target_status,
|
|
51
|
+
force: options[:force],
|
|
52
|
+
dry_run: options[:dry_run],
|
|
53
|
+
cherry_pick: options[:cherry_pick],
|
|
54
|
+
verbose: options[:verbose],
|
|
55
|
+
commits: options[:commits],
|
|
56
|
+
)
|
|
44
57
|
rescue StandardError => e
|
|
45
58
|
fatal!(e.message)
|
|
46
59
|
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Afterlife
|
|
4
|
+
module Clickup
|
|
5
|
+
class CommitInputSplitter
|
|
6
|
+
SUBJECT_PATTERN = /\A(?:revert\b|\w+(?:\(.+\))?!?:\s|.+#(?:CU[-_])?[a-z0-9]{8,})/i
|
|
7
|
+
|
|
8
|
+
def self.call(input)
|
|
9
|
+
new(input).call
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(input)
|
|
13
|
+
@input = input.to_s.strip
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
return [] if input.empty?
|
|
18
|
+
|
|
19
|
+
return split_github_input if input.include?('\\n')
|
|
20
|
+
|
|
21
|
+
split_real_newline_input
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
attr_reader :input
|
|
27
|
+
|
|
28
|
+
def split_github_input
|
|
29
|
+
input.lines(chomp: true).filter_map do |line|
|
|
30
|
+
line = line.strip
|
|
31
|
+
line.gsub('\\n', "\n") unless line.empty?
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def split_real_newline_input
|
|
36
|
+
commits = []
|
|
37
|
+
current = []
|
|
38
|
+
|
|
39
|
+
input.lines(chomp: true).each do |line|
|
|
40
|
+
if subject?(line) && current.any?
|
|
41
|
+
commits << normalize(current)
|
|
42
|
+
current = []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
current << line
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
commits << normalize(current) if current.any?
|
|
49
|
+
commits.reject(&:empty?)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def subject?(line)
|
|
53
|
+
return false if line.empty? || line.start_with?('*', '-', ' ')
|
|
54
|
+
return false if line.match?(/\AThis reverts commit\b/i)
|
|
55
|
+
|
|
56
|
+
line.match?(SUBJECT_PATTERN)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def normalize(lines)
|
|
60
|
+
lines.join("\n").strip
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Afterlife
|
|
4
|
+
module Clickup
|
|
5
|
+
class NextTaskStatusDecider
|
|
6
|
+
REVERT_SOURCE_STATUS = 'ready for qa'
|
|
7
|
+
REVERT_TARGET_STATUS = 'needs rework'
|
|
8
|
+
|
|
9
|
+
def self.call(**args)
|
|
10
|
+
new(**args).call
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(clickup_task:, target_status:, force: false, reverted: false)
|
|
14
|
+
@clickup_task = clickup_task
|
|
15
|
+
@target_status = target_status
|
|
16
|
+
@force = force
|
|
17
|
+
@reverted = reverted
|
|
18
|
+
@precedence_checker = StatusPrecedenceChecker.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def call
|
|
22
|
+
return if current_status.nil?
|
|
23
|
+
|
|
24
|
+
return reverted_status if reverted
|
|
25
|
+
|
|
26
|
+
skip_update? ? nil : target_status
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
attr_reader :clickup_task, :target_status, :force, :reverted, :precedence_checker
|
|
32
|
+
|
|
33
|
+
def current_status
|
|
34
|
+
@current_status ||= clickup_task&.dig('status', 'status')&.downcase
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def reverted_status
|
|
38
|
+
REVERT_TARGET_STATUS if current_status == REVERT_SOURCE_STATUS
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def skip_update?
|
|
42
|
+
!force && precedence_checker.should_skip_update?(current_status, target_status)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Afterlife
|
|
4
|
+
module Clickup
|
|
5
|
+
class TaskRevertDetector
|
|
6
|
+
def initialize(commits)
|
|
7
|
+
@commits = CommitInputSplitter.call(commits)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def reverted?(task_id)
|
|
11
|
+
reverted = false
|
|
12
|
+
|
|
13
|
+
@commits.each do |commit|
|
|
14
|
+
next unless commit.match?(/#?(?:CU[-_])?#{Regexp.escape(task_id)}/i)
|
|
15
|
+
|
|
16
|
+
reverted = revert_count(commit, task_id).odd?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
reverted
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def revert_count(line, task_id)
|
|
25
|
+
before_task_id = line.split(/#?(?:CU[-_])?#{Regexp.escape(task_id)}/i, 2).first
|
|
26
|
+
before_task_id.scan(/\brevert\b/i).count
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -3,50 +3,101 @@
|
|
|
3
3
|
module Afterlife
|
|
4
4
|
module Clickup
|
|
5
5
|
class UpdateTaskStatus
|
|
6
|
-
attr_reader :
|
|
6
|
+
attr_reader :api, :force, :dry_run, :cherry_pick, :verbose, :revert_detector, :slack_output_path
|
|
7
7
|
|
|
8
|
-
def self.call(
|
|
9
|
-
|
|
8
|
+
def self.call(
|
|
9
|
+
task_ids, target_status, force: false, dry_run: false, cherry_pick: false, verbose: true, commits: nil
|
|
10
|
+
)
|
|
11
|
+
new(force:, dry_run:, cherry_pick:, verbose:, commits:).call(task_ids, target_status)
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
def initialize(force: false, dry_run: false)
|
|
14
|
+
def initialize(force: false, dry_run: false, cherry_pick: false, verbose: true, commits: nil)
|
|
13
15
|
@force = force
|
|
14
16
|
@dry_run = dry_run
|
|
17
|
+
@cherry_pick = cherry_pick
|
|
18
|
+
@verbose = verbose
|
|
19
|
+
@slack_output_path = ENV.fetch('AFTERLIFE_SLACK_OUTPUT', nil)
|
|
20
|
+
write_slack_output('') if slack_output_path
|
|
21
|
+
@revert_detector = TaskRevertDetector.new(commits)
|
|
15
22
|
token = ENV['CLICKUP_TOKEN'] || fail('CLICKUP_TOKEN required, put `export CLICKUP_TOKEN=...` or the equivalent in your shell') # rubocop:disable Layout/LineLength
|
|
16
|
-
@api = Api.new(token:
|
|
17
|
-
@precedence_checker = StatusPrecedenceChecker.new
|
|
23
|
+
@api = Api.new(token:)
|
|
18
24
|
end
|
|
19
25
|
|
|
20
|
-
def call(task_ids, target_status) # rubocop:disable Metrics/AbcSize
|
|
26
|
+
def call(task_ids, target_status) # rubocop:disable Metrics/AbcSize
|
|
21
27
|
if task_ids.empty?
|
|
22
|
-
|
|
28
|
+
log 'No tasks to update'
|
|
23
29
|
return []
|
|
24
30
|
end
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
log 'WARNING: Forcing status updates...' if force
|
|
33
|
+
log 'WARNING: Dry run, no tasks will be updated' if dry_run
|
|
34
|
+
log "#{dry_run ? 'Would update' : 'Updating'} #{task_ids.length} tasks to '#{target_status}'"
|
|
29
35
|
moved_task_ids = task_ids.map { |task_id| move_task(task_id, target_status) }.compact
|
|
30
|
-
|
|
36
|
+
log "#{dry_run ? 'Would have moved' : 'Moved'} #{moved_task_ids.length} tasks:"
|
|
31
37
|
moved_task_ids.each do |task|
|
|
32
|
-
|
|
38
|
+
cherry_pick_status = " - Cherry Pick: #{task[:is_cherry_pick] ? '✅' : '❌'}" if cherry_pick
|
|
39
|
+
log "- #{task[:link]} (from '#{task[:previous_status]}' to '#{task[:new_status]}')#{cherry_pick_status}"
|
|
33
40
|
end
|
|
34
41
|
moved_task_ids
|
|
35
42
|
end
|
|
36
43
|
|
|
37
44
|
private
|
|
38
45
|
|
|
39
|
-
def move_task(task_id, target_status)
|
|
40
|
-
|
|
46
|
+
def move_task(task_id, target_status) # rubocop:disable Metrics/AbcSize
|
|
47
|
+
task = api.get_task(task_id)
|
|
48
|
+
current_status = task&.dig('status', 'status')&.downcase
|
|
49
|
+
if current_status.nil?
|
|
50
|
+
log "WARNING: Task #{task_id} not found", verbose: true
|
|
51
|
+
return
|
|
52
|
+
end
|
|
41
53
|
|
|
42
|
-
|
|
54
|
+
is_cherry_pick = Array(task['custom_fields']).any? do |field|
|
|
55
|
+
field['name'].match?(/cherry pick/i) && [true, 'true'].include?(field['value'])
|
|
56
|
+
end
|
|
43
57
|
|
|
44
|
-
should_skip_update = !force && precedence_checker.should_skip_update?(current_status, target_status)
|
|
45
58
|
task_link = "https://app.clickup.com/t/#{task_id}"
|
|
46
|
-
|
|
59
|
+
next_status = next_status_for(task_id, task, target_status)
|
|
60
|
+
return if next_status.nil?
|
|
61
|
+
|
|
62
|
+
api.update_task(task_id, { status: next_status }) unless dry_run
|
|
63
|
+
|
|
64
|
+
{
|
|
65
|
+
id: task_id,
|
|
66
|
+
link: task_link,
|
|
67
|
+
previous_status: current_status,
|
|
68
|
+
new_status: next_status,
|
|
69
|
+
is_cherry_pick:,
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def next_status_for(task_id, task, target_status)
|
|
74
|
+
current_status = task.dig('status', 'status')&.downcase
|
|
75
|
+
reverted = revert_detector.reverted?(task_id)
|
|
76
|
+
next_status = NextTaskStatusDecider.call(clickup_task: task, target_status:, force:, reverted:)
|
|
77
|
+
|
|
78
|
+
if reverted && next_status
|
|
79
|
+
log "Moving task https://app.clickup.com/t/#{task_id} to '#{next_status}': reverted in pushed commits"
|
|
80
|
+
elsif !reverted && next_status.nil?
|
|
81
|
+
log(
|
|
82
|
+
"Skipping task https://app.clickup.com/t/#{task_id} because it's already at '#{current_status}'",
|
|
83
|
+
verbose: true,
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
next_status
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def log(message, verbose: false)
|
|
91
|
+
return if verbose && !@verbose
|
|
92
|
+
|
|
93
|
+
puts message
|
|
94
|
+
write_slack_output("#{message}\n", mode: 'a') if !verbose && slack_output_path
|
|
95
|
+
end
|
|
47
96
|
|
|
48
|
-
|
|
49
|
-
|
|
97
|
+
def write_slack_output(message, mode: 'w')
|
|
98
|
+
File.write(slack_output_path, message, mode:)
|
|
99
|
+
rescue SystemCallError
|
|
100
|
+
nil
|
|
50
101
|
end
|
|
51
102
|
end
|
|
52
103
|
end
|
data/lib/afterlife/config/cli.rb
CHANGED
data/lib/afterlife/deploy/cli.rb
CHANGED
data/lib/afterlife/notify.rb
CHANGED
|
@@ -28,8 +28,8 @@ module Afterlife
|
|
|
28
28
|
def send_request(repository, branch)
|
|
29
29
|
uri = URI(notification_url)
|
|
30
30
|
body = {
|
|
31
|
-
branch
|
|
32
|
-
repository
|
|
31
|
+
branch:,
|
|
32
|
+
repository:,
|
|
33
33
|
}
|
|
34
34
|
headers = { 'Content-Type': 'application/json' }
|
|
35
35
|
Net::HTTP.post(uri, body.to_json, headers)
|
|
@@ -116,7 +116,7 @@ module Afterlife
|
|
|
116
116
|
|
|
117
117
|
def generate_tag_name
|
|
118
118
|
now = Time.now
|
|
119
|
-
year = now.year.to_s[2..3]
|
|
119
|
+
year = now.year.to_s[2..3] # Last two digits of year
|
|
120
120
|
month = format('%02d', now.month)
|
|
121
121
|
day = format('%02d', now.day)
|
|
122
122
|
"#{year}#{month}#{day}"
|
|
@@ -26,7 +26,7 @@ module Afterlife
|
|
|
26
26
|
assert_git_dependency
|
|
27
27
|
fatal! "Part '#{part}' is not allowed" unless CreateHelper::PARTS.include?(part.to_sym)
|
|
28
28
|
|
|
29
|
-
CreateHelper.call(self, options.merge(part:
|
|
29
|
+
CreateHelper.call(self, options.merge(part:))
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
desc 'hotfix', 'create a hotfix branch'
|
|
@@ -19,7 +19,7 @@ module Afterlife
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def call
|
|
22
|
-
|
|
22
|
+
creation_prompt unless cli.options[:yes]
|
|
23
23
|
make_assertions unless cli.options[:force]
|
|
24
24
|
create_branch
|
|
25
25
|
ChangeVersion.call(new_version)
|
|
@@ -49,10 +49,11 @@ module Afterlife
|
|
|
49
49
|
cli.fatal! 'Local and remote are not on the same commit'
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def
|
|
52
|
+
def creation_prompt
|
|
53
53
|
cli.sure? 'You are about to create the branch ' \
|
|
54
54
|
"#{cli.set_color(branch_name, :bold)} " \
|
|
55
55
|
"from #{cli.set_color(from, :bold)}"
|
|
56
|
+
nil
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
def create_branch
|
|
@@ -4,20 +4,21 @@ module Afterlife
|
|
|
4
4
|
module Release
|
|
5
5
|
class PreHelper < Helper
|
|
6
6
|
def call
|
|
7
|
-
|
|
7
|
+
creation_prompt
|
|
8
8
|
check_tag_does_not_exist
|
|
9
9
|
commit
|
|
10
10
|
create_tag
|
|
11
11
|
push_tag if cli.options[:push]
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def
|
|
14
|
+
def creation_prompt
|
|
15
15
|
return if cli.options[:yes]
|
|
16
16
|
|
|
17
|
-
cli.
|
|
18
|
-
|
|
17
|
+
action = cli.options[:push] ? '(and push) ' : ''
|
|
18
|
+
cli.sure? "You are about to create #{action}" \
|
|
19
19
|
"the tag #{cli.set_color(tag, :bold)} " \
|
|
20
20
|
'in the current commit'
|
|
21
|
+
nil
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
def check_tag_does_not_exist
|
|
@@ -5,24 +5,24 @@ module Afterlife
|
|
|
5
5
|
# Reads configuration from the repo,
|
|
6
6
|
# either from YML or from the repo instance methods
|
|
7
7
|
class Config
|
|
8
|
-
Error
|
|
8
|
+
class Error < StandardError; end
|
|
9
9
|
|
|
10
10
|
attr_reader :path
|
|
11
11
|
|
|
12
|
-
def self.read(path, &
|
|
13
|
-
new(path).read(&
|
|
12
|
+
def self.read(path, &)
|
|
13
|
+
new(path).read(&)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def initialize(path)
|
|
17
17
|
@path = path
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def read(&
|
|
20
|
+
def read(&)
|
|
21
21
|
case from_yml
|
|
22
22
|
when Hash
|
|
23
23
|
yield(JSON.generate(from_yml))
|
|
24
24
|
when Array
|
|
25
|
-
from_yml.each(&
|
|
25
|
+
from_yml.each(&)
|
|
26
26
|
when String, Symbol
|
|
27
27
|
yield(from_yml)
|
|
28
28
|
else
|
data/lib/afterlife/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: afterlife
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Genaro Madrid
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-07-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -24,6 +24,20 @@ dependencies:
|
|
|
24
24
|
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: ostruct
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
27
41
|
- !ruby/object:Gem::Dependency
|
|
28
42
|
name: racc
|
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -97,9 +111,12 @@ files:
|
|
|
97
111
|
- lib/afterlife/clickup.rb
|
|
98
112
|
- lib/afterlife/clickup/api.rb
|
|
99
113
|
- lib/afterlife/clickup/cli.rb
|
|
114
|
+
- lib/afterlife/clickup/commit_input_splitter.rb
|
|
100
115
|
- lib/afterlife/clickup/get_ids_from_text.rb
|
|
101
116
|
- lib/afterlife/clickup/get_range_commits.rb
|
|
117
|
+
- lib/afterlife/clickup/next_task_status_decider.rb
|
|
102
118
|
- lib/afterlife/clickup/status_precedence_checker.rb
|
|
119
|
+
- lib/afterlife/clickup/task_revert_detector.rb
|
|
103
120
|
- lib/afterlife/clickup/update_task_status.rb
|
|
104
121
|
- lib/afterlife/config.rb
|
|
105
122
|
- lib/afterlife/config/cli.rb
|
|
@@ -144,14 +161,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
144
161
|
requirements:
|
|
145
162
|
- - ">="
|
|
146
163
|
- !ruby/object:Gem::Version
|
|
147
|
-
version: '
|
|
164
|
+
version: '3.3'
|
|
148
165
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
149
166
|
requirements:
|
|
150
167
|
- - ">="
|
|
151
168
|
- !ruby/object:Gem::Version
|
|
152
169
|
version: '0'
|
|
153
170
|
requirements: []
|
|
154
|
-
rubygems_version: 3.
|
|
171
|
+
rubygems_version: 3.5.16
|
|
155
172
|
signing_key:
|
|
156
173
|
specification_version: 4
|
|
157
174
|
summary: Devops utils
|