newsman 0.1.8 → 0.1.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/newsman/html_output.rb +47 -0
- data/lib/newsman/report.rb +2 -2
- data/lib/newsman.rb +38 -8
- data/test/test_htmlout.rb +59 -0
- data/test/test_report.rb +1 -1
- metadata +33 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1183add95adc6b8574a0c0ffaa9dc50b472edaf3daa2219d9a48b4b0887c822e
|
4
|
+
data.tar.gz: a74b77f973ff3fee1d9ebd455ab13148d748d9dfa34ca4f328223957f3f672ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa81431ca58fe417bd8208ada0b642d121faa5c07f3b4633fe43fc12340e938d84688f23f4027d4eb7f9a491ce2f6105ab36a28f77db8248aca7a368623711f4
|
7
|
+
data.tar.gz: 8c03d5d177c3e9d9b2caf7add86e210429afd52a174506b8333466c80ac47a3e72b313d27a9c7be673914a9d10ce80b81ea2a46871173dd0590f47598176a3b6
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'redcarpet'
|
3
|
+
require 'nokogiri'
|
4
|
+
# frozen_string_literal: true
|
5
|
+
|
6
|
+
class Htmlout
|
7
|
+
|
8
|
+
TEMPLATE = "
|
9
|
+
<head>
|
10
|
+
<title><%= title %></title>
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
<h1><%= title %></h1>
|
14
|
+
<%= body %>
|
15
|
+
</body>
|
16
|
+
"
|
17
|
+
|
18
|
+
def initialize(root = '.')
|
19
|
+
@root = root
|
20
|
+
end
|
21
|
+
|
22
|
+
def print(report, reporter)
|
23
|
+
title = title(reporter)
|
24
|
+
renderer = Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true, prettify: true)
|
25
|
+
markdown = Redcarpet::Markdown.new(renderer, autolink: true, tables: true)
|
26
|
+
body = markdown.render(report)
|
27
|
+
renderer = ERB.new(TEMPLATE)
|
28
|
+
html_content = renderer.result(binding)
|
29
|
+
html_content = Nokogiri::HTML(html_content, &:noblanks).to_xhtml(indent: 2)
|
30
|
+
puts "Create a html file in a directory #{@root}"
|
31
|
+
file = File.new(File.join(@root, filename(reporter)), 'w')
|
32
|
+
puts "File #{file.path} was successfully created"
|
33
|
+
file.puts html_content
|
34
|
+
puts "Report was successfully printed to a #{file.path}"
|
35
|
+
file.close
|
36
|
+
end
|
37
|
+
|
38
|
+
def title(reporter)
|
39
|
+
date = Time.new.strftime('%d.%m.%Y')
|
40
|
+
"#{reporter} #{date}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def filename(reporter)
|
44
|
+
date = Time.new.strftime('%d.%m.%Y')
|
45
|
+
"#{date}.#{reporter}.html"
|
46
|
+
end
|
47
|
+
end
|
data/lib/newsman/report.rb
CHANGED
@@ -6,8 +6,8 @@ class Report
|
|
6
6
|
@position = position
|
7
7
|
@title = title
|
8
8
|
end
|
9
|
-
def build(achievements, plans, date)
|
10
|
-
return "From: #{@user}\nSubject: #{week_of_a_year(@title, date)}\n\nHi all,\n\nLast week achievements:\n#{achievements}\n\nNext week plans:\n#{plans}\n\nRisks:\n
|
9
|
+
def build(achievements, plans, risks, date)
|
10
|
+
return "From: #{@user}\nSubject: #{week_of_a_year(@title, date)}\n\nHi all,\n\nLast week achievements:\n#{achievements}\n\nNext week plans:\n#{plans}\n\nRisks:\n#{risks}\n\nBest regards,\n#{@user}\n#{@position}\n#{date}"
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
data/lib/newsman.rb
CHANGED
@@ -9,6 +9,7 @@ require_relative 'newsman/pull_request'
|
|
9
9
|
require_relative 'newsman/issues'
|
10
10
|
require_relative 'newsman/stdout_output'
|
11
11
|
require_relative 'newsman/txt_output'
|
12
|
+
require_relative 'newsman/html_output'
|
12
13
|
require_relative 'newsman/report'
|
13
14
|
|
14
15
|
def generate
|
@@ -32,7 +33,7 @@ def generate
|
|
32
33
|
options[:position] = p
|
33
34
|
end
|
34
35
|
opts.on('-o', '--output OUTPUT',
|
35
|
-
"Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html' or '-o
|
36
|
+
"Output type. Newsman prints a report to a stdout by default. You can choose another options like '-o html', '-o txt' or even '-o html'") do |o|
|
36
37
|
options[:output] = o
|
37
38
|
end
|
38
39
|
opts.on('-t', '--title TITLE', 'Project Title. Empty by default') do |t|
|
@@ -116,20 +117,27 @@ def generate
|
|
116
117
|
puts "\nNow lets test some aggregation using OpenAI\n\n"
|
117
118
|
openai_client = OpenAI::Client.new(access_token: openai_token)
|
118
119
|
|
119
|
-
example = "
|
120
|
+
example = "some-repository-name-x:
|
120
121
|
- Added 100 new files to the Dataset [#168]
|
121
122
|
- Fixed the deployment of XYZ [#169]
|
122
123
|
- Refined the requirements [#177]
|
123
|
-
|
124
|
+
some-repository-name-y:
|
124
125
|
- Removed XYZ class [#57]
|
125
126
|
- Refactored http module [#69]"
|
126
127
|
|
127
|
-
example_plans = "
|
128
|
+
example_plans = "some-repository-name-x:
|
128
129
|
- To publish ABC package draft [#27]
|
129
130
|
- To review first draft of the report [#56]
|
130
|
-
|
131
|
+
some-repository-name-y:
|
131
132
|
- To implement optimization for the class X [#125]"
|
132
133
|
|
134
|
+
example_risks = "some-repository-name-x:
|
135
|
+
- The server is weak, we may fail the delivery
|
136
|
+
of the dataset, report milestone will be missed [#487].
|
137
|
+
some-repository-name-y:
|
138
|
+
- The code in repository is suboptimal, we might have some problems for the future maintainability [#44].
|
139
|
+
"
|
140
|
+
|
133
141
|
response = openai_client.chat(
|
134
142
|
parameters: {
|
135
143
|
model: 'gpt-3.5-turbo',
|
@@ -137,7 +145,7 @@ def generate
|
|
137
145
|
{ role: 'system',
|
138
146
|
content: 'You are a developer tasked with composing a concise report detailing your activities and progress for the previous week, intended for submission to your supervisor.' },
|
139
147
|
{ role: 'user',
|
140
|
-
content: "Please compile a summary of the work completed in the following Pull Requests (PRs). Each PR should be summarized in a single sentence, focusing more on the PR title and less on implementation details. Group the sentences by repositories, each identified by its name mentioned in the 'repository:[name]' attribute of the PR. The grouping is important an should be precise. Ensure that each sentence includes the corresponding issue number as an integer value. If a PR doesn't mention an issue number, just print [#chore]. Combine all the information from each PR into a concise and fluent sentence, as if you were a developer reporting on your work. Please strictly adhere to the example template provided. Example of a report: #{example}. List of Pull Requests: [#{prs}]" }
|
148
|
+
content: "Please compile a summary of the work completed in the following Pull Requests (PRs). Each PR should be summarized in a single sentence, focusing more on the PR title and less on implementation details. Group the sentences by repositories, each identified by its name mentioned in the 'repository:[name]' attribute of the PR. Pay attention, that you don't lose any PR. The grouping is important an should be precise. Ensure that each sentence includes the corresponding issue number as an integer value. If a PR doesn't mention an issue number, just print [#chore]. Combine all the information from each PR into a concise and fluent sentence, as if you were a developer reporting on your work. Please strictly adhere to the example template provided. Example of a report: #{example}. List of Pull Requests: [#{prs}]" }
|
141
149
|
],
|
142
150
|
temperature: 0.3
|
143
151
|
}
|
@@ -150,19 +158,41 @@ def generate
|
|
150
158
|
{ role: 'system',
|
151
159
|
content: 'You are a developer tasked with composing a concise report detailing your activities and progress for the previous week, intended for submission to your supervisor.' },
|
152
160
|
{ role: 'user',
|
153
|
-
content: "Please compile a summary of the plans for the next week using the following GitHub Issues descriptions. Each issue should be summarized in a single sentence, focusing more on the issue title and less on implementation details. Group the sentences by repositories, each identified by its name mentioned in the 'repository:[name]' attribute of the issue. The grouping is important an should be precise. Ensure that each sentence includes the corresponding issue number as an integer value. If an issue doesn't mention an issue number, just print [#chore]. Combine all the information from each Issue into a concise and fluent sentences, as if you were a developer reporting on your work. Please strictly adhere to the example template provided: #{example_plans}. List of GitHub issues to aggregate: [#{issues}]. Use the same formatting as here \n```#{answer}```\n" }
|
161
|
+
content: "Please compile a summary of the plans for the next week using the following GitHub Issues descriptions. Each issue should be summarized in a single sentence, focusing more on the issue title and less on implementation details. Group the sentences by repositories, each identified by its name mentioned in the 'repository:[name]' attribute of the issue. Pat attention, that you din't loose any issue. The grouping is important an should be precise. Ensure that each sentence includes the corresponding issue number as an integer value. If an issue doesn't mention an issue number, just print [#chore]. Combine all the information from each Issue into a concise and fluent sentences, as if you were a developer reporting on your work. Please strictly adhere to the example template provided: #{example_plans}. List of GitHub issues to aggregate: [#{issues}]. Use the same formatting as here \n```#{answer}```\n" }
|
154
162
|
],
|
155
163
|
temperature: 0.3
|
156
164
|
}
|
157
165
|
)
|
158
166
|
issues_full_answer = issues_response.dig('choices', 0, 'message', 'content')
|
167
|
+
|
168
|
+
|
169
|
+
risks_full_answer = openai_client.chat(
|
170
|
+
parameters: {
|
171
|
+
model: 'gpt-3.5-turbo',
|
172
|
+
messages: [
|
173
|
+
{ role: 'system',
|
174
|
+
content: 'You are a developer tasked with composing a concise report detailing your activities and progress for the previous week, intended for submission to your supervisor.' },
|
175
|
+
{ role: 'user',
|
176
|
+
content: "Please compile a summary of the risks identified in some repositories. If you can't find anything, just leave answer empty. Add some entries to a report only if you are sure it's a risk. Developers usually mention some risks in pull request descriptions. They either mention 'risk' or 'issue'. I will give you a list of pull requests. Each risk should be summarized in a single sentence. Ensure that each sentence includes the corresponding issue number or PR number as an integer value. If a PR or an issue doesn't mention an issue number, just print [#chore]. Combine all the information from each PR into a concise and fluent sentence, as if you were a developer reporting on your work. Please strictly adhere to the example template provided. Example of a report: #{example_risks}. List of Pull Requests: ```#{prs}```.]"}
|
177
|
+
],
|
178
|
+
temperature: 0.3
|
179
|
+
}
|
180
|
+
).dig('choices', 0, 'message', 'content')
|
181
|
+
|
182
|
+
|
159
183
|
output_mode = options[:output]
|
160
184
|
puts "Output mode is '#{output_mode}'"
|
161
|
-
full_answer = Report.new(reporter, reporter_position, options[:title]).build(answer, issues_full_answer, Date.today)
|
185
|
+
full_answer = Report.new(reporter, reporter_position, options[:title]).build(answer, issues_full_answer, risks_full_answer, Date.today)
|
162
186
|
if output_mode.eql? 'txt'
|
187
|
+
puts "Print result to txy file"
|
163
188
|
output = Txtout.new('.')
|
164
189
|
output.print(full_answer, github_username)
|
190
|
+
elsif output_mode.eql? 'html'
|
191
|
+
puts "Print result to html file"
|
192
|
+
output = Htmlout.new('.')
|
193
|
+
output.print(full_answer, github_username)
|
165
194
|
else
|
195
|
+
puts "Print result to stdout"
|
166
196
|
output = Stdout.new
|
167
197
|
output.print(full_answer)
|
168
198
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in all
|
14
|
+
# copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
22
|
+
# SOFTWARE.
|
23
|
+
|
24
|
+
require 'minitest/autorun'
|
25
|
+
require_relative '../lib/newsman/html_output'
|
26
|
+
|
27
|
+
class TestHtmlout < Minitest::Test
|
28
|
+
|
29
|
+
|
30
|
+
EXPECTED = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" \"http://www.w3.org/TR/REC-html40/loose.dtd\">
|
31
|
+
<html>
|
32
|
+
<head>
|
33
|
+
<title>volodya-lombrozo #{Time.new.strftime('%d.%m.%Y')}</title>
|
34
|
+
</head>
|
35
|
+
<body>
|
36
|
+
<h1>volodya-lombrozo #{Time.new.strftime('%d.%m.%Y')}</h1>
|
37
|
+
<p>Issue description</p>
|
38
|
+
|
39
|
+
<p>Here is a new paragraph<br/>
|
40
|
+
List is here:<br/>
|
41
|
+
- one<br/>
|
42
|
+
- two<br/>
|
43
|
+
- three</p>
|
44
|
+
|
45
|
+
</body>
|
46
|
+
</html>
|
47
|
+
"
|
48
|
+
|
49
|
+
def test_writes_to_a_html_file
|
50
|
+
Dir.mktmpdir do |temp_dir|
|
51
|
+
output = Htmlout.new(temp_dir)
|
52
|
+
today = Date.today.strftime('%d.%m.%Y')
|
53
|
+
expected = "#{today}.volodya-lombrozo.html"
|
54
|
+
output.print("Issue description\n\nHere is a new paragraph\nList is here:\n - one\n - two\n - three", 'volodya-lombrozo')
|
55
|
+
assert(File.exist?(File.join(temp_dir, expected)))
|
56
|
+
assert_equal(EXPECTED, File.read(File.join(temp_dir, expected)))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/test/test_report.rb
CHANGED
@@ -47,7 +47,7 @@ User
|
|
47
47
|
Developer
|
48
48
|
2024-03-14"
|
49
49
|
report = Report.new('User', 'Developer', 'Project')
|
50
|
-
out = report.build("repository-a:\n - Did a lot of for (a) repository", "repository-b:\n - I will do a lot for repository (b)", Date.new(2024, 3, 14))
|
50
|
+
out = report.build("repository-a:\n - Did a lot of for (a) repository", "repository-b:\n - I will do a lot for repository (b)", "- <todo>", Date.new(2024, 3, 14))
|
51
51
|
assert_equal expected, out
|
52
52
|
end
|
53
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newsman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Volodya Lombrozo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-04-
|
11
|
+
date: 2024-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -122,6 +122,34 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0.4'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: redcarpet
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.6'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.6'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: nokogiri
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.16'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.16'
|
125
153
|
description: A simple gem that gathers GitHub statistics and creates human-readable
|
126
154
|
report
|
127
155
|
email:
|
@@ -135,11 +163,13 @@ files:
|
|
135
163
|
- README.md
|
136
164
|
- bin/newsman
|
137
165
|
- lib/newsman.rb
|
166
|
+
- lib/newsman/html_output.rb
|
138
167
|
- lib/newsman/issues.rb
|
139
168
|
- lib/newsman/pull_request.rb
|
140
169
|
- lib/newsman/report.rb
|
141
170
|
- lib/newsman/stdout_output.rb
|
142
171
|
- lib/newsman/txt_output.rb
|
172
|
+
- test/test_htmlout.rb
|
143
173
|
- test/test_pdd_issue.rb
|
144
174
|
- test/test_report.rb
|
145
175
|
- test/test_txtout.rb
|
@@ -165,7 +195,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
195
|
- !ruby/object:Gem::Version
|
166
196
|
version: '0'
|
167
197
|
requirements: []
|
168
|
-
rubygems_version: 3.5.
|
198
|
+
rubygems_version: 3.5.7
|
169
199
|
signing_key:
|
170
200
|
specification_version: 4
|
171
201
|
summary: GitHub user weekly news
|