allure-report-publisher 0.0.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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