marlens-jira-api 0.5.1 → 0.5.2
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 +5 -1
- data/lib/marlens/jira_api/cli.rb +23 -6
- data/lib/marlens/jira_api/client.rb +12 -6
- data/lib/marlens/jira_api/remote_image_attachment_uploader.rb +16 -1
- data/lib/marlens/jira_api/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 89d099771b89c4a51659eaca4c4242d7102762ec507e4d80265ce2e1612d756c
|
|
4
|
+
data.tar.gz: 93682e74950ac69b58316049b1251f61eb6f1a8eed75d7d14695585da4ad45d9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 20e4b6ecd4f692d4c9b699f1ed4d0a3fe2f3ae5be5de2bb7970c540efacdbd08ec45a9dd9384184fb38300b23d5ac07dd0adec482eb93025ec9f8d8d6e28ecfb
|
|
7
|
+
data.tar.gz: ad230b1e8235738fecc90762794c5e8ca2fd07f62fa3d551c2f47eca630177676c3d04e5af53e7d5f699f6ce1ce9ff511971b037cef1e01c663b21a08f2ae98c
|
data/README.md
CHANGED
|
@@ -50,6 +50,8 @@ jira-comment delete --issue-key WRAPX-123 --comment-id 10001
|
|
|
50
50
|
|
|
51
51
|
Remote Markdown image URLs are advanced opt-in behavior. Pass `allowed_image_hosts:` in Ruby or repeat `--image-host` in the CLI only when you intentionally want the gem to fetch images from trusted hosts, upload them to Jira, and convert them into Jira media attachments.
|
|
52
52
|
|
|
53
|
+
Ruby callers that need to detect degraded images can pass an array via `image_upload_failures:`. Add `strict_images: true` in Ruby or `--strict-images` in the CLI to raise `Marlens::JiraApi::ImageUploadError` instead of falling back to `Alt text: URL` when an image cannot be fetched or uploaded.
|
|
54
|
+
|
|
53
55
|
## Feature and Issue Workflow
|
|
54
56
|
|
|
55
57
|
Preferred flow for issue and feature work:
|
|
@@ -61,4 +63,6 @@ Preferred flow for issue and feature work:
|
|
|
61
63
|
5. Open a draft PR, link the issue, include the checks run, and mark it ready only after verification.
|
|
62
64
|
6. Merge the PR to `main` so GitHub records the review path.
|
|
63
65
|
7. After merge, build and publish the gem version to RubyGems with `gem build marlens-jira-api.gemspec` and `gem push marlens-jira-api-<version>.gem`.
|
|
64
|
-
8. Verify RubyGems lists the released version with `gem list --remote marlens-jira-api --exact --all
|
|
66
|
+
8. Verify RubyGems lists the released version with `gem list --remote marlens-jira-api --exact --all`; if that output is stale, verify the specific version API at `https://rubygems.org/api/v2/rubygems/marlens-jira-api/versions/<version>.json`.
|
|
67
|
+
9. Run an install or CLI smoke check against the published gem.
|
|
68
|
+
10. Keep one-off smoke cleanup helpers in `tmp/`, delete them before committing, and do not turn cleanup-only scripts into product API.
|
data/lib/marlens/jira_api/cli.rb
CHANGED
|
@@ -37,14 +37,14 @@ module Marlens
|
|
|
37
37
|
|
|
38
38
|
@out.puts JSON.pretty_generate(send(config.fetch(:action), options))
|
|
39
39
|
0
|
|
40
|
-
rescue OptionParser::ParseError, KeyError => error
|
|
40
|
+
rescue OptionParser::ParseError, KeyError, ImageUploadError => error
|
|
41
41
|
fail_with(error.message)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
private
|
|
45
45
|
|
|
46
46
|
def parse_options
|
|
47
|
-
options = { allowed_image_hosts: [] }
|
|
47
|
+
options = { allowed_image_hosts: [], strict_images: false }
|
|
48
48
|
parser = OptionParser.new do |parser|
|
|
49
49
|
parser.banner = "Usage: jira-comment [#{COMMANDS.keys.join("|")}] [options]"
|
|
50
50
|
parser.on("--issue-key ISSUE", "Jira issue key") { |value| options[:issue_key] = value }
|
|
@@ -53,6 +53,9 @@ module Marlens
|
|
|
53
53
|
parser.on("--image-host HOST", "Allowed remote image host; repeatable") do |value|
|
|
54
54
|
options[:allowed_image_hosts] << value
|
|
55
55
|
end
|
|
56
|
+
parser.on("--strict-images", "Fail create/update when a remote image cannot be uploaded") do
|
|
57
|
+
options[:strict_images] = true
|
|
58
|
+
end
|
|
56
59
|
end
|
|
57
60
|
parser.parse!(@argv)
|
|
58
61
|
options
|
|
@@ -67,20 +70,28 @@ module Marlens
|
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
def create_comment(options)
|
|
70
|
-
|
|
73
|
+
image_upload_failures = []
|
|
74
|
+
result = client.create_markdown_comment(
|
|
71
75
|
issue_key: options.fetch(:issue_key),
|
|
72
76
|
markdown: File.read(options.fetch(:markdown_file)),
|
|
73
|
-
allowed_image_hosts: options.fetch(:allowed_image_hosts)
|
|
77
|
+
allowed_image_hosts: options.fetch(:allowed_image_hosts),
|
|
78
|
+
strict_images: options.fetch(:strict_images),
|
|
79
|
+
image_upload_failures: image_upload_failures
|
|
74
80
|
)
|
|
81
|
+
result_with_image_failures(result, image_upload_failures)
|
|
75
82
|
end
|
|
76
83
|
|
|
77
84
|
def update_comment(options)
|
|
78
|
-
|
|
85
|
+
image_upload_failures = []
|
|
86
|
+
result = client.update_markdown_comment(
|
|
79
87
|
issue_key: options.fetch(:issue_key),
|
|
80
88
|
comment_id: options.fetch(:comment_id),
|
|
81
89
|
markdown: File.read(options.fetch(:markdown_file)),
|
|
82
|
-
allowed_image_hosts: options.fetch(:allowed_image_hosts)
|
|
90
|
+
allowed_image_hosts: options.fetch(:allowed_image_hosts),
|
|
91
|
+
strict_images: options.fetch(:strict_images),
|
|
92
|
+
image_upload_failures: image_upload_failures
|
|
83
93
|
)
|
|
94
|
+
result_with_image_failures(result, image_upload_failures)
|
|
84
95
|
end
|
|
85
96
|
|
|
86
97
|
def delete_comment(options)
|
|
@@ -88,6 +99,12 @@ module Marlens
|
|
|
88
99
|
{ deleted: true }
|
|
89
100
|
end
|
|
90
101
|
|
|
102
|
+
def result_with_image_failures(result, image_upload_failures)
|
|
103
|
+
return result if image_upload_failures.empty?
|
|
104
|
+
|
|
105
|
+
result.merge("image_upload_failures" => image_upload_failures)
|
|
106
|
+
end
|
|
107
|
+
|
|
91
108
|
def client
|
|
92
109
|
@client ||= @client_factory.call(env: @env)
|
|
93
110
|
end
|
|
@@ -54,20 +54,24 @@ module Marlens
|
|
|
54
54
|
raise "Failed to delete Jira comment #{comment_id} for #{issue_key}: #{response.code} #{response.body}"
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
-
def create_markdown_comment(issue_key:, markdown:, allowed_image_hosts: [])
|
|
57
|
+
def create_markdown_comment(issue_key:, markdown:, allowed_image_hosts: [], strict_images: false, image_upload_failures: nil)
|
|
58
58
|
document = markdown_document(
|
|
59
59
|
issue_key: issue_key,
|
|
60
60
|
markdown: markdown,
|
|
61
|
-
allowed_image_hosts: allowed_image_hosts
|
|
61
|
+
allowed_image_hosts: allowed_image_hosts,
|
|
62
|
+
strict_images: strict_images,
|
|
63
|
+
image_upload_failures: image_upload_failures
|
|
62
64
|
)
|
|
63
65
|
create_comment(issue_key: issue_key, document: document)
|
|
64
66
|
end
|
|
65
67
|
|
|
66
|
-
def update_markdown_comment(issue_key:, comment_id:, markdown:, allowed_image_hosts: [])
|
|
68
|
+
def update_markdown_comment(issue_key:, comment_id:, markdown:, allowed_image_hosts: [], strict_images: false, image_upload_failures: nil)
|
|
67
69
|
document = markdown_document(
|
|
68
70
|
issue_key: issue_key,
|
|
69
71
|
markdown: markdown,
|
|
70
|
-
allowed_image_hosts: allowed_image_hosts
|
|
72
|
+
allowed_image_hosts: allowed_image_hosts,
|
|
73
|
+
strict_images: strict_images,
|
|
74
|
+
image_upload_failures: image_upload_failures
|
|
71
75
|
)
|
|
72
76
|
update_comment(issue_key: issue_key, comment_id: comment_id, document: document)
|
|
73
77
|
end
|
|
@@ -94,11 +98,13 @@ module Marlens
|
|
|
94
98
|
|
|
95
99
|
private
|
|
96
100
|
|
|
97
|
-
def markdown_document(issue_key:, markdown:, allowed_image_hosts:)
|
|
101
|
+
def markdown_document(issue_key:, markdown:, allowed_image_hosts:, strict_images:, image_upload_failures:)
|
|
98
102
|
image_uploader = RemoteImageAttachmentUploader.new(
|
|
99
103
|
client: self,
|
|
100
104
|
issue_key: issue_key,
|
|
101
|
-
allowed_hosts: allowed_image_hosts
|
|
105
|
+
allowed_hosts: allowed_image_hosts,
|
|
106
|
+
strict: strict_images,
|
|
107
|
+
failures: image_upload_failures
|
|
102
108
|
)
|
|
103
109
|
MarkdownToAdf.call(markdown) do |image|
|
|
104
110
|
image_uploader.media_node_for(image)
|
|
@@ -7,13 +7,24 @@ require "uri"
|
|
|
7
7
|
|
|
8
8
|
module Marlens
|
|
9
9
|
module JiraApi
|
|
10
|
+
class ImageUploadError < StandardError
|
|
11
|
+
attr_reader :failure
|
|
12
|
+
|
|
13
|
+
def initialize(failure)
|
|
14
|
+
@failure = failure
|
|
15
|
+
super("Failed to upload image #{failure.fetch(:url)}: #{failure.fetch(:error_class)}: #{failure.fetch(:error_message)}")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
10
19
|
class RemoteImageAttachmentUploader
|
|
11
20
|
MAX_REDIRECTS = 5
|
|
12
21
|
|
|
13
|
-
def initialize(client:, issue_key:, allowed_hosts:)
|
|
22
|
+
def initialize(client:, issue_key:, allowed_hosts:, strict: false, failures: nil)
|
|
14
23
|
@allowed_hosts = allowed_hosts
|
|
15
24
|
@client = client
|
|
25
|
+
@failures = failures
|
|
16
26
|
@issue_key = issue_key
|
|
27
|
+
@strict = strict
|
|
17
28
|
end
|
|
18
29
|
|
|
19
30
|
def media_node_for(image)
|
|
@@ -27,6 +38,10 @@ module Marlens
|
|
|
27
38
|
height: image_dimension_value(image[:height], dimensions.fetch("height"))
|
|
28
39
|
)
|
|
29
40
|
rescue StandardError => error
|
|
41
|
+
failure = { url: image[:url], alt: image[:alt], error_class: error.class.name, error_message: error.message }
|
|
42
|
+
@failures << failure if @failures
|
|
43
|
+
raise ImageUploadError.new(failure) if @strict
|
|
44
|
+
|
|
30
45
|
warn "Failed to upload image #{image[:url]}: #{error.class}: #{error.message}"
|
|
31
46
|
MarkdownToAdf.paragraph("#{image[:alt] || "Image"}: #{image[:url]}")
|
|
32
47
|
end
|