Skip to content
This repository was archived by the owner on Mar 6, 2024. It is now read-only.

Commit f63fbce

Browse files
authored
incrementally summarize (#211)
1 parent c236ecc commit f63fbce

File tree

8 files changed

+287
-276
lines changed

8 files changed

+287
-276
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# OpenAI ChatGPT based PR reviewer and summarizer
1+
# OpenAI ChatGPT-based PR reviewer and summarizer
22

33
![AI](./docs/images/ai.png)
44

55
## Overview
66

7-
This [OpenAI ChatGPT](https://platform.openai.com/docs/guides/chat) based GitHub
7+
This [OpenAI ChatGPT-based](https://platform.openai.com/docs/guides/chat) GitHub
88
Action provides a summary, release notes and review of pull requests. The
99
prompts have been tuned for a concise response. To prevent excessive
1010
notifications, this action can be configured to skip adding review comments when
@@ -22,6 +22,8 @@ NOTES:
2222
has a
2323
[more conservative data usage policy](https://openai.com/policies/api-data-usage-policies)
2424
compared to their ChatGPT offering.
25+
- This action is not affiliated with OpenAI.
26+
- This action is going through rapid iteration, so expect breaking changes.
2527

2628
## Usage
2729

@@ -178,7 +180,7 @@ $ npm run build && npm run package
178180

179181
## FAQs
180182

181-
### Review pull request from forks
183+
### Review pull requests from forks
182184

183185
GitHub Actions limits the access of secrets from forked repositories. To enable
184186
this feature, you need to use the `pull_request_target` event instead of

action.yml

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@ inputs:
99
required: false
1010
description: 'Enable debug mode'
1111
default: 'false'
12-
max_files_to_summarize:
12+
max_files:
1313
required: false
1414
description:
15-
'Max files to summarize. Less than or equal to 0 means no limit.'
16-
default: '40'
17-
max_files_to_review:
18-
required: false
19-
description: 'Max files to review. Less than or equal to 0 means no limit.'
15+
'Max files to summarize and review. Less than or equal to 0 means no
16+
limit.'
2017
default: '0'
2118
review_comment_lgtm:
2219
required: false
@@ -109,7 +106,7 @@ inputs:
109106
disregarding minor issues.
110107
summarize_file_diff:
111108
required: false
112-
description: 'The prompt for file'
109+
description: 'The prompt for summarizing a file'
113110
default: |
114111
GitHub pull request title:
115112
`$title`
@@ -124,7 +121,7 @@ inputs:
124121
$file_content
125122
```
126123
127-
Diff:
124+
Diff for `$filename`:
128125
```diff
129126
$file_diff
130127
```
@@ -134,17 +131,17 @@ inputs:
134131
required: false
135132
description: 'The prompt for final summarization response'
136133
default: |
137-
Here is the summary of changes you have generated for each file:
134+
Here is the summary of changes you have generated for files:
138135
```
139-
$summary
136+
$raw_summary
140137
```
141138
142139
Provide your final response in the `markdown` format with
143140
the following content:
144141
- High-level summary (comment on the overall change instead of
145142
specific files within 80 words)
146143
- Table of files and their summaries. You can group files with
147-
similar changes together into one row to save space.
144+
similar changes together into a single row to save space.
148145
149146
Avoid additional commentary as this summary will be added as a
150147
comment on the GitHub pull request.

dist/index.js

Lines changed: 116 additions & 107 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/commenter.ts

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ export const DESCRIPTION_TAG =
2424
export const DESCRIPTION_TAG_END =
2525
'<!-- end of auto-generated comment: release notes by openai -->'
2626

27+
export const RAW_SUMMARY_TAG =
28+
'<!-- This is an auto-generated comment: raw summary by openai -->'
29+
export const RAW_SUMMARY_TAG_END =
30+
'<!-- end of auto-generated comment: raw summary by openai -->'
31+
2732
export class Commenter {
2833
/**
2934
* @param mode Can be "create", "replace". Default is "replace".
@@ -61,32 +66,52 @@ ${tag}`
6166
}
6267
}
6368

64-
get_description(description: string) {
65-
// remove our summary from description by looking for description_tag and description_tag_end
66-
const start = description.indexOf(DESCRIPTION_TAG)
67-
const end = description.indexOf(DESCRIPTION_TAG_END)
69+
getContentWithinTags(content: string, startTag: string, endTag: string) {
70+
const start = content.indexOf(startTag)
71+
const end = content.indexOf(endTag)
6872
if (start >= 0 && end >= 0) {
69-
return (
70-
description.slice(0, start) +
71-
description.slice(end + DESCRIPTION_TAG_END.length)
72-
)
73+
return content.slice(start + startTag.length, end)
7374
}
74-
return description
75+
return ''
7576
}
7677

77-
get_release_notes(description: string) {
78-
// get our summary from description by looking for description_tag and description_tag_end
79-
// and remove any content within that which is in markdown quote (>)
80-
const start = description.indexOf(DESCRIPTION_TAG)
81-
const end = description.indexOf(DESCRIPTION_TAG_END)
78+
removeContentWithinTags(content: string, startTag: string, endTag: string) {
79+
const start = content.indexOf(startTag)
80+
const end = content.indexOf(endTag)
8281
if (start >= 0 && end >= 0) {
83-
const release_notes = description.slice(
84-
start + DESCRIPTION_TAG.length,
85-
end
86-
)
87-
return release_notes.replace(/(^|\n)> .*/g, '')
82+
return content.slice(0, start) + content.slice(end + endTag.length)
8883
}
89-
return ''
84+
return content
85+
}
86+
87+
get_raw_summary(summary: string) {
88+
const content = this.getContentWithinTags(
89+
summary,
90+
RAW_SUMMARY_TAG,
91+
RAW_SUMMARY_TAG_END
92+
)
93+
// remove the first and last line
94+
const lines = content.split('\n')
95+
lines.shift()
96+
lines.pop()
97+
return lines.join('\n')
98+
}
99+
100+
get_description(description: string) {
101+
return this.removeContentWithinTags(
102+
description,
103+
DESCRIPTION_TAG,
104+
DESCRIPTION_TAG_END
105+
)
106+
}
107+
108+
get_release_notes(description: string) {
109+
const release_notes = this.getContentWithinTags(
110+
description,
111+
DESCRIPTION_TAG,
112+
DESCRIPTION_TAG_END
113+
)
114+
return release_notes.replace(/(^|\n)> .*/g, '')
90115
}
91116

92117
async update_description(pull_number: number, message: string) {

src/main.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ async function run(): Promise<void> {
88
const options: Options = new Options(
99
core.getBooleanInput('debug'),
1010
core.getBooleanInput('summary_only'),
11-
core.getInput('max_files_to_summarize'),
12-
core.getInput('max_files_to_review'),
11+
core.getInput('max_files'),
1312
core.getBooleanInput('review_comment_lgtm'),
1413
core.getMultilineInput('path_filters'),
1514
core.getInput('system_message'),

src/options.ts

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class Inputs {
4747
system_message: string
4848
title: string
4949
description: string
50-
summary: string
50+
raw_summary: string
5151
release_notes: string
5252
filename: string
5353
file_content: string
@@ -74,7 +74,7 @@ export class Inputs {
7474
this.system_message = system_message
7575
this.title = title
7676
this.description = description
77-
this.summary = summary
77+
this.raw_summary = summary
7878
this.release_notes = release_notes
7979
this.filename = filename
8080
this.file_content = file_content
@@ -90,7 +90,7 @@ export class Inputs {
9090
this.system_message,
9191
this.title,
9292
this.description,
93-
this.summary,
93+
this.raw_summary,
9494
this.release_notes,
9595
this.filename,
9696
this.file_content,
@@ -115,8 +115,8 @@ export class Inputs {
115115
if (this.description) {
116116
content = content.replace('$description', this.description)
117117
}
118-
if (this.summary) {
119-
content = content.replace('$summary', this.summary)
118+
if (this.raw_summary) {
119+
content = content.replace('$raw_summary', this.raw_summary)
120120
}
121121
if (this.release_notes) {
122122
content = content.replace('$release_notes', this.release_notes)
@@ -186,8 +186,7 @@ export class OpenAIOptions {
186186
export class Options {
187187
debug: boolean
188188
summary_only: boolean
189-
max_files_to_summarize: number
190-
max_files_to_review: number
189+
max_files: number
191190
review_comment_lgtm: boolean
192191
path_filters: PathFilter
193192
system_message: string
@@ -203,8 +202,7 @@ export class Options {
203202
constructor(
204203
debug: boolean,
205204
summary_only: boolean,
206-
max_files_to_summarize = '40',
207-
max_files_to_review = '0',
205+
max_files = '0',
208206
review_comment_lgtm = false,
209207
path_filters: string[] | null = null,
210208
system_message = '',
@@ -217,8 +215,7 @@ export class Options {
217215
) {
218216
this.debug = debug
219217
this.summary_only = summary_only
220-
this.max_files_to_summarize = parseInt(max_files_to_summarize)
221-
this.max_files_to_review = parseInt(max_files_to_review)
218+
this.max_files = parseInt(max_files)
222219
this.review_comment_lgtm = review_comment_lgtm
223220
this.path_filters = new PathFilter(path_filters)
224221
this.system_message = system_message
@@ -236,8 +233,7 @@ export class Options {
236233
print(): void {
237234
core.info(`debug: ${this.debug}`)
238235
core.info(`summary_only: ${this.summary_only}`)
239-
core.info(`max_files_to_summarize: ${this.max_files_to_summarize}`)
240-
core.info(`max_files_to_review: ${this.max_files_to_review}`)
236+
core.info(`max_files: ${this.max_files}`)
241237
core.info(`review_comment_lgtm: ${this.review_comment_lgtm}`)
242238
core.info(`path_filters: ${this.path_filters}`)
243239
core.info(`system_message: ${this.system_message}`)

src/review-comment.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
Commenter,
66
COMMENT_REPLY_TAG,
77
COMMENT_TAG,
8-
EXTRA_CONTENT_TAG,
98
SUMMARIZE_TAG
109
} from './commenter.js'
1110
import {octokit} from './octokit.js'
@@ -147,16 +146,6 @@ export const handleReviewComment = async (
147146
}
148147
}
149148

150-
// get summary of the PR
151-
const summary = await commenter.find_comment_with_tag(
152-
SUMMARIZE_TAG,
153-
pull_number
154-
)
155-
if (summary) {
156-
// remove all content below EXTRA_CONTENT_TAG
157-
inputs.summary = summary.body.split(EXTRA_CONTENT_TAG)[0]
158-
}
159-
160149
// get tokens so far
161150
let tokens = tokenizer.get_token_count(prompts.render_comment(inputs))
162151

@@ -168,7 +157,6 @@ export const handleReviewComment = async (
168157
)
169158
return
170159
}
171-
172160
// pack file content and diff into the inputs if they are not too long
173161
if (file_content.length > 0) {
174162
// count occurrences of $file_content in prompt
@@ -199,6 +187,24 @@ export const handleReviewComment = async (
199187
}
200188
}
201189

190+
// get summary of the PR
191+
const summary = await commenter.find_comment_with_tag(
192+
SUMMARIZE_TAG,
193+
pull_number
194+
)
195+
if (summary) {
196+
// pack summary into the inputs if it is not too long
197+
const raw_summary = commenter.get_raw_summary(summary.body)
198+
const summary_tokens = tokenizer.get_token_count(raw_summary)
199+
if (
200+
tokens + summary_tokens <=
201+
options.heavy_token_limits.request_tokens
202+
) {
203+
tokens += summary_tokens
204+
inputs.raw_summary = raw_summary
205+
}
206+
}
207+
202208
const [reply] = await heavyBot.chat(prompts.render_comment(inputs), {})
203209

204210
await commenter.review_comment_reply(pull_number, topLevelComment, reply)

0 commit comments

Comments
 (0)