allure-report-publisher 4.5.0 → 4.7.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: 82efde728a5903d3410e98eec0b35a0f9a3789c79619c0aafe92c604937aa1fd
4
- data.tar.gz: a1cd5018bc9d904459fe7eaf613dee24907adbe5d0242b6524bb802bca826bb7
3
+ metadata.gz: 383b5a328cf9acc9c7ef65bf6e63f807d936dc38a4125e908a5ea6c29ac6df18
4
+ data.tar.gz: 4348a6696f84c9c2fa5c36584b7e8e4313db19965ae2b182aeba8087a2520dc5
5
5
  SHA512:
6
- metadata.gz: 0fbedf74afe01d091999267911a1d2016686bfa717c3139e888cb25635cbc88d87c216be08cb25876943c78512907a79e5fedfed4de9ddbff1b430b80b1b2f87
7
- data.tar.gz: b848cdfeb884f56dda77c0214ecf786ad3f40f9f8af9b71fa3e8a7400110ff1146ce36c15d7d23485694ccc981607f0fbd26f3480e203d34a21ce285ad2cbd3a
6
+ metadata.gz: a1b0faa886ce9d3ee4ccb0e3d3459190121b40fc136571476caa859f66480e2284d10b38570fea07ace0284b4fd711db114c4151968cdc95882c54b10e11c452
7
+ data.tar.gz: 710dc295a857b1fdc771f46e9a8c51b018f5832e43fc2e78fd5a9f800c5bfbf3b1326e0c0ae4aea02fd19b577a24dc18d2aedb988f634bda3c9c05fe8b1d2f6e
data/README.md CHANGED
@@ -3,8 +3,6 @@
3
3
  [![Docker Image Version (latest semver)](https://img.shields.io/docker/v/andrcuns/allure-report-publisher?color=blue&label=docker&sort=semver)](https://hub.docker.com/r/andrcuns/allure-report-publisher)
4
4
  [![Docker Pulls](https://img.shields.io/docker/pulls/andrcuns/allure-report-publisher)](https://hub.docker.com/r/andrcuns/allure-report-publisher)
5
5
  ![Workflow status](https://github.com/andrcuns/allure-report-publisher/workflows/Test/badge.svg)
6
- [![Maintainability](https://api.codeclimate.com/v1/badges/210eaa4f74588fb08313/maintainability)](https://codeclimate.com/github/andrcuns/allure-report-publisher/maintainability)
7
- [![Test Coverage](https://api.codeclimate.com/v1/badges/210eaa4f74588fb08313/test_coverage)](https://codeclimate.com/github/andrcuns/allure-report-publisher/test_coverage)
8
6
 
9
7
  Upload your report to a file storage of your choice.
10
8
 
@@ -38,22 +36,23 @@ Description:
38
36
  Generate and upload allure report
39
37
 
40
38
  Arguments:
41
- TYPE # REQUIRED Cloud storage type: (s3/gcs)
39
+ TYPE # REQUIRED Cloud storage type: (gcs/s3/gitlab-artifacts)
42
40
 
43
41
  Options:
44
42
  --results-glob=VALUE # Glob pattern to return allure results directories. Required: true
45
- --bucket=VALUE # Bucket name. Required: true
46
- --prefix=VALUE # Optional prefix for report path. Required: false
43
+ --bucket=VALUE # Bucket name. Required: true (gcs|s3), false (gitlab-artifacts)
44
+ --output=VALUE # Output directory for the report. Required: false. Defaults to 'allure-report' for gitlab-artifacts and random temporary directory for cloud based storage
45
+ --prefix=VALUE # Optional prefix for report path. Required: false. Ignored for gitlab-artifacts
47
46
  --update-pr=VALUE # Add report url to PR via comment or description update. Required: false: (comment/description/actions)
48
47
  --report-title=VALUE # Title for url section in PR comment/description. Required: false, default: "Allure Report"
49
48
  --report-name=VALUE # Custom report name in final Allure report. Required: false
50
49
  --summary=VALUE # Additionally add summary table to PR comment or description. Required: false: (behaviors/suites/packages/total), default: "total"
51
50
  --summary-table-type=VALUE # Summary table type. Required: false: (ascii/markdown), default: "ascii"
52
- --base-url=VALUE # Use custom base url instead of default cloud provider one. Required: false
51
+ --base-url=VALUE # Use custom base url instead of default cloud provider one. Required: false. Ignored for gitlab-artifacts
53
52
  --parallel=VALUE # Number of parallel threads to use for report file upload to cloud storage. Required: false, default: 8
54
53
  --[no-]flaky-warning-status # Mark run with a '!' status in PR comment/description if report contains flaky tests, default: false
55
54
  --[no-]collapse-summary # Create summary as a collapsible section, default: false
56
- --[no-]copy-latest # Keep copy of latest report at base prefix path, default: false
55
+ --[no-]copy-latest # Keep copy of latest report at base prefix path. Ignored for gitlab-artifacts, default: false
57
56
  --[no-]color # Force color output
58
57
  --[no-]ignore-missing-results # Ignore missing allure results, default: false
59
58
  --[no-]debug # Print additional debug output, default: false
@@ -62,6 +61,17 @@ Options:
62
61
  Examples:
63
62
  allure-report-publisher upload s3 --results-glob='path/to/allure-results' --bucket=my-bucket
64
63
  allure-report-publisher upload gcs --results-glob='paths/to/**/allure-results' --bucket=my-bucket --prefix=my-project/prs
64
+ allure-report-publisher upload gitlab-artifacts --results-glob='paths/to/**/allure-results'
65
+ ```
66
+
67
+ ## Extra arguments
68
+
69
+ You can pass any extra arguments to the `allure generate` command by using `--` before the arguments.
70
+
71
+ Example:
72
+
73
+ ```shell
74
+ allure-report-publisher upload s3 --results-glob='path/to/allure-results' --bucket=my-bucket -- --lang en
65
75
  ```
66
76
 
67
77
  ## Environment variables
@@ -105,6 +115,23 @@ credentials.json contents:
105
115
  - `GOOGLE_CLOUD_KEYFILE_JSON`
106
116
  - `GCLOUD_KEYFILE_JSON`
107
117
 
118
+ ## Gitlab Artifacts
119
+
120
+ This storage provider is only supported for GitLab CI. Because GitLab does not expose public api for uploading artifacts, a job must be configured to upload the report as an artifact. Example:
121
+
122
+ ```yaml
123
+ # .gitlab-ci.yml
124
+ artifacts:
125
+ paths:
126
+ - allure-report
127
+ ```
128
+
129
+ where `allure-report` is the directory containing the generated Allure report and can be overridden via `--output` option.
130
+
131
+ Requires environment variable `GITLAB_AUTH_TOKEN` where token is a GitLab personal access token with `api` scope capable of downloading artifacts and retrieving job and pipeline information.
132
+
133
+ This provider is meant to be used with [GitLab CI](#gitlab-ci).
134
+
108
135
  # CI
109
136
 
110
137
  `allure-report-publisher` will automatically detect if used in CI environment and add relevant executor info and history.
@@ -7,20 +7,25 @@ module Publisher
7
7
  class Upload < Dry::CLI::Command
8
8
  include Helpers
9
9
 
10
+ STORAGE_PROVIDERS = %w[gcs s3 gitlab-artifacts].freeze
11
+
10
12
  desc "Generate and upload allure report"
11
13
 
12
14
  argument :type,
13
15
  type: :string,
14
16
  required: true,
15
- values: %w[s3 gcs],
17
+ values: STORAGE_PROVIDERS,
16
18
  desc: "Cloud storage type"
17
19
 
20
+ # rubocop:disable Layout/LineLength
18
21
  option :results_glob,
19
22
  desc: "Glob pattern to return allure results directories. Required: true"
20
23
  option :bucket,
21
- desc: "Bucket name. Required: true"
24
+ desc: "Bucket name. Required: true (gcs|s3), false (gitlab-artifacts)"
25
+ option :output,
26
+ desc: "Output directory for the report. Required: false. Defaults to 'allure-report' for gitlab-artifacts and random temporary directory for cloud based storage"
22
27
  option :prefix,
23
- desc: "Optional prefix for report path. Required: false"
28
+ desc: "Optional prefix for report path. Required: false. Ignored for gitlab-artifacts"
24
29
  option :update_pr,
25
30
  type: :string,
26
31
  desc: "Add report url to PR via comment or description update. Required: false",
@@ -52,7 +57,7 @@ module Publisher
52
57
  ]
53
58
  option :base_url,
54
59
  type: :string,
55
- desc: "Use custom base url instead of default cloud provider one. Required: false"
60
+ desc: "Use custom base url instead of default cloud provider one. Required: false. Ignored for gitlab-artifacts"
56
61
  option :parallel,
57
62
  type: :integer,
58
63
  desc: "Number of parallel threads to use for report file upload to cloud storage. Required: false",
@@ -68,7 +73,7 @@ module Publisher
68
73
  option :copy_latest,
69
74
  type: :boolean,
70
75
  default: false,
71
- desc: "Keep copy of latest report at base prefix path"
76
+ desc: "Keep copy of latest report at base prefix path. Ignored for gitlab-artifacts"
72
77
  option :color,
73
78
  type: :boolean,
74
79
  desc: "Force color output"
@@ -80,22 +85,24 @@ module Publisher
80
85
  type: :boolean,
81
86
  default: false,
82
87
  desc: "Print additional debug output"
88
+ # rubocop:enable Layout/LineLength
83
89
 
84
90
  example [
85
91
  "s3 --results-glob='path/to/allure-results' --bucket=my-bucket",
86
- "gcs --results-glob='paths/to/**/allure-results' --bucket=my-bucket --prefix=my-project/prs"
92
+ "gcs --results-glob='paths/to/**/allure-results' --bucket=my-bucket --prefix=my-project/prs",
93
+ "gitlab-artifacts --results-glob='paths/to/**/allure-results'"
87
94
  ]
88
95
 
89
- def call(**args)
90
- Helpers.pastel(force_color: args[:color])
91
- @args = args
96
+ def call(args: [], **arguments)
97
+ Helpers.pastel(force_color: arguments[:color])
98
+ @args = arguments
92
99
 
93
- validate_args
100
+ validate_args!
94
101
  scan_results_paths
95
102
 
96
- generate_report
103
+ generate_report(args)
97
104
  upload_report
98
- return unless args[:update_pr] && Providers.info&.pr?
105
+ return unless arguments[:update_pr] && Providers.info&.pr?
99
106
 
100
107
  add_report_urls
101
108
  rescue StandardError => e
@@ -106,6 +113,17 @@ module Publisher
106
113
 
107
114
  attr_reader :args
108
115
 
116
+ # Report output path
117
+ #
118
+ # @return [String] output path
119
+ def output
120
+ @output ||= args[:output].then do |path|
121
+ next if path
122
+
123
+ gitlab_artifacts? ? "allure-report" : File.join(Dir.tmpdir, "allure-report-#{Time.now.to_i}")
124
+ end
125
+ end
126
+
109
127
  # Uploader instance
110
128
  #
111
129
  # @return [Publisher::Uploaders::Uploader]
@@ -113,6 +131,7 @@ module Publisher
113
131
  @uploader ||= uploaders(args[:type]).new(
114
132
  result_paths: @result_paths,
115
133
  parallel: parallel_threads,
134
+ output: output,
116
135
  **args.slice(:bucket, :prefix, :base_url, :copy_latest, :report_name)
117
136
  )
118
137
  end
@@ -123,7 +142,7 @@ module Publisher
123
142
  def ci_provider
124
143
  @ci_provider = Providers.provider&.new(
125
144
  report_url: uploader.report_url,
126
- report_path: uploader.report_path,
145
+ report_path: output,
127
146
  summary_type: args[:summary],
128
147
  **args.slice(
129
148
  :update_pr,
@@ -142,19 +161,39 @@ module Publisher
142
161
  def uploaders(uploader)
143
162
  {
144
163
  "s3" => Uploaders::S3,
145
- "gcs" => Uploaders::GCS
164
+ "gcs" => Uploaders::GCS,
165
+ "gitlab-artifacts" => Uploaders::GitlabArtifacts
146
166
  }.fetch(uploader)
147
167
  end
148
168
 
149
169
  # Validate required args
150
170
  #
151
171
  # @return [void]
152
- def validate_args
153
- error("Unsupported cloud storage type! Supported types are: s3, gcs") unless %w[s3 gcs].include?(args[:type])
172
+ def validate_args!
173
+ validate_base_args!
174
+ validate_base_url!
175
+ cast_parallel_threads_arg!
176
+ end
177
+
178
+ # Check base arguments
179
+ #
180
+ # @return [void]
181
+ def validate_base_args!
182
+ unless STORAGE_PROVIDERS.include?(args[:type])
183
+ error("Unsupported storage type! Supported types are: #{STORAGE_PROVIDERS.join(', ')}")
184
+ end
185
+
154
186
  error("Missing argument --results-glob!") unless args[:results_glob]
155
- error("Missing argument --bucket!") unless args[:bucket]
156
- URI.parse(args[:base_url]) if args[:base_url]
157
- validate_parallel_args
187
+ error("Missing argument --bucket!") unless gitlab_artifacts? || args[:bucket]
188
+ end
189
+
190
+ # Check base URL is a valid URI
191
+ #
192
+ # @return [void]
193
+ def validate_base_url!
194
+ return unless args[:base_url] && !gitlab_artifacts?
195
+
196
+ URI.parse(args[:base_url])
158
197
  rescue URI::InvalidURIError
159
198
  error("Invalid --base-url value!")
160
199
  end
@@ -169,7 +208,7 @@ module Publisher
169
208
  rescue ArgumentError
170
209
  error("Invalid --parallel value, must be a positive number!")
171
210
  end
172
- alias validate_parallel_args parallel_threads
211
+ alias cast_parallel_threads_arg! parallel_threads
173
212
 
174
213
  # Scan for allure results paths
175
214
  #
@@ -186,12 +225,20 @@ module Publisher
186
225
  exit(ignore ? 0 : 1)
187
226
  end
188
227
 
228
+ # Gitlab artifacts store
229
+ #
230
+ # @return [Boolean] true if gitlab artifacts store is used
231
+ def gitlab_artifacts?
232
+ args[:type] == "gitlab-artifacts"
233
+ end
234
+
189
235
  # Generate allure report
190
236
  #
237
+ # @param [Array<String>] extra_args
191
238
  # @return [void]
192
- def generate_report
239
+ def generate_report(extra_args)
193
240
  log("Generating allure report")
194
- Spinner.spin("generating", debug: args[:debug]) { uploader.generate_report }
241
+ Spinner.spin("generating", debug: args[:debug]) { uploader.generate_report(extra_args) }
195
242
  end
196
243
 
197
244
  # Upload report to cloud storage
@@ -199,7 +246,13 @@ module Publisher
199
246
  # @return [void]
200
247
  def upload_report
201
248
  log("Uploading allure report to #{args[:type]}")
202
- Spinner.spin("uploading", debug: args[:debug]) { uploader.upload }
249
+ # gitlab-artifacts by default will raise error with info about upload using artifacts
250
+ spinner_args = {
251
+ debug: args[:debug],
252
+ exit_on_error: !gitlab_artifacts?,
253
+ failed_message: gitlab_artifacts? ? "skipped" : nil
254
+ }.compact
255
+ Spinner.spin("uploading", **spinner_args) { uploader.upload }
203
256
  uploader.report_urls.each { |k, v| log("#{k}: #{v}", :green) }
204
257
  end
205
258
 
@@ -64,6 +64,18 @@ module Publisher
64
64
  ENV[name]
65
65
  end
66
66
 
67
+ # Return environment variable as integer if it's numeric
68
+ #
69
+ # @param [String] name
70
+ # @return [Integer, nil]
71
+ def env_int(name)
72
+ value = env(name)
73
+ return unless value
74
+ raise("Invalid integer value for #{name}") unless value.match?(/\A-?\d+\z/)
75
+
76
+ value.to_i
77
+ end
78
+
67
79
  module_function
68
80
 
69
81
  # Colorize string
@@ -24,20 +24,27 @@ module Publisher
24
24
  # @param [Boolean] exit_on_error
25
25
  # @param [Proc] &block
26
26
  # @return [void]
27
- def self.spin(spinner_message, done_message: "done", exit_on_error: true, debug: false, &block)
28
- new(spinner_message, exit_on_error: exit_on_error, debug: debug).spin(done_message, &block)
27
+ def self.spin(
28
+ spinner_message,
29
+ done_message: "done",
30
+ failed_message: "failed",
31
+ exit_on_error: true,
32
+ debug: false,
33
+ &block
34
+ )
35
+ new(spinner_message, exit_on_error: exit_on_error, debug: debug).spin(done_message, failed_message, &block)
29
36
  end
30
37
 
31
38
  # Run code block inside spinner
32
39
  #
33
40
  # @param [String] done_message
34
41
  # @return [Boolean]
35
- def spin(done_message = "done")
42
+ def spin(done_message = "done", failed_message = "failed")
36
43
  spinner.auto_spin
37
44
  yield
38
45
  spinner_success(done_message)
39
46
  rescue StandardError => e
40
- spinner_error(e)
47
+ spinner_error(e, done_message: failed_message)
41
48
  raise(Failure, e.message) if exit_on_error
42
49
  ensure
43
50
  print_debug
@@ -119,8 +126,8 @@ module Publisher
119
126
  #
120
127
  # @param [StandardError] error
121
128
  # @return [void]
122
- def spinner_error(error)
123
- message = ["failed", error.message]
129
+ def spinner_error(error, done_message: "failed")
130
+ message = [done_message, error.message]
124
131
  log_debug("Error: #{error.message}\n#{error.backtrace.join("\n")}")
125
132
 
126
133
  colored_message = colorize(message.compact.join("\n"), error_color)
@@ -19,18 +19,8 @@ module Publisher
19
19
  def_delegators :"Publisher::Providers::Info::Github.instance",
20
20
  :repository,
21
21
  :server_url,
22
- :build_name
23
-
24
- # Github api client
25
- #
26
- # @return [Octokit::Client]
27
- def client
28
- @client ||= begin
29
- raise("Missing GITHUB_AUTH_TOKEN environment variable!") unless ENV["GITHUB_AUTH_TOKEN"]
30
-
31
- Octokit::Client.new(access_token: ENV["GITHUB_AUTH_TOKEN"], api_endpoint: ENV["GITHUB_API_URL"])
32
- end
33
- end
22
+ :build_name,
23
+ :client
34
24
 
35
25
  # Update pull request description
36
26
  #
@@ -15,21 +15,8 @@ module Publisher
15
15
  :mr_iid,
16
16
  :allure_mr_iid,
17
17
  :server_url,
18
- :build_name
19
-
20
- # Get gitlab client
21
- #
22
- # @return [Gitlab::Client]
23
- def client
24
- @client ||= begin
25
- raise("Missing GITLAB_AUTH_TOKEN environment variable!") unless env("GITLAB_AUTH_TOKEN")
26
-
27
- ::Gitlab::Client.new(
28
- endpoint: "#{server_url}/api/v4",
29
- private_token: env("GITLAB_AUTH_TOKEN")
30
- )
31
- end
32
- end
18
+ :build_name,
19
+ :client
33
20
 
34
21
  # Current pull request description
35
22
  #
@@ -11,6 +11,13 @@ module Publisher
11
11
 
12
12
  # :nocov:
13
13
 
14
+ # CI provider api client
15
+ #
16
+ # @return [Object]
17
+ def client
18
+ raise("Not implemented!")
19
+ end
20
+
14
21
  # CI Provider executor info
15
22
  #
16
23
  # @param [String] report_url
@@ -23,6 +23,17 @@ module Publisher
23
23
  }
24
24
  end
25
25
 
26
+ # Github api client
27
+ #
28
+ # @return [Octokit::Client]
29
+ def client
30
+ @client ||= begin
31
+ raise("Missing GITHUB_AUTH_TOKEN environment variable!") unless ENV["GITHUB_AUTH_TOKEN"]
32
+
33
+ Octokit::Client.new(access_token: ENV["GITHUB_AUTH_TOKEN"], api_endpoint: ENV["GITHUB_API_URL"])
34
+ end
35
+ end
36
+
26
37
  # Pull request run
27
38
  #
28
39
  # @return [Boolean]
@@ -23,6 +23,20 @@ module Publisher
23
23
  }
24
24
  end
25
25
 
26
+ # Get gitlab client
27
+ #
28
+ # @return [Gitlab::Client]
29
+ def client
30
+ @client ||= begin
31
+ raise("Missing GITLAB_AUTH_TOKEN environment variable!") unless env("GITLAB_AUTH_TOKEN")
32
+
33
+ ::Gitlab::Client.new(
34
+ endpoint: "#{server_url}/api/v4",
35
+ private_token: env("GITLAB_AUTH_TOKEN")
36
+ )
37
+ end
38
+ end
39
+
26
40
  # Pull request run
27
41
  #
28
42
  # @return [Boolean]
@@ -32,9 +46,48 @@ module Publisher
32
46
 
33
47
  # Get ci run ID without creating instance of ci provider
34
48
  #
35
- # @return [String]
49
+ # @return [Integer]
36
50
  def run_id
37
- @run_id ||= env(ALLURE_RUN_ID) || ENV["CI_PIPELINE_ID"]
51
+ @run_id ||= env_int(ALLURE_RUN_ID) || env_int("CI_PIPELINE_ID")
52
+ end
53
+
54
+ # CI job ID
55
+ #
56
+ # @return [Integer]
57
+ def job_id
58
+ @job_id ||= env_int("CI_JOB_ID")
59
+ end
60
+
61
+ # Gitlab pages hostname
62
+ #
63
+ # @return [String]
64
+ def pages_hostname
65
+ @pages_hostname ||= env("CI_PAGES_HOSTNAME")
66
+ end
67
+
68
+ # CI project name
69
+ #
70
+ # @return [String]
71
+ def project_name
72
+ @project_name ||= env("CI_PROJECT_NAME")
73
+ end
74
+
75
+ # CI project ID
76
+ #
77
+ # @return [Integer]
78
+ def project_id
79
+ @project_id ||= env_int("CI_PROJECT_ID")
80
+ end
81
+
82
+ # Project directory
83
+ #
84
+ # @return [String] build directory
85
+ def build_dir
86
+ @build_dir ||= env("CI_PROJECT_DIR")
87
+ end
88
+
89
+ def branch
90
+ @branch ||= env("CI_MERGE_REQUEST_SOURCE_BRANCH_NAME") || env("CI_COMMIT_REF_NAME")
38
91
  end
39
92
 
40
93
  # Server url
@@ -62,21 +115,28 @@ module Publisher
62
115
  #
63
116
  # @return [Integer]
64
117
  def mr_iid
65
- @mr_iid ||= allure_mr_iid || env("CI_MERGE_REQUEST_IID")
118
+ @mr_iid ||= allure_mr_iid || env_int("CI_MERGE_REQUEST_IID")
66
119
  end
67
120
 
68
121
  # Custom mr iid name
69
122
  #
70
- # @return [String]
123
+ # @return [Integer]
71
124
  def allure_mr_iid
72
- @allure_mr_iid ||= env("ALLURE_MERGE_REQUEST_IID")
125
+ @allure_mr_iid ||= env_int("ALLURE_MERGE_REQUEST_IID")
73
126
  end
74
127
 
75
- # Job name
128
+ # Job name used in report
76
129
  #
77
130
  # @return [String]
78
131
  def build_name
79
- @build_name ||= env(ALLURE_JOB_NAME) || env("CI_JOB_NAME")
132
+ @build_name ||= env(ALLURE_JOB_NAME) || job_name
133
+ end
134
+
135
+ # CI job name
136
+ #
137
+ # @return [String]
138
+ def job_name
139
+ @job_name ||= env("CI_JOB_NAME")
80
140
  end
81
141
  end
82
142
  end
@@ -10,18 +10,20 @@ module Publisher
10
10
  class ReportGenerator
11
11
  include Helpers
12
12
 
13
- def initialize(result_paths, report_name)
13
+ def initialize(result_paths, report_name, report_path)
14
14
  @result_paths = result_paths.join(" ")
15
15
  @report_name = report_name
16
+ @report_path = report_path
16
17
  end
17
18
 
18
19
  # Generate allure report
19
20
  #
21
+ # @param [Array<String>] extra_args
20
22
  # @return [void]
21
- def generate
23
+ def generate(extra_args = [])
22
24
  create_common_path
23
25
 
24
- generate_report
26
+ generate_report(extra_args)
25
27
  end
26
28
 
27
29
  # Common path for history and executor info
@@ -34,12 +36,8 @@ module Publisher
34
36
  end
35
37
  alias create_common_path common_info_path
36
38
 
37
- # Allure report directory
38
- #
39
- # @return [String]
40
- def report_path
41
- @report_path ||= File.join(Dir.tmpdir, "allure-report-#{Time.now.to_i}")
42
- end
39
+ # @return [String] report path
40
+ attr_reader :report_path
43
41
 
44
42
  private
45
43
 
@@ -51,11 +49,13 @@ module Publisher
51
49
  # Generate allure report
52
50
  #
53
51
  # @return [void]
54
- def generate_report
52
+ def generate_report(extra_args)
55
53
  log_debug("Generating allure report")
56
54
  cmd = ["allure generate --clean"]
57
55
  cmd << "--report-name '#{report_name}'" if report_name
58
56
  cmd << "--output #{report_path} #{common_info_path} #{result_paths}"
57
+ cmd.push(*extra_args) if extra_args.any?
58
+
59
59
  out = execute_shell(cmd.join(" "))
60
60
  log_debug("Generated allure report. #{out}".strip)
61
61
 
@@ -30,6 +30,7 @@ module Publisher
30
30
  # @option args [String] :copy_latest
31
31
  # @option args [String] :report_name
32
32
  # @option args [Integer] :parallel
33
+ # @option args [String] :output
33
34
  def initialize(**args)
34
35
  @result_paths = args[:result_paths]
35
36
  @bucket_name = args[:bucket]
@@ -38,24 +39,17 @@ module Publisher
38
39
  @copy_latest = ci_info && args[:copy_latest] # copy latest for ci only
39
40
  @report_name = args[:report_name]
40
41
  @parallel = args[:parallel]
41
- end
42
-
43
- # Execute allure report generation and upload
44
- #
45
- # @return [void]
46
- def execute
47
- generate_report
48
- upload
42
+ @report_path = args[:output]
49
43
  end
50
44
 
51
45
  # Generate allure report
52
46
  #
53
47
  # @return [void]
54
- def generate_report
48
+ def generate_report(extra_arguments = [])
55
49
  add_history
56
50
  add_executor_info
57
51
 
58
- report_generator.generate
52
+ report_generator.generate(extra_arguments)
59
53
  end
60
54
 
61
55
  # Upload report to storage provider
@@ -98,7 +92,8 @@ module Publisher
98
92
  :base_url,
99
93
  :copy_latest,
100
94
  :report_name,
101
- :parallel
95
+ :parallel,
96
+ :report_path
102
97
 
103
98
  def_delegator :report_generator, :common_info_path
104
99
 
@@ -159,7 +154,7 @@ module Publisher
159
154
  #
160
155
  # @return [Publisher::ReportGenerator]
161
156
  def report_generator
162
- @report_generator ||= ReportGenerator.new(result_paths, report_name)
157
+ @report_generator ||= ReportGenerator.new(result_paths, report_name, report_path)
163
158
  end
164
159
 
165
160
  # Report path prefix
@@ -218,7 +213,7 @@ module Publisher
218
213
  end
219
214
  end
220
215
 
221
- # Fetch allure report history
216
+ # Create allure report history dir
222
217
  #
223
218
  # @return [void]
224
219
  def create_history_dir
@@ -0,0 +1,122 @@
1
+ module Publisher
2
+ module Uploaders
3
+ # Uploads artifacts to GitLab
4
+ #
5
+ class GitlabArtifacts < Uploader
6
+ extend Forwardable
7
+
8
+ def initialize(**args)
9
+ super
10
+
11
+ # gitlab artifacts do not support having url to latest report
12
+ @copy_latest = false
13
+ end
14
+
15
+ # Report url
16
+ #
17
+ # @return [String]
18
+ def report_url
19
+ @report_url ||= "https://#{pages_hostname}/-/#{project_name}/-/jobs/#{job_id}/artifacts/#{report_path}/index.html"
20
+ end
21
+
22
+ # No-op method as gitlab does not expose api to upload artifacts
23
+ #
24
+ # @return [void]
25
+ def upload
26
+ raise("Gitlab artifacts does not support upload operation! Report upload must be configured in the CI job.")
27
+ end
28
+
29
+ private
30
+
31
+ def_delegators :ci_info,
32
+ :pages_hostname,
33
+ :project_name,
34
+ :project_id,
35
+ :job_name,
36
+ :job_id,
37
+ :branch,
38
+ :build_dir,
39
+ :build_name,
40
+ :server_url,
41
+ :client
42
+
43
+ # Download allure history
44
+ #
45
+ # @return [void]
46
+ def download_history
47
+ log_debug("Downloading allure history from previous executions")
48
+
49
+ unless previous_job_id
50
+ log_debug("Previous execution not found, skipping history download")
51
+ return
52
+ end
53
+
54
+ log_debug("Fetching history from artifacts of job: #{previous_job_id}")
55
+ HISTORY.each do |file_name|
56
+ download_artifact_file(
57
+ previous_job_id,
58
+ "#{report_path}/history/#{file_name}",
59
+ path(common_info_path, "history", file_name)
60
+ )
61
+ end
62
+ end
63
+
64
+ # Last job from previous pipeline
65
+ #
66
+ # @return [Integer, nil] job id or nil if not found
67
+ def previous_job_id
68
+ return @previous_job_id if defined?(@previous_job_id)
69
+
70
+ log_debug("Fetching previous pipelines for ref: #{branch}")
71
+ pipelines = client.pipelines(
72
+ project_id,
73
+ ref: branch,
74
+ per_page: 50
75
+ ).map(&:id)
76
+ return @previous_pipeline_job_id = nil if pipelines.size < 2
77
+
78
+ previous_pipeline_index = pipelines.index(run_id) + 1
79
+ return @previous_job_id = nil if previous_pipeline_index >= pipelines.size
80
+
81
+ log_debug("Fetching last job id from pipeline: #{pipelines[previous_pipeline_index]}")
82
+ @previous_job_id = client.pipeline_jobs(
83
+ project_id,
84
+ pipelines[previous_pipeline_index],
85
+ scope: %w[success failed]
86
+ ).find { |job| job.name == build_name }&.id
87
+ end
88
+
89
+ # Current ref pipelines
90
+ #
91
+ # @return [Array<Hash>]
92
+ def pipelines
93
+ @pipelines ||= client.pipelines(project_id, ref: branch, per_page: 10)
94
+ end
95
+
96
+ def latest_job
97
+ @latest_job ||= pipelines.max_by(&:id)
98
+ end
99
+
100
+ # CI info
101
+ #
102
+ # @return [Providers::Info::Gitlab]
103
+ def ci_info
104
+ Providers::Info::Gitlab.instance
105
+ end
106
+
107
+ # Download specific artifact file
108
+ #
109
+ # @param job_id [Integer] job id
110
+ # @param artifact_path [String] path within artifacts
111
+ # @param local_path [String] local file path to save
112
+ # @return [void]
113
+ def download_artifact_file(job_id, artifact_path, local_path)
114
+ log_debug("Downloading artifact file: #{artifact_path} to #{local_path}")
115
+ # this will only work with history json files, see: https://github.com/NARKOZ/gitlab/issues/621
116
+ response = client.download_job_artifact_file(project_id, job_id, artifact_path)
117
+
118
+ File.write(local_path, response.to_json)
119
+ end
120
+ end
121
+ end
122
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Publisher
4
- VERSION = "4.5.0"
4
+ VERSION = "4.7.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: allure-report-publisher
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.5.0
4
+ version: 4.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrejs Cunskis
@@ -18,7 +18,7 @@ dependencies:
18
18
  version: 1.93.1
19
19
  - - "<"
20
20
  - !ruby/object:Gem::Version
21
- version: 1.184.0
21
+ version: 1.197.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -28,7 +28,7 @@ dependencies:
28
28
  version: 1.93.1
29
29
  - - "<"
30
30
  - !ruby/object:Gem::Version
31
- version: 1.184.0
31
+ version: 1.197.0
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: dry-cli
34
34
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +38,7 @@ dependencies:
38
38
  version: '0.6'
39
39
  - - "<"
40
40
  - !ruby/object:Gem::Version
41
- version: '1.3'
41
+ version: '1.4'
42
42
  type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
@@ -48,7 +48,7 @@ dependencies:
48
48
  version: '0.6'
49
49
  - - "<"
50
50
  - !ruby/object:Gem::Version
51
- version: '1.3'
51
+ version: '1.4'
52
52
  - !ruby/object:Gem::Dependency
53
53
  name: faraday-retry
54
54
  requirement: !ruby/object:Gem::Requirement
@@ -240,6 +240,7 @@ files:
240
240
  - lib/allure_report_publisher/lib/report_generator.rb
241
241
  - lib/allure_report_publisher/lib/uploaders/_uploader.rb
242
242
  - lib/allure_report_publisher/lib/uploaders/gcs.rb
243
+ - lib/allure_report_publisher/lib/uploaders/gitlab_artifacts.rb
243
244
  - lib/allure_report_publisher/lib/uploaders/s3.rb
244
245
  - lib/allure_report_publisher/version.rb
245
246
  homepage: https://github.com/andrcuns/allure-report-uploader
@@ -265,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
265
266
  - !ruby/object:Gem::Version
266
267
  version: '0'
267
268
  requirements: []
268
- rubygems_version: 3.6.7
269
+ rubygems_version: 3.6.9
269
270
  specification_version: 4
270
271
  summary: Allure report uploader
271
272
  test_files: []