Created
April 11, 2025 14:13
-
-
Save dmzoneill/80bfef9603448c33df02ce0aa98fcd59 to your computer and use it in GitHub Desktop.
AI git Commit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/python3 | |
| import os | |
| import sys | |
| import requests | |
| import subprocess | |
| import argparse | |
| class OpenAIProvider: | |
| def __init__(self): | |
| self.api_key = os.getenv("AI_API_KEY") | |
| if not self.api_key: | |
| raise EnvironmentError("AI_API_KEY not set in environment.") | |
| self.endpoint = "https://api.openai.com/v1/chat/completions" | |
| self.model = os.getenv("OPENAI_MODEL", "gpt-4o-mini") | |
| def improve_text(self, prompt: str, text: str) -> str: | |
| headers = { | |
| "Authorization": f"Bearer {self.api_key}", | |
| "Content-Type": "application/json", | |
| } | |
| body = { | |
| "model": self.model, | |
| "messages": [ | |
| {"role": "system", "content": prompt}, | |
| {"role": "user", "content": text}, | |
| ], | |
| "temperature": 0.3, | |
| } | |
| response = requests.post(self.endpoint, json=body, headers=headers, timeout=30) | |
| if response.status_code == 200: | |
| return response.json()["choices"][0]["message"]["content"].strip() | |
| raise Exception( | |
| f"OpenAI API call failed: {response.status_code} - {response.text}" | |
| ) | |
| def get_diff_from_stdin(): | |
| """Reads the diff from stdin (useful for piped input).""" | |
| return sys.stdin.read() | |
| def get_diff_from_git(): | |
| """Runs 'git diff HEAD~1' and captures the output.""" | |
| return subprocess.check_output( | |
| "GIT_PAGER=cat git diff HEAD~1", shell=True, text=True | |
| ) | |
| def main(): | |
| # Step 1: Parse command-line arguments | |
| parser = argparse.ArgumentParser(description="Generate and commit a git commit message.") | |
| parser.add_argument( | |
| "--print", action="store_true", help="Print the commit message without creating the commit" | |
| ) | |
| args = parser.parse_args() | |
| # Step 2: Get the current working directory | |
| cwd = os.getcwd() | |
| # Step 3: Get the diff | |
| diff = None | |
| if not sys.stdin.isatty(): | |
| print("Reading git diff from stdin...") | |
| diff = get_diff_from_stdin() | |
| else: | |
| print("Getting git diff from HEAD~1...") | |
| diff = get_diff_from_git() | |
| if not diff: | |
| print("No diff found, nothing to commit.") | |
| return | |
| # Step 4: Prepare the prompt for OpenAI | |
| prompt = "Take the diff and give me a good commit message, give me the commit message and nothing else" | |
| # Create an instance of OpenAIProvider | |
| openai_provider = OpenAIProvider() | |
| # Step 5: Get the commit message from OpenAI | |
| print("Generating commit message from OpenAI...") | |
| commit_message = openai_provider.improve_text(prompt, diff) | |
| if not commit_message: | |
| print("No commit message generated. Aborting commit.") | |
| return | |
| # Step 6: Handle --print argument | |
| if args.print: | |
| print(f"Commit message (not committing): {commit_message}") | |
| return | |
| # Step 7: Create the commit with the message from OpenAI | |
| print(f"Committing with message: {commit_message}") | |
| # Run git commit and suppress interactive editor | |
| result = subprocess.run( | |
| ["git", "commit", "-m", commit_message], | |
| check=True, | |
| cwd=cwd, | |
| stdin=subprocess.DEVNULL, # Prevents editor from being opened | |
| stdout=subprocess.PIPE, # Captures stdout to prevent blocking | |
| stderr=subprocess.PIPE # Captures stderr to prevent blocking | |
| ) | |
| # Print the result of the commit | |
| print(f"Commit successful! {result.stdout.decode('utf-8')}") | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment