apadmi_grout 0.0.5 → 1.2.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/CHANGELOG.md +13 -4
- data/lib/apadmi/grout/di.rb +4 -3
- data/lib/apadmi/grout/jira/actions/find_tickets_to_move_action.rb +57 -18
- data/lib/apadmi/grout/jira/models/find_tickets_options.rb +10 -0
- data/lib/apadmi/grout/jira/models/flag_messages.rb +23 -6
- data/lib/apadmi/grout/jira/wrapper/jira_wrapper.rb +5 -2
- data/lib/apadmi/grout/release_notes/actions/issues_from_changelog_action.rb +0 -2
- data/lib/apadmi/grout/utils/filename_utils.rb +40 -0
- data/lib/apadmi/grout/utils/git_utils.rb +39 -0
- data/lib/apadmi/grout/version.rb +1 -1
- data/lib/apadmi_grout.rb +3 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9a8f0b024bb98a0372b85755e14bc753370328418273d6e0d07aba74f664bb9a
|
4
|
+
data.tar.gz: '04286d3e985378d78f1dec57c220f1a4a5ec35d90ccf4a407d3dde66f75f9a6d'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c9d6d5fce5da1ffaa1ab71a7f54e4bba85a3f4fda470b0613049a2169ca9466d180b655c3129561e9046fe3d0a4041b85c2cf25d70dfd8ac7f521b70a6d5113
|
7
|
+
data.tar.gz: 13b59090e27577e87f7a52ef9dbcc085db1af1b0575a20e98642669155b0652e0e91976a4943f027e33c25d325fe0aa205afa481d761b7a944f5aebf3bf4138a
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# Core Changelog
|
2
2
|
|
3
|
-
## [
|
3
|
+
## [1.2.0] - 2022-05-17
|
4
|
+
* Filter out issues missing from git changelogs when finding tickets to move.
|
4
5
|
|
5
|
-
## [
|
6
|
+
## [1.1.0] - 2022-05-12
|
7
|
+
* Support allowing tickets that aren't assigned to a sprint to be moved.
|
8
|
+
* Created utilities for getting the git root and number of commits
|
6
9
|
|
7
|
-
- Initial release
|
10
|
+
## [1.0.0] - 2022-05-09 - Initial release
|
11
|
+
|
12
|
+
* Various JIRA utilities to simplify JIRA interactions
|
13
|
+
* Action for searching JIRA tickets
|
14
|
+
* Action for transitioning JIRA tickets
|
15
|
+
* Action for generating release notes
|
16
|
+
* Action for extracting ticket keys from Git changelog
|
data/lib/apadmi/grout/di.rb
CHANGED
@@ -4,7 +4,7 @@ module Apadmi
|
|
4
4
|
module Grout
|
5
5
|
# Convenience class for initializing and accessing the various actions
|
6
6
|
class DependencyInjector
|
7
|
-
attr_reader :move_jira_tickets_action, :find_tickets_to_move_action, :generate_release_notes_action, :issues_from_changelog_action
|
7
|
+
attr_reader :jira_wrapper, :move_jira_tickets_action, :find_tickets_to_move_action, :generate_release_notes_action, :issues_from_changelog_action
|
8
8
|
|
9
9
|
# @param [String] username
|
10
10
|
# @param [String] token
|
@@ -15,10 +15,11 @@ module Apadmi
|
|
15
15
|
def initialize(username, token, base_url, context_path, project, logger)
|
16
16
|
@jira_wrapper = Apadmi::Grout::JiraWrapper.new(username, token, base_url, context_path, project)
|
17
17
|
|
18
|
+
git_utils = Apadmi::Grout::GitUtils
|
18
19
|
@move_jira_tickets_action = Apadmi::Grout::MoveJiraTicketsAction.new(@jira_wrapper, logger)
|
19
|
-
@find_tickets_to_move_action = Apadmi::Grout::FindTicketsToMoveAction.new(@jira_wrapper, logger)
|
20
|
-
@generate_release_notes_action = Apadmi::Grout::GenerateReleaseNotesAction.new(base_url)
|
21
20
|
@issues_from_changelog_action = Apadmi::Grout::IssuesFromChangelogAction.new(@jira_wrapper, logger)
|
21
|
+
@find_tickets_to_move_action = Apadmi::Grout::FindTicketsToMoveAction.new(@jira_wrapper, git_utils, issues_from_changelog_action, logger)
|
22
|
+
@generate_release_notes_action = Apadmi::Grout::GenerateReleaseNotesAction.new(base_url)
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
@@ -2,74 +2,113 @@
|
|
2
2
|
|
3
3
|
module Apadmi
|
4
4
|
module Grout
|
5
|
+
module PrStatus
|
6
|
+
MERGED = 1
|
7
|
+
UNMERGED_BUT_INCLUDED = 2
|
8
|
+
UN_INCLUDED = 3
|
9
|
+
end
|
10
|
+
|
11
|
+
# ATTENTION: Any changes to the logic here should be reflected in the docs (find-tickets.md)
|
12
|
+
|
5
13
|
# Finds and returns a list of all the issues that are ready to be moved
|
6
14
|
# Any tickets found that have the given status but *don't* appear ready to be moved will
|
7
15
|
# be flagged.
|
8
16
|
class FindTicketsToMoveAction
|
9
17
|
# @param [Apadmi::Grout::JiraWrapper]
|
18
|
+
# @param [Apadmi::Grout::GitUtils]
|
19
|
+
# @param [Apadmi::Grout::IssuesFromChangelogAction]
|
10
20
|
# @param [Apadmi::Grout::DefaultLogger] // or your own logger!
|
11
|
-
def initialize(jira_wrapper, logger)
|
21
|
+
def initialize(jira_wrapper, git_utils, issues_from_chnglg, logger)
|
12
22
|
@jira_wrapper = jira_wrapper
|
23
|
+
@git_utils = git_utils
|
24
|
+
@issues_from_changelog_action = issues_from_chnglg
|
13
25
|
@logger = logger
|
14
26
|
end
|
15
27
|
|
16
28
|
# @param component [String] Only include tickets tagged with this component
|
17
29
|
# @param status [String] The status of tickets to be moved (Usually "Awaiting QA Release")
|
18
30
|
# @param excluded_ticket_keys [Array<String>] ticket keys to be excluded from consideration
|
19
|
-
# @param custom_flag_messages [FlagMessages]
|
31
|
+
# @param custom_flag_messages [Apadmi::Grout::FlagMessages]
|
32
|
+
# @param options [Apadmi::Grout::FindTicketsOptions]
|
20
33
|
# @return [Array<JIRA::Resource::Issue>] the issues ready to move
|
21
34
|
def run(
|
22
35
|
component,
|
23
36
|
status,
|
24
37
|
excluded_ticket_keys,
|
25
|
-
custom_flag_messages =
|
26
|
-
|
27
|
-
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has no MERGED PRs and at least one OPEN PR",
|
28
|
-
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has only DECLINED PRs",
|
29
|
-
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has no MERGED PRs"
|
30
|
-
)
|
38
|
+
custom_flag_messages = nil,
|
39
|
+
options = nil
|
31
40
|
)
|
32
|
-
|
33
|
-
|
41
|
+
custom_flag_messages ||= Apadmi::Grout::FlagMessages.default(status)
|
42
|
+
options ||= Apadmi::Grout::FindTicketsOptions.new(include_no_sprint_tickets: false)
|
43
|
+
|
44
|
+
issues = @jira_wrapper.search_unblocked_issues(
|
45
|
+
component, status, [],
|
46
|
+
allow_no_sprint: options.include_no_sprint_tickets
|
47
|
+
).reject do |issue|
|
34
48
|
excluded_ticket_keys.include? issue.key
|
35
49
|
end
|
36
50
|
|
37
|
-
|
51
|
+
issue_keys = issues.map(&:key)
|
52
|
+
@logger.message("Found issues to consider #{issue_keys.join(", ")}")
|
53
|
+
|
54
|
+
# Get the issues in the git changelog, filtered for the issues being considered
|
55
|
+
changelog_ids = @issues_from_changelog_action.issue_ids_from_changelog(
|
56
|
+
@git_utils.merge_changelog(issue_keys)
|
57
|
+
)
|
58
|
+
|
38
59
|
final_list = issues.filter do |issue|
|
39
60
|
# Decide whether to include this ticket based on PRs
|
40
|
-
process_prs(issue, custom_flag_messages)
|
61
|
+
status = process_prs(issue, custom_flag_messages)
|
62
|
+
decide_should_include(issue, status, changelog_ids)
|
41
63
|
end
|
64
|
+
|
42
65
|
@logger.message("Final list: #{final_list.map(&:key).join(", ")}")
|
43
66
|
final_list
|
44
67
|
end
|
45
68
|
|
46
69
|
private
|
47
70
|
|
71
|
+
# @param issue [JIRA::Resource::Issue]
|
72
|
+
# @param pr_status [Int] status of whether or not we can move
|
73
|
+
# @param changelog_ids [Array<String>] the ticket ids pulled from git
|
74
|
+
def decide_should_include(issue, pr_status, changelog_ids)
|
75
|
+
# For merged PRs, check if the ticket appears in the changelog.
|
76
|
+
# If it doesn't then it's likely it was merged AFTER this release build was triggered and shouldn't be moved
|
77
|
+
# by this build
|
78
|
+
if pr_status == PrStatus::MERGED
|
79
|
+
is_in_changelog = changelog_ids.include?(issue.key)
|
80
|
+
@logger.message("NOTE: Not including #{issue.key} since it's not in the git changelog.") unless is_in_changelog
|
81
|
+
return is_in_changelog
|
82
|
+
end
|
83
|
+
|
84
|
+
pr_status != PrStatus::UN_INCLUDED
|
85
|
+
end
|
86
|
+
|
48
87
|
# @param issue [JIRA::Resource::Issue]
|
49
88
|
# @param custom_flag_messages [FlagMessages]
|
50
|
-
# @return [
|
89
|
+
# @return [Int] status of whether or not we can move
|
51
90
|
def process_prs(issue, custom_flag_messages)
|
52
91
|
prs = @jira_wrapper.get_ticket_prs(issue)
|
53
92
|
|
54
93
|
if prs.empty?
|
55
94
|
@logger.message("#{issue.key} has no PRs. Flagging it: STILL MOVABLE")
|
56
95
|
@jira_wrapper.flag_ticket(issue.key, custom_flag_messages.no_prs_flag_msg)
|
57
|
-
return
|
96
|
+
return PrStatus::UNMERGED_BUT_INCLUDED
|
58
97
|
elsif prs.all?(&:open)
|
59
98
|
@logger.message("#{issue.key} has only open PRs. Flagging it: NOT MOVABLE")
|
60
99
|
@jira_wrapper.flag_ticket(issue.key, custom_flag_messages.open_prs_flag_msg)
|
61
|
-
return
|
100
|
+
return PrStatus::UN_INCLUDED
|
62
101
|
elsif prs.all?(&:declined)
|
63
102
|
@logger.message("#{issue.key} has only declined PRs. Flagging it: NOT MOVABLE")
|
64
103
|
@jira_wrapper.flag_ticket(issue.key, custom_flag_messages.declined_prs_flag_msg)
|
65
|
-
return
|
104
|
+
return PrStatus::UN_INCLUDED
|
66
105
|
elsif prs.none?(&:merged)
|
67
106
|
@logger.message("#{issue.key} has no merged PRs. Flagging it: NOT MOVABLE")
|
68
107
|
@jira_wrapper.flag_ticket(issue.key, custom_flag_messages.no_merged_prs_flag_msg)
|
69
|
-
return
|
108
|
+
return PrStatus::UN_INCLUDED
|
70
109
|
end
|
71
110
|
|
72
|
-
|
111
|
+
PrStatus::MERGED # At least one merged PR
|
73
112
|
end
|
74
113
|
end
|
75
114
|
end
|
@@ -1,8 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Apadmi
|
4
|
+
module Grout
|
5
|
+
FlagMessages = Struct.new(
|
6
|
+
:no_prs_flag_msg,
|
7
|
+
:open_prs_flag_msg,
|
8
|
+
:declined_prs_flag_msg,
|
9
|
+
:no_merged_prs_flag_msg
|
10
|
+
) do
|
11
|
+
# Get default flag messages
|
12
|
+
# @param status [String] status ticket will be moving to
|
13
|
+
# @return [Apadmi::Grout::FlagMessages]
|
14
|
+
def self.default(status)
|
15
|
+
FlagMessages.new(
|
16
|
+
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has no PRs connected to it. CI still moved it. " \
|
17
|
+
"(WARNING: this may cause the `fix_versions` to be incorrect)",
|
18
|
+
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has no MERGED PRs and at least one OPEN PR",
|
19
|
+
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has only DECLINED PRs",
|
20
|
+
"REASON FOR FLAG: Check this ticket - it was put in #{status} but has no MERGED PRs"
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -46,16 +46,19 @@ module Apadmi
|
|
46
46
|
# @param [String] component
|
47
47
|
# @param [String] status
|
48
48
|
# @param [String[]] ticket_types
|
49
|
+
# @param [Boolean] allow_no_sprint
|
49
50
|
# @return [Array<JIRA::Resource::Issue>]
|
50
|
-
def search_unblocked_issues(component, status, ticket_types = [])
|
51
|
+
def search_unblocked_issues(component, status, ticket_types = [], allow_no_sprint: false)
|
51
52
|
component_filter = (" AND component = '#{component}' " unless component.empty?) || ""
|
52
53
|
status_filter = (" AND status = '#{status}' " unless status.empty?) || ""
|
53
54
|
type_filter = ("AND (#{ticket_types.map { |type| "type = #{type}" }.join("OR ")})" unless ticket_types.empty?) || ""
|
55
|
+
empty_sprint_condition = ("OR sprint is EMPTY" if allow_no_sprint) || ""
|
54
56
|
|
55
57
|
jql_search = %{
|
56
58
|
project = '#{@project}'
|
57
59
|
#{status_filter} #{component_filter} #{type_filter}
|
58
|
-
AND sprint in openSprints() AND (labels not in(Blocked) or labels is EMPTY)
|
60
|
+
AND (sprint in openSprints() #{empty_sprint_condition}) AND (labels not in(Blocked) or labels is EMPTY)
|
61
|
+
AND Flagged is EMPTY
|
59
62
|
}
|
60
63
|
|
61
64
|
@jira_client.Issue.jql(jql_search, { max_results: 1000 }).uniq
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apadmi
|
4
|
+
module Grout
|
5
|
+
# Generic Filename Utils
|
6
|
+
class FilenameUtils
|
7
|
+
# Constructs a standard Apadmi filename for a build output binary
|
8
|
+
# @param [Hash] options the options to create a filename with
|
9
|
+
# @option options [String] :client_name The client name
|
10
|
+
# @option options [String] :product_name The product name
|
11
|
+
# @option options [String] :platform The product's platform
|
12
|
+
# @option options [String] :version Version number
|
13
|
+
# @option options [String] :build_number Build number
|
14
|
+
# @option options [String] :data (Today) The date for the file
|
15
|
+
# @option options [String] :suffix Suffix to identify what this output is (e.g. SOURCE, UAT, QA, DEV)
|
16
|
+
# @return [String] A filename formatted such as "Apadmi-Grout-Ruby-v1.0.0(2921)-2021-06-22-DEV"
|
17
|
+
def self.binary_output_filename(options = {})
|
18
|
+
client_name = options[:client_name]
|
19
|
+
raise ":client_name shouldn't be empty" if client_name.blank?
|
20
|
+
|
21
|
+
product_name = options[:product_name]
|
22
|
+
raise ":product_name shouldn't be empty" if product_name.blank?
|
23
|
+
|
24
|
+
platform = options[:platform]
|
25
|
+
raise ":platform shouldn't be empty" if platform.blank?
|
26
|
+
|
27
|
+
version = options[:version]
|
28
|
+
raise ":version shouldn't be empty" if version.blank?
|
29
|
+
|
30
|
+
build_number = options[:build_number]
|
31
|
+
raise ":build_number shouldn't be empty" if build_number.blank?
|
32
|
+
|
33
|
+
date = options[:date] || Time.now.strftime("%Y-%m-%d")
|
34
|
+
suffix = ("-#{options[:suffix]}" unless options[:suffix].blank?) || ""
|
35
|
+
|
36
|
+
"#{client_name}-#{product_name}-#{platform}-v#{version}(#{build_number})-#{date}#{suffix}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open3"
|
4
|
+
|
5
|
+
module Apadmi
|
6
|
+
module Grout
|
7
|
+
# Generic Git related utils
|
8
|
+
class GitUtils
|
9
|
+
# Gets the root of the Git repo we're in
|
10
|
+
# @return [String] The full path for the root of this Git repo
|
11
|
+
def self.git_root
|
12
|
+
stdout, stderr, = Open3.capture3("git rev-parse --show-toplevel")
|
13
|
+
raise "Failed to get git root: #{stderr}" unless stderr.strip.empty?
|
14
|
+
|
15
|
+
stdout.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets the number of commits accessible from HEAD treating the history as a graph.
|
19
|
+
# See more details here: https://git-scm.com/docs/git-rev-list
|
20
|
+
# @return [String] The number of commits
|
21
|
+
def self.number_of_commits
|
22
|
+
stdout, stderr, = Open3.capture3("git rev-list HEAD --count")
|
23
|
+
raise "Failed to get commit number: #{stderr}" unless stderr.strip.empty?
|
24
|
+
|
25
|
+
stdout.strip
|
26
|
+
end
|
27
|
+
|
28
|
+
# Gets all the merges accessible from the current HEAD which matches at least one of the given grep conditions
|
29
|
+
# @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
|
30
|
+
def self.merge_changelog(grep_conditions)
|
31
|
+
command = "git log HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
|
32
|
+
stdout, stderr, = Open3.capture3(command)
|
33
|
+
raise "Failed to get changelog: #{stderr}" unless stderr.strip.empty?
|
34
|
+
|
35
|
+
stdout
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/apadmi/grout/version.rb
CHANGED
data/lib/apadmi_grout.rb
CHANGED
@@ -16,5 +16,8 @@ require_relative "apadmi/grout/jira/wrapper/jira_wrapper"
|
|
16
16
|
require_relative "apadmi/grout/jira/models/pull_request"
|
17
17
|
require_relative "apadmi/grout/jira/models/version"
|
18
18
|
require_relative "apadmi/grout/jira/models/flag_messages"
|
19
|
+
require_relative "apadmi/grout/jira/models/find_tickets_options"
|
19
20
|
|
20
21
|
require_relative "apadmi/grout/utils/logger"
|
22
|
+
require_relative "apadmi/grout/utils/git_utils"
|
23
|
+
require_relative "apadmi/grout/utils/filename_utils"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apadmi_grout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Apadmi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-05-
|
11
|
+
date: 2022-05-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- lib/apadmi/grout/di.rb
|
67
67
|
- lib/apadmi/grout/jira/actions/find_tickets_to_move_action.rb
|
68
68
|
- lib/apadmi/grout/jira/actions/move_jira_tickets_action.rb
|
69
|
+
- lib/apadmi/grout/jira/models/find_tickets_options.rb
|
69
70
|
- lib/apadmi/grout/jira/models/flag_messages.rb
|
70
71
|
- lib/apadmi/grout/jira/models/pull_request.rb
|
71
72
|
- lib/apadmi/grout/jira/models/version.rb
|
@@ -74,6 +75,8 @@ files:
|
|
74
75
|
- lib/apadmi/grout/release_notes/actions/issues_from_changelog_action.rb
|
75
76
|
- lib/apadmi/grout/release_notes/models/release_notes_config.rb
|
76
77
|
- lib/apadmi/grout/release_notes/models/release_notes_templates.rb
|
78
|
+
- lib/apadmi/grout/utils/filename_utils.rb
|
79
|
+
- lib/apadmi/grout/utils/git_utils.rb
|
77
80
|
- lib/apadmi/grout/utils/logger.rb
|
78
81
|
- lib/apadmi/grout/version.rb
|
79
82
|
- lib/apadmi_grout.rb
|