allure-report-publisher 1.1.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc21e0f3488c76bf88a227a59a470d1959f5aadb813fc86986f7a7a175793efc
4
- data.tar.gz: 641b2e9a9e6587a3246bdcdbf4e34cc3b952f56c46773e495473db9749e68e80
3
+ metadata.gz: 60bffdf8cfaef83d728fa0f0ddb3d5f87227f5fd3f3af1df048ac5859a7e21c7
4
+ data.tar.gz: d3a83dd85d3c3586db99d0c26bf6c5323e4bdc23beff83d80beae12ae0dfcdca
5
5
  SHA512:
6
- metadata.gz: 2ef72a1f8869b175110a7377418bc3a4b369bbb44329965b2b76184c905dc38293b845cf0d661dbe1ff6eb66c2b87804d6fdc74b06eefa58d30826b863c6f0f9
7
- data.tar.gz: d15121ee77d77a467a7e9f6a28b447218711aacc3aa63586f2a0cac424e1abdd129ac2aa7aaba654ddce25f8cf4aec0049d39d4b6cf8be8348515cac6f1854de
6
+ metadata.gz: 1811d5892f98e633ab10585425c359839da9bdef5828389b18c7e10591031b2dae88b920f7d291d72ddcf7b2894ad457ff975769e74e03f84e4baa0bd94a88ab
7
+ data.tar.gz: e27359fd763ce52f1ce55522681e06d446c44d815980b0e2777c9181073a5270d78148f1820afff893406483bd24732e778c0ccbff512d0537511efe00234e6e
@@ -70,7 +70,7 @@ module Publisher
70
70
  @args = args
71
71
 
72
72
  validate_args
73
- validate_result_files
73
+ scan_results_paths
74
74
 
75
75
  generate_report
76
76
  upload_report
@@ -91,8 +91,8 @@ module Publisher
91
91
  def uploader
92
92
  @uploader ||= uploaders(args[:type]).new(
93
93
  summary_type: args[:summary],
94
+ result_paths: @result_paths,
94
95
  **args.slice(
95
- :results_glob,
96
96
  :bucket,
97
97
  :prefix,
98
98
  :copy_latest,
@@ -122,16 +122,18 @@ module Publisher
122
122
  error("Missing argument --bucket!") unless args[:bucket]
123
123
  end
124
124
 
125
- # Check if allure results present
125
+ # Scan for allure results paths
126
126
  #
127
127
  # @param [String] results_glob
128
128
  # @return [void]
129
- def validate_result_files
129
+ def scan_results_paths
130
130
  results_glob = args[:results_glob]
131
131
  ignore = args[:ignore_missing_results]
132
- return unless Dir.glob(results_glob).empty?
132
+ @result_paths = Dir.glob(results_glob)
133
+ log_debug("Glob '#{results_glob}' found #{@result_paths.size} paths")
134
+ return unless @result_paths.empty?
133
135
 
134
- log("Glob '#{results_glob}' did not match any files!", ignore ? :yellow : :red)
136
+ log("Glob '#{results_glob}' did not match any paths!", ignore ? :yellow : :red)
135
137
  exit(ignore ? 0 : 1)
136
138
  end
137
139
 
@@ -29,15 +29,6 @@ module Publisher
29
29
  )
30
30
  end
31
31
 
32
- # Check if gsutil is installed and executable
33
- #
34
- # @return [Boolean]
35
- def gsutil?
36
- execute_shell("which gsutil") && true
37
- rescue StandardError
38
- false
39
- end
40
-
41
32
  # Debug logging session output
42
33
  #
43
34
  # @return [StringIO]
@@ -10,8 +10,8 @@ module Publisher
10
10
  class ReportGenerator
11
11
  include Helpers
12
12
 
13
- def initialize(results_glob)
14
- @results_glob = results_glob
13
+ def initialize(result_paths)
14
+ @result_paths = result_paths.join(" ")
15
15
  end
16
16
 
17
17
  # Generate allure report
@@ -42,25 +42,14 @@ module Publisher
42
42
 
43
43
  private
44
44
 
45
- attr_reader :results_glob
46
-
47
- # Return all allure results paths from glob
48
- #
49
- # @return [String]
50
- def result_paths
51
- @result_paths ||= begin
52
- paths = Dir.glob(results_glob)
53
- raise(NoAllureResultsError, "Missing allure results") if paths.empty?
54
-
55
- paths.join(" ")
56
- end
57
- end
45
+ # @return [String] result paths string
46
+ attr_reader :result_paths
58
47
 
59
48
  # Generate allure report
60
49
  #
61
50
  # @return [void]
62
51
  def generate_report
63
- log_debug("Generating allure report from following paths: #{result_paths}")
52
+ log_debug("Generating allure report")
64
53
  cmd = "allure generate --clean --output #{report_path} #{common_info_path} #{result_paths}"
65
54
  out = execute_shell(cmd)
66
55
  log_debug("Generated allure report. #{out}")
@@ -5,6 +5,8 @@ module Publisher
5
5
  module Uploaders
6
6
  class HistoryNotFoundError < StandardError; end
7
7
 
8
+ PARALLEL_THREADS = 8
9
+
8
10
  # Uploader implementation
9
11
  #
10
12
  class Uploader
@@ -23,7 +25,7 @@ module Publisher
23
25
  # Uploader instance
24
26
  #
25
27
  # @param [Hash] args
26
- # @option args [String] :results_glob
28
+ # @option args [Array] :result_paths
27
29
  # @option args [String] :bucket
28
30
  # @option args [String] :prefix
29
31
  # @option args [Boolean] :update_pr
@@ -32,7 +34,7 @@ module Publisher
32
34
  # @option args [Boolean] :collapse_summary
33
35
  # @option args [String] :copy_latest
34
36
  def initialize(**args)
35
- @results_glob = args[:results_glob]
37
+ @result_paths = args[:result_paths]
36
38
  @bucket_name = args[:bucket]
37
39
  @prefix = args[:prefix]
38
40
  @update_pr = args[:update_pr]
@@ -65,7 +67,9 @@ module Publisher
65
67
  #
66
68
  # @return [void]
67
69
  def upload
68
- run_uploads
70
+ upload_history unless !run_id || copy_latest
71
+ upload_report
72
+ upload_latest_copy if copy_latest
69
73
  end
70
74
 
71
75
  # Add allure report url to pull request description
@@ -97,7 +101,7 @@ module Publisher
97
101
 
98
102
  private
99
103
 
100
- attr_reader :results_glob,
104
+ attr_reader :result_paths,
101
105
  :bucket_name,
102
106
  :prefix,
103
107
  :update_pr,
@@ -164,7 +168,7 @@ module Publisher
164
168
  #
165
169
  # @return [Publisher::ReportGenerator]
166
170
  def report_generator
167
- @report_generator ||= ReportGenerator.new(results_glob)
171
+ @report_generator ||= ReportGenerator.new(result_paths)
168
172
  end
169
173
 
170
174
  # Report path prefix
@@ -234,15 +238,6 @@ module Publisher
234
238
  log_debug("Saved '#{EXECUTOR_JSON}' as '#{json_path}'\n#{JSON.pretty_generate(ci_provider.executor_info)}")
235
239
  end
236
240
 
237
- # Run upload commands
238
- #
239
- # @return [void]
240
- def run_uploads
241
- upload_history unless !run_id || copy_latest
242
- upload_report
243
- upload_latest_copy if copy_latest
244
- end
245
-
246
241
  # Fetch allure report history
247
242
  #
248
243
  # @return [void]
@@ -14,13 +14,6 @@ module Publisher
14
14
  @client ||= Google::Cloud::Storage.new
15
15
  end
16
16
 
17
- # Gsutil class
18
- #
19
- # @return [Helpers::Gsutil]
20
- def gsutil
21
- @gsutil ||= Helpers::Gsutil.init
22
- end
23
-
24
17
  # GCS bucket
25
18
  #
26
19
  # @return [Google::Cloud::Storage::Bucket]
@@ -70,8 +63,6 @@ module Publisher
70
63
  # @return [void]
71
64
  def upload_report
72
65
  log_debug("Uploading report files")
73
- return batch_upload_to_gcs(report_path, full_prefix) if gsutil.valid?
74
-
75
66
  upload_to_gcs(report_files, full_prefix)
76
67
  end
77
68
 
@@ -79,10 +70,21 @@ module Publisher
79
70
  #
80
71
  # @return [void]
81
72
  def upload_latest_copy
82
- log_debug("Uploading report copy as latest report")
83
- return batch_upload_to_gcs(report_path, prefix, cache_control: 60) if gsutil.valid?
73
+ log_debug("Copying report as latest")
74
+
75
+ args = report_files.map do |file|
76
+ {
77
+ source_file: bucket.file(key(full_prefix, file.relative_path_from(report_path))),
78
+ destination: key(prefix, file.relative_path_from(report_path))
79
+ }
80
+ end
84
81
 
85
- upload_to_gcs(report_files, prefix, cache_control: 60)
82
+ Parallel.each(args, in_threads: PARALLEL_THREADS) do |obj|
83
+ obj[:source_file].copy(obj[:destination], force_copy_metadata: true) do |f|
84
+ f.cache_control = "public, max-age=60"
85
+ end
86
+ end
87
+ log_debug("Finished latest report copy successfully")
86
88
  end
87
89
 
88
90
  # Upload files to gcs
@@ -90,38 +92,22 @@ module Publisher
90
92
  # @param [Array<Pathname>] files
91
93
  # @param [String] key_prefix
92
94
  # @param [Hash] params
93
- # @return [void]
94
- def upload_to_gcs(files, key_prefix, cache_control: 3600)
95
- threads = 8
95
+ # @return [Array<Hash>]
96
+ def upload_to_gcs(files, key_prefix)
96
97
  args = files.map do |file|
97
98
  {
98
99
  file: file.to_s,
99
- path: key(key_prefix, file.relative_path_from(report_path)),
100
- cache_control: "public, max-age=#{cache_control}"
100
+ path: key(key_prefix, file.relative_path_from(report_path))
101
101
  }
102
102
  end
103
103
 
104
- log_debug("Uploading '#{args.size}' files in '#{threads}' threads to bucker '#{bucket_name}'")
105
- Parallel.each(args, in_threads: threads) do |obj|
106
- bucket.create_file(*obj.slice(:file, :path).values, **obj.slice(:cache_control))
104
+ log_debug("Uploading '#{args.size}' files in '#{PARALLEL_THREADS}' threads")
105
+ Parallel.each(args, in_threads: PARALLEL_THREADS) do |obj|
106
+ bucket.create_file(*obj.slice(:file, :path).values, cache_control: "public, max-age=3600")
107
107
  end
108
108
  log_debug("Finished upload successfully")
109
109
  end
110
110
 
111
- # Batch upload whole directory
112
- #
113
- # @param [String] source_dir
114
- # @param [String] destination_dir
115
- # @return [void]
116
- def batch_upload_to_gcs(source_dir, destination_dir, cache_control: 3600)
117
- gsutil.batch_copy(
118
- source_dir: source_dir,
119
- destination_dir: destination_dir,
120
- bucket: bucket_name,
121
- cache_control: cache_control
122
- )
123
- end
124
-
125
111
  # Fabricate key for s3 object
126
112
  #
127
113
  # @param [String] *args
@@ -81,8 +81,21 @@ module Publisher
81
81
  #
82
82
  # @return [void]
83
83
  def upload_latest_copy
84
- log_debug("Uploading report copy as latest report")
85
- upload_to_s3(report_files, prefix, cache_control: 60)
84
+ log_debug("Copying report as latest")
85
+
86
+ args = report_files.map do |file|
87
+ {
88
+ bucket: bucket_name,
89
+ copy_source: "/#{bucket_name}/#{key(full_prefix, file.relative_path_from(report_path))}",
90
+ key: key(prefix, file.relative_path_from(report_path)),
91
+ metadata_directive: "REPLACE",
92
+ content_type: MiniMime.lookup_by_filename(file).content_type,
93
+ cache_control: "max-age=60"
94
+ }
95
+ end
96
+
97
+ Parallel.each(args, in_threads: PARALLEL_THREADS) { |obj| client.copy_object(obj) }
98
+ log_debug("Finished latest report copy successfully")
86
99
  end
87
100
 
88
101
  # Upload files to s3
@@ -90,20 +103,19 @@ module Publisher
90
103
  # @param [Array<Pathname>] files
91
104
  # @param [String] key_prefix
92
105
  # @return [Array<Hash>]
93
- def upload_to_s3(files, key_prefix, cache_control: 3600)
94
- threads = 8
106
+ def upload_to_s3(files, key_prefix)
95
107
  args = files.map do |file|
96
108
  {
97
109
  body: File.new(file),
98
110
  bucket: bucket_name,
99
111
  key: key(key_prefix, file.relative_path_from(report_path)),
100
112
  content_type: MiniMime.lookup_by_filename(file).content_type,
101
- cache_control: "max-age=#{cache_control}"
113
+ cache_control: "max-age=3600"
102
114
  }
103
115
  end
104
116
 
105
- log_debug("Uploading '#{args.size}' files in '#{threads}' threads")
106
- Parallel.each(args, in_threads: threads) { |obj| client.put_object(obj) }
117
+ log_debug("Uploading '#{args.size}' files in '#{PARALLEL_THREADS}' threads")
118
+ Parallel.each(args, in_threads: PARALLEL_THREADS) { |obj| client.put_object(obj) }
107
119
  log_debug("Finished upload successfully")
108
120
  end
109
121
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Publisher
4
- VERSION = "1.1.0"
4
+ VERSION = "1.3.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allure-report-publisher
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrejs Cunskis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-17 00:00:00.000000000 Z
11
+ date: 2022-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-s3
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 1.93.1
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 1.115.0
22
+ version: 1.118.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 1.93.1
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 1.115.0
32
+ version: 1.118.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: dry-cli
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -121,7 +121,7 @@ dependencies:
121
121
  version: '4.21'
122
122
  - - "<"
123
123
  - !ruby/object:Gem::Version
124
- version: '6.0'
124
+ version: '7.0'
125
125
  type: :runtime
126
126
  prerelease: false
127
127
  version_requirements: !ruby/object:Gem::Requirement
@@ -131,7 +131,7 @@ dependencies:
131
131
  version: '4.21'
132
132
  - - "<"
133
133
  - !ruby/object:Gem::Version
134
- version: '6.0'
134
+ version: '7.0'
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: parallel
137
137
  requirement: !ruby/object:Gem::Requirement
@@ -248,6 +248,9 @@ dependencies:
248
248
  name: debug
249
249
  requirement: !ruby/object:Gem::Requirement
250
250
  requirements:
251
+ - - "~>"
252
+ - !ruby/object:Gem::Version
253
+ version: '1.0'
251
254
  - - ">="
252
255
  - !ruby/object:Gem::Version
253
256
  version: 1.0.0
@@ -255,6 +258,9 @@ dependencies:
255
258
  prerelease: false
256
259
  version_requirements: !ruby/object:Gem::Requirement
257
260
  requirements:
261
+ - - "~>"
262
+ - !ruby/object:Gem::Version
263
+ version: '1.0'
258
264
  - - ">="
259
265
  - !ruby/object:Gem::Version
260
266
  version: 1.0.0
@@ -397,7 +403,6 @@ files:
397
403
  - lib/allure_report_publisher.rb
398
404
  - lib/allure_report_publisher/commands/upload.rb
399
405
  - lib/allure_report_publisher/commands/version.rb
400
- - lib/allure_report_publisher/lib/helpers/gsutil.rb
401
406
  - lib/allure_report_publisher/lib/helpers/helpers.rb
402
407
  - lib/allure_report_publisher/lib/helpers/spinner.rb
403
408
  - lib/allure_report_publisher/lib/helpers/summary.rb
@@ -1,120 +0,0 @@
1
- require "tempfile"
2
-
3
- module Publisher
4
- module Helpers
5
- # Helper class for gsutil cli utility
6
- #
7
- class Gsutil
8
- class UnsupportedConfig < StandardError; end
9
- class Uninitialised < StandardError; end
10
-
11
- include Helpers
12
-
13
- def self.init
14
- new.init!
15
- end
16
-
17
- private_class_method :new
18
-
19
- # Initialize gsutil
20
- #
21
- # @return [Gsutil]
22
- def init!
23
- log_debug("Setting up gsutil")
24
- @valid = execute_shell("which gsutil") && true
25
-
26
- log_debug("Checking google credentials")
27
- check_credentials
28
- log_debug("Credentials valid, gsutil initialized")
29
- self
30
- rescue StandardError => e
31
- case e
32
- when UnsupportedConfig
33
- log_debug("credentials not compatible with gsutil! Falling back to google sdk client for batch uploads")
34
- when ShellCommandFailure
35
- log_debug("gsutil command not found, falling back to gcs client")
36
- else
37
- log_debug("gsutil init failed: error: #{e}\nbacktrace: #{e.backtrace&.join("\n")}")
38
- end
39
-
40
- @valid = false
41
- self
42
- end
43
-
44
- # Check if gsutil is valid
45
- #
46
- # @return [Boolean]
47
- def valid?
48
- @valid
49
- end
50
-
51
- # Perform batch copy operation
52
- #
53
- # @param [String] source_dir
54
- # @param [String] destination_dir
55
- # @param [String] bucket
56
- # @param [String] cache_control
57
- # @return [void]
58
- def batch_copy(source_dir:, destination_dir:, bucket:, cache_control: 3600)
59
- raise(Uninitialised, "gsutil has not been properly set up!") unless valid?
60
-
61
- log_debug("Uploading '#{source_dir}' using gsutil to bucket '#{bucket}' with destination '#{destination_dir}'")
62
- with_credentials do |key_file|
63
- execute_shell([
64
- base_cmd(key_file),
65
- "-h 'Cache-Control:private, max-age=#{cache_control}'",
66
- "rsync -r #{source_dir} gs://#{bucket}/#{destination_dir}"
67
- ].join(" "))
68
- end
69
- log_debug("Finished upload successfully")
70
- end
71
-
72
- private
73
-
74
- # Execute block with gcs credentials
75
- #
76
- # @return [void]
77
- def with_credentials
78
- if json_key[:file]
79
- yield(json_key[:key])
80
- else
81
- Tempfile.create("auth") do |f|
82
- f.write(json_key[:key])
83
- f.close
84
-
85
- yield(f.path)
86
- end
87
- end
88
- end
89
-
90
- # Google auth default credentials
91
- #
92
- # @return [String, Hash]
93
- def gcs_credentials
94
- @gcs_credentials ||= Google::Cloud::Storage.default_credentials
95
- end
96
-
97
- # Google auth json key
98
- #
99
- # @return [Hash]
100
- def json_key
101
- @json_key ||= if gcs_credentials.is_a?(Hash)
102
- { file: false, key: gcs_credentials.to_json }
103
- elsif gcs_credentials.is_a?(String) && File.exist?(gcs_credentials)
104
- { file: true, key: gcs_credentials.tap { |f| JSON.parse(File.read(f)) } }
105
- else
106
- raise(UnsupportedConfig, "only google key json credentials are supported for gsutil")
107
- end
108
- end
109
- alias check_credentials json_key
110
-
111
- # Base command
112
- #
113
- # @param [String] key_file
114
- # @return [String]
115
- def base_cmd(key_file)
116
- "gsutil -o 'Credentials:gs_service_key_file=#{key_file}' -m"
117
- end
118
- end
119
- end
120
- end