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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e0b76df23c180a0cc0a30bdc4d60fd675ece0c5201605bcbdea44bd0a7d25bce
4
- data.tar.gz: 72e37a051f065fcc3a625ba3175439b1351e28acc6e0b2cc33a352c3f5dda652
3
+ metadata.gz: c0ec4c08d224982a75fc3ae533368cdeff2c4d7cab0072441fcfbd604f194b42
4
+ data.tar.gz: 8633c4f4dc84b0f6a285e06b67b0cb9dd3f9e7a18d6dc032589237652181d36f
5
5
  SHA512:
6
- metadata.gz: e66602a260c38095c76e367b8a84f52f1f16bc6a74b103e3b0c0e6e8690e8bea1d1d54b41ca97cc0c259c55b571485e788864b3f788251730759ffd19ce356ec
7
- data.tar.gz: e4d0aef6d9a2958084402468adc84f2e24d8f7da507ea8a2dab7515f5855411f6e6a73e1969a4cc30f413e180eee2ceaab520c5addb7d59fa780090516dc7e76
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](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE.txt)
5
+ [![Gem Version](https://img.shields.io/gem/v/newsman.svg)](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 Reporter position in a company. Default value is a 'Software Developer'.
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
@@ -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
- <title><%= title %></title>
12
- </head>
13
- <body>
14
- <h1><%= title %></h1>
15
- <%= body %>
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
- renderer = Redcarpet::Render::HTML.new(no_links: true, hard_wrap: true, prettify: true)
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 html_content
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
@@ -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
- # frozen_string_literal: true
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, url: 'undefined')
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
- @url = url
36
+ @additional = defaults.merge(additional)
16
37
  end
17
38
 
18
39
  def to_s
19
- "title: ```#{@title}```,\ndescription: ```#{@body}```,\nrepo: ```#{@repo}```,\nissue number: \##{@number}\n"
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 detailed_title
23
- "title: #{@title}, repo: #{@repo}, number: \##{@number}, url: #{@url}"
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
- def initialize(title, body, repo, number, url: 'undefined')
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
- @url = url
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].gsub('https://github.com', 'https://raw.githubusercontent.com').gsub(
46
- 'blob/', ''
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
- "title: ```#{@title}```,\ndescription: ```#{extract_real_body}```,\nrepo: ```#{@repo}```,\nissue number: \##{@number}\n"
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: #{@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
@@ -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
@@ -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
- start = "From: #{@user}\nSubject: #{week_of_a_year(@title,
14
- 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}"
15
-
16
- finish = ''
17
- if !@additional.empty?
18
- finish = "\n------\n" + @additional.to_s
19
- end
20
- return start + finish;
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
- return "Closed Pull Requests:\n#{prs_list}\nOpen Issues:\n#{issues_list}"
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'
@@ -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