newsman 0.1.13 → 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 +4 -4
- data/README.md +7 -1
- data/lib/newsman/assistant.rb +136 -0
- data/lib/newsman/github.rb +80 -0
- data/lib/newsman/html_output.rb +42 -17
- data/lib/newsman/issues.rb +94 -15
- data/lib/newsman/pull_request.rb +32 -1
- data/lib/newsman/report.rb +49 -13
- data/lib/newsman/stdout_output.rb +22 -0
- data/lib/newsman/txt_output.rb +21 -0
- data/lib/newsman.rb +67 -127
- data/test/test_assistant.rb +38 -0
- data/test/test_htmlout.rb +1 -1
- data/test/test_issue.rb +62 -0
- data/test/test_pdd_issue.rb +35 -5
- data/test/test_pull_request.rb +39 -0
- data/test/test_report.rb +32 -24
- data/test/test_week_before.rb +1 -1
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0ec4c08d224982a75fc3ae533368cdeff2c4d7cab0072441fcfbd604f194b42
|
4
|
+
data.tar.gz: 8633c4f4dc84b0f6a285e06b67b0cb9dd3f9e7a18d6dc032589237652181d36f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 85df6a743456154cdfcd2999a2f3a1977347cf9b101c8f2e35bd0b13024e6e1d66e8cf699bc7a11feac586f5b7bb6a2bdc08b75936bf967b011afdc2f1963716
|
7
|
+
data.tar.gz: e4aa02defb4c4a02dee05fe334fb799f0f10b825110e194e0f3d7e5da79ce54144e5a77d1543c57acbdc56ca444fa4be625f4e16a9c83487abc917711d0e771c
|
data/README.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# Newsman
|
2
2
|
|
3
|
+
|
4
|
+
[](LICENSE.txt)
|
5
|
+
[](https://rubygems.org/gems/newsman)
|
6
|
+
|
3
7
|
Newsman is a simple script that collects information about a developer's weekly activity on GitHub and creates a human-readable summary of the work done. To create the summary, Newsman asks ChatGPT to handle all the information about a developer's activity, including their pull requests and created issues.
|
4
8
|
|
5
9
|
## Install
|
@@ -31,7 +35,9 @@ Usage: newsman [options]
|
|
31
35
|
-n, --name NAME Reporter name. Human readable name that will be used in a report
|
32
36
|
-u, --username USERNAME GitHub username. For example, 'volodya-lombrozo'
|
33
37
|
-r, --repository REPOSITORIES Specify which repositories to include in a report. You can specify several repositories using a comma separator, for example: '-r objectionary/jeo-maven-plugin,objectionary/opeo-maven-plugin'
|
34
|
-
-p, --position
|
38
|
+
-p, --position POSITION Reporter position in a company. Default value is a 'Software Developer'.
|
39
|
+
-o, --output OUTPUT 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'
|
40
|
+
-t, --title TITLE Project Title. Empty by default
|
35
41
|
```
|
36
42
|
|
37
43
|
### Example
|
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
require 'openai'
|
24
|
+
|
25
|
+
# This class mimics a robot that can analyse a developer activity.
|
26
|
+
# The assistant uses OpenAI API to analyze.
|
27
|
+
class Assistant
|
28
|
+
CONTEXT = 'You are a developer tasked'\
|
29
|
+
' with composing a concise report detailing your activities'\
|
30
|
+
' and progress for the previous week,'\
|
31
|
+
' intended for submission to your supervisor.'
|
32
|
+
|
33
|
+
def initialize(token, model: 'gpt-3.5-turbo', temperature: 0.3)
|
34
|
+
@token = token
|
35
|
+
@model = model
|
36
|
+
@temperature = temperature
|
37
|
+
@client = OpenAI::Client.new(access_token: token)
|
38
|
+
end
|
39
|
+
|
40
|
+
def say_hello
|
41
|
+
<<~HELLO
|
42
|
+
I'm an assistant that can work with OpenAI client.
|
43
|
+
Please, use me, if you need any help.
|
44
|
+
I'm using #{@model}, with #{@temperature} temperature.
|
45
|
+
HELLO
|
46
|
+
end
|
47
|
+
|
48
|
+
# rubocop:disable Metrics/MethodLength
|
49
|
+
def next_plans(issues)
|
50
|
+
example = "repository-name:\n
|
51
|
+
- To publish ABC package draft [#27]\n
|
52
|
+
- To review first draft of the report [#56]\n
|
53
|
+
- To implement optimization for the class X [#125]"
|
54
|
+
prompt = <<~PROMPT
|
55
|
+
Please compile a summary of the plans for the next week using the GitHub Issues.
|
56
|
+
Each issue should be summarized in a single sentence.
|
57
|
+
Combine all the information from each Issue into a concise and fluent sentence.
|
58
|
+
Pay attention, that you didn't loose any issue.
|
59
|
+
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].
|
60
|
+
If several issues have the same number, combine them into a single sentence.
|
61
|
+
Please strictly adhere to the example template provided: "#{example}".
|
62
|
+
List of GitHub Issues in JSON format: ```json #{issues}```.
|
63
|
+
PROMPT
|
64
|
+
send(prompt)
|
65
|
+
end
|
66
|
+
# rubocop:enable Metrics/MethodLength
|
67
|
+
|
68
|
+
# rubocop:disable Metrics/MethodLength
|
69
|
+
def prev_results(prs)
|
70
|
+
example = "repository-name:\n
|
71
|
+
- Added 100 new files to the Dataset [#168]\n
|
72
|
+
- Fixed the deployment of XYZ [#169]\n
|
73
|
+
- Refined the requirements [#177]\n"
|
74
|
+
prompt = <<~PROMPT
|
75
|
+
Please compile a summary of the work completed in the following Pull Requests (PRs).
|
76
|
+
Each PR should be summarized in a single sentence, focusing on the PR title rather than the implementation details.
|
77
|
+
Ensure no PR is omitted.
|
78
|
+
Each sentence must include the corresponding issue number as an integer value. If a PR does not mention an issue number, use [#chore].
|
79
|
+
If several PRs have the same number, combine them into a single sentence.
|
80
|
+
Combine the information from each PR into a concise and fluent sentence.
|
81
|
+
Follow the provided example template strictly: "#{example}".
|
82
|
+
List of Pull Requests in JSON format: ```json #{prs}```.
|
83
|
+
PROMPT
|
84
|
+
send(prompt)
|
85
|
+
end
|
86
|
+
# rubocop:enable Metrics/MethodLength
|
87
|
+
|
88
|
+
# rubocop:disable Metrics/MethodLength
|
89
|
+
def risks(all)
|
90
|
+
example = "repository-name:\n
|
91
|
+
- The server is weak, we may fail the delivery\n
|
92
|
+
of the dataset, report milestone will be missed [#487].\n
|
93
|
+
- The code in repository is suboptimal, we might have some problems for the future maintainability [#44].\n"
|
94
|
+
prompt = <<~PROMPT
|
95
|
+
Please compile a summary of the risks identified in the repository from the list of pull requests provided.
|
96
|
+
If no risks are identified in a pull request, just answer 'No risks identified' for that PR.
|
97
|
+
Each risk should be summarized in a concise and fluent single sentence.
|
98
|
+
Developers usually mention some risks in pull request descriptions, either as 'risk' or 'issue'.#{' '}
|
99
|
+
Ensure that each sentence includes the corresponding PR number as an integer value. If a PR doesn't mention an issue number, just print [#chore].
|
100
|
+
Please strictly adhere to the example template provided: "#{example}".
|
101
|
+
List of Pull Requests: ```json #{all}```.
|
102
|
+
PROMPT
|
103
|
+
send(prompt)
|
104
|
+
end
|
105
|
+
# rubocop:enable Metrics/MethodLength
|
106
|
+
|
107
|
+
def format(report)
|
108
|
+
prompt = <<~PROMPT
|
109
|
+
I have a weekly report with different parts that use various formatting styles.
|
110
|
+
Please format the entire report into a single cohesive format while preserving the original text without any changes.
|
111
|
+
Ensure that the formatting is consistent throughout the document.
|
112
|
+
|
113
|
+
Here is the report:
|
114
|
+
|
115
|
+
#{report}
|
116
|
+
PROMPT
|
117
|
+
send(prompt)
|
118
|
+
end
|
119
|
+
|
120
|
+
def send(request)
|
121
|
+
@client.chat(
|
122
|
+
parameters: {
|
123
|
+
model: @model,
|
124
|
+
messages: [
|
125
|
+
{ role: 'system', content: CONTEXT },
|
126
|
+
{ role: 'user', content: request.to_s }
|
127
|
+
],
|
128
|
+
temperature: @temperature
|
129
|
+
}
|
130
|
+
).dig('choices', 0, 'message', 'content')
|
131
|
+
end
|
132
|
+
|
133
|
+
def deprecated(method)
|
134
|
+
warn "Warning! '#{method}' is deprecated and will be removed in future versions."
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
6
|
+
#
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
8
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
12
|
+
# furnished to do so, subject to the following conditions:
|
13
|
+
#
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
15
|
+
# copies or substantial portions of the Software.
|
16
|
+
#
|
17
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
23
|
+
# SOFTWARE.
|
24
|
+
|
25
|
+
# This class represents a useful abstraction over Github API.
|
26
|
+
class Github
|
27
|
+
def initialize(token)
|
28
|
+
@client = Octokit::Client.new(github_token: token)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pull_requests(username, repositories)
|
32
|
+
query = "is:pr author:#{username} created:>=#{date_one_week_ago(Date.today)} #{repositories}"
|
33
|
+
puts "Searching pull requests for #{username}."
|
34
|
+
puts 'Newsman uses the following request to GitHub to gather the'\
|
35
|
+
" required information about user activity: '#{query}'"
|
36
|
+
@client.search_issues(query).items.map do |pull_request|
|
37
|
+
parse_pr(pull_request)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def issues(username, repositories)
|
42
|
+
one_month_ago = Date.today.prev_month.strftime('%Y-%m-%d')
|
43
|
+
query = "is:issue is:open author:#{username}"\
|
44
|
+
" author:0pdd created:>=#{one_month_ago} #{repositories}"
|
45
|
+
puts "Searching issues using the following query: '#{query}'"
|
46
|
+
@client.search_issues(query).items.map do |issue|
|
47
|
+
parse_issue(issue)
|
48
|
+
end.select(&:important?)
|
49
|
+
end
|
50
|
+
|
51
|
+
def parse_pr(pull_request)
|
52
|
+
title = pull_request.title.to_s
|
53
|
+
repository = pull_request.repository_url.split('/').last
|
54
|
+
puts "Found PR in #{repository}: #{title}"
|
55
|
+
PullRequest.new(repository, title, pull_request.body.to_s, url: pull_request.html_url)
|
56
|
+
end
|
57
|
+
|
58
|
+
def parse_issue(issue)
|
59
|
+
title, repository, number = issue_details(issue)
|
60
|
+
if issue.user.login == '0pdd'
|
61
|
+
PddIssue.new(title, issue.body.to_s, repository, number, url: issue.html_url, labels: issue.labels.map(&:name))
|
62
|
+
else
|
63
|
+
Issue.new(title, issue.body.to_s, repository, number, url: issue.html_url, labels: issue.labels.map(&:name))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def issue_details(issue)
|
68
|
+
title = issue.title.to_s
|
69
|
+
repository = issue.repository_url.split('/').last
|
70
|
+
number = issue.number.to_s
|
71
|
+
puts "Found issue in #{repository}:[##{number}] #{title}"
|
72
|
+
[title, repository, number]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def date_one_week_ago(today)
|
77
|
+
today = Date.parse(today) unless today.is_a?(Date)
|
78
|
+
one_week_ago = today - 7
|
79
|
+
one_week_ago.strftime('%Y-%m-%d')
|
80
|
+
end
|
data/lib/newsman/html_output.rb
CHANGED
@@ -1,40 +1,57 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
3
23
|
require 'erb'
|
4
24
|
require 'redcarpet'
|
5
25
|
require 'nokogiri'
|
6
|
-
# frozen_string_literal: true
|
7
26
|
|
27
|
+
# This class represents a report output in HTML format.
|
8
28
|
class Htmlout
|
9
|
-
TEMPLATE =
|
10
|
-
<head>
|
11
|
-
|
12
|
-
</head>
|
13
|
-
<body>
|
14
|
-
|
15
|
-
|
16
|
-
</body>
|
17
|
-
|
29
|
+
TEMPLATE = <<~HTML
|
30
|
+
<head>
|
31
|
+
<title><%= title %></title>
|
32
|
+
</head>
|
33
|
+
<body>
|
34
|
+
<h1><%= title %></h1>
|
35
|
+
<%= body %>
|
36
|
+
</body>
|
37
|
+
HTML
|
18
38
|
|
19
39
|
def initialize(root = '.')
|
20
40
|
@root = root
|
21
41
|
end
|
22
42
|
|
43
|
+
# rubocop:disable Metrics/AbcSize
|
23
44
|
def print(report, reporter)
|
24
45
|
title = title(reporter)
|
25
|
-
|
26
|
-
markdown = Redcarpet::Markdown.new(renderer, autolink: true, tables: true)
|
27
|
-
body = markdown.render(report)
|
28
|
-
renderer = ERB.new(TEMPLATE)
|
29
|
-
html_content = renderer.result(binding)
|
30
|
-
html_content = Nokogiri::HTML(html_content, &:noblanks).to_xhtml(indent: 2)
|
46
|
+
body = to_html(report)
|
31
47
|
puts "Create a html file in a directory #{@root}"
|
32
48
|
file = File.new(File.join(@root, filename(reporter)), 'w')
|
33
49
|
puts "File #{file.path} was successfully created"
|
34
|
-
file.puts
|
50
|
+
file.puts Nokogiri::HTML(ERB.new(TEMPLATE).result(binding), &:noblanks).to_xhtml(indent: 2)
|
35
51
|
puts "Report was successfully printed to a #{file.path}"
|
36
52
|
file.close
|
37
53
|
end
|
54
|
+
# rubocop:enable Metrics/AbcSize
|
38
55
|
|
39
56
|
def title(reporter)
|
40
57
|
date = Time.new.strftime('%d.%m.%Y')
|
@@ -45,4 +62,12 @@ class Htmlout
|
|
45
62
|
date = Time.new.strftime('%d.%m.%Y')
|
46
63
|
"#{date}.#{reporter}.html"
|
47
64
|
end
|
65
|
+
|
66
|
+
def to_html(report)
|
67
|
+
Redcarpet::Markdown.new(
|
68
|
+
Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true, prettify: true),
|
69
|
+
autolink: true,
|
70
|
+
tables: true
|
71
|
+
).render(report)
|
72
|
+
end
|
48
73
|
end
|
data/lib/newsman/issues.rb
CHANGED
@@ -1,37 +1,89 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
3
23
|
require 'net/http'
|
4
|
-
|
24
|
+
require 'json'
|
5
25
|
|
26
|
+
# This class represents a GitHub Issue abstraction created by a user.
|
6
27
|
class Issue
|
7
28
|
attr_accessor :title, :body, :repo, :number
|
8
|
-
attr_reader :url
|
9
29
|
|
10
|
-
def initialize(title, body, repo, number,
|
30
|
+
def initialize(title, body, repo, number, **additional)
|
31
|
+
defaults = { url: 'undefined', labels: [] }
|
11
32
|
@title = title
|
12
33
|
@body = body
|
13
34
|
@repo = repo
|
14
35
|
@number = number
|
15
|
-
@
|
36
|
+
@additional = defaults.merge(additional)
|
16
37
|
end
|
17
38
|
|
18
39
|
def to_s
|
19
|
-
|
40
|
+
<<~MARKDOWN
|
41
|
+
title: ```#{@title}```,
|
42
|
+
description: ```#{@body}```,
|
43
|
+
repo: ```#{@repo}```,
|
44
|
+
issue number: \##{@number},
|
45
|
+
additional: #{@additional}
|
46
|
+
MARKDOWN
|
47
|
+
end
|
48
|
+
|
49
|
+
def detailed_title
|
50
|
+
"title: #{@title}, repo: #{@repo}, number: \##{@number}, url: #{url}, labels: #{labels}"
|
20
51
|
end
|
21
52
|
|
22
|
-
def
|
23
|
-
|
53
|
+
def url
|
54
|
+
@additional[:url]
|
55
|
+
end
|
56
|
+
|
57
|
+
def labels
|
58
|
+
@additional[:labels]
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_json(*_args)
|
62
|
+
{
|
63
|
+
number: @number,
|
64
|
+
title: @title,
|
65
|
+
description: @body,
|
66
|
+
repository: @repo,
|
67
|
+
url: url.to_s
|
68
|
+
}.to_json
|
69
|
+
end
|
70
|
+
|
71
|
+
def important?
|
72
|
+
labels.include? 'soon'
|
24
73
|
end
|
25
|
-
|
26
74
|
end
|
27
75
|
|
76
|
+
# This class represents a GitHub issue abstraction created by a 0pdd robot.
|
28
77
|
class PddIssue
|
29
|
-
|
78
|
+
attr_accessor :repo
|
79
|
+
|
80
|
+
def initialize(title, body, repo, number, **additional)
|
81
|
+
defaults = { url: 'undefined', labels: [] }
|
30
82
|
@title = title
|
31
83
|
@body = body
|
32
84
|
@repo = repo
|
33
85
|
@number = number
|
34
|
-
@
|
86
|
+
@additional = defaults.merge(additional)
|
35
87
|
end
|
36
88
|
|
37
89
|
def extract_real_body
|
@@ -42,17 +94,44 @@ class PddIssue
|
|
42
94
|
end
|
43
95
|
|
44
96
|
def issue_link
|
45
|
-
@body[%r{https://github\.com/[\w\-/]+/blob/[\w\d]+/[\w/.-]+#\w+-\w+}, 0]
|
46
|
-
'
|
47
|
-
|
97
|
+
@body[%r{https://github\.com/[\w\-/]+/blob/[\w\d]+/[\w/.-]+#\w+-\w+}, 0]
|
98
|
+
.gsub('https://github.com', 'https://raw.githubusercontent.com')
|
99
|
+
.gsub('blob/', '')
|
48
100
|
end
|
49
101
|
|
50
102
|
def to_s
|
51
|
-
|
103
|
+
<<~MARKDOWN
|
104
|
+
title: ```#{@title}```,
|
105
|
+
description: ```#{extract_real_body}```,
|
106
|
+
repo: ```#{@repo}```,
|
107
|
+
issue number: \##{@number},
|
108
|
+
additional: #{@additional}
|
109
|
+
MARKDOWN
|
52
110
|
end
|
53
111
|
|
54
112
|
def detailed_title
|
55
|
-
"title: #{@title}, repo: #{@repo}, issue number: \##{@number}, url: #{
|
113
|
+
"title: #{@title}, repo: #{@repo}, issue number: \##{@number}, url: #{url}, labels: #{labels}"
|
56
114
|
end
|
57
115
|
|
116
|
+
def to_json(*_args)
|
117
|
+
{
|
118
|
+
number: @number,
|
119
|
+
title: @title,
|
120
|
+
description: @body,
|
121
|
+
repository: @repo,
|
122
|
+
url: url.to_s
|
123
|
+
}.to_json
|
124
|
+
end
|
125
|
+
|
126
|
+
def important?
|
127
|
+
labels.include? 'soon'
|
128
|
+
end
|
129
|
+
|
130
|
+
def url
|
131
|
+
@additional[:url]
|
132
|
+
end
|
133
|
+
|
134
|
+
def labels
|
135
|
+
@additional[:labels]
|
136
|
+
end
|
58
137
|
end
|
data/lib/newsman/pull_request.rb
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
require 'json'
|
23
|
+
|
24
|
+
# This class represents GitHub Pull Request abstraction.
|
25
|
+
# In the future, it might be any Pull or Merge request.
|
3
26
|
class PullRequest
|
4
27
|
attr_accessor :repository, :title, :description
|
5
28
|
attr_reader :url
|
@@ -11,6 +34,15 @@ class PullRequest
|
|
11
34
|
@url = url
|
12
35
|
end
|
13
36
|
|
37
|
+
def to_json(*_args)
|
38
|
+
{
|
39
|
+
title: @title,
|
40
|
+
description: @description,
|
41
|
+
repository: @repository,
|
42
|
+
url: @url
|
43
|
+
}.to_json
|
44
|
+
end
|
45
|
+
|
14
46
|
def to_s
|
15
47
|
"title: ```#{@title}```,\ndescription: ```#{@description}```,\nrepo: ```#{@repository}```\n"
|
16
48
|
end
|
@@ -18,5 +50,4 @@ class PullRequest
|
|
18
50
|
def detailed_title
|
19
51
|
"title: #{@title}, repo: #{@repository}, url: #{@url}"
|
20
52
|
end
|
21
|
-
|
22
53
|
end
|
data/lib/newsman/report.rb
CHANGED
@@ -1,8 +1,29 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
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
|
+
# This class builds entire report based on issues and pull requests passed.
|
4
25
|
class Report
|
5
|
-
def initialize(user, position, title, additional: ReportItems.new([],[]))
|
26
|
+
def initialize(user, position, title, additional: ReportItems.new([], []))
|
6
27
|
@user = user
|
7
28
|
@position = position
|
8
29
|
@title = title
|
@@ -10,14 +31,30 @@ class Report
|
|
10
31
|
end
|
11
32
|
|
12
33
|
def build(achievements, plans, risks, date)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
34
|
+
<<~TEMPLATE
|
35
|
+
From: #{@user}
|
36
|
+
Subject: #{week_of_a_year(@title, date)}
|
37
|
+
|
38
|
+
Hi all,
|
39
|
+
|
40
|
+
Last week achievements:
|
41
|
+
#{achievements}
|
42
|
+
|
43
|
+
Next week plans:
|
44
|
+
#{plans}
|
45
|
+
|
46
|
+
Risks:
|
47
|
+
#{risks}
|
48
|
+
|
49
|
+
Best regards,
|
50
|
+
#{@user}
|
51
|
+
#{@position}
|
52
|
+
#{date}
|
53
|
+
TEMPLATE
|
54
|
+
end
|
55
|
+
|
56
|
+
def append_additional(report)
|
57
|
+
"#{report}\n#{"------\n#{@additional}" unless @additional.empty?}"
|
21
58
|
end
|
22
59
|
end
|
23
60
|
|
@@ -26,9 +63,8 @@ def week_of_a_year(project, today)
|
|
26
63
|
"WEEK #{number} #{project}"
|
27
64
|
end
|
28
65
|
|
29
|
-
|
66
|
+
# Report items inner class.
|
30
67
|
class ReportItems
|
31
|
-
|
32
68
|
def initialize(prs, issues)
|
33
69
|
@prs = prs || []
|
34
70
|
@issues = issues || []
|
@@ -41,7 +77,7 @@ class ReportItems
|
|
41
77
|
|
42
78
|
def to_s
|
43
79
|
prs_list = @prs.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
44
|
-
issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
45
|
-
|
80
|
+
issues_list = @issues.map(&:detailed_title).map { |obj| " - #{obj}\n" }.join
|
81
|
+
"Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
|
46
82
|
end
|
47
83
|
end
|
@@ -1,5 +1,27 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
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
|
+
# This class prints report to a console.
|
3
25
|
class Stdout
|
4
26
|
def print(report)
|
5
27
|
puts 'Print a report to stdout'
|
data/lib/newsman/txt_output.rb
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright (c) 2024 Volodya Lombrozo
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
# SOFTWARE.
|
22
|
+
|
23
|
+
# This class knows how to print a report to a separate file.
|
3
24
|
class Txtout
|
4
25
|
def initialize(root = '.')
|
5
26
|
@root = root
|