apadmi_grout 2.6.1 → 2.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8db6b7eca5ee2eb554e888bd25c267dde94978757015ed037c0d193dc372bc51
4
- data.tar.gz: 514ebf8f1057e01d9b36867b5e6ee419c037691039f5a2165cca471c56a2bd9b
3
+ metadata.gz: 75c06e02304d0547ca158b319c9c88e895753233fd06da8d864c402ae89946e1
4
+ data.tar.gz: 6fda7788c5401a14481f715f4007dec869219438304b0206dfce5eb3735c3e07
5
5
  SHA512:
6
- metadata.gz: d9fc365c23f6292fe1690b8b3250e7e9dd7195854f6dceb5cb0a704fb4849c9b63c1a514e786df4b911c08805237416d59c21f191e631f3bec65273a329abff1
7
- data.tar.gz: 0d45b1e9c056154c19733486bad4dd34ed37fb3f7da68c825a2c639eeda9514138fce722bfe546d4238ab9d24da96597ac8520796c1132f58537e79bc776fd54
6
+ metadata.gz: b34320096c5d746f833c48ab31d00933188fdfe86c607a5529f58f03f15b8fb2636ba752b8d5a2743bf4b0d98563c39d21a64b950fb8706b278cc4ddca2500fb
7
+ data.tar.gz: 38c1b2705c12d5fb8480270a26022f1266f0bb9b15da84ffde2447ada05e7de497356a46ae759a1fc3a91fefb1aa50524a30bf52094e0da6fec31ebcdc9f763c
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Core Changelog
2
2
 
3
+ ## [2.8.0] - 2025-05-22
4
+ * Add ability to disable use of the undocumented JIRA apis
5
+
6
+ ## [2.7.0] - 2024-09-24
7
+ * Add utility for checking for unmerged release branches before deployments
8
+
3
9
  ## [2.6.1] - 2024-01-09
4
10
  * Fix: missing blank? method because ActiveSupport requires you to load the extensions explicitly from 7.1
5
11
 
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "semantic" # We'll use this gem for semantic versioning comparison
4
+
5
+ module Apadmi
6
+ module Grout
7
+ # Checks that all releases before this one are ancestors in the commit
8
+ # history to ensure that any unmerged fixes don't get missed
9
+ class CheckUnfinishedReleasesAction
10
+ # @param [Apadmi::Grout::GitUtils]
11
+ # @param [Apadmi::Grout::DefaultLogger] // or your own logger!
12
+ def initialize(git_utils, logger)
13
+ @git_utils = git_utils
14
+ @logger = logger
15
+ end
16
+
17
+ # Runs the action.
18
+ # @param current_version [String] The version of this release.
19
+ # @param suppress_error_versions [Array<String>] Errors from unmerged versions in this list will be suppressed
20
+ def run(current_version, suppress_error_versions)
21
+ @git_utils.fetch_all
22
+
23
+ @logger.message("Checking for unmerged versions")
24
+ @logger.message("Suppressing checks for versions: #{suppress_error_versions}") if suppress_error_versions
25
+ this_version = Semantic::Version.new current_version
26
+ versions = extract_non_ancestor_versions
27
+ suppressed = suppress_error_versions.map do |version|
28
+ Semantic::Version.new version
29
+ end
30
+
31
+ # Only older versions should cause errors since features in newer
32
+ # versions have legitimate reasons not to be in this release
33
+ versions.select do |version|
34
+ version < this_version && !suppressed.include?(version)
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def extract_non_ancestor_versions
41
+ refs = @git_utils.list_tags(
42
+ "--no-merged"
43
+ ) + @git_utils.branch(
44
+ " --list '*release*' '*hotfix*' --all --no-merged"
45
+ ).split("\n")
46
+
47
+ version_strings = refs.map do |ref|
48
+ match = ref.match(/.*(\d+\.\d+\.\d.*)/)
49
+ match[1] if match
50
+ end.compact
51
+ @logger.message("Found versions to compare #{version_strings}")
52
+ version_strings.map do |version_string|
53
+ Semantic::Version.new version_string
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -39,7 +39,7 @@ module Apadmi
39
39
  options = nil
40
40
  )
41
41
  custom_flag_messages ||= Apadmi::Grout::FlagMessages.default(status)
42
- options ||= Apadmi::Grout::JiraFindTicketsOptions.new(include_no_sprint_tickets: false)
42
+ options ||= Apadmi::Grout::JiraFindTicketsOptions.new(include_no_sprint_tickets: false, inspect_prs: true)
43
43
 
44
44
  issues = @jira_board_service.search_unblocked_issues(
45
45
  component, status, [], options
@@ -55,11 +55,7 @@ module Apadmi
55
55
  @git_utils.merge_changelog(issue_keys)
56
56
  )
57
57
 
58
- final_list = issues.filter do |issue|
59
- # Decide whether to include this ticket based on PRs
60
- status = process_prs(issue, custom_flag_messages)
61
- decide_should_include(issue, status, changelog_ids)
62
- end
58
+ final_list = filter_on_prs(changelog_ids, custom_flag_messages, issues, options)
63
59
 
64
60
  @logger.message("Final list: #{final_list.map(&:key).join(", ")}")
65
61
  final_list
@@ -67,6 +63,18 @@ module Apadmi
67
63
 
68
64
  private
69
65
 
66
+ def filter_on_prs(changelog_ids, custom_flag_messages, issues, options)
67
+ if options.inspect_prs
68
+ issues.filter do |issue|
69
+ # Decide whether to include this ticket based on PRs
70
+ status = process_prs(issue, custom_flag_messages)
71
+ decide_should_include(issue, status, changelog_ids)
72
+ end
73
+ else
74
+ issues
75
+ end
76
+ end
77
+
70
78
  # @param issue [Apadmi::Grout::Issue]
71
79
  # @param pr_status [Int] status of whether or not we can move
72
80
  # @param changelog_ids [Array<String>] the ticket ids pulled from git
@@ -27,7 +27,7 @@ module Apadmi
27
27
  )
28
28
  network_service = Apadmi::Grout::NetworkService.init_for_basic_auth(username, token, base_url)
29
29
  jira_board_service = Apadmi::Grout::JiraBoardService.new(username, token, base_url, context_path, project, network_service)
30
- git_utils = Apadmi::Grout::GitUtils
30
+ git_utils = Apadmi::Grout::GitUtils.new
31
31
  issues_from_changelog_action = Apadmi::Grout::IssuesFromChangelogAction.new(jira_board_service, "#{project}-", logger)
32
32
 
33
33
  DependencyInjector.new(
@@ -53,7 +53,7 @@ module Apadmi
53
53
  ticket_prefix = "#"
54
54
  network_service = Apadmi::Grout::NetworkService.init_for_basic_auth("", personal_access_token, base_url)
55
55
  ado_board_service = Apadmi::Grout::AdoBoardService.new(network_service, ado_config, logger)
56
- git_utils = Apadmi::Grout::GitUtils
56
+ git_utils = Apadmi::Grout::GitUtils.new
57
57
  issues_from_changelog_action = Apadmi::Grout::IssuesFromChangelogAction.new(ado_board_service, ticket_prefix, logger)
58
58
 
59
59
  DependencyInjector.new(
@@ -10,7 +10,7 @@ module Apadmi
10
10
 
11
11
  BitriseBuild = Struct.new(:triggered_at, :slug, :status, :commit_hash) do
12
12
  def finished_with_success
13
- STATUS_SUCCESS == status
13
+ status == STATUS_SUCCESS
14
14
  end
15
15
  end
16
16
 
@@ -18,7 +18,7 @@ module Apadmi
18
18
 
19
19
  TriggeredBitriseBuild = Struct.new(:build_number, :build_slug, :build_url, :message, :service, :slug, :status, :triggered_workflow) do
20
20
  def finished_with_success
21
- STATUS_SUCCESS == status
21
+ status == STATUS_SUCCESS
22
22
  end
23
23
 
24
24
  def self.from_json(json)
@@ -7,11 +7,12 @@ module Apadmi
7
7
 
8
8
  # Jira specific find tickets options
9
9
  class JiraFindTicketsOptions < FindTicketsOptions
10
- attr_reader :include_no_sprint_tickets
10
+ attr_reader :include_no_sprint_tickets, :inspect_prs
11
11
 
12
12
  # @param include_no_sprint_tickets [String] whether or not to include tickets with no sprint assigned
13
- def initialize(include_no_sprint_tickets: false)
13
+ def initialize(include_no_sprint_tickets: false, inspect_prs: true)
14
14
  @include_no_sprint_tickets = include_no_sprint_tickets
15
+ @inspect_prs = inspect_prs
15
16
  end
16
17
 
17
18
  def ==(other)
@@ -19,7 +20,7 @@ module Apadmi
19
20
  end
20
21
 
21
22
  def state
22
- [@include_no_sprint_tickets]
23
+ [@include_no_sprint_tickets, @inspect_prs]
23
24
  end
24
25
  end
25
26
 
@@ -6,60 +6,140 @@ module Apadmi
6
6
  module Grout
7
7
  # Generic Git related utils
8
8
  class GitUtils
9
+ def initialize(repo_path = nil)
10
+ @repo_path_arg = repo_path.nil? ? "" : " -C #{repo_path} "
11
+ end
12
+
13
+ # rubocop:disable Style/ClassVars:
14
+ @@default = Apadmi::Grout::GitUtils.new(nil)
15
+ # rubocop:enable Style/ClassVars:
16
+
9
17
  # Gets the root of the Git repo we're in
10
18
  # @return [String] The full path for the root of this Git repo
11
- def self.git_root
12
- stdout, stderr, status = Open3.capture3("git rev-parse --show-toplevel")
19
+ def git_root
20
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} rev-parse --show-toplevel")
13
21
  raise "Failed to get git root: #{stderr}" unless status.success?
14
22
 
15
23
  stdout.strip
16
24
  end
17
25
 
26
+ def self.git_root
27
+ @@default.git_root
28
+ end
29
+
30
+ # Returns all the tags in the repo
31
+ # @return [String[]] The tags
32
+ def list_tags(args = "")
33
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} tag --list #{args}")
34
+ raise "Failed to list tags: #{stderr}" unless status.success?
35
+
36
+ stdout.strip.split("\n")
37
+ end
38
+
39
+ # Returns all the tags in the repo
40
+ # @return [String[]] The tags
41
+ def self.list_tags(args = "")
42
+ @@default.list_tags(args)
43
+ end
44
+
45
+ # Runs git branch command with given args
46
+ def branch(args = "")
47
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} branch #{args}")
48
+ raise "Failed to run branch: #{stderr}" unless status.success?
49
+
50
+ stdout.strip
51
+ end
52
+
53
+ # Runs git branch command with given args
54
+ def self.branch(args = "")
55
+ @@default.branch(args)
56
+ end
57
+
18
58
  # Gets the commit hash of the current HEAD
19
- def self.commit_hash
20
- stdout, stderr, status = Open3.capture3("git rev-parse HEAD")
59
+ def commit_hash
60
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} rev-parse HEAD")
21
61
  raise "Failed to get hash: #{stderr}" unless status.success?
22
62
 
23
63
  stdout.strip
24
64
  end
25
65
 
66
+ # Gets the commit hash of the current HEAD
67
+ def self.commit_hash
68
+ @@default.commit_hash
69
+ end
70
+
26
71
  # Gets the number of commits accessible from HEAD treating the history as a graph.
27
72
  # See more details here: https://git-scm.com/docs/git-rev-list
28
73
  # @return [String] The number of commits
29
- def self.number_of_commits
30
- stdout, stderr, status = Open3.capture3("git rev-list HEAD --count")
74
+ def number_of_commits
75
+ raise "Repo is a shallow clone so this method will always return 1" if is_shallow_clone
76
+
77
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} rev-list HEAD --count")
31
78
  raise "Failed to get commit number: #{stderr}" unless status.success?
32
79
 
33
80
  stdout.strip
34
81
  end
35
82
 
83
+ # Helper function to check if a repo is a shallow clone
84
+ # @return [Boolean] If the repo is a shallow clone
85
+ def is_shallow_clone
86
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} rev-parse --is-shallow-repository")
87
+ raise "Failed to check if repo is shallow clone: #{stderr}" unless status.success?
88
+
89
+ stdout.strip.downcase == "true"
90
+ end
91
+
92
+ # Gets the number of commits accessible from HEAD treating the history as a graph.
93
+ # See more details here: https://git-scm.com/docs/git-rev-list
94
+ # @return [String] The number of commits
95
+ def self.number_of_commits
96
+ @@default.number_of_commits
97
+ end
98
+
36
99
  # Runs a git fetch all
37
- def self.fetch_all
38
- stdout, stderr, status = Open3.capture3("git fetch --all")
100
+ def fetch_all
101
+ stdout, stderr, status = Open3.capture3("git #{@repo_path_arg} fetch --all")
39
102
  raise "Failed to fetch #{stderr}" unless status.success?
40
103
 
41
104
  stdout.strip
42
105
  end
43
106
 
107
+ # Runs a git fetch all
108
+ def self.fetch_all
109
+ @@default.fetch_all
110
+ end
111
+
44
112
  # Gets all the merges accessible from the current HEAD which matches at least one of the given grep conditions
45
113
  # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
46
- def self.merge_changelog(grep_conditions)
47
- command = "git log HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
114
+ def merge_changelog(grep_conditions)
115
+ command = "git #{@repo_path_arg} log HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
48
116
  stdout, stderr, status = Open3.capture3(command)
49
117
  raise "Failed to get changelog: #{stderr}" unless status.success?
50
118
 
51
119
  stdout
52
120
  end
53
121
 
122
+ # Gets all the merges accessible from the current HEAD which matches at least one of the given grep conditions
123
+ # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
124
+ def self.merge_changelog(grep_conditions)
125
+ @@default.merge_changelog(grep_conditions)
126
+ end
127
+
54
128
  # Gets all the merges that are NOT accessible from HEAD which matches at least one of the given grep conditions
55
129
  # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
56
- def self.invert_changelog(grep_conditions)
57
- command = "git log --all ^HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
130
+ def invert_changelog(grep_conditions)
131
+ command = "git #{@repo_path_arg} log --all ^HEAD --merges --format=%s#{grep_conditions.map { |c| " --grep #{c}" }.join(" ")}"
58
132
  stdout, stderr, status = Open3.capture3(command)
59
133
  raise "Failed to get changelog: #{stderr}" unless status.success?
60
134
 
61
135
  stdout
62
136
  end
137
+
138
+ # Gets all the merges that are NOT accessible from HEAD which matches at least one of the given grep conditions
139
+ # @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
140
+ def self.invert_changelog(grep_conditions)
141
+ @@default.invert_changelog(grep_conditions)
142
+ end
63
143
  end
64
144
  end
65
145
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Apadmi
4
4
  module Grout
5
- VERSION = "2.6.1"
5
+ VERSION = "2.8.0"
6
6
  end
7
7
  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: 2.6.1
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Apadmi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-01-09 00:00:00.000000000 Z
11
+ date: 2025-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: semantic
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.5.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.5.0
55
69
  description: Apadmi build tool utils for use through Fastlane on Android and iOS.
56
70
  email:
57
71
  - samdc@apadmi.com
@@ -63,6 +77,7 @@ files:
63
77
  - CODE_OF_CONDUCT.md
64
78
  - LICENSE
65
79
  - README.md
80
+ - lib/apadmi/grout/actions/check_unfinished_releases_action.rb
66
81
  - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_action.rb
67
82
  - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_ado_action.rb
68
83
  - lib/apadmi/grout/actions/find_tickets_to_move_action/find_tickets_to_move_jira_action.rb
@@ -105,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
105
120
  requirements:
106
121
  - - ">="
107
122
  - !ruby/object:Gem::Version
108
- version: 2.7.6
123
+ version: 3.0.0
109
124
  required_rubygems_version: !ruby/object:Gem::Requirement
110
125
  requirements:
111
126
  - - ">="