Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP refactor #1

Merged
merged 4 commits into from
Apr 22, 2023
Merged
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
19 changes: 19 additions & 0 deletions .github/workflows/cr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Code Review

permissions:
contents: read
pull-requests: write

on:
pull_request:
types: [opened, reopened, synchronize]

jobs:
test:
# if: ${{ contains(github.event.*.labels.*.name, 'gpt review') }} # Optional; to run only when a label is attached
runs-on: ubuntu-latest
steps:
- uses: anc95/ChatGPT-CodeReview@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code patch is for a GitHub Action that runs a code review using OpenAI's GPT (Generative Pre-trained Transformer) model. The permissions are set to allow reading contents and writing pull requests. The action is triggered for pull request events when they are opened, reopened, or synchronized.

The "test" job is specified to run on a Ubuntu Latest environment. The steps in the job involve using the "anc95/ChatGPT-CodeReview@main" action and setting environment variables for the GitHub token and OpenAI API key.

One possible improvement suggestion could be to add more specific conditions for triggering the code review, such as only triggering it when certain criteria are met, e.g., specific file changes or changes in certain lines of code.

It is hard to assess bug risks without looking at the implementation of the ChatGPT-CodeReview action, but it would be important to thoroughly test the functionality and ensure that it is secure before using it in a production environment.

78 changes: 46 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,69 @@
# Pull Request Description Generator
# GPT-PullRequest-Updater

This Go program automates the process of generating GitHub pull request descriptions based on the changes made in each file. It uses OpenAI's GPT-3.5-turbo model to generate the descriptions and Jira issue links based on the PR title.
This repository contains a tool for updating and reviewing GitHub pull requests using OpenAI's GPT language model. The project has two commands: `description` and `review`. The `description` command updates the pull request description with a high-level summary of the changes made. The `review` command creates individual comments for each file and an overall review summary comment.

## Requirements

- GitHub token with access to the desired repository
- OpenAI API token

## Installation

To install the program, clone the repository and build the binary:
1. Clone the repository:

```sh
git clone https://github.com/your-repo/pull-request-description-generator.git
cd pull-request-description-generator
go build
```
```
git clone https://github.com/ravilushqa/gpt-pullrequest-updater.git
```

2. Navigate to the project root:

```
cd gpt-pullrequest-updater
```

3. Build the commands:

```
go build -o description ./cmd/description
go build -o review ./cmd/review
```

## Usage

Before running the program, you'll need to set the following environment variables:
Before running the commands, make sure you have set the following environment variables:

- `GITHUB_TOKEN`: Your GitHub token
- `OPENAI_TOKEN`: Your OpenAI API token
- `OWNER`: The owner of the GitHub repository
- `REPO`: The name of the GitHub repository
- `PR_NUMBER`: The pull request number you want to update or review

- `GITHUB_TOKEN`: Your GitHub access token.
- `OPENAI_TOKEN`: Your OpenAI access token.
- `OWNER`: The GitHub owner (username or organization) of the repository.
- `REPO`: The GitHub repository name.
- `PR_NUMBER`: The pull request number.
### Description Command

You can also use flags to provide the required information:
The `description` command updates the pull request description with a high-level summary of the changes made. To run the command, execute:

```
./pull-request-description-generator --gh-token <GITHUB_TOKEN> --openai-token <OPENAI_TOKEN> --owner <OWNER> --repo <REPO> --pr-number <PR_NUMBER>
./description
```

Optional flags:
### Review Command

- `--test`: Test mode. The generated description will be printed to the console without updating the pull request.
- `--skip-files`: Comma-separated list of files to skip when generating the description (default: "go.mod,go.sum,.pb.go").
The `review` command creates individual comments for each file and an overall review summary comment. To run the command, execute:

After running the program, the pull request description will be updated with the generated content.
```
./review
```

## Dependencies
### Test Mode

- [go-flags](https://github.com/jessevdk/go-flags): A Go library for command line flag parsing.
- [go-openai](https://github.com/sashabaranov/go-openai): A Go client for the OpenAI API.
Both commands support a test mode that prints the generated content to the console instead of updating the pull request. To enable test mode, set the `TEST` environment variable to `true`:

## Functions
```
export TEST=true
```

- `getDiffContent`: Fetches the diff content from the GitHub API.
- `parseGitDiffAndSplitPerFile`: Parses the git diff and splits it into a slice of FileDiff.
- `getFilenameFromDiffHeader`: Extracts the filename from a diff header.
- `generatePRDescription`: Generates the pull request description using the OpenAI API.
- `getPullRequestTitle`: Fetches the pull request title from the GitHub API.
- `generateJiraLinkByTitle`: Generates a Jira issue link based on the PR title.
- `updatePullRequestDescription`: Updates the pull request description on GitHub.
Then, run the desired command as described above. The generated content will be printed to the console.

## License

This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
This project is licensed under the MIT License.
64 changes: 64 additions & 0 deletions cmd/description/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# GPT Pull Request Updater

GPT Pull Request Updater is a command line tool that uses OpenAI's GPT-4 model to generate a comprehensive description of a GitHub pull request, including a summary of code changes. It then updates the pull request description with the generated summary.

## Prerequisites

To use the GPT Pull Request Updater, you need the following:
- A GitHub token with repository access
- An OpenAI API token

## Installation

1. Clone the repository:

```sh
git clone https://github.com/ravilushqa/gpt-pullrequest-updater.git
```

1. Change to the repository directory:

```sh
cd gpt-pullrequest-updater
```

1. Build the binary:

```sh
go build -o gpt-pr-updater
```

1. Add the binary to your PATH:

```sh
export PATH=$PATH:$(pwd)
```

## Usage

Run the GPT Pull Request Updater with the following command, providing the required flags:

```sh
gpt-pr-updater --gh-token GITHUB_TOKEN --openai-token OPENAI_TOKEN --owner OWNER --repo REPO --pr-number PR_NUMBER
```

### Flags

- `--gh-token` (required): Your GitHub token. Can also be set with the `GITHUB_TOKEN` environment variable.
- `--openai-token` (required): Your OpenAI API token. Can also be set with the `OPENAI_TOKEN` environment variable.
- `--owner` (required): GitHub repository owner. Can also be set with the `OWNER` environment variable.
- `--repo` (required): GitHub repository name. Can also be set with the `REPO` environment variable.
- `--pr-number` (required): The number of the pull request to update. Can also be set with the `PR_NUMBER` environment variable.
- `--test` (optional): If set, the tool will print the generated description to the console without updating the pull request. Can also be set with the `TEST` environment variable.

## Example

```sh
gpt-pr-updater --gh-token your_github_token --openai-token your_openai_token --owner ravilushqa --repo myrepo --pr-number 42
```

This command will fetch the pull request #42 from the `myrepo` repository, generate a summary of code changes using GPT-4, and update the pull request description with the generated summary.

## License

This project is released under the [MIT License](LICENSE).
103 changes: 103 additions & 0 deletions cmd/description/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package main

import (
"context"
"fmt"
"os"
"os/signal"
"syscall"

"github.com/google/go-github/v51/github"
"github.com/jessevdk/go-flags"
"github.com/sashabaranov/go-openai"

ghClient "github.com/ravilushqa/gpt-pullrequest-updater/github"
oAIClient "github.com/ravilushqa/gpt-pullrequest-updater/openai"
)

var opts struct {
GithubToken string `long:"gh-token" env:"GITHUB_TOKEN" description:"GitHub token" required:"true"`
OpenAIToken string `long:"openai-token" env:"OPENAI_TOKEN" description:"OpenAI token" required:"true"`
Owner string `long:"owner" env:"OWNER" description:"GitHub owner" required:"true"`
Repo string `long:"repo" env:"REPO" description:"GitHub repo" required:"true"`
PRNumber int `long:"pr-number" env:"PR_NUMBER" description:"Pull request number" required:"true"`
Test bool `long:"test" env:"TEST" description:"Test mode"`
}

func main() {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

if _, err := flags.Parse(&opts); err != nil {
if err.(*flags.Error).Type != flags.ErrHelp {
fmt.Printf("Error parsing flags: %v \n", err)
}
os.Exit(0)
}

if err := run(ctx); err != nil {
panic(err)
}
}

func run(ctx context.Context) error {
openAIClient := oAIClient.NewClient(opts.OpenAIToken)
githubClient := ghClient.NewClient(ctx, opts.GithubToken)

pr, err := githubClient.GetPullRequest(ctx, opts.Owner, opts.Repo, opts.PRNumber)
if err != nil {
return fmt.Errorf("error getting pull request: %w", err)
}

diff, err := githubClient.CompareCommits(ctx, opts.Owner, opts.Repo, pr.GetBase().GetSHA(), pr.GetHead().GetSHA())
if err != nil {
return fmt.Errorf("error getting commits: %w", err)
}

var OverallDescribeCompletion string
OverallDescribeCompletion += fmt.Sprintf("Pull request title: %s, body: %s\n\n", pr.GetTitle(), pr.GetBody())
for _, file := range diff.Files {
prompt := fmt.Sprintf(oAIClient.PromptDescribeChanges, *file.Patch)

if len(prompt) > 4096 {
prompt = fmt.Sprintf("%s...", prompt[:4093])
}

completion, err := openAIClient.ChatCompletion(ctx, []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: prompt,
},
})
if err != nil {
return fmt.Errorf("error getting review: %w", err)
}
OverallDescribeCompletion += fmt.Sprintf("File: %s \nDescription: %s \n\n", file.GetFilename(), completion)
}

overallCompletion, err := openAIClient.ChatCompletion(ctx, []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleUser,
Content: fmt.Sprintf(oAIClient.PromptOverallDescribe, OverallDescribeCompletion),
},
})
if err != nil {
return fmt.Errorf("error getting overall review: %w", err)
}

if opts.Test {
fmt.Println(OverallDescribeCompletion)
fmt.Println("=====================================")
fmt.Println(overallCompletion)

return nil
}

// Update the pull request description
updatePr := &github.PullRequest{Body: github.String(overallCompletion)}
if _, err = githubClient.UpdatePullRequest(ctx, opts.Owner, opts.Repo, opts.PRNumber, updatePr); err != nil {
return fmt.Errorf("error updating pull request: %w", err)
}

return nil
}
Loading