From 34550d128b1804d364e026929d0302d5b6ed0f41 Mon Sep 17 00:00:00 2001 From: bucolucas Date: Tue, 20 Aug 2024 18:49:00 -0500 Subject: [PATCH 1/4] Add project management functions for creating boards, columns, and cards. --- tools/github_tool.py | 326 +++++++++++++++++++++---------------------- 1 file changed, 162 insertions(+), 164 deletions(-) diff --git a/tools/github_tool.py b/tools/github_tool.py index 24c5492..8267f46 100644 --- a/tools/github_tool.py +++ b/tools/github_tool.py @@ -1,4 +1,3 @@ -# tools/github_tool.py from .base_tool import BaseTool from .metrics import metrics import requests @@ -407,6 +406,104 @@ class GitHubTool(BaseTool): }, "required": ["issue_number"] } + }, + { + "name": "create_project_board", + "description": "Create a new project board", + "parameters": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the project board" + }, + "body": { + "type": "string", + "description": "Body of the project board" + } + }, + "required": ["name"] + } + }, + { + "name": "create_project_column", + "description": "Create a new column in a project board", + "parameters": { + "type": "object", + "properties": { + "project_id": { + "type": "integer", + "description": "ID of the project board" + }, + "column_name": { + "type": "string", + "description": "Name of the column" + } + }, + "required": ["project_id", "column_name"] + } + }, + { + "name": "create_project_card", + "description": "Create a new card in a project column", + "parameters": { + "type": "object", + "properties": { + "column_id": { + "type": "integer", + "description": "ID of the project column" + }, + "note": { + "type": "string", + "description": "Note for the project card" + } + }, + "required": ["column_id", "note"] + } + }, + { + "name": "move_project_card", + "description": "Move a card to a new position", + "parameters": { + "type": "object", + "properties": { + "card_id": { + "type": "integer", + "description": "ID of the project card" + }, + "position": { + "type": "string", + "description": "New position of the card" + }, + "column_id": { + "type": "integer", + "description": "ID of the target column" + } + }, + "required": ["card_id", "position", "column_id"] + } + }, + { + "name": "link_issue_to_project_card", + "description": "Link an issue or pull request to a project card", + "parameters": { + "type": "object", + "properties": { + "card_id": { + "type": "integer", + "description": "ID of the project card" + }, + "content_id": { + "type": "integer", + "description": "ID of the issue or pull request" + }, + "content_type": { + "type": "string", + "description": "Type of the content (Issue or PullRequest)" + } + }, + "required": ["card_id", "content_id", "content_type"] + } } ] @@ -432,31 +529,16 @@ class GitHubTool(BaseTool): return self._get_current_branch() elif function_name == "set_current_branch": return self._set_current_branch(kwargs["branch_name"]) - elif function_name == "get_file_at_commit": - return self._get_file_at_commit(kwargs["file_path"], kwargs["commit_sha"]) - elif function_name == "list_branches": - return self._list_branches(kwargs.get("per_page", 100), kwargs.get("all_pages", True)) - elif function_name == "get_branch_sha": - return self._get_branch_sha(kwargs["branch"]) - elif function_name == "approve_pull_request": - return self._approve_pull_request(kwargs["pull_number"]) - elif function_name == "close_pull_request": - return self._close_pull_request(kwargs["pull_number"]) - elif function_name == "merge_pull_request": - return self._merge_pull_request(kwargs["pull_number"], kwargs.get("commit_title", "Merge pull request"), - kwargs.get("commit_message", ""), kwargs.get("merge_method", "merge")) - elif function_name == "delete_branch": - return self._delete_branch(kwargs["branch_name"]) - elif function_name == "get_issue_details": - return self._get_issue_details(kwargs["issue_number"]) - elif function_name == "create_issue": - return self._create_issue(kwargs["title"], kwargs["body"], kwargs.get("labels", [])) - elif function_name == "list_issues": - return self._list_issues(kwargs.get("state", "open"), kwargs.get("per_page", 30), kwargs.get("page", 1)) - elif function_name == "add_issue_comment": - return self._add_issue_comment(kwargs["issue_number"], kwargs["comment"]) - elif function_name == "get_issue_comments": - return self._get_issue_comments(kwargs["issue_number"]) + elif function_name == "create_project_board": + return self._create_project_board(kwargs["name"], kwargs.get("body")) + elif function_name == "create_project_column": + return self._create_project_column(kwargs["project_id"], kwargs["column_name"]) + elif function_name == "create_project_card": + return self._create_project_card(kwargs["column_id"], kwargs["note"]) + elif function_name == "move_project_card": + return self._move_project_card(kwargs["card_id"], kwargs["position"], kwargs["column_id"]) + elif function_name == "link_issue_to_project_card": + return self._link_issue_to_project_card(kwargs["card_id"], kwargs["content_id"], kwargs["content_type"]) else: error_message = f"Unknown function: {function_name}" self.logger.error(error_message) @@ -478,127 +560,75 @@ class GitHubTool(BaseTool): return error_message @metrics.measure - def _create_branch(self, branch_name, base_branch): - self.logger.info(f"Creating branch: {branch_name} from base: {base_branch}") - url = f"{self.base_url}/repos/{self.repo}/git/refs" - response = requests.get(f"{url}/heads/{base_branch}", headers=self.headers) - if response.status_code != 200: - error_message = f"Error getting base branch: {response.status_code}" - self.logger.error(error_message) - return error_message - - sha = response.json()["object"]["sha"] - data = { - "ref": f"refs/heads/{branch_name}", - "sha": sha - } + def _create_project_board(self, name, body=None): + url = f"{self.base_url}/repos/{self.repo}/projects" + data = {"name": name, "body": body} response = requests.post(url, headers=self.headers, json=data) if response.status_code == 201: - self.current_branch = branch_name - success_message = f"Branch '{branch_name}' created successfully and set as current branch" + project = response.json() + success_message = f"Project board '{name}' created successfully." self.logger.info(success_message) return success_message else: - error_message = f"Error creating branch: {response.status_code}" + error_message = f"Error creating project board: {response.status_code}" self.logger.error(error_message) return error_message @metrics.measure - def _commit_file(self, file_path, content, commit_message): - self.logger.info(f"Committing file: {file_path} to branch: {self.current_branch}") - if self.current_branch == "main": - error_message = "Cannot commit directly to main branch" - self.logger.error(error_message) - return error_message - - url = f"{self.base_url}/repos/{self.repo}/contents/{file_path}" - - self.logger.info("Checking if file already exists") - response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) - - data = { - "message": commit_message, - "content": base64.b64encode(content.encode()).decode(), - "branch": self.current_branch - } - - if response.status_code == 200: - self.logger.info("File exists, updating") - file_sha = response.json()["sha"] - data["sha"] = file_sha - else: - self.logger.info("File does not exist, creating new file") - - response = requests.put(url, headers=self.headers, json=data) - - if response.status_code in [200, 201]: - success_message = f"File committed successfully to branch '{self.current_branch}'" - self.logger.info(success_message) - return success_message - else: - error_message = f"Error committing file: {response.status_code}\nResponse: {response.text}" - self.logger.error(error_message) - return error_message - - @metrics.measure - def _create_pull_request(self, title, body, base): - self.logger.info(f"Creating pull request: {title} from {self.current_branch} to {base}") - url = f"{self.base_url}/repos/{self.repo}/pulls" - data = { - "title": title, - "body": body, - "head": self.current_branch, - "base": base - } + def _create_project_column(self, project_id, column_name): + url = f"{self.base_url}/projects/{project_id}/columns" + data = {"name": column_name} response = requests.post(url, headers=self.headers, json=data) if response.status_code == 201: - success_message = f"Pull request created successfully: {response.json()['html_url']}" + column = response.json() + success_message = f"Column '{column_name}' created successfully in project {project_id}." self.logger.info(success_message) return success_message else: - error_message = f"Error creating pull request: {response.status_code}\nResponse: {response.text}" + error_message = f"Error creating project column: {response.status_code}" self.logger.error(error_message) return error_message @metrics.measure - def _get_branch_sha(self, branch): - url = f"{self.base_url}/repos/{self.repo}/git/refs/heads/{branch}" - response = requests.get(url, headers=self.headers) - if response.status_code == 200: - return response.json()["object"]["sha"] - else: - return f"Error getting branch SHA: {response.status_code}" - - @metrics.measure - def _list_files(self, path): - self.logger.info(f"Listing files in: {path} on branch: {self.current_branch}") - url = f"{self.base_url}/repos/{self.repo}/contents/{path}" - response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) - if response.status_code == 200: - files = [item["name"] for item in response.json() if item["type"] == "file"] - directories = [item["name"] for item in response.json() if item["type"] == "dir"] - self.logger.info(f"Successfully listed files and directories in {path}") - return {"files": files, "directories": directories} + def _create_project_card(self, column_id, note): + url = f"{self.base_url}/projects/columns/{column_id}/cards" + data = {"note": note} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + card = response.json() + success_message = f"Card created successfully in column {column_id}." + self.logger.info(success_message) + return success_message else: - error_message = f"Error listing files: {response.status_code}" + error_message = f"Error creating project card: {response.status_code}" self.logger.error(error_message) return error_message @metrics.measure - def _search_code(self, query): - self.logger.info(f"Searching code with query: {query}") - url = f"{self.base_url}/search/code" - params = { - "q": f"{query} repo:{self.repo}", - "per_page": 10 - } - response = requests.get(url, headers=self.headers, params=params) - if response.status_code == 200: - results = [{"file": item["path"], "url": item["html_url"]} for item in response.json()["items"]] - self.logger.info(f"Successfully searched code. Found {len(results)} results.") - return results + def _move_project_card(self, card_id, position, column_id): + url = f"{self.base_url}/projects/columns/cards/{card_id}/moves" + data = {"position": position, "column_id": column_id} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + success_message = f"Card {card_id} moved successfully." + self.logger.info(success_message) + return success_message else: - error_message = f"Error searching code: {response.status_code}" + error_message = f"Error moving project card: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _link_issue_to_project_card(self, card_id, content_id, content_type): + url = f"{self.base_url}/projects/columns/cards/{card_id}" + data = {"content_id": content_id, "content_type": content_type} + response = requests.patch(url, headers=self.headers, json=data) + if response.status_code == 200: + success_message = f"Issue/PR linked to card {card_id} successfully." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error linking issue/PR to project card: {response.status_code}" self.logger.error(error_message) return error_message @@ -606,10 +636,7 @@ class GitHubTool(BaseTool): def _get_commit_history(self, file_path, num_commits): self.logger.info(f"Getting commit history for file: {file_path}, number of commits: {num_commits}") url = f"{self.base_url}/repos/{self.repo}/commits" - params = { - "path": file_path, - "per_page": num_commits - } + params = {"path": file_path, "per_page": num_commits} response = requests.get(url, headers=self.headers, params=params) if response.status_code == 200: commits = [{"sha": commit["sha"], "message": commit["commit"]["message"], "date": commit["commit"]["author"]["date"]} for commit in response.json()] @@ -680,9 +707,7 @@ class GitHubTool(BaseTool): def _approve_pull_request(self, pull_number): self.logger.info(f"Approving pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}/reviews" - data = { - "event": "APPROVE" - } + data = {"event": "APPROVE"} response = requests.post(url, headers=self.headers, json=data) if response.status_code == 200: success_message = f"Pull request {pull_number} approved successfully" @@ -697,9 +722,7 @@ class GitHubTool(BaseTool): def _close_pull_request(self, pull_number): self.logger.info(f"Closing pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}" - data = { - "state": "closed" - } + data = {"state": "closed"} response = requests.patch(url, headers=self.headers, json=data) if response.status_code == 200: success_message = f"Pull request {pull_number} closed successfully" @@ -714,11 +737,7 @@ class GitHubTool(BaseTool): def _merge_pull_request(self, pull_number, commit_title, commit_message, merge_method): self.logger.info(f"Merging pull request: {pull_number}") url = f"{self.base_url}/repos/{self.repo}/pulls/{pull_number}/merge" - data = { - "commit_title": commit_title, - "commit_message": commit_message, - "merge_method": merge_method - } + data = {"commit_title": commit_title, "commit_message": commit_message, "merge_method": merge_method} response = requests.put(url, headers=self.headers, json=data) if response.status_code == 200: success_message = f"Pull request {pull_number} merged successfully" @@ -771,10 +790,7 @@ class GitHubTool(BaseTool): def _create_issue(self, title, body, labels=None): self.logger.info(f"Creating issue: {title}") url = f"{self.base_url}/repos/{self.repo}/issues" - data = { - "title": title, - "body": body - } + data = {"title": title, "body": body} if labels: data["labels"] = labels response = requests.post(url, headers=self.headers, json=data) @@ -792,20 +808,10 @@ class GitHubTool(BaseTool): def _list_issues(self, state="open", per_page=30, page=1): self.logger.info(f"Listing issues. State: {state}, Per page: {per_page}, Page: {page}") url = f"{self.base_url}/repos/{self.repo}/issues" - params = { - "state": state, - "per_page": per_page, - "page": page - } + params = {"state": state, "per_page": per_page, "page": page} response = requests.get(url, headers=self.headers, params=params) if response.status_code == 200: - issues = [{ - "number": issue["number"], - "title": issue["title"], - "state": issue["state"], - "created_at": issue["created_at"], - "url": issue["html_url"] - } for issue in response.json()] + issues = [{"number": issue["number"], "title": issue["title"], "state": issue["state"], "created_at": issue["created_at"], "url": issue["html_url"]} for issue in response.json()] self.logger.info(f"Successfully listed issues. Found {len(issues)} issues.") return issues else: @@ -817,9 +823,7 @@ class GitHubTool(BaseTool): def _add_issue_comment(self, issue_number, comment): self.logger.info(f"Adding comment to issue: {issue_number}") url = f"{self.base_url}/repos/{self.repo}/issues/{issue_number}/comments" - data = { - "body": comment - } + data = {"body": comment} response = requests.post(url, headers=self.headers, json=data) if response.status_code == 201: comment_data = response.json() @@ -837,13 +841,7 @@ class GitHubTool(BaseTool): url = f"{self.base_url}/repos/{self.repo}/issues/{issue_number}/comments" response = requests.get(url, headers=self.headers) if response.status_code == 200: - comments = [{ - "id": comment["id"], - "user": comment["user"]["login"], - "body": comment["body"], - "created_at": comment["created_at"], - "updated_at": comment["updated_at"] - } for comment in response.json()] + comments = [{"id": comment["id"], "user": comment["user"]["login"], "body": comment["body"], "created_at": comment["created_at"], "updated_at": comment["updated_at"]} for comment in response.json()] self.logger.info(f"Successfully retrieved comments for issue {issue_number}. Found {len(comments)} comments.") return comments else: From ca2b0bd6677da07ddfeccba054f121d447a1992e Mon Sep 17 00:00:00 2001 From: bucolucas Date: Tue, 20 Aug 2024 18:54:57 -0500 Subject: [PATCH 2/4] Recommit github_tool.py with missing pieces added back --- tools/github_tool.py | 160 +++++++++++++++++++++++++++++-------------- 1 file changed, 108 insertions(+), 52 deletions(-) diff --git a/tools/github_tool.py b/tools/github_tool.py index 8267f46..1b07ce5 100644 --- a/tools/github_tool.py +++ b/tools/github_tool.py @@ -1,3 +1,4 @@ +# tools/github_tool.py from .base_tool import BaseTool from .metrics import metrics import requests @@ -560,75 +561,127 @@ class GitHubTool(BaseTool): return error_message @metrics.measure - def _create_project_board(self, name, body=None): - url = f"{self.base_url}/repos/{self.repo}/projects" - data = {"name": name, "body": body} + def _create_branch(self, branch_name, base_branch): + self.logger.info(f"Creating branch: {branch_name} from base: {base_branch}") + url = f"{self.base_url}/repos/{self.repo}/git/refs" + response = requests.get(f"{url}/heads/{base_branch}", headers=self.headers) + if response.status_code != 200: + error_message = f"Error getting base branch: {response.status_code}" + self.logger.error(error_message) + return error_message + + sha = response.json()["object"]["sha"] + data = { + "ref": f"refs/heads/{branch_name}", + "sha": sha + } response = requests.post(url, headers=self.headers, json=data) if response.status_code == 201: - project = response.json() - success_message = f"Project board '{name}' created successfully." + self.current_branch = branch_name + success_message = f"Branch '{branch_name}' created successfully and set as current branch" self.logger.info(success_message) return success_message else: - error_message = f"Error creating project board: {response.status_code}" + error_message = f"Error creating branch: {response.status_code}" self.logger.error(error_message) return error_message @metrics.measure - def _create_project_column(self, project_id, column_name): - url = f"{self.base_url}/projects/{project_id}/columns" - data = {"name": column_name} - response = requests.post(url, headers=self.headers, json=data) - if response.status_code == 201: - column = response.json() - success_message = f"Column '{column_name}' created successfully in project {project_id}." - self.logger.info(success_message) - return success_message - else: - error_message = f"Error creating project column: {response.status_code}" + def _commit_file(self, file_path, content, commit_message): + self.logger.info(f"Committing file: {file_path} to branch: {self.current_branch}") + if self.current_branch == "main": + error_message = "Cannot commit directly to main branch" self.logger.error(error_message) return error_message - @metrics.measure - def _create_project_card(self, column_id, note): - url = f"{self.base_url}/projects/columns/{column_id}/cards" - data = {"note": note} - response = requests.post(url, headers=self.headers, json=data) - if response.status_code == 201: - card = response.json() - success_message = f"Card created successfully in column {column_id}." - self.logger.info(success_message) - return success_message - else: - error_message = f"Error creating project card: {response.status_code}" - self.logger.error(error_message) - return error_message + url = f"{self.base_url}/repos/{self.repo}/contents/{file_path}" - @metrics.measure - def _move_project_card(self, card_id, position, column_id): - url = f"{self.base_url}/projects/columns/cards/{card_id}/moves" - data = {"position": position, "column_id": column_id} - response = requests.post(url, headers=self.headers, json=data) - if response.status_code == 201: - success_message = f"Card {card_id} moved successfully." - self.logger.info(success_message) - return success_message - else: - error_message = f"Error moving project card: {response.status_code}" - self.logger.error(error_message) - return error_message + self.logger.info("Checking if file already exists") + response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) + + data = { + "message": commit_message, + "content": base64.b64encode(content.encode()).decode(), + "branch": self.current_branch + } - @metrics.measure - def _link_issue_to_project_card(self, card_id, content_id, content_type): - url = f"{self.base_url}/projects/columns/cards/{card_id}" - data = {"content_id": content_id, "content_type": content_type} - response = requests.patch(url, headers=self.headers, json=data) if response.status_code == 200: - success_message = f"Issue/PR linked to card {card_id} successfully." + self.logger.info("File exists, updating") + file_sha = response.json()["sha"] + data["sha"] = file_sha + else: + self.logger.info("File does not exist, creating new file") + + response = requests.put(url, headers=self.headers, json=data) + + if response.status_code in [200, 201]: + success_message = f"File committed successfully to branch '{self.current_branch}'" self.logger.info(success_message) return success_message else: - error_message = f"Error linking issue/PR to project card: {response.status_code}" + error_message = f"Error committing file: {response.status_code}\nResponse: {response.text}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _create_pull_request(self, title, body, base): + self.logger.info(f"Creating pull request: {title} from {self.current_branch} to {base}") + url = f"{self.base_url}/repos/{self.repo}/pulls" + data = { + "title": title, + "body": body, + "head": self.current_branch, + "base": base + } + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + success_message = f"Pull request created successfully: {response.json()['html_url']}" + self.logger.info(success_message) + return success_message + else: + error_message = f"Error creating pull request: {response.status_code}\nResponse: {response.text}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _get_branch_sha(self, branch): + url = f"{self.base_url}/repos/{self.repo}/git/refs/heads/{branch}" + response = requests.get(url, headers=self.headers) + if response.status_code == 200: + return response.json()["object"]["sha"] + else: + return f"Error getting branch SHA: {response.status_code}" + + @metrics.measure + def _list_files(self, path): + self.logger.info(f"Listing files in: {path} on branch: {self.current_branch}") + url = f"{self.base_url}/repos/{self.repo}/contents/{path}" + response = requests.get(url, headers=self.headers, params={"ref": self.current_branch}) + if response.status_code == 200: + files = [item["name"] for item in response.json() if item["type"] == "file"] + directories = [item["name"] for item in response.json() if item["type"] == "dir"] + self.logger.info(f"Successfully listed files and directories in {path}") + return {"files": files, "directories": directories} + else: + error_message = f"Error listing files: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _search_code(self, query): + self.logger.info(f"Searching code with query: {query}") + url = f"{self.base_url}/search/code" + params = { + "q": f"{query} repo:{self.repo}", + "per_page": 10 + } + response = requests.get(url, headers=self.headers, params=params) + if response.status_code == 200: + results = [{"file": item["path"], "url": item["html_url"]} for item in response.json()["items"]] + self.logger.info(f"Successfully searched code. Found {len(results)} results.") + return results + else: + error_message = f"Error searching code: {response.status_code}" self.logger.error(error_message) return error_message @@ -636,7 +689,10 @@ class GitHubTool(BaseTool): def _get_commit_history(self, file_path, num_commits): self.logger.info(f"Getting commit history for file: {file_path}, number of commits: {num_commits}") url = f"{self.base_url}/repos/{self.repo}/commits" - params = {"path": file_path, "per_page": num_commits} + params = { + "path": file_path, + "per_page": num_commits + } response = requests.get(url, headers=self.headers, params=params) if response.status_code == 200: commits = [{"sha": commit["sha"], "message": commit["commit"]["message"], "date": commit["commit"]["author"]["date"]} for commit in response.json()] From e3fd071dc211ed65cb882fbb71dcf287672e8f6d Mon Sep 17 00:00:00 2001 From: bucolucas Date: Tue, 20 Aug 2024 19:09:19 -0500 Subject: [PATCH 3/4] Recommit github_tool.py with all function calls and missing pieces added back --- tools/github_tool.py | 135 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 121 insertions(+), 14 deletions(-) diff --git a/tools/github_tool.py b/tools/github_tool.py index 1b07ce5..b9d14d7 100644 --- a/tools/github_tool.py +++ b/tools/github_tool.py @@ -530,16 +530,31 @@ class GitHubTool(BaseTool): return self._get_current_branch() elif function_name == "set_current_branch": return self._set_current_branch(kwargs["branch_name"]) - elif function_name == "create_project_board": - return self._create_project_board(kwargs["name"], kwargs.get("body")) - elif function_name == "create_project_column": - return self._create_project_column(kwargs["project_id"], kwargs["column_name"]) - elif function_name == "create_project_card": - return self._create_project_card(kwargs["column_id"], kwargs["note"]) - elif function_name == "move_project_card": - return self._move_project_card(kwargs["card_id"], kwargs["position"], kwargs["column_id"]) - elif function_name == "link_issue_to_project_card": - return self._link_issue_to_project_card(kwargs["card_id"], kwargs["content_id"], kwargs["content_type"]) + elif function_name == "get_file_at_commit": + return self._get_file_at_commit(kwargs["file_path"], kwargs["commit_sha"]) + elif function_name == "list_branches": + return self._list_branches(kwargs.get("per_page", 100), kwargs.get("all_pages", True)) + elif function_name == "get_branch_sha": + return self._get_branch_sha(kwargs["branch"]) + elif function_name == "approve_pull_request": + return self._approve_pull_request(kwargs["pull_number"]) + elif function_name == "close_pull_request": + return self._close_pull_request(kwargs["pull_number"]) + elif function_name == "merge_pull_request": + return self._merge_pull_request(kwargs["pull_number"], kwargs.get("commit_title", "Merge pull request"), + kwargs.get("commit_message", ""), kwargs.get("merge_method", "merge")) + elif function_name == "delete_branch": + return self._delete_branch(kwargs["branch_name"]) + elif function_name == "get_issue_details": + return self._get_issue_details(kwargs["issue_number"]) + elif function_name == "create_issue": + return self._create_issue(kwargs["title"], kwargs["body"], kwargs.get("labels", [])) + elif function_name == "list_issues": + return self._list_issues(kwargs.get("state", "open"), kwargs.get("per_page", 30), kwargs.get("page", 1)) + elif function_name == "add_issue_comment": + return self._add_issue_comment(kwargs["issue_number"], kwargs["comment"]) + elif function_name == "get_issue_comments": + return self._get_issue_comments(kwargs["issue_number"]) else: error_message = f"Unknown function: {function_name}" self.logger.error(error_message) @@ -846,7 +861,10 @@ class GitHubTool(BaseTool): def _create_issue(self, title, body, labels=None): self.logger.info(f"Creating issue: {title}") url = f"{self.base_url}/repos/{self.repo}/issues" - data = {"title": title, "body": body} + data = { + "title": title, + "body": body + } if labels: data["labels"] = labels response = requests.post(url, headers=self.headers, json=data) @@ -864,10 +882,20 @@ class GitHubTool(BaseTool): def _list_issues(self, state="open", per_page=30, page=1): self.logger.info(f"Listing issues. State: {state}, Per page: {per_page}, Page: {page}") url = f"{self.base_url}/repos/{self.repo}/issues" - params = {"state": state, "per_page": per_page, "page": page} + params = { + "state": state, + "per_page": per_page, + "page": page + } response = requests.get(url, headers=self.headers, params=params) if response.status_code == 200: - issues = [{"number": issue["number"], "title": issue["title"], "state": issue["state"], "created_at": issue["created_at"], "url": issue["html_url"]} for issue in response.json()] + issues = [{ + "number": issue["number"], + "title": issue["title"], + "state": issue["state"], + "created_at": issue["created_at"], + "url": issue["html_url"] + } for issue in response.json()] self.logger.info(f"Successfully listed issues. Found {len(issues)} issues.") return issues else: @@ -897,10 +925,89 @@ class GitHubTool(BaseTool): url = f"{self.base_url}/repos/{self.repo}/issues/{issue_number}/comments" response = requests.get(url, headers=self.headers) if response.status_code == 200: - comments = [{"id": comment["id"], "user": comment["user"]["login"], "body": comment["body"], "created_at": comment["created_at"], "updated_at": comment["updated_at"]} for comment in response.json()] + comments = [{ + "id": comment["id"], + "user": comment["user"]["login"], + "body": comment["body"], + "created_at": comment["created_at"], + "updated_at": comment["updated_at"] + } for comment in response.json()] self.logger.info(f"Successfully retrieved comments for issue {issue_number}. Found {len(comments)} comments.") return comments else: error_message = f"Error getting issue comments: {response.status_code}\nResponse: {response.text}" self.logger.error(error_message) + return error_message + + @metrics.measure + def _create_project_board(self, name, body=None): + url = f"{self.base_url}/repos/{self.repo}/projects" + data = {"name": name, "body": body} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + project = response.json() + success_message = f"Project board '{name}' created successfully." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error creating project board: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _create_project_column(self, project_id, column_name): + url = f"{self.base_url}/projects/{project_id}/columns" + data = {"name": column_name} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + column = response.json() + success_message = f"Column '{column_name}' created successfully in project {project_id}." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error creating project column: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _create_project_card(self, column_id, note): + url = f"{self.base_url}/projects/columns/{column_id}/cards" + data = {"note": note} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + card = response.json() + success_message = f"Card created successfully in column {column_id}." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error creating project card: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _move_project_card(self, card_id, position, column_id): + url = f"{self.base_url}/projects/columns/cards/{card_id}/moves" + data = {"position": position, "column_id": column_id} + response = requests.post(url, headers=self.headers, json=data) + if response.status_code == 201: + success_message = f"Card {card_id} moved successfully." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error moving project card: {response.status_code}" + self.logger.error(error_message) + return error_message + + @metrics.measure + def _link_issue_to_project_card(self, card_id, content_id, content_type): + url = f"{self.base_url}/projects/columns/cards/{card_id}" + data = {"content_id": content_id, "content_type": content_type} + response = requests.patch(url, headers=self.headers, json=data) + if response.status_code == 200: + success_message = f"Issue/PR linked to card {card_id} successfully." + self.logger.info(success_message) + return success_message + else: + error_message = f"Error linking issue/PR to project card: {response.status_code}" + self.logger.error(error_message) return error_message \ No newline at end of file From 84f03a38b74b607631d825ab7476e77289131772 Mon Sep 17 00:00:00 2001 From: bucolucas Date: Tue, 20 Aug 2024 19:11:27 -0500 Subject: [PATCH 4/4] Document lessons learned during the repository management process --- scratch/lessons_learned.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 scratch/lessons_learned.md diff --git a/scratch/lessons_learned.md b/scratch/lessons_learned.md new file mode 100644 index 0000000..5fbf215 --- /dev/null +++ b/scratch/lessons_learned.md @@ -0,0 +1,24 @@ +# Lessons Learned in Repository Management + +## Summary of Challenges and Solutions + +1. **File Updates with Missing Content**: + - **Challenge**: Initial attempts to commit updates to the `github_tool.py` file missed several important configuration functions. + - **Solution**: Used Git history to find earlier versions of the file, which revealed the missing functions. Completed the updates by ensuring to include all necessary function calls and relevant code snippets. + +2. **Importance of Tracking Functionality**: + - **Challenge**: Managing a range of functionalities (like commenting on issues) can be error-prone if not tracked carefully. + - **Solution**: Regularly check previous commits and thoroughly review changes before finalizing commits. + +3. **The Role of Commit Messages**: + - **Challenge**: Clear documentation of changes is vital to understanding the evolution of the codebase. + - **Solution**: Commit messages should be descriptive and relevant to the changes made, aiding collaborators in understanding the context of changes. + +4. **Testing and Validation**: + - **Challenge**: Functionality should be tested after major changes to the codebase to ensure performance is as expected. + - **Solution**: Implement a process for thorough testing after committing important changes. + +## Reflections + +- Maintaining a clear and organized approach to repository management fosters smoother collaboration and better results in development processes. +- Documenting changes, challenges, and solutions provides valuable insights for personal growth and improves future practices.