allure-report-publisher 0.0.4 → 0.2.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: f0a1bb3d8d9d7a22c080bcb2ce71fcf4d082d49b8ffd528fb3ef409d4afbf0ef
4
- data.tar.gz: 992e16c2cb4ee7feabefd9250efb13f824804e2a30bec5c6f031666f41e8f9a9
3
+ metadata.gz: 4b5ab2c7fe9d71734c9f57324a411d2dfb3034a63152e75a3827f3629375371b
4
+ data.tar.gz: 56296208184a82b42bfb04c7132788e6b4f924be16c4059a4e03e6782f9f54f2
5
5
  SHA512:
6
- metadata.gz: 9806755fe1c216f8c590e183e0b667060a92017d42991a65663ed74aa8519d8e390e2eafe6dd35d67dacd0f40df3e1c75feab23498869073fe343d2514c02767
7
- data.tar.gz: 6a04f0503833d6378c3f4923b159a2567e8b3a9fc3ee642825ec45ef921d514616a2b93c39d50204cd29573dc88723b4ef2c47f9d3c05a30942dff63f6d91433
6
+ metadata.gz: 60889df0f7995284adc34651a042f90f29a0a32f93895636b991205eafc078f696dd9f0117f28e3d85b111bf0d7fe84c4daa5a89f95a5cf4a295547a20c9c8b9
7
+ data.tar.gz: 0a5c6206ed052dd912b57e524190209993d5e58435a5ce4a28d3a1117fd4bc1191b6ae23d441ab2ec98588518bb18bba7aa9b3a9a2b6ed6fdd6c42480d0614ec
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  [![Gem Version](https://img.shields.io/gem/v/allure-report-publisher?color=red)](https://rubygems.org/gems/allure-report-publisher)
2
+ [![Gem Pulls](https://img.shields.io/gem/dt/allure-report-publisher)](https://rubygems.org/gems/allure-report-publisher)
2
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
+ [![Docker Pulls](https://img.shields.io/docker/pulls/andrcuns/allure-report-publisher)](https://hub.docker.com/r/andrcuns/allure-report-publisher)
3
5
  ![Workflow status](https://github.com/andrcuns/allure-report-publisher/workflows/Test/badge.svg)
6
+ [![Test Report](https://img.shields.io/badge/report-allure-blue.svg)](https://storage.googleapis.com/allure-test-reports/allure-report-publisher/refs/heads/main/index.html)
4
7
  [![Maintainability](https://api.codeclimate.com/v1/badges/210eaa4f74588fb08313/maintainability)](https://codeclimate.com/github/andrcuns/allure-report-publisher/maintainability)
5
8
  [![Test Coverage](https://api.codeclimate.com/v1/badges/210eaa4f74588fb08313/test_coverage)](https://codeclimate.com/github/andrcuns/allure-report-publisher/test_coverage)
6
9
 
@@ -28,36 +31,61 @@ docker pull andrcuns/allure-report-publisher:latest
28
31
 
29
32
  allure-report-publisher will automatically detect if used in CI environment and add relevant executor info and history
30
33
 
31
- ### AWS S3
32
-
33
- - `AWS authentication`: requires environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` or credentials file `~/.aws/credentials`
34
- - `Allure report link`: requires `GITHUB_AUTH_TOKEN` or `GITLAB_AUTH_TOKEN` in order to update pull request description with link to latest report
34
+ - `--update-pr=(comment|description)`: requires `GITHUB_AUTH_TOKEN` or `GITLAB_AUTH_TOKEN` in order to update pull request with links to allure reports
35
35
 
36
36
  ```shell
37
- $ (allure-report-publisher|docker run --rm andrcuns/allure-report-publisher:latest) upload s3 --help
37
+ $ (allure-report-publisher|docker run --rm andrcuns/allure-report-publisher:latest) upload --help
38
38
  Command:
39
- allure-report-publisher upload s3
39
+ allure-report-publisher upload
40
40
 
41
41
  Usage:
42
- allure-report-publisher upload s3
42
+ allure-report-publisher upload TYPE
43
43
 
44
44
  Description:
45
45
  Generate and upload allure report
46
46
 
47
+ Arguments:
48
+ TYPE # REQUIRED Cloud storage type: (s3/gcs)
49
+
47
50
  Options:
48
- --[no-]color # Toggle color output, default: false
49
- --[no-]update-pr # Update pull request description with url to allure report, default: false
50
- --[no-]copy-latest # Keep copy of latest report at base prefix path, default: false
51
- --results-glob=VALUE # Allure results files glob. Required: true
52
- --bucket=VALUE # Bucket name. Required: true
53
- --prefix=VALUE # Optional prefix for report path. Required: false
54
- --help, -h # Print this help
51
+ --results-glob=VALUE # Allure results files glob. Required: true
52
+ --bucket=VALUE # Bucket name. Required: true
53
+ --prefix=VALUE # Optional prefix for report path. Required: false
54
+ --update-pr=VALUE # Add report url to PR via comment or description update. Required: false: (comment/description)
55
+ --[no-]copy-latest # Keep copy of latest report at base prefix path, default: false
56
+ --[no-]color # Toggle color output, default: false
57
+ --help, -h # Print this help
55
58
 
56
59
  Examples:
57
60
  allure-report-publisher upload s3 --results-glob='path/to/allure-result/**/*' --bucket=my-bucket
58
- allure-report-publisher upload s3 --results-glob='path/to/allure-result/**/*' --bucket=my-bucket --project=my-project/prs
61
+ allure-report-publisher upload gcs --results-glob='path/to/allure-result/**/*' --bucket=my-bucket --prefix=my-project/prs
59
62
  ```
60
63
 
64
+ ### AWS S3
65
+
66
+ Requires environment variables `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` or credentials file `~/.aws/credentials`
67
+
68
+ ### Google Cloud Storage
69
+
70
+ Requires on of the following environment variables.
71
+
72
+ credentials.json file location:
73
+
74
+ - `STORAGE_CREDENTIALS`
75
+ - `STORAGE_KEYFILE`
76
+ - `GOOGLE_CLOUD_CREDENTIALS`
77
+ - `GOOGLE_CLOUD_KEYFILE`
78
+ - `GCLOUD_KEYFILE`
79
+
80
+ credentials.json contents:
81
+
82
+ - `GOOGLE_CLOUD_CREDENTIALS_JSON`
83
+ - `STORAGE_CREDENTIALS_JSON`
84
+ - `STORAGE_KEYFILE_JSON`
85
+ - `GOOGLE_CLOUD_CREDENTIALS_JSON`
86
+ - `GOOGLE_CLOUD_KEYFILE_JSON`
87
+ - `GCLOUD_KEYFILE_JSON`
88
+
61
89
  ## Development
62
90
 
63
91
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -14,11 +14,8 @@ module Publisher
14
14
  extend Dry::CLI::Registry
15
15
 
16
16
  register "version", Version, aliases: ["-v", "--version"]
17
-
18
- register "upload" do |prefix|
19
- prefix.register "s3", UploadS3
20
- end
17
+ register "upload", Upload, aliases: ["u"]
21
18
  end
22
19
  end
23
20
 
24
- Publisher::Commands.before("upload s3") { Publisher::Helpers.validate_allure_cli_present }
21
+ Publisher::Commands.before("upload") { Publisher::Helpers.validate_allure_cli_present }
@@ -0,0 +1,90 @@
1
+ module Publisher
2
+ module Commands
3
+ # Upload allure report
4
+ #
5
+ class Upload < Dry::CLI::Command
6
+ include Helpers
7
+
8
+ desc "Generate and upload allure report"
9
+
10
+ argument :type,
11
+ type: :string,
12
+ required: true,
13
+ values: %w[s3 gcs],
14
+ desc: "Cloud storage type"
15
+
16
+ option :results_glob,
17
+ desc: "Allure results files glob. Required: true"
18
+ option :bucket,
19
+ desc: "Bucket name. Required: true"
20
+ option :prefix,
21
+ desc: "Optional prefix for report path. Required: false"
22
+ option :update_pr,
23
+ type: :string,
24
+ values: %w[comment description],
25
+ desc: "Add report url to PR via comment or description update. Required: false"
26
+ option :copy_latest,
27
+ type: :boolean,
28
+ default: false,
29
+ desc: "Keep copy of latest report at base prefix path"
30
+ option :color,
31
+ type: :boolean,
32
+ default: false,
33
+ desc: "Toggle color output"
34
+
35
+ example [
36
+ "s3 --results-glob='path/to/allure-result/**/*' --bucket=my-bucket",
37
+ "gcs --results-glob='path/to/allure-result/**/*' --bucket=my-bucket --prefix=my-project/prs"
38
+ ]
39
+
40
+ def call(**args)
41
+ validate_args(args)
42
+ validate_result_files(args[:results_glob])
43
+ Helpers.pastel(force_color: args[:color] || nil)
44
+
45
+ uploader = uploaders(args[:type]).new(**args.slice(:results_glob, :bucket, :prefix, :copy_latest, :update_pr))
46
+
47
+ log("Generating allure report")
48
+ Spinner.spin("generating") { uploader.generate_report }
49
+
50
+ log("Uploading allure report to #{args[:type]}")
51
+ Spinner.spin("uploading") { uploader.upload }
52
+ uploader.report_urls.each { |k, v| log("#{k}: #{v}", :green) }
53
+ return unless args[:update_pr] && uploader.pr?
54
+
55
+ log("Adding reports urls")
56
+ Spinner.spin("updating", exit_on_error: false) { uploader.add_url_to_pr }
57
+ end
58
+
59
+ private
60
+
61
+ # Uploader class
62
+ #
63
+ # @param [String] uploader
64
+ # @return [Publisher::Uploaders::Uploader]
65
+ def uploaders(uploader)
66
+ {
67
+ "s3" => Uploaders::S3,
68
+ "gcs" => Uploaders::GCS
69
+ }[uploader]
70
+ end
71
+
72
+ # Validate required args
73
+ #
74
+ # @param [Hash] args
75
+ # @return [void]
76
+ def validate_args(args)
77
+ error("Missing argument --results-glob!") unless args[:results_glob]
78
+ error("Missing argument --bucket!") unless args[:bucket]
79
+ end
80
+
81
+ # Check if allure results present
82
+ #
83
+ # @param [String] results_glob
84
+ # @return [void]
85
+ def validate_result_files(results_glob)
86
+ Dir.glob(results_glob).empty? && error("Glob '#{results_glob}' did not match any files!")
87
+ end
88
+ end
89
+ end
90
+ end
@@ -10,7 +10,7 @@ module Publisher
10
10
  # @param [Boolean] force_color
11
11
  # @return [Pastel]
12
12
  def self.pastel(force_color: nil)
13
- @pastel ||= Pastel.new(enabled: force_color)
13
+ @pastel ||= Pastel.new(enabled: force_color, eachline: "\n")
14
14
  end
15
15
 
16
16
  # Check allure cli is installed and executable
@@ -99,7 +99,7 @@ module Publisher
99
99
  # @param [String] error_message
100
100
  # @return [void]
101
101
  def spinner_error(error_message)
102
- colored_message = colorize(error_message, error_color)
102
+ colored_message = colorize("failed\n#{error_message}", error_color)
103
103
  return spinner.error(colored_message) if tty?
104
104
 
105
105
  spinner.stop
@@ -12,13 +12,12 @@ module Publisher
12
12
 
13
13
  # Base class for CI executor info
14
14
  #
15
- class Base
16
- EXECUTOR_JSON = "executor.json".freeze
17
- DESCRIPTION_PATTERN = /<!-- allure -->[\s\S]+<!-- allurestop -->/.freeze
15
+ class Provider
16
+ ALLURE_JOB_NAME = "ALLURE_JOB_NAME".freeze
18
17
 
19
- def initialize(results_path, report_url)
20
- @results_path = results_path
18
+ def initialize(report_url:, update_pr:)
21
19
  @report_url = report_url
20
+ @update_pr = update_pr
22
21
  end
23
22
 
24
23
  # :nocov:
@@ -29,42 +28,27 @@ module Publisher
29
28
  def self.run_id
30
29
  raise("Not implemented!")
31
30
  end
32
- # :nocov:
33
31
 
34
- # Write executor info file
32
+ # Get executor info
35
33
  #
36
- # @return [void]
37
- def write_executor_info
38
- File.open("#{results_path}/#{EXECUTOR_JSON}", "w") do |file|
39
- file.write(executor_info.to_json)
40
- end
34
+ # @return [Hash]
35
+ def executor_info
36
+ raise("Not implemented!")
41
37
  end
38
+ # :nocov:
42
39
 
43
40
  # Add report url to pull request description
44
41
  #
45
42
  # @return [void]
46
43
  def add_report_url
47
44
  raise("Not a pull request, skipped!") unless pr?
45
+ return add_comment if comment?
48
46
 
49
- reported = pr_description.match?(DESCRIPTION_PATTERN)
50
- return update_pr_description(pr_description.gsub(DESCRIPTION_PATTERN, description_template).strip) if reported
51
-
52
- update_pr_description("#{pr_description}\n\n#{description_template}".strip)
47
+ update_pr_description
53
48
  end
54
49
 
55
- private
56
-
57
- attr_reader :results_path, :report_url
58
-
59
50
  # :nocov:
60
51
 
61
- # Get executor info
62
- #
63
- # @return [Hash]
64
- def executor_info
65
- raise("Not implemented!")
66
- end
67
-
68
52
  # Pull request run
69
53
  #
70
54
  # @return [Boolean]
@@ -72,6 +56,10 @@ module Publisher
72
56
  raise("Not implemented!")
73
57
  end
74
58
 
59
+ private
60
+
61
+ attr_reader :report_url, :update_pr
62
+
75
63
  # Current pull request description
76
64
  #
77
65
  # @return [String]
@@ -81,9 +69,29 @@ module Publisher
81
69
 
82
70
  # Update pull request description
83
71
  #
84
- # @param [String] _desc
85
72
  # @return [void]
86
- def update_pr_description(_desc)
73
+ def update_pr_description
74
+ raise("Not implemented!")
75
+ end
76
+
77
+ # Add comment with report url
78
+ #
79
+ # @return [void]
80
+ def add_comment
81
+ raise("Not implemented!")
82
+ end
83
+
84
+ # Build name
85
+ #
86
+ # @return [String]
87
+ def build_name
88
+ raise("Not implemented!")
89
+ end
90
+
91
+ # Commit SHA url
92
+ #
93
+ # @return [String]
94
+ def sha_url
87
95
  raise("Not implemented!")
88
96
  end
89
97
  # :nocov:
@@ -95,16 +103,18 @@ module Publisher
95
103
  self.class.run_id
96
104
  end
97
105
 
98
- # Allure report url pr description
106
+ # Add report url as comment
99
107
  #
100
- # @return [String]
101
- def description_template
102
- <<~DESC
103
- <!-- allure -->
104
- ---
105
- 📝 [Latest allure report](#{report_url})
106
- <!-- allurestop -->
107
- DESC
108
+ # @return [Boolean]
109
+ def comment?
110
+ update_pr == "comment"
111
+ end
112
+
113
+ # Report urls section creator
114
+ #
115
+ # @return [ReportUrls]
116
+ def report_urls
117
+ @report_urls ||= UrlSectionBuilder.new(report_url: report_url, build_name: build_name, sha_url: sha_url)
108
118
  end
109
119
  end
110
120
  end
@@ -4,7 +4,13 @@ module Publisher
4
4
  module Providers
5
5
  # Github implementation
6
6
  #
7
- class Github < Base
7
+ class Github < Provider
8
+ # Set octokit to autopaginate
9
+ #
10
+ Octokit.configure do |config|
11
+ config.auto_paginate = true
12
+ end
13
+
8
14
  # Run id
9
15
  #
10
16
  # @return [String]
@@ -12,7 +18,12 @@ module Publisher
12
18
  @run_id ||= ENV["GITHUB_RUN_ID"]
13
19
  end
14
20
 
15
- private
21
+ # Pull request run
22
+ #
23
+ # @return [Boolean]
24
+ def pr?
25
+ ENV["GITHUB_EVENT_NAME"] == "pull_request"
26
+ end
16
27
 
17
28
  # Executor info
18
29
  #
@@ -30,6 +41,8 @@ module Publisher
30
41
  }
31
42
  end
32
43
 
44
+ private
45
+
33
46
  # Github api client
34
47
  #
35
48
  # @return [Octokit::Client]
@@ -41,11 +54,36 @@ module Publisher
41
54
  end
42
55
  end
43
56
 
44
- # Pull request run
57
+ # Update pull request description
45
58
  #
46
- # @return [Boolean]
47
- def pr?
48
- ENV["GITHUB_EVENT_NAME"] == "pull_request"
59
+ # @return [void]
60
+ def update_pr_description
61
+ client.update_pull_request(repository, pr_id, body: report_urls.updated_pr_description(pr_description))
62
+ end
63
+
64
+ # Add comment with report url
65
+ #
66
+ # @return [void]
67
+ def add_comment
68
+ return client.add_comment(repository, pr_id, report_urls.comment_body) unless comment
69
+
70
+ client.update_comment(repository, comment[:id], report_urls.comment_body(comment[:body]))
71
+ end
72
+
73
+ # Existing comment with allure urls
74
+ #
75
+ # @return [Sawyer::Resource]
76
+ def comment
77
+ @comment ||= client.issue_comments(repository, pr_id).detect do |comment|
78
+ UrlSectionBuilder.match?(comment[:body])
79
+ end
80
+ end
81
+
82
+ # Github event
83
+ #
84
+ # @return [Hash]
85
+ def github_event
86
+ @github_event ||= JSON.parse(File.read(ENV["GITHUB_EVENT_PATH"]), symbolize_names: true)
49
87
  end
50
88
 
51
89
  # Pull request description
@@ -55,19 +93,11 @@ module Publisher
55
93
  @pr_description ||= client.pull_request(repository, pr_id)[:body]
56
94
  end
57
95
 
58
- # Update pull request description
59
- #
60
- # @param [String] _desc
61
- # @return [void]
62
- def update_pr_description(desc)
63
- client.update_pull_request(repository, pr_id, body: desc)
64
- end
65
-
66
96
  # Pull request id
67
97
  #
68
98
  # @return [Integer]
69
99
  def pr_id
70
- @pr_id ||= JSON.parse(File.read(ENV["GITHUB_EVENT_PATH"]))["number"]
100
+ @pr_id ||= github_event[:number]
71
101
  end
72
102
 
73
103
  # Server url
@@ -88,7 +118,7 @@ module Publisher
88
118
  #
89
119
  # @return [String]
90
120
  def build_name
91
- @build_name ||= ENV["GITHUB_JOB"]
121
+ @build_name ||= ENV[ALLURE_JOB_NAME] || ENV["GITHUB_JOB"]
92
122
  end
93
123
 
94
124
  # Github repository
@@ -97,6 +127,16 @@ module Publisher
97
127
  def repository
98
128
  @repository ||= ENV["GITHUB_REPOSITORY"]
99
129
  end
130
+
131
+ # Commit sha url
132
+ #
133
+ # @return [String]
134
+ def sha_url
135
+ sha = github_event.dig(:pull_request, :head, :sha)
136
+ short_sha = sha[0..7]
137
+
138
+ "[#{short_sha}](#{server_url}/#{repository}/pull/#{pr_id}/commits/#{sha})"
139
+ end
100
140
  end
101
141
  end
102
142
  end