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 +4 -4
- data/README.md +34 -7
- data/lib/allure_report_publisher/commands/upload.rb +76 -23
- data/lib/allure_report_publisher/lib/helpers/helpers.rb +12 -0
- data/lib/allure_report_publisher/lib/helpers/spinner.rb +13 -6
- data/lib/allure_report_publisher/lib/providers/github.rb +2 -12
- data/lib/allure_report_publisher/lib/providers/gitlab.rb +2 -15
- data/lib/allure_report_publisher/lib/providers/info/_base.rb +7 -0
- data/lib/allure_report_publisher/lib/providers/info/github.rb +11 -0
- data/lib/allure_report_publisher/lib/providers/info/gitlab.rb +67 -7
- data/lib/allure_report_publisher/lib/report_generator.rb +10 -10
- data/lib/allure_report_publisher/lib/uploaders/_uploader.rb +8 -13
- data/lib/allure_report_publisher/lib/uploaders/gitlab_artifacts.rb +122 -0
- data/lib/allure_report_publisher/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 383b5a328cf9acc9c7ef65bf6e63f807d936dc38a4125e908a5ea6c29ac6df18
|
4
|
+
data.tar.gz: 4348a6696f84c9c2fa5c36584b7e8e4313db19965ae2b182aeba8087a2520dc5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1b0faa886ce9d3ee4ccb0e3d3459190121b40fc136571476caa859f66480e2284d10b38570fea07ace0284b4fd711db114c4151968cdc95882c54b10e11c452
|
7
|
+
data.tar.gz: 710dc295a857b1fdc771f46e9a8c51b018f5832e43fc2e78fd5a9f800c5bfbf3b1326e0c0ae4aea02fd19b577a24dc18d2aedb988f634bda3c9c05fe8b1d2f6e
|
data/README.md
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
[](https://hub.docker.com/r/andrcuns/allure-report-publisher)
|
4
4
|
[](https://hub.docker.com/r/andrcuns/allure-report-publisher)
|
5
5
|

|
6
|
-
[](https://codeclimate.com/github/andrcuns/allure-report-publisher/maintainability)
|
7
|
-
[](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/
|
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
|
-
--
|
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:
|
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(**
|
90
|
-
Helpers.pastel(force_color:
|
91
|
-
@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
|
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:
|
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
|
-
|
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
|
-
|
157
|
-
|
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
|
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
|
-
|
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(
|
28
|
-
|
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 = [
|
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
|
#
|
@@ -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 [
|
49
|
+
# @return [Integer]
|
36
50
|
def run_id
|
37
|
-
@run_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 ||
|
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 [
|
123
|
+
# @return [Integer]
|
71
124
|
def allure_mr_iid
|
72
|
-
@allure_mr_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) ||
|
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
|
-
#
|
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
|
-
|
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
|
-
#
|
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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
269
|
+
rubygems_version: 3.6.9
|
269
270
|
specification_version: 4
|
270
271
|
summary: Allure report uploader
|
271
272
|
test_files: []
|