apadmi_grout 2.0.0 → 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/apadmi/grout/di.rb +7 -2
- data/lib/apadmi/grout/models/bitrise.rb +38 -0
- data/lib/apadmi/grout/models/release_notes_templates.rb +2 -2
- data/lib/apadmi/grout/service/bitrise_service/bitrise_service.rb +103 -0
- data/lib/apadmi/grout/utils/git_utils.rb +18 -10
- data/lib/apadmi/grout/utils/network_service.rb +40 -5
- data/lib/apadmi/grout/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58507ab047f8ae45fff33f92ac13ae75d57680c0d29abdaaedf39ea0e27e82c2
|
4
|
+
data.tar.gz: d598788e30b14c306d107c7522c2e1646f95f54e92cb8f4aa74806326a85b10d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acc0fa240dde5f43293978694005ff9509dd39fdfeb89ea2db207f0944ab54d8eab598da6f133d9595e12c870b4a1ee7d6307c3060f376544231bff2493572c5
|
7
|
+
data.tar.gz: 230e4d0c686736605ac0a2548fc500c398d4e7c41b39d1aff55b93ed567cad887503cfa2684066a06a59f8f77e0f0bc05a5298d5647074235e1ef7ee06968ec7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
# Core Changelog
|
2
2
|
|
3
|
+
## [2.2.1] - 2022-08-21
|
4
|
+
* Reduce ruby version to match what bitrise has installed
|
5
|
+
|
6
|
+
## [2.2.0] - 2022-08-16
|
7
|
+
* Bumped min ruby version to 3.0.0 to prevent subtle bugs
|
8
|
+
* Removed references to JIRA in default release note templates
|
9
|
+
* Fixed issues with git warnings being treated like errors
|
10
|
+
|
11
|
+
## [2.1.0] - 2022-07-26
|
12
|
+
* Added a few bitrise utils to support listing builds, triggering builds and downloading artifacts.
|
13
|
+
* Added utilities to the network service to upload files
|
14
|
+
|
3
15
|
## [2.0.0] - 2022-05-25
|
4
16
|
* Almost total refactor to support having different board providers (other than jira)
|
5
17
|
* Implement ADO support for all existing actions
|
data/lib/apadmi/grout/di.rb
CHANGED
@@ -25,7 +25,7 @@ module Apadmi
|
|
25
25
|
project,
|
26
26
|
logger = Apadmi::Grout::DefaultLogger.new
|
27
27
|
)
|
28
|
-
network_service = Apadmi::Grout::NetworkService.
|
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
30
|
git_utils = Apadmi::Grout::GitUtils
|
31
31
|
issues_from_changelog_action = Apadmi::Grout::IssuesFromChangelogAction.new(jira_board_service, "#{project}-", logger)
|
@@ -51,7 +51,7 @@ module Apadmi
|
|
51
51
|
)
|
52
52
|
)
|
53
53
|
ticket_prefix = "#"
|
54
|
-
network_service = Apadmi::Grout::NetworkService.
|
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
56
|
git_utils = Apadmi::Grout::GitUtils
|
57
57
|
issues_from_changelog_action = Apadmi::Grout::IssuesFromChangelogAction.new(ado_board_service, ticket_prefix, logger)
|
@@ -65,6 +65,11 @@ module Apadmi
|
|
65
65
|
generate_release_notes_action: Apadmi::Grout::GenerateReleaseNotesAction.new(Apadmi::Grout::AdoIssueClassifier.new)
|
66
66
|
)
|
67
67
|
end
|
68
|
+
|
69
|
+
def self.bitrise_service(api_token, base_url, app_slug)
|
70
|
+
network_service = Apadmi::Grout::NetworkService.new(api_token, base_url)
|
71
|
+
Apadmi::Grout::BitriseService.new(app_slug, network_service)
|
72
|
+
end
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apadmi
|
4
|
+
module Grout
|
5
|
+
STATUS_RUNNING = 0
|
6
|
+
STATUS_SUCCESS = 1
|
7
|
+
STATUS_FAILED = 2
|
8
|
+
STATUS_ABORTED_FAIL = 3
|
9
|
+
STATUS_ABORTED_SUCCESS = 4
|
10
|
+
|
11
|
+
BitriseBuild = Struct.new(:triggered_at, :slug, :status, :commit_hash) do
|
12
|
+
def finished_with_success
|
13
|
+
STATUS_SUCCESS == status
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
Artifact = Struct.new(:title, :download_url)
|
18
|
+
|
19
|
+
TriggeredBitriseBuild = Struct.new(:build_number, :build_slug, :build_url, :message, :service, :slug, :status, :triggered_workflow) do
|
20
|
+
def finished_with_success
|
21
|
+
STATUS_SUCCESS == status
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_json(json)
|
25
|
+
TriggeredBitriseBuild.new(
|
26
|
+
json["build_number"],
|
27
|
+
json["build_slug"],
|
28
|
+
json["build_url"],
|
29
|
+
json["message"],
|
30
|
+
json["service"],
|
31
|
+
json["slug"],
|
32
|
+
json["status"],
|
33
|
+
json["triggered_workflow"]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -20,9 +20,9 @@ module Apadmi
|
|
20
20
|
Commit Hash: {{config.commit_hash}}
|
21
21
|
[CI/CD build \#{{config.ci_build_number}}]({{config.ci_build_url}})
|
22
22
|
|
23
|
-
##
|
23
|
+
## Tickets Moved By This Build
|
24
24
|
{{ rendered_moved_issues }}
|
25
|
-
##
|
25
|
+
## Sprint Release notes
|
26
26
|
{{ rendered_release_issues }} }
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "open-uri"
|
4
|
+
require "fileutils"
|
5
|
+
|
6
|
+
module Apadmi
|
7
|
+
module Grout
|
8
|
+
# Utility class for abstracting a some of the bitrise APIs
|
9
|
+
class BitriseService
|
10
|
+
# @param [String] app_slug
|
11
|
+
# @param [Apadmi::Grout::NetworkService] network_service
|
12
|
+
def initialize(app_slug, network_service)
|
13
|
+
@app_slug = app_slug
|
14
|
+
@network_service = network_service
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [Integer] pull_request_id
|
18
|
+
# @param [String] workflow
|
19
|
+
# @return [Array<BitriseBuild>]
|
20
|
+
def list_builds(pull_request_id, workflow)
|
21
|
+
res = @network_service.do_get("/#{@app_slug}/builds?pull_request_id=#{pull_request_id}&workflow=#{workflow}")
|
22
|
+
parsed = JSON.parse(res.body)
|
23
|
+
items = parsed["data"]
|
24
|
+
|
25
|
+
return [] if items.nil? || items.empty?
|
26
|
+
|
27
|
+
items.map do |item|
|
28
|
+
BitriseBuild.new(
|
29
|
+
item["triggered_at"],
|
30
|
+
item["slug"],
|
31
|
+
item["status"],
|
32
|
+
item["commit_hash"]
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [String] build_slug
|
38
|
+
# @param [String] artifact_slug
|
39
|
+
# @return [Artifact]
|
40
|
+
def retrieve_artifact_metadata(build_slug, artifact_slug)
|
41
|
+
res = @network_service.do_get("/#{@app_slug}/builds/#{build_slug}/artifacts/#{artifact_slug}")
|
42
|
+
parsed = JSON.parse(res.body)
|
43
|
+
|
44
|
+
Artifact.new(parsed["data"]["title"], parsed["data"]["expiring_download_url"])
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [String] build_slug
|
48
|
+
# @param [String] output_dir
|
49
|
+
# Download all artifacts from a given build to a specified directory
|
50
|
+
def download_artifacts(build_slug, output_dir)
|
51
|
+
res = @network_service.do_get("/#{@app_slug}/builds/#{build_slug}/artifacts")
|
52
|
+
parsed = JSON.parse(res.body)
|
53
|
+
items = parsed["data"]
|
54
|
+
|
55
|
+
artifacts = items.map do |item|
|
56
|
+
retrieve_artifact_metadata(build_slug, item["slug"])
|
57
|
+
end
|
58
|
+
|
59
|
+
FileUtils.mkdir_p output_dir
|
60
|
+
|
61
|
+
artifacts.each do |item|
|
62
|
+
File.open("#{output_dir}/#{item.title}", "wb") do |file|
|
63
|
+
# rubocop:disable Security/Open
|
64
|
+
file.write URI.open(item.download_url).read
|
65
|
+
# rubocop:enable Security/Open
|
66
|
+
end
|
67
|
+
end
|
68
|
+
artifacts
|
69
|
+
end
|
70
|
+
|
71
|
+
# @param [String] workflow
|
72
|
+
# @param [String] branch
|
73
|
+
# @param [String] dest the destination branch of the pr
|
74
|
+
# @param [String] pull_request_id
|
75
|
+
# @param [String] pull_request_repo_url
|
76
|
+
# @param [String] commit_hash
|
77
|
+
def trigger_build(workflow, branch, dest, pull_request_id, pull_request_repo_url, commit_hash)
|
78
|
+
params = {
|
79
|
+
workflow_id: workflow,
|
80
|
+
branch: branch,
|
81
|
+
commit_hash: commit_hash
|
82
|
+
}
|
83
|
+
|
84
|
+
params[:branch_dest] = dest unless dest.strip.blank?
|
85
|
+
params[:pull_request_id] = pull_request_id unless pull_request_id.strip.blank?
|
86
|
+
params[:pull_request_repository_url] = pull_request_repo_url unless pull_request_repo_url.strip.blank?
|
87
|
+
|
88
|
+
payload = {
|
89
|
+
hook_info: {
|
90
|
+
type: "bitrise"
|
91
|
+
},
|
92
|
+
build_params: params,
|
93
|
+
triggered_by: "curl"
|
94
|
+
}
|
95
|
+
|
96
|
+
res = @network_service.do_post("/#{@app_slug}/builds", payload.to_json)
|
97
|
+
parsed = JSON.parse(res.body)
|
98
|
+
|
99
|
+
TriggeredBitriseBuild.from_json(parsed)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -9,8 +9,16 @@ module Apadmi
|
|
9
9
|
# Gets the root of the Git repo we're in
|
10
10
|
# @return [String] The full path for the root of this Git repo
|
11
11
|
def self.git_root
|
12
|
-
stdout, stderr, = Open3.capture3("git rev-parse --show-toplevel")
|
13
|
-
raise "Failed to get git root: #{stderr}" unless
|
12
|
+
stdout, stderr, status = Open3.capture3("git rev-parse --show-toplevel")
|
13
|
+
raise "Failed to get git root: #{stderr}" unless status.success?
|
14
|
+
|
15
|
+
stdout.strip
|
16
|
+
end
|
17
|
+
|
18
|
+
# Gets the commit hash of the current HEAD
|
19
|
+
def self.commit_hash
|
20
|
+
stdout, stderr, status = Open3.capture3("git rev-parse HEAD")
|
21
|
+
raise "Failed to get hash: #{stderr}" unless status.success?
|
14
22
|
|
15
23
|
stdout.strip
|
16
24
|
end
|
@@ -19,16 +27,16 @@ module Apadmi
|
|
19
27
|
# See more details here: https://git-scm.com/docs/git-rev-list
|
20
28
|
# @return [String] The number of commits
|
21
29
|
def self.number_of_commits
|
22
|
-
stdout, stderr, = Open3.capture3("git rev-list HEAD --count")
|
23
|
-
raise "Failed to get commit number: #{stderr}" unless
|
30
|
+
stdout, stderr, status = Open3.capture3("git rev-list HEAD --count")
|
31
|
+
raise "Failed to get commit number: #{stderr}" unless status.success?
|
24
32
|
|
25
33
|
stdout.strip
|
26
34
|
end
|
27
35
|
|
28
36
|
# Runs a git fetch all
|
29
37
|
def self.fetch_all
|
30
|
-
stdout, stderr, = Open3.capture3("git fetch --all")
|
31
|
-
raise "Failed to fetch #{stderr}" unless
|
38
|
+
stdout, stderr, status = Open3.capture3("git fetch --all")
|
39
|
+
raise "Failed to fetch #{stderr}" unless status.success?
|
32
40
|
|
33
41
|
stdout.strip
|
34
42
|
end
|
@@ -37,8 +45,8 @@ module Apadmi
|
|
37
45
|
# @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
|
38
46
|
def self.merge_changelog(grep_conditions)
|
39
47
|
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
|
48
|
+
stdout, stderr, status = Open3.capture3(command)
|
49
|
+
raise "Failed to get changelog: #{stderr}" unless status.success?
|
42
50
|
|
43
51
|
stdout
|
44
52
|
end
|
@@ -47,8 +55,8 @@ module Apadmi
|
|
47
55
|
# @param grep_conditions [Array<String>] values to be passed in as grep cases (https://git-scm.com/docs/git-log)
|
48
56
|
def self.invert_changelog(grep_conditions)
|
49
57
|
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
|
58
|
+
stdout, stderr, status = Open3.capture3(command)
|
59
|
+
raise "Failed to get changelog: #{stderr}" unless status.success?
|
52
60
|
|
53
61
|
stdout
|
54
62
|
end
|
@@ -6,8 +6,11 @@ module Apadmi
|
|
6
6
|
module Grout
|
7
7
|
# Utility class for running REST network calls
|
8
8
|
class NetworkService
|
9
|
+
attr_reader :base_url
|
10
|
+
|
9
11
|
APPLICATION_JSON = "application/json"
|
10
12
|
PATCH_CONTENT_TYPE = "application/json-patch+json"
|
13
|
+
FORM_CONTENT_TYPE = "application/x-www-form-urlencoded"
|
11
14
|
CONTENT_TYPE = "Content-Type"
|
12
15
|
private_constant :CONTENT_TYPE, :APPLICATION_JSON
|
13
16
|
|
@@ -15,10 +18,18 @@ module Apadmi
|
|
15
18
|
# @param password [String]
|
16
19
|
# @param base_url [String]
|
17
20
|
# Params are encoded for use in Basic Auth https://datatracker.ietf.org/doc/html/rfc7617
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
+
def self.init_for_basic_auth(username, password, base_url, timeout = 30)
|
22
|
+
auth_str = "#{username}:#{password}"
|
23
|
+
auth_header = "Basic #{Base64.strict_encode64(auth_str)}"
|
24
|
+
NetworkService.new(auth_header, base_url, timeout)
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param auth_header [String]
|
28
|
+
# @param base_url [String]
|
29
|
+
def initialize(auth_header, base_url, timeout = 30)
|
21
30
|
@base_url = base_url
|
31
|
+
@auth_header = auth_header
|
32
|
+
@timeout = timeout
|
22
33
|
end
|
23
34
|
|
24
35
|
# @param [String] path
|
@@ -50,6 +61,30 @@ module Apadmi
|
|
50
61
|
response
|
51
62
|
end
|
52
63
|
|
64
|
+
def do_form_encoded_post(path, payload)
|
65
|
+
conn = setup_con
|
66
|
+
response = conn.post("#{@base_url}#{path}") do |req|
|
67
|
+
req.headers[CONTENT_TYPE] = FORM_CONTENT_TYPE
|
68
|
+
req.body = URI.encode_www_form(payload)
|
69
|
+
end
|
70
|
+
throw_if_error(response)
|
71
|
+
response
|
72
|
+
end
|
73
|
+
|
74
|
+
def do_file_post(path, file_path, type)
|
75
|
+
conn = Faraday.new do |f|
|
76
|
+
f.request :multipart
|
77
|
+
f.adapter :net_http
|
78
|
+
end
|
79
|
+
conn.options.timeout = @timeout
|
80
|
+
conn.headers["Authorization"] = @auth_header
|
81
|
+
|
82
|
+
payload = { file: Faraday::UploadIO.new(file_path, type) }
|
83
|
+
response = conn.post("#{@base_url}#{path}", payload)
|
84
|
+
throw_if_error(response)
|
85
|
+
response
|
86
|
+
end
|
87
|
+
|
53
88
|
# @param [String] path
|
54
89
|
# @param [String] payload
|
55
90
|
# @return [Faraday::Response]
|
@@ -73,9 +108,9 @@ module Apadmi
|
|
73
108
|
|
74
109
|
# @return [Faraday::Connection]
|
75
110
|
def setup_con
|
76
|
-
auth_str = "#{@username}:#{@password}"
|
77
111
|
conn = Faraday.new # create a new Connection with base URL
|
78
|
-
conn.headers["Authorization"] =
|
112
|
+
conn.headers["Authorization"] = @auth_header
|
113
|
+
conn.options.timeout = @timeout
|
79
114
|
conn
|
80
115
|
end
|
81
116
|
|
data/lib/apadmi/grout/version.rb
CHANGED
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.
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Apadmi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-08-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -72,12 +72,14 @@ files:
|
|
72
72
|
- lib/apadmi/grout/actions/move_tickets_action.rb
|
73
73
|
- lib/apadmi/grout/di.rb
|
74
74
|
- lib/apadmi/grout/models/ado_config.rb
|
75
|
+
- lib/apadmi/grout/models/bitrise.rb
|
75
76
|
- lib/apadmi/grout/models/find_tickets_options.rb
|
76
77
|
- lib/apadmi/grout/models/flag_messages.rb
|
77
78
|
- lib/apadmi/grout/models/issue.rb
|
78
79
|
- lib/apadmi/grout/models/pull_request.rb
|
79
80
|
- lib/apadmi/grout/models/release_notes_config.rb
|
80
81
|
- lib/apadmi/grout/models/release_notes_templates.rb
|
82
|
+
- lib/apadmi/grout/service/bitrise_service/bitrise_service.rb
|
81
83
|
- lib/apadmi/grout/service/board_service/ado_board_service.rb
|
82
84
|
- lib/apadmi/grout/service/board_service/board_service.rb
|
83
85
|
- lib/apadmi/grout/service/board_service/jira_board_service.rb
|
@@ -102,14 +104,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
102
104
|
requirements:
|
103
105
|
- - ">="
|
104
106
|
- !ruby/object:Gem::Version
|
105
|
-
version: 2.7.
|
107
|
+
version: 2.7.6
|
106
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
109
|
requirements:
|
108
110
|
- - ">="
|
109
111
|
- !ruby/object:Gem::Version
|
110
112
|
version: '0'
|
111
113
|
requirements: []
|
112
|
-
rubygems_version: 3.
|
114
|
+
rubygems_version: 3.2.3
|
113
115
|
signing_key:
|
114
116
|
specification_version: 4
|
115
117
|
summary: Apadmi build tool utils for use through Fastlane on Android and iOS.
|