apadmi_grout 2.0.0 → 2.1.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: 8da866b98ba10eeb0dd9a8a664bd926e8c657cb918bf8a73474d1e3aacd941c4
4
- data.tar.gz: '0759b30f1bcbe228e7c1a22eecc52bad02f8174d31584d130936a9d3203d35ef'
3
+ metadata.gz: f1a387b90108f0657af3875457b1eb98440b54d7fdf6d62a9750fe1af10aeca5
4
+ data.tar.gz: 25fe6b6ca1083a991f088d2161f49997f04944dda1225617192c9fcf2494f511
5
5
  SHA512:
6
- metadata.gz: fd158cbb2bda541b4fbb80137200c60793d86d1257705aec7ffe5450f1fd66a6d8dc13f6e1135ca5c2db28a8049a92db4e1d76b678b0aa745314cdd7bdd92fed
7
- data.tar.gz: f0a7a913306577749fcba0a68ce1311e073ce4f21ac0e15d50f87527f7a65a8c27e0f3136e871d7d0b5ab457da99369bc9c99a91007f361f4cb102c435e3751f
6
+ metadata.gz: ca2dee35cca80456ca3ebd01b8ab1e1c89eb6c9bad069b36a1e20f8ae36bb511144fed3de12d8dccc31cc8c9dd364684bbdcee4af69244ff180d6e8af4ac24d2
7
+ data.tar.gz: 49414ee4d8507110fed1bbf50946c16357039aacbc1e6657f32c1c4b4777d0ea013559da5c99fc65c77ea5a55d5d4e61479ed7b433dac81885d532dcab4eeaaa
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Core Changelog
2
2
 
3
+ ## [2.1.0] - 22-07-26
4
+ * Added a few bitrise utils to support listing builds, triggering builds and downloading artifacts.
5
+ * Added utilities to the network service to upload files
6
+
3
7
  ## [2.0.0] - 2022-05-25
4
8
  * Almost total refactor to support having different board providers (other than jira)
5
9
  * Implement ADO support for all existing actions
@@ -25,7 +25,7 @@ module Apadmi
25
25
  project,
26
26
  logger = Apadmi::Grout::DefaultLogger.new
27
27
  )
28
- network_service = Apadmi::Grout::NetworkService.new(username, token, base_url)
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.new("", personal_access_token, base_url)
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
@@ -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
@@ -15,6 +15,14 @@ module Apadmi
15
15
  stdout.strip
16
16
  end
17
17
 
18
+ # Gets the commit hash of the current HEAD
19
+ def self.commit_hash
20
+ stdout, stderr, = Open3.capture3("git rev-parse HEAD")
21
+ raise "Failed to get hash: #{stderr}" unless stderr.strip.empty?
22
+
23
+ stdout.strip
24
+ end
25
+
18
26
  # Gets the number of commits accessible from HEAD treating the history as a graph.
19
27
  # See more details here: https://git-scm.com/docs/git-rev-list
20
28
  # @return [String] The number of commits
@@ -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 initialize(username, password, base_url)
19
- @username = username
20
- @password = password
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"] = "Basic #{Base64.strict_encode64(auth_str)}"
112
+ conn.headers["Authorization"] = @auth_header
113
+ conn.options.timeout = @timeout
79
114
  conn
80
115
  end
81
116
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Apadmi
4
4
  module Grout
5
- VERSION = "2.0.0"
5
+ VERSION = "2.1.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.0.0
4
+ version: 2.1.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-25 00:00:00.000000000 Z
11
+ date: 2022-07-26 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