Skip to content

Commit

Permalink
Merge pull request #16 from ca-dp/releases/add-chat-cmd
Browse files Browse the repository at this point in the history
add chat cmd
  • Loading branch information
ouchi2501 authored Sep 27, 2023
2 parents 2ea8460 + 401e3ee commit 528b85e
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 24 deletions.
13 changes: 13 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Overview

copilot:summary

# Explanation of Changes

copilot: walkthrough

copilot:poem

# Related Issues

<!---Please lint to the issue here.--->
2 changes: 2 additions & 0 deletions .github/linters/.markdown-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ MD029:
# Line length
MD013:
line_length: 120

MD025: false
39 changes: 38 additions & 1 deletion __tests__/github.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import * as core from '@actions/core'
import * as github from '@actions/github'
import nock from 'nock' // Import nock for mocking HTTP requests

import { getPullRequestDiff, createGitHubComment } from '../src/github' // Please specify the path to your module
import {
getPullRequestDiff,
createGitHubComment,
getIssueComment
} from '../src/github' // Please specify the path to your module

const getInputMock = jest.spyOn(core, 'getInput')
// Set the GITHUB_REPOSITORY environment variable for testing
Expand Down Expand Up @@ -76,3 +80,36 @@ describe('createGitHubComment', () => {
// Test that the GitHub API request is successful
})
})

describe('getIssueComment', () => {
it('should return the issue comment', async () => {
getInputMock.mockImplementation((name: string): string => {
switch (name) {
case 'GITHUB_TOKEN':
return 'token'
default:
return ''
}
})
github.context.payload = {
issue: {
// Mock the issue number
number: 2
}
}
nock('https://api.github.com', {
reqheaders: {
accept: 'application/vnd.github.v3+json',
authorization: 'token token',
'accept-encoding': 'gzip,deflate'
}
})
.get('/repos/test-org/test-repo/issues/comments/2')
.reply(200, {
body: 'This is a test comment'
})

const comment = await getIssueComment()
expect(comment).toBe('This is a test comment')
})
})
99 changes: 98 additions & 1 deletion __tests__/main.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as github from '../src/github'
import * as ai from '../src/ai'
import * as process from 'process'
import * as prompt from '../src/prompt'
import * as main from '../src/main' // Import the main module
import * as main from '../src/main'

const getInputMock = jest.spyOn(core, 'getInput')
// Set the GITHUB_REPOSITORY environment variable for testing
Expand All @@ -34,6 +34,8 @@ describe('run', () => {
switch (name) {
case 'OPENAI_API_KEY':
return 'mocked-api-key'
case 'cmd':
return 'review'
default:
return ''
}
Expand Down Expand Up @@ -66,6 +68,8 @@ describe('run', () => {
return 'token'
case 'OPENAI_API_KEY':
return 'mocked-api-key'
case 'cmd':
return 'review'
default:
return ''
}
Expand All @@ -92,5 +96,98 @@ describe('run', () => {
delete process.env.OPENAI_API_KEY
})

it('should handle unknown command', async () => {
getInputMock.mockImplementation((name: string): string => {
switch (name) {
case 'GITHUB_TOKEN':
return 'token'
case 'OPENAI_API_KEY':
return 'mocked-api-key'
case 'cmd':
return 'unknown'
default:
return ''
}
})
const setFailedMock = jest.spyOn(core, 'setFailed')
await main.run()
expect(setFailedMock).toHaveBeenCalledWith('Unknown command')
})

it('should run the action successfully on chat', async () => {
// Create mock functions
const getIssueCommentMock = jest.spyOn(github, 'getIssueComment')
getIssueCommentMock.mockResolvedValue('Mocked issue comment')

const completionRequestMock = jest.spyOn(ai, 'completionRequest')
completionRequestMock.mockResolvedValue('Mocked AI response')

const createGitHubCommentMock = jest.spyOn(github, 'createGitHubComment')
createGitHubCommentMock.mockResolvedValue(undefined)

// Set required environment variables
getInputMock.mockImplementation((name: string): string => {
switch (name) {
case 'OPENAI_API_KEY':
return 'mocked-api-key'
case 'cmd':
return 'chat'
default:
return ''
}
})

// Set a dummy prompt
const getChatSystemPromptMock = jest.spyOn(prompt, 'getChatSystemPrompt')
getChatSystemPromptMock.mockReturnValue('Mocked system prompt')

// Call the function under test
await main.run()

// Ensure each function was called correctly
expect(getIssueCommentMock).toHaveBeenCalled()
expect(completionRequestMock).toHaveBeenCalledWith(
'mocked-api-key',
'Mocked system prompt',
'Mocked issue comment'
)
expect(createGitHubCommentMock).toHaveBeenCalledWith('Mocked AI response')
})

it('should handle empty AI response message on chat', async () => {
getInputMock.mockImplementation((name: string): string => {
switch (name) {
case 'GITHUB_TOKEN':
return 'token'
case 'OPENAI_API_KEY':
return 'mocked-api-key'
case 'cmd':
return 'chat'
default:
return ''
}
})

// Set up a spy to capture the error message
const setFailedMock = jest.spyOn(core, 'setFailed')

// Create mock functions
const getIssueCommentMock = jest.spyOn(github, 'getIssueComment')
getIssueCommentMock.mockResolvedValue('Mocked issue comment')

// Mock AI response with an empty message
const completionRequestMock = jest.spyOn(ai, 'completionRequest')
completionRequestMock.mockResolvedValue('')

// Call the function under test
await main.run()

// Ensure the error message was set correctly
expect(setFailedMock).toHaveBeenCalledWith('Response content is missing')

// Clear environment variables
delete process.env.OPENAI_API_KEY
})

// Additional test cases for other error scenarios can be added
})
15 changes: 15 additions & 0 deletions __tests__/prompt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,18 @@ describe('getCodeReviewSystemPrompt', () => {
expect(result).toEqual(expectedPrompt)
})
})

describe('getChatSystemPrompt', () => {
it('should return the correct system prompt', () => {
const expectedPrompt = `
You are Software-Developer, a language model designed to chat with software developers.
Your task is to chat with the user, and respond to questions from troubled software developers and solve their problems.
Please ignore the '/chat' at the beginning of the question.
Also, don't repeat the prompt in your answer.
`

const result = prompt.getChatSystemPrompt()

expect(result).toEqual(expectedPrompt)
})
})
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ inputs:
OPENAI_API_KEY:
description: 'OpenAI API Key'
required: true
cmd:
description: 'Command to run(review or chat)'
required: true

runs:
using: node20
Expand Down
2 changes: 1 addition & 1 deletion badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 50 additions & 11 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions src/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,16 @@ export async function createGitHubComment(message: string): Promise<void> {
body: message
})
}

export async function getIssueComment(): Promise<string> {
const token = core.getInput('GITHUB_TOKEN', { required: true })
const octokit = github.getOctokit(token)

const { data: comment } = await octokit.rest.issues.getComment({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
comment_id: github.context.issue.number
})

return (comment.body as unknown as string) || ''
}
Loading

0 comments on commit 528b85e

Please sign in to comment.