apadmi_grout 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -1
  3. data/lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_action.rb +24 -0
  4. data/lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_ado_action.rb +91 -0
  5. data/lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_jira_action.rb +114 -0
  6. data/lib/apadmi/grout/actions/generate_release_notes_action/generate_release_notes_action.rb +48 -0
  7. data/lib/apadmi/grout/actions/generate_release_notes_action/issue_classifier.rb +51 -0
  8. data/lib/apadmi/grout/{release_notes/actions → actions}/issues_from_changelog_action.rb +11 -8
  9. data/lib/apadmi/grout/actions/move_tickets_action.rb +34 -0
  10. data/lib/apadmi/grout/di.rb +54 -9
  11. data/lib/apadmi/grout/models/ado_config.rb +10 -0
  12. data/lib/apadmi/grout/models/find_tickets_options.rb +44 -0
  13. data/lib/apadmi/grout/models/flag_messages.rb +25 -0
  14. data/lib/apadmi/grout/models/issue.rb +49 -0
  15. data/lib/apadmi/grout/{jira/models → models}/pull_request.rb +0 -0
  16. data/lib/apadmi/grout/models/release_notes_config.rb +47 -0
  17. data/lib/apadmi/grout/{release_notes/models → models}/release_notes_templates.rb +6 -6
  18. data/lib/apadmi/grout/service/board_service/ado_board_service.rb +199 -0
  19. data/lib/apadmi/grout/service/board_service/board_service.rb +59 -0
  20. data/lib/apadmi/grout/{jira/wrapper/jira_wrapper.rb → service/board_service/jira_board_service.rb} +68 -107
  21. data/lib/apadmi/grout/utils/filename_utils.rb +40 -0
  22. data/lib/apadmi/grout/utils/git_utils.rb +57 -0
  23. data/lib/apadmi/grout/utils/network_service.rb +88 -0
  24. data/lib/apadmi/grout/version.rb +1 -1
  25. data/lib/apadmi_grout.rb +3 -18
  26. metadata +23 -13
  27. data/lib/apadmi/grout/jira/actions/find_tickets_to_move_action.rb +0 -76
  28. data/lib/apadmi/grout/jira/actions/move_jira_tickets_action.rb +0 -58
  29. data/lib/apadmi/grout/jira/models/flag_messages.rb +0 -8
  30. data/lib/apadmi/grout/jira/models/version.rb +0 -23
  31. data/lib/apadmi/grout/release_notes/actions/generate_release_notes_action.rb +0 -39
  32. data/lib/apadmi/grout/release_notes/models/release_notes_config.rb +0 -74
@@ -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,57 @@
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
+ # Runs a git fetch all
29
+ def self.fetch_all
30
+ stdout, stderr, = Open3.capture3("git fetch --all")
31
+ raise "Failed to fetch #{stderr}" unless stderr.strip.empty?
32
+
33
+ stdout.strip
34
+ end
35
+
36
+ # Gets all the merges accessible from the current HEAD which matches at least one of the given grep conditions
37
+ # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
38
+ def self.merge_changelog(grep_conditions)
39
+ command = "git log HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
40
+ stdout, stderr, = Open3.capture3(command)
41
+ raise "Failed to get changelog: #{stderr}" unless stderr.strip.empty?
42
+
43
+ stdout
44
+ end
45
+
46
+ # Gets all the merges that are NOT accessible from HEAD which matches at least one of the given grep conditions
47
+ # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
48
+ def self.invert_changelog(grep_conditions)
49
+ command = "git log --all ^HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
50
+ stdout, stderr, = Open3.capture3(command)
51
+ raise "Failed to get changelog: #{stderr}" unless stderr.strip.empty?
52
+
53
+ stdout
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+
5
+ module Apadmi
6
+ module Grout
7
+ # Utility class for running REST network calls
8
+ class NetworkService
9
+ APPLICATION_JSON = "application/json"
10
+ PATCH_CONTENT_TYPE = "application/json-patch+json"
11
+ CONTENT_TYPE = "Content-Type"
12
+ private_constant :CONTENT_TYPE, :APPLICATION_JSON
13
+
14
+ # @param username [String]
15
+ # @param password [String]
16
+ # @param base_url [String]
17
+ # Params are encoded for use in Basic Auth https://datatracker.ietf.org/doc/html/rfc7617
18
+ def initialize(username, password, base_url)
19
+ @username = username
20
+ @password = password
21
+ @base_url = base_url
22
+ end
23
+
24
+ # @param [String] path
25
+ # @return [Faraday::Response]
26
+ def do_get(path)
27
+ conn = setup_con
28
+ response = conn.get("#{@base_url}#{path}", CONTENT_TYPE => APPLICATION_JSON)
29
+ throw_if_error(response)
30
+ response
31
+ end
32
+
33
+ # @param [String] path
34
+ # @param [String] payload
35
+ # @return [Faraday::Response]
36
+ def do_put(path, payload)
37
+ conn = setup_con
38
+ response = conn.put("#{@base_url}#{path}", payload, CONTENT_TYPE => APPLICATION_JSON)
39
+ throw_if_error(response)
40
+ response
41
+ end
42
+
43
+ # @param [String] path
44
+ # @param [String] payload
45
+ # @return [Faraday::Response]
46
+ def do_post(path, payload)
47
+ conn = setup_con
48
+ response = conn.post("#{@base_url}#{path}", payload, CONTENT_TYPE => APPLICATION_JSON)
49
+ throw_if_error(response)
50
+ response
51
+ end
52
+
53
+ # @param [String] path
54
+ # @param [String] payload
55
+ # @return [Faraday::Response]
56
+ def do_patch(path, payload)
57
+ conn = setup_con
58
+ response = conn.patch("#{@base_url}#{path}", payload, CONTENT_TYPE => PATCH_CONTENT_TYPE)
59
+ throw_if_error(response)
60
+ response
61
+ end
62
+
63
+ # @param [String] path
64
+ # @return [Faraday::Response]
65
+ def do_delete(path)
66
+ conn = setup_con
67
+ response = conn.delete("#{@base_url}#{path}", CONTENT_TYPE => APPLICATION_JSON)
68
+ throw_if_error(response)
69
+ response
70
+ end
71
+
72
+ private
73
+
74
+ # @return [Faraday::Connection]
75
+ def setup_con
76
+ auth_str = "#{@username}:#{@password}"
77
+ conn = Faraday.new # create a new Connection with base URL
78
+ conn.headers["Authorization"] = "Basic #{Base64.strict_encode64(auth_str)}"
79
+ conn
80
+ end
81
+
82
+ # @param [Faraday::Response] response
83
+ def throw_if_error(response)
84
+ raise "Network call failed #{response.status} #{response.body}" unless (200..210).include?(response.status)
85
+ end
86
+ end
87
+ end
88
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Apadmi
4
4
  module Grout
5
- VERSION = "1.0.0"
5
+ VERSION = "2.0.0"
6
6
  end
7
7
  end
data/lib/apadmi_grout.rb CHANGED
@@ -1,20 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "apadmi/grout/version"
4
- require_relative "apadmi/grout/di"
5
-
6
- require_relative "apadmi/grout/release_notes/actions/issues_from_changelog_action"
7
- require_relative "apadmi/grout/release_notes/actions/generate_release_notes_action"
8
- require_relative "apadmi/grout/release_notes/models/release_notes_config"
9
- require_relative "apadmi/grout/release_notes/models/release_notes_templates"
10
-
11
- require_relative "apadmi/grout/jira/actions/move_jira_tickets_action"
12
- require_relative "apadmi/grout/jira/actions/find_tickets_to_move_action"
13
-
14
- require_relative "apadmi/grout/jira/wrapper/jira_wrapper"
15
-
16
- require_relative "apadmi/grout/jira/models/pull_request"
17
- require_relative "apadmi/grout/jira/models/version"
18
- require_relative "apadmi/grout/jira/models/flag_messages"
19
-
20
- require_relative "apadmi/grout/utils/logger"
3
+ Dir[File.expand_path("apadmi/grout/**/*.rb", File.dirname(__FILE__))].sort.each do |current|
4
+ require current
5
+ end
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: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Sam
7
+ - Apadmi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-09 00:00:00.000000000 Z
11
+ date: 2022-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -63,18 +63,28 @@ files:
63
63
  - CODE_OF_CONDUCT.md
64
64
  - LICENSE
65
65
  - README.md
66
+ - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_action.rb
67
+ - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_ado_action.rb
68
+ - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_jira_action.rb
69
+ - lib/apadmi/grout/actions/generate_release_notes_action/generate_release_notes_action.rb
70
+ - lib/apadmi/grout/actions/generate_release_notes_action/issue_classifier.rb
71
+ - lib/apadmi/grout/actions/issues_from_changelog_action.rb
72
+ - lib/apadmi/grout/actions/move_tickets_action.rb
66
73
  - lib/apadmi/grout/di.rb
67
- - lib/apadmi/grout/jira/actions/find_tickets_to_move_action.rb
68
- - lib/apadmi/grout/jira/actions/move_jira_tickets_action.rb
69
- - lib/apadmi/grout/jira/models/flag_messages.rb
70
- - lib/apadmi/grout/jira/models/pull_request.rb
71
- - lib/apadmi/grout/jira/models/version.rb
72
- - lib/apadmi/grout/jira/wrapper/jira_wrapper.rb
73
- - lib/apadmi/grout/release_notes/actions/generate_release_notes_action.rb
74
- - lib/apadmi/grout/release_notes/actions/issues_from_changelog_action.rb
75
- - lib/apadmi/grout/release_notes/models/release_notes_config.rb
76
- - lib/apadmi/grout/release_notes/models/release_notes_templates.rb
74
+ - lib/apadmi/grout/models/ado_config.rb
75
+ - lib/apadmi/grout/models/find_tickets_options.rb
76
+ - lib/apadmi/grout/models/flag_messages.rb
77
+ - lib/apadmi/grout/models/issue.rb
78
+ - lib/apadmi/grout/models/pull_request.rb
79
+ - lib/apadmi/grout/models/release_notes_config.rb
80
+ - lib/apadmi/grout/models/release_notes_templates.rb
81
+ - lib/apadmi/grout/service/board_service/ado_board_service.rb
82
+ - lib/apadmi/grout/service/board_service/board_service.rb
83
+ - lib/apadmi/grout/service/board_service/jira_board_service.rb
84
+ - lib/apadmi/grout/utils/filename_utils.rb
85
+ - lib/apadmi/grout/utils/git_utils.rb
77
86
  - lib/apadmi/grout/utils/logger.rb
87
+ - lib/apadmi/grout/utils/network_service.rb
78
88
  - lib/apadmi/grout/version.rb
79
89
  - lib/apadmi_grout.rb
80
90
  homepage: https://bitbucket.org/apadmi/apadmi-grout-ruby/
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Apadmi
4
- module Grout
5
- # Finds and returns a list of all the issues that are ready to be moved
6
- # Any tickets found that have the given status but *don't* appear ready to be moved will
7
- # be flagged.
8
- class FindTicketsToMoveAction
9
- # @param [Apadmi::Grout::JiraWrapper]
10
- # @param [Apadmi::Grout::DefaultLogger] // or your own logger!
11
- def initialize(jira_wrapper, logger)
12
- @jira_wrapper = jira_wrapper
13
- @logger = logger
14
- end
15
-
16
- # @param component [String] Only include tickets tagged with this component
17
- # @param status [String] The status of tickets to be moved (Usually "Awaiting QA Release")
18
- # @param excluded_ticket_keys [Array<String>] ticket keys to be excluded from consideration
19
- # @param custom_flag_messages [FlagMessages]
20
- # @return [Array<JIRA::Resource::Issue>] the issues ready to move
21
- def run(
22
- component,
23
- status,
24
- excluded_ticket_keys,
25
- custom_flag_messages = FlagMessages.new(
26
- "REASON FOR FLAG: Check this ticket - it was put in #{status} but has no PRs connected to it. CI still moved it",
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
- )
31
- )
32
- issues = @jira_wrapper.search_unblocked_issues(component, status).reject do |issue|
33
- puts issue.key
34
- excluded_ticket_keys.include? issue.key
35
- end
36
-
37
- @logger.message("Found issues to consider #{issues.map(&:key).join(", ")}")
38
- final_list = issues.filter do |issue|
39
- # Decide whether to include this ticket based on PRs
40
- process_prs(issue, custom_flag_messages)
41
- end
42
- @logger.message("Final list: #{final_list.map(&:key).join(", ")}")
43
- final_list
44
- end
45
-
46
- private
47
-
48
- # @param issue [JIRA::Resource::Issue]
49
- # @param custom_flag_messages [FlagMessages]
50
- # @return [Boolean] whether or not this ticket can be moved
51
- def process_prs(issue, custom_flag_messages)
52
- prs = @jira_wrapper.get_ticket_prs(issue)
53
-
54
- if prs.empty?
55
- @logger.message("#{issue.key} has no PRs. Flagging it: STILL MOVABLE")
56
- @jira_wrapper.flag_ticket(issue.key, custom_flag_messages.no_prs_flag_msg)
57
- return true
58
- elsif prs.all?(&:open)
59
- @logger.message("#{issue.key} has only open PRs. Flagging it: NOT MOVABLE")
60
- @jira_wrapper.flag_ticket(issue.key, custom_flag_messages.open_prs_flag_msg)
61
- return false
62
- elsif prs.all?(&:declined)
63
- @logger.message("#{issue.key} has only declined PRs. Flagging it: NOT MOVABLE")
64
- @jira_wrapper.flag_ticket(issue.key, custom_flag_messages.declined_prs_flag_msg)
65
- return false
66
- elsif prs.none?(&:merged)
67
- @logger.message("#{issue.key} has no merged PRs. Flagging it: NOT MOVABLE")
68
- @jira_wrapper.flag_ticket(issue.key, custom_flag_messages.no_merged_prs_flag_msg)
69
- return false
70
- end
71
-
72
- true # At least one merged PR, so it's included
73
- end
74
- end
75
- end
76
- end
@@ -1,58 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Apadmi
4
- module Grout
5
- # Moves all given jira tickets to a given status and assigns fix versions
6
- class MoveJiraTicketsAction
7
- # @param [Apadmi::Grout::JiraWrapper]
8
- # @param [Apadmi::Grout::DefaultLogger] // or your own logger!
9
- def initialize(jira_wrapper, logger)
10
- @jira_wrapper = jira_wrapper
11
- @logger = logger
12
- end
13
-
14
- # @param [Array<String>] version_strings
15
- # @param [Array<JIRA::Resource::Issue>] issues
16
- # @param [String] new_status
17
- def run(version_strings, issues, new_status)
18
- if issues.empty?
19
- @logger.error("No issues found, aborting")
20
- return
21
- end
22
-
23
- @logger.message("Creating versions #{version_strings}")
24
- versions = create_or_get_versions(version_strings)
25
-
26
- @logger.message("Transitioning issues: #{issues.map(&:key).join(", ")}")
27
- issues.each { |issue| move_issue(issue, new_status, versions) }
28
-
29
- @logger.success("Issues transitioned successfully :D")
30
- end
31
-
32
- # @param [Array<String>] version_strings
33
- # @return [Array<JIRA::Resource::Version>]
34
- def create_or_get_versions(version_strings)
35
- all_versions = @jira_wrapper.all_versions
36
- version_strings.map do |version|
37
- existing_version = all_versions.find { |v| v.name == version }
38
- if !existing_version.nil?
39
- existing_version
40
- else
41
- date = Time.now.strftime("%Y-%m-%d")
42
- @jira_wrapper.create_version(date, version)
43
- end
44
- end
45
- end
46
-
47
- # @param [JIRA::Resource::Issue] issue
48
- # @param [String] new_status
49
- # @param [Array<JIRA::Resource::Version>] versions
50
- def move_issue(issue, new_status, versions)
51
- @jira_wrapper.transition_issue(issue, new_status)
52
- @jira_wrapper.assign_fixversions(issue.id, versions)
53
- end
54
-
55
- private :create_or_get_versions, :move_issue
56
- end
57
- end
58
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- FlagMessages = Struct.new(
4
- :no_prs_flag_msg,
5
- :open_prs_flag_msg,
6
- :declined_prs_flag_msg,
7
- :no_merged_prs_flag_msg
8
- )
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Apadmi
4
- module Grout
5
- # Represents a version object derived from the Jira REST API response.
6
- class Version
7
- attr_reader :self, :id, :description, :name, :archived, :released, :release_date, :overdue, :user_release_date, :project_id
8
-
9
- def initialize(json)
10
- @self = json["self"]
11
- @id = json["id"]
12
- @description = json["description"]
13
- @name = json["name"]
14
- @archived = json["archived"]
15
- @released = json["released"]
16
- @release_date = json["release_date"]
17
- @overdue = json["overdue"]
18
- @user_release_date = json["user_release_date"]
19
- @project_id = json["project_id"]
20
- end
21
- end
22
- end
23
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "mustache"
4
-
5
- module Apadmi
6
- module Grout
7
- # Finds and returns a list of all the issues who's ids exist in the given changelog
8
- class GenerateReleaseNotesAction
9
- # @param jira_base_url [String] Jira base url
10
- def initialize(jira_base_url)
11
- @jira_base_url = jira_base_url
12
- end
13
-
14
- # @param config [Apadmi::Grout::ReleaseNotesConfig]
15
- def run(config)
16
- base_url = "#{@jira_base_url}/browse/"
17
-
18
- Mustache.render(
19
- config.templates.document_template,
20
- config: config,
21
- rendered_moved_issues: render_classified_issues(config.templates.list_template, base_url, config.classified_moved_issues),
22
- rendered_release_issues: render_classified_issues(config.templates.list_template, base_url, config.classified_release_issues)
23
- ).strip
24
- end
25
-
26
- private
27
-
28
- def render_classified_issues(template, base_url, classified_issues)
29
- return if classified_issues.empty
30
-
31
- Mustache.render(
32
- template,
33
- classified_issues: classified_issues,
34
- base_url: base_url
35
- )
36
- end
37
- end
38
- end
39
- end
@@ -1,74 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Apadmi
4
- module Grout
5
- # @param tasks [Array<JIRA::Resource::Issue>]
6
- # @param features [Array<JIRA::Resource::Issue>] aka stories
7
- # @param improvements [Array<JIRA::Resource::Issue>]
8
- # @param defects [Array<JIRA::Resource::Issue>] aka bugs
9
- # @param others [Array<JIRA::Resource::Issue>] any other non-standard issue types
10
- ClassifiedIssues = Struct.new(
11
- :tasks,
12
- :features,
13
- :improvements,
14
- :defects,
15
- :others
16
- ) do
17
- # @return returns true if all categories are empty
18
- def empty
19
- tasks.empty? && features.empty? &&
20
- improvements.empty? && defects.empty? && others.empty?
21
- end
22
- end
23
-
24
- # @param title [String] The title of the document
25
- # @param app_version [String] The app version pertaining to this release
26
- # @param min_os_version [String] The min supported os version of this release
27
- # @param date [String] Today's date
28
- # @param moved_issues [Array<JIRA::Resource::Issue>] Issues moved to a new state by this build job
29
- # @param release_issues [Array<JIRA::Resource::Issue>] Issues considered part of this release
30
- # @param commit_hash [String] Commit hash from which release was built
31
- # @param ci_build_number [String] CI build number which built the release
32
- # @param ci_build_url [String] Link to CI build job
33
- # @param templates [Apadmi::Grout::Templates] Mustache templates to use to generate the document
34
- ReleaseNotesConfig = Struct.new(
35
- :title,
36
- :app_version,
37
- :min_os_version,
38
- :date,
39
- :moved_issues,
40
- :release_issues,
41
- :commit_hash,
42
- :ci_build_number,
43
- :ci_build_url,
44
- :templates
45
- ) do
46
- def classified_moved_issues
47
- classify_issues(moved_issues)
48
- end
49
-
50
- def classified_release_issues
51
- classify_issues(release_issues)
52
- end
53
-
54
- private
55
-
56
- def classify_issues(issues)
57
- ClassifiedIssues.new(
58
- filter_issues_by_type(%w[Task], issues),
59
- filter_issues_by_type(%w[Story Debt], issues),
60
- filter_issues_by_type(%w[Improvement Rework], issues),
61
- filter_issues_by_type(%w[Bug], issues),
62
- issues - filter_issues_by_type(%w[Task Story Debt Improvement Rework Bug], issues)
63
- )
64
- end
65
-
66
- # @param types [Array<String>] List of types to match on
67
- # @param issues [Array<JIRA::Resource::Issue>]
68
- # @return [Array<JIRA::Resource::Issue>]
69
- def filter_issues_by_type(types, issues)
70
- issues.find_all { |issue| types.include?(issue.issuetype.name) }
71
- end
72
- end
73
- end
74
- end