Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 22 additions & 6 deletions pr-review/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ Input parameters for the action:
| `prompt` | The base prompt that is used to generate the review. <br /> Default: See [action.yml](action.yml#L36-L43) |
| `prompt-addition` | The addition to the base prompt that is used to generate the review. |
| `disclaimer-prompt` | The prompt that is used to generate the disclaimer. <br /> Default: See [action.yml](action.yml#L51-L53) |
| `summary-prompt` | The prompt that is used to generate the summary shown in the review body. <br /> Default: `Append a brief summary of the key review findings. No lists, no headings.` |
| `header-text` | Text to be inserted before the review. |
| `footer-text` | Text to be inserted after the review. |
| `previous-results` | Define what to do with previous results. Possible values are `keep` or `hide`. <br /> Default: `keep` |
Comment thread
daniel-richter marked this conversation as resolved.
Expand All @@ -114,11 +115,12 @@ Input parameters for the action:

Output parameters for the action:

| Name | Description |
| ---------- | --------------------------------------- |
| `comments` | An array of review comments for the PR. |
| `reviewId` | The ID of the created GitHub PR review. |
| `review` | The created GitHub PR review. |
| Name | Description |
| ---------- | --------------------------------------------------------- |
| `comments` | The AI-generated review comments as a JSON array. |
| `reviewId` | The ID of the created GitHub PR review. |
| `review` | The full GitHub PR review object returned by the API. |
| `summary` | The AI-generated summary text used in the PR review body. |

## Advanced Examples

Expand Down Expand Up @@ -206,6 +208,20 @@ jobs:

### Influence the Display Mode

#### Customize the review summary:

The `summary-prompt` parameter controls how the review body text is generated. The action runs a separate AI call with this prompt and the review findings as input.

To add static content around it, see [Add a header or footer](#add-a-header-or-footer).

```yaml
- uses: ai-assisted-actions/pr-review@v2
with:
model: gpt-5.4
summary-prompt: |
Summarize the findings in bullet points, grouped by severity.
```

#### Add a header or footer:

```yaml
Expand Down Expand Up @@ -254,7 +270,7 @@ jobs:
```yaml
- uses: SAP/ai-assisted-github-actions/pr-review@v3
with:
model: anthropic--claude-3.5-sonnet
model: anthropic--claude-4.6-opus
```

- The `model` parameter can be set to the executable ID of the [available generative AI models](https://me.sap.com/notes/3437766/E).
Expand Down
9 changes: 9 additions & 0 deletions pr-review/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ inputs:
default: |
Create a kind alternative for the following term: Here's a helpful review of your code with support from AI. Some insights are predictions, not guaranteed facts, so feel free to use what works best for you. Your decisions lead the way—AI is just here to assist.
Do not use more than 80 words. Do not use quotation marks.
summary-prompt:
description: "Prompt used to generate a summary of review findings in the review body. When not set, the LLM is called with only the disclaimer prompt (no review comments are sent)."
required: false
Comment thread
daniel-richter marked this conversation as resolved.

display-mode:
Comment thread
daniel-richter marked this conversation as resolved.
description: "Defines where the review will be posted (`review-comment`, `review-comment-delta`, or `none`)."
Expand Down Expand Up @@ -105,8 +108,14 @@ inputs:
default: "${{ github.api_url }}"

outputs:
comments:
description: "The AI-generated review comments as a JSON array."
reviewId:
description: "The ID of the created GitHub PR review."
review:
description: "The full GitHub PR review object returned by the API."
summary:
description: "The AI-generated summary text used in the PR review body."

runs:
using: node20
Expand Down
3 changes: 3 additions & 0 deletions pr-review/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ export const config = {
/** The prompt to use for the disclaimer. */
disclaimerPrompt: parseInput(z.string(), "disclaimer-prompt"),

/** The prompt to use for the summary. When empty, review comments are not sent to the LLM. */
summaryPrompt: parseInput(z.string(), "summary-prompt"),

/** The text that is placed before the review. */
Comment thread
daniel-richter marked this conversation as resolved.
headerText: parseInput(z.string(), "header-text"),

Expand Down
18 changes: 12 additions & 6 deletions pr-review/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,16 @@ export async function run(config: Config): Promise<void> {
)
}

core.startGroup(`Ask LLM for a disclaimer text to add to the review description`)
const disclaimer = await aiCoreClient.chatCompletion([{ role: "user", content: config.disclaimerPrompt }])
core.info(inspect(disclaimer, { depth: undefined, colors: true }))
core.setOutput("disclaimer", disclaimer)
core.startGroup(`Ask LLM for a summary to add to the review description`)
const summary = await aiCoreClient.chatCompletion([
{
role: "system",
content: [config.disclaimerPrompt, config.summaryPrompt].join("\n\n"),
},
...(config.summaryPrompt ? [{ role: "user" as const, content: `Review findings:\n${JSON.stringify(comments.map(({ path, body }) => ({ path, body })))}` }] : []),
Comment thread
daniel-richter marked this conversation as resolved.
Comment thread
daniel-richter marked this conversation as resolved.
Comment thread
daniel-richter marked this conversation as resolved.
])
core.info(inspect(summary, { depth: undefined, colors: true }))
Comment thread
daniel-richter marked this conversation as resolved.
core.setOutput("summary", summary)
Comment thread
daniel-richter marked this conversation as resolved.
Comment thread
daniel-richter marked this conversation as resolved.
Comment thread
daniel-richter marked this conversation as resolved.
Comment thread
daniel-richter marked this conversation as resolved.

core.startGroup(`Create a PR review as comment with the generated comments`)
const baseheadMaker = `<!-- ${base}...${head} -->`
Expand All @@ -180,8 +186,8 @@ export async function run(config: Config): Promise<void> {
`Completion Tokens: ${aiCoreClient.getCompletionTokens()}`,
base !== pullRequest.base.sha || head !== pullRequest.head.sha ? `Diff Range: ${base.slice(0, 7)}...${head.slice(0, 7)}` : "",
]
const modelMetadataFooter = config.showModelMetadataFooter ? `<sub>${metadata.filter(Boolean).join(" | ")}</sub>` : ""
const displayText = [markerStart, baseheadMaker, header, disclaimer, footer, modelMetadataFooter, markerEnd].filter(Boolean).join("\n")
const modelMetadataFooter = config.showModelMetadataFooter ? `\n<sub>${metadata.filter(Boolean).join(" | ")}</sub>` : ""
const displayText = [markerStart, baseheadMaker, header, summary, footer, modelMetadataFooter, markerEnd].filter(Boolean).join("\n")

Comment thread
daniel-richter marked this conversation as resolved.
type CreateReviewParameter = Parameters<typeof octokit.rest.pulls.createReview>[0]
const review: CreateReviewParameter = { ...repoRef, pull_number: config.prNumber, commit_id: head, event: "COMMENT", body: displayText, comments }
Expand Down
Loading