allure-report-publisher 0.0.3 → 0.1.1

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: 818cdc599b432cb8484e95662881253a9f0df4265eb742f3f56f459ecbe57dfd
4
- data.tar.gz: a261391b7851b0305883c6cd15a9789854051b30d39184728235641f881fe3fa
3
+ metadata.gz: 9bb81eada76c7024e4a570187d02e2383677552daef81b14e1e1457ca2fbc6be
4
+ data.tar.gz: 27db25caad167473b073a6057f82981d648889d800c3fddb879c3c046d5dc951
5
5
  SHA512:
6
- metadata.gz: 9e8ea6e47d729b8e484c660a5add949546662deb3d339caf6d95b4e45c5970db7137375cf3dd67764f5dcb7e9b78859eb52f8dfc3da0e5dedbcb7d346a5f5e26
7
- data.tar.gz: dec6eec389f65663b7b6f7531796e0e7c0a39a2137e5f94c0dd881e87284ca31b6a268462a7dca99909250b91b911f250e378319dcb3b97930078eaa22b858c9
6
+ metadata.gz: 5b3d2e2a7faa93ad323cb24ea892aeb3601c904e30c4fdadaf78732bd903945c7ba2e488440bb5a1d834e0ec62a1616c83aea48e697596edd02d271fcf8d0719
7
+ data.tar.gz: 400d890b0e1b315d1aab1a246482a31849a38c3a78b231310ffc285b5fd14d677ee3b3badfcf098f9f15d982091f7d85dac6642f5e6b0d0bd2f7e1b5f1509510
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,35 +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
34
  - `Allure report link`: requires `GITHUB_AUTH_TOKEN` or `GITLAB_AUTH_TOKEN` in order to update pull request description with link to latest report
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
49
- --[no-]update-pr # Update pull request description with url to allure report, default: false
50
- --result-files-glob=VALUE # Allure results files glob. Required: true
51
- --bucket=VALUE # Bucket name. Required: true
52
- --prefix=VALUE # Optional prefix for report path. Required: false
53
- --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
54
58
 
55
59
  Examples:
56
- allure-report-publisher upload s3 --result-files-glob='path/to/allure-result/**/*' --bucket=my-bucket
57
- allure-report-publisher upload s3 --result-files-glob='path/to/allure-result/**/*' --bucket=my-bucket --project=my-project/prs
60
+ allure-report-publisher upload s3 --results-glob='path/to/allure-result/**/*' --bucket=my-bucket
61
+ allure-report-publisher upload gcs --results-glob='path/to/allure-result/**/*' --bucket=my-bucket --prefix=my-project/prs
58
62
  ```
59
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
+
60
89
  ## Development
61
90
 
62
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
@@ -0,0 +1,174 @@
1
+ module Publisher
2
+ # Namespace for providers executing tests
3
+ #
4
+ module Providers
5
+ # Detect CI provider
6
+ #
7
+ # @return [Publisher::Providers::Base]
8
+ def self.provider
9
+ return Github if ENV["GITHUB_WORKFLOW"]
10
+ return Gitlab if ENV["GITLAB_CI"]
11
+ end
12
+
13
+ # Base class for CI executor info
14
+ #
15
+ class Provider
16
+ DESCRIPTION_PATTERN = /<!-- allure -->[\s\S]+<!-- allurestop -->/.freeze
17
+ ALLURE_JOB_NAME = "ALLURE_JOB_NAME".freeze
18
+
19
+ def initialize(report_url:, update_pr:)
20
+ @report_url = report_url
21
+ @update_pr = update_pr
22
+ end
23
+
24
+ # :nocov:
25
+
26
+ # Get ci run ID without creating instance of ci provider
27
+ #
28
+ # @return [String]
29
+ def self.run_id
30
+ raise("Not implemented!")
31
+ end
32
+
33
+ # Get executor info
34
+ #
35
+ # @return [Hash]
36
+ def executor_info
37
+ raise("Not implemented!")
38
+ end
39
+ # :nocov:
40
+
41
+ # Add report url to pull request description
42
+ #
43
+ # @return [void]
44
+ def add_report_url
45
+ raise("Not a pull request, skipped!") unless pr?
46
+ return add_comment if comment?
47
+
48
+ update_pr_description
49
+ end
50
+
51
+ # :nocov:
52
+
53
+ # Pull request run
54
+ #
55
+ # @return [Boolean]
56
+ def pr?
57
+ raise("Not implemented!")
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :report_url, :update_pr
63
+
64
+ # Current pull request description
65
+ #
66
+ # @return [String]
67
+ def pr_description
68
+ raise("Not implemented!")
69
+ end
70
+
71
+ # Update pull request description
72
+ #
73
+ # @return [void]
74
+ def update_pr_description
75
+ raise("Not implemented!")
76
+ end
77
+
78
+ # Add comment with report url
79
+ #
80
+ # @return [void]
81
+ def add_comment
82
+ raise("Not implemented!")
83
+ end
84
+
85
+ # Commit SHA url
86
+ #
87
+ # @return [String]
88
+ def sha_url
89
+ raise("Not implemented!")
90
+ end
91
+ # :nocov:
92
+
93
+ # Add report url as comment
94
+ #
95
+ # @return [Boolean]
96
+ def comment?
97
+ update_pr == "comment"
98
+ end
99
+
100
+ # CI run id
101
+ #
102
+ # @return [String]
103
+ def run_id
104
+ self.class.run_id
105
+ end
106
+
107
+ # Check if PR already has report urls
108
+ #
109
+ # @return [Boolean]
110
+ def reported?
111
+ @reported ||= pr_description.match?(DESCRIPTION_PATTERN)
112
+ end
113
+
114
+ # Full PR description
115
+ #
116
+ # @return [String]
117
+ def updated_pr_description
118
+ reported? ? existing_pr_description : initial_pr_descripion
119
+ end
120
+
121
+ # Updated PR description
122
+ #
123
+ # @return [String]
124
+ def existing_pr_description
125
+ pr_description.gsub(DESCRIPTION_PATTERN, pr_body).strip
126
+ end
127
+
128
+ # Initial PR description
129
+ #
130
+ # @return [String]
131
+ def initial_pr_descripion
132
+ "#{pr_description}\n\n#{pr_body}".strip
133
+ end
134
+
135
+ # Heading for report urls
136
+ #
137
+ # @return [String]
138
+ def heading
139
+ @heading ||= <<~HEADING.strip
140
+ # Allure report
141
+ `allure-report-publisher` generated allure report for #{sha_url}!
142
+ HEADING
143
+ end
144
+
145
+ # Allure report url pr description
146
+ #
147
+ # @return [String]
148
+ def pr_body
149
+ @pr_body ||= <<~DESC
150
+ <!-- allure -->
151
+ ---
152
+ #{heading}
153
+
154
+ #{job_entry}
155
+ <!-- allurestop -->
156
+ DESC
157
+ end
158
+
159
+ # Allure report url comment body
160
+ #
161
+ # @return [String]
162
+ def comment_body
163
+ @comment_body ||= pr_body.gsub("---\n", "")
164
+ end
165
+
166
+ # Single job report URL entry
167
+ #
168
+ # @return [String]
169
+ def job_entry
170
+ @job_entry ||= "**#{build_name}**: 📝 [allure report](#{report_url})"
171
+ end
172
+ end
173
+ end
174
+ 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: updated_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, comment_body) unless comment
69
+
70
+ client.update_comment(repository, comment[:id], 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
+ comment[:body].match?(DESCRIPTION_PATTERN)
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