-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaction.yaml
142 lines (125 loc) · 4.8 KB
/
action.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
name: ChatGPT Code Review
description: Request code review from ChatGPT
inputs:
openai-api-key:
description: Github token
required: true
openai-model:
description: OpenAI model to use
default: gpt-3.5-turbo-16k
required: false
token-limit:
description: OpenAI model token limit
default: 16000
required: false
github-token:
description: Github token
required: true
runs:
using: composite
steps:
- name: Determine fetch depth
shell: bash
run: |
COMMITS=${{ github.event.pull_request.commits }}
echo BASE_REF="HEAD~$COMMITS" >> $GITHUB_ENV
echo FETCH_DEPTH=$(( COMMITS + 1 )) >> $GITHUB_ENV
- name: Checkout repository
uses: actions/checkout@v3
with:
ref: ${{ github.head_ref }}
fetch-depth: ${{ env.FETCH_DEPTH }}
- name: Install tiktoken
shell: bash
run: pip install tiktoken
- name: Request to ChatGPT Server
shell: python
env:
OPENAI_API_KEY: ${{ inputs.openai-api-key }}
OPENAI_MODEL: ${{ inputs.openai-model }}
TOKEN_LIMIT: ${{ inputs.token-limit }}
run: |
import os
import requests
import subprocess
import tiktoken
INSTRUCTIONS = """You are an expert code reviewer who upon receiving
the output of git diff command can automatically infer the programming
language and provide meaningful feedback on aspect of code changes that
are good and aspects that could be improved with example suggested code
improvements encapsulated in markdown code blocks where appropriate.
Pay special attention to distinguish between lines that are additions
and deletions focus on reviewing those, not the untouched code. Mention
the filename and the line number range if appropriate for each section
of code that you review."""
OPENAI_API_URL = "https://api.openai.com/v1/chat/completions"
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
OPENAI_MODEL = os.environ["OPENAI_MODEL"]
TOKEN_LIMIT = int(os.environ["TOKEN_LIMIT"])
BASE_REF = os.environ["BASE_REF"]
GITHUB_OUTPUT = os.environ["GITHUB_OUTPUT"]
def get_diff():
arguments = [
"git", "--no-pager", "diff", f"--diff-filter=ACDMRTUXB", f"{BASE_REF}..HEAD"
]
diff_process = subprocess.run(arguments,
capture_output=True,
text=True)
diff_process.check_returncode()
return diff_process.stdout.strip()
def complete(prompt):
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {OPENAI_API_KEY}"
}
body = {
"model": OPENAI_MODEL,
"messages": [{"role": "system", "content": INSTRUCTIONS}, {"role": "user", "content": prompt}], # hard cutoff
"temperature": 0.7,
}
response = requests.post(OPENAI_API_URL, headers=headers, json=body)
response.raise_for_status()
completion = response.json()["choices"][0]["message"]["content"].strip()
return completion
def review_diff(diff):
return complete(diff)
if __name__ == "__main__":
diff = get_diff()
print(diff)
if not diff:
review = "Nothing to review."
else:
enc = tiktoken.encoding_for_model(OPENAI_MODEL)
if (n_tokens := len(enc.encode(diff))) < TOKEN_LIMIT:
review = review_diff(diff)
else:
review = f"I cannot meaningfully review a diff with {n_tokens} tokens. Anything under {TOKEN_LIMIT} tokens is fine however."
with open(GITHUB_OUTPUT, "w") as f:
print("message<<EOF", file=f)
print(review, file=f)
print("EOF", file=f)
id: code_review
- name: Delete Previous Comment
uses: brtknr/delete-comment@v1
with:
github_token: "${{ inputs.github-token }}"
delete_user_name: "github-actions[bot]"
body_regex: "ChatGPT Code Review"
issue_number: "${{ github.event.number }}"
- name: PR comment URL
uses: actions/github-script@v6
env:
MESSAGE: ${{ steps.code_review.outputs.message }}
with:
github-token: ${{ inputs.github-token }}
script: |
const output = `
# :sparkles: ChatGPT Code Review :sparkles:
${process.env.MESSAGE}
`;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: output
})