Skip to content
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
80 changes: 80 additions & 0 deletions apps/sim/blocks/blocks/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,15 @@ export const GitHubBlock: BlockConfig<GitHubResponse> = {
{ label: 'Get PR files', id: 'github_get_pr_files' },
{ label: 'Close pull request', id: 'github_close_pr' },
{ label: 'Request PR reviewers', id: 'github_request_reviewers' },
{ label: 'Create PR review', id: 'github_create_pr_review' },
// File Operations
{ label: 'Get file content', id: 'github_get_file_content' },
{ label: 'Create file', id: 'github_create_file' },
{ label: 'Update file', id: 'github_update_file' },
{ label: 'Delete file', id: 'github_delete_file' },
{ label: 'Get directory tree', id: 'github_get_tree' },
{ label: 'Get README', id: 'github_get_readme' },
{ label: 'List tags', id: 'github_list_tags' },
// Branch Operations
{ label: 'List branches', id: 'github_list_branches' },
{ label: 'Get branch', id: 'github_get_branch' },
Expand All @@ -71,6 +74,7 @@ export const GitHubBlock: BlockConfig<GitHubResponse> = {
{ label: 'Update release', id: 'github_update_release' },
{ label: 'List releases', id: 'github_list_releases' },
{ label: 'Get release', id: 'github_get_release' },
{ label: 'Get latest release', id: 'github_get_latest_release' },
{ label: 'Delete release', id: 'github_delete_release' },
// Workflow Operations
{ label: 'List workflows', id: 'github_list_workflows' },
Expand Down Expand Up @@ -1598,6 +1602,68 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
},
mode: 'advanced',
},
// Create PR review parameters
{
id: 'pullNumber',
title: 'Pull Request Number',
type: 'short-input',
placeholder: 'e.g., 123',
required: true,
condition: { field: 'operation', value: 'github_create_pr_review' },
},
{
id: 'event',
title: 'Review Action',
type: 'dropdown',
options: [
{ label: 'Approve', id: 'APPROVE' },
{ label: 'Request changes', id: 'REQUEST_CHANGES' },
{ label: 'Comment', id: 'COMMENT' },
],
required: true,
condition: { field: 'operation', value: 'github_create_pr_review' },
},
{
id: 'body',
title: 'Review Body',
type: 'long-input',
placeholder: 'Review text (required for Request changes and Comment)',
condition: { field: 'operation', value: 'github_create_pr_review' },
},
{
id: 'commit_id',
title: 'Commit SHA',
type: 'short-input',
placeholder: 'e.g., 6dcb09b (defaults to the latest commit)',
condition: { field: 'operation', value: 'github_create_pr_review' },
mode: 'advanced',
},
// Get README parameters
{
id: 'ref',
title: 'Git Reference',
type: 'short-input',
placeholder: 'e.g., main (leave empty for default branch)',
condition: { field: 'operation', value: 'github_get_readme' },
mode: 'advanced',
},
// List tags parameters
{
id: 'per_page',
title: 'Results Per Page',
type: 'short-input',
placeholder: 'e.g., 30 (default: 30, max: 100)',
condition: { field: 'operation', value: 'github_list_tags' },
mode: 'advanced',
},
{
id: 'page',
title: 'Page Number',
type: 'short-input',
placeholder: 'e.g., 1',
condition: { field: 'operation', value: 'github_list_tags' },
mode: 'advanced',
},
],
tools: {
access: [
Expand All @@ -1619,12 +1685,15 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
'github_get_pr_files',
'github_close_pr',
'github_request_reviewers',
'github_create_pr_review',
// File tools
'github_get_file_content',
'github_create_file',
'github_update_file',
'github_delete_file',
'github_get_tree',
'github_get_readme',
'github_list_tags',
// Branch tools
'github_list_branches',
'github_get_branch',
Expand All @@ -1646,6 +1715,7 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
'github_update_release',
'github_list_releases',
'github_get_release',
'github_get_latest_release',
'github_delete_release',
// Workflow tools
'github_list_workflows',
Expand Down Expand Up @@ -1737,6 +1807,8 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
return 'github_close_pr'
case 'github_request_reviewers':
return 'github_request_reviewers'
case 'github_create_pr_review':
return 'github_create_pr_review'
// File operations
case 'github_get_file_content':
return 'github_get_file_content'
Expand All @@ -1748,6 +1820,10 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
return 'github_delete_file'
case 'github_get_tree':
return 'github_get_tree'
case 'github_get_readme':
return 'github_get_readme'
case 'github_list_tags':
return 'github_list_tags'
// Branch operations
case 'github_list_branches':
return 'github_list_branches'
Expand Down Expand Up @@ -1787,6 +1863,8 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
return 'github_list_releases'
case 'github_get_release':
return 'github_get_release'
case 'github_get_latest_release':
return 'github_get_latest_release'
case 'github_delete_release':
return 'github_delete_release'
// Workflow operations
Expand Down Expand Up @@ -1917,6 +1995,8 @@ Return ONLY the timestamp string - no explanations, no quotes, no extra text.`,
commit_title: { type: 'string', description: 'Commit title' },
reviewers: { type: 'string', description: 'Reviewer usernames' },
team_reviewers: { type: 'string', description: 'Team reviewer slugs' },
event: { type: 'string', description: 'PR review action' },
commit_id: { type: 'string', description: 'Commit SHA' },
// File parameters
content: { type: 'string', description: 'File content' },
message: { type: 'string', description: 'Commit message' },
Expand Down
8 changes: 5 additions & 3 deletions apps/sim/tools/github/add_labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const addLabelsTool: ToolConfig<AddLabelsParams, LabelsResponse> = {
},
},

transformResponse: async (response) => {
transformResponse: async (response, params) => {
const labelsData = await response.json()

const labels = labelsData.map((label: any) => label.name)
Expand All @@ -74,8 +74,10 @@ All labels on issue: ${labels.join(', ')}`
content,
metadata: {
labels,
issue_number: 0, // Will be filled from params in actual implementation
html_url: '', // Will be constructed from params
issue_number: params?.issue_number ?? 0,
html_url: params
? `https://github.com/${params.owner}/${params.repo}/issues/${params.issue_number}`
: '',
},
},
}
Expand Down
182 changes: 182 additions & 0 deletions apps/sim/tools/github/create_pr_review.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import type { CreatePRReviewParams, PRReviewResponse } from '@/tools/github/types'
import { USER_OUTPUT } from '@/tools/github/types'
import type { ToolConfig } from '@/tools/types'

export const createPRReviewTool: ToolConfig<CreatePRReviewParams, PRReviewResponse> = {
id: 'github_create_pr_review',
name: 'GitHub Create PR Review',
description:
'Submit a review for a pull request. Use APPROVE, REQUEST_CHANGES, or COMMENT. A body is required for REQUEST_CHANGES and COMMENT reviews.',
version: '1.0.0',

params: {
owner: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Repository owner',
},
repo: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'Repository name',
},
pullNumber: {
type: 'number',
required: true,
visibility: 'user-or-llm',
description: 'Pull request number',
},
event: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The review action to perform: APPROVE, REQUEST_CHANGES, or COMMENT',
},
body: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The body text of the review (required for REQUEST_CHANGES and COMMENT)',
},
commit_id: {
type: 'string',
required: false,
visibility: 'user-or-llm',
description: 'The SHA of the commit that needs a review (defaults to the most recent commit)',
},
apiKey: {
type: 'string',
required: true,
visibility: 'user-only',
description: 'GitHub API token',
},
},

request: {
url: (params) =>
`https://api.github.com/repos/${params.owner}/${params.repo}/pulls/${params.pullNumber}/reviews`,
method: 'POST',
headers: (params) => ({
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${params.apiKey}`,
'X-GitHub-Api-Version': '2022-11-28',
}),
body: (params) => {
const body: Record<string, any> = {
event: params.event,
}
if (params.body) body.body = params.body
if (params.commit_id) body.commit_id = params.commit_id
return body
},
},

transformResponse: async (response) => {
if (!response.ok) {
const error = await response.json().catch(() => ({}))
return {
success: false,
error: error.message || `Failed to submit PR review (HTTP ${response.status})`,
output: {
content: '',
metadata: { id: 0, state: '', body: '', html_url: '', commit_id: '' },
},
}
}

const review = await response.json()

const content = `Review submitted for PR #${review.pull_request_url?.split('/').pop() ?? ''}
State: ${review.state}
URL: ${review.html_url}`

return {
success: true,
output: {
content,
metadata: {
id: review.id,
state: review.state,
body: review.body ?? '',
html_url: review.html_url,
commit_id: review.commit_id,
},
},
}
},

outputs: {
content: { type: 'string', description: 'Human-readable review confirmation' },
metadata: {
type: 'object',
description: 'Review metadata',
properties: {
id: { type: 'number', description: 'Review ID' },
state: {
type: 'string',
description: 'Review state (APPROVED/CHANGES_REQUESTED/COMMENTED)',
},
body: { type: 'string', description: 'Review body text' },
html_url: { type: 'string', description: 'GitHub web URL for the review' },
commit_id: { type: 'string', description: 'SHA of the reviewed commit' },
},
},
},
}

export const createPRReviewV2Tool: ToolConfig<CreatePRReviewParams, any> = {
id: 'github_create_pr_review_v2',
name: createPRReviewTool.name,
description: createPRReviewTool.description,
version: '2.0.0',
params: createPRReviewTool.params,
request: createPRReviewTool.request,

transformResponse: async (response: Response) => {
if (!response.ok) {
const error = await response.json().catch(() => ({}))
return {
success: false,
error: error.message || `Failed to submit PR review (HTTP ${response.status})`,
output: {
id: 0,
user: null,
body: null,
state: '',
html_url: '',
pull_request_url: '',
commit_id: '',
submitted_at: null,
},
}
}

const review = await response.json()
return {
success: true,
output: {
id: review.id,
user: review.user ?? null,
body: review.body ?? null,
state: review.state,
html_url: review.html_url,
pull_request_url: review.pull_request_url,
commit_id: review.commit_id,
submitted_at: review.submitted_at ?? null,
},
}
},

outputs: {
id: { type: 'number', description: 'Review ID' },
user: { ...USER_OUTPUT, optional: true },
body: { type: 'string', description: 'Review body text' },
state: { type: 'string', description: 'Review state (APPROVED/CHANGES_REQUESTED/COMMENTED)' },
html_url: { type: 'string', description: 'GitHub web URL for the review' },
pull_request_url: { type: 'string', description: 'API URL of the reviewed pull request' },
commit_id: { type: 'string', description: 'SHA of the reviewed commit' },
submitted_at: { type: 'string', description: 'Review submission timestamp' },
},
}
19 changes: 12 additions & 7 deletions apps/sim/tools/github/delete_comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,20 @@ export const deleteCommentTool: ToolConfig<DeleteCommentParams, DeleteCommentRes
}),
},

transformResponse: async (response) => {
const content = `Comment #${response.url.split('/').pop()} successfully deleted`
transformResponse: async (response, params) => {
const deleted = response.status === 204
const commentId = params?.comment_id ?? Number(response.url.split('/').pop())
const content = deleted
? `Comment #${commentId} successfully deleted`
: `Failed to delete comment #${commentId}`

return {
success: true,
success: deleted,
output: {
content,
metadata: {
deleted: true,
comment_id: Number(response.url.split('/').pop()),
deleted,
comment_id: commentId,
},
},
}
Comment thread
waleedlatif1 marked this conversation as resolved.
Expand Down Expand Up @@ -82,10 +86,11 @@ export const deleteCommentV2Tool: ToolConfig<DeleteCommentParams, any> = {
request: deleteCommentTool.request,

transformResponse: async (response: Response, params) => {
const deleted = response.status === 204
return {
success: true,
success: deleted,
output: {
deleted: response.status === 204,
deleted,
comment_id: params?.comment_id || 0,
},
}
Expand Down
Loading
Loading