Automating Code Reviews with Git Hooks and Oracle Generative AI

Automating Code Reviews with Git Hooks and Oracle Generative AI

A few years ago, I wrote a Groovy script for a client to automate peer reviews of their Oracle Data Integrator (ODI) development. It was a complex script, embodying the collective knowledge of the development team: standards, expectations, and best practices. Reflecting on that project now, I can’t help but think how much simpler it would have been with generative AI. The ability to incorporate AI into the process opens exciting possibilities.

In this blog post, I’ll demonstrate how we can use Oracle Generative AI to automate peer reviews for files being committed to a Git repository. This approach is not only efficient but also leverages AI's strengths in identifying performance issues, security vulnerabilities, and style inconsistencies.

You can also view the code in our Git repo.

GitHub - RittmanMead/oracle-gen-ai-git-hook: An example of using Oracle Gen AI with a Git hook
An example of using Oracle Gen AI with a Git hook. Contribute to RittmanMead/oracle-gen-ai-git-hook development by creating an account on GitHub.

Why Use Oracle Generative AI for Code Reviews?

Oracle Generative AI offers unique advantages that make it an excellent choice for this task:

  • Data Privacy: Oracle emphasises enterprise-grade data privacy and security.
  • Extensive Training: Trained on diverse datasets, including:
    • Security vulnerabilities
    • Vendor documentation
    • Community code examples
  • Consistency: Delivers consistent, repeatable feedback.
  • Customisable: Configurable through prompts and model tuning.
  • Continuous Improvement: Benefits from ongoing model updates and enhancements.

By leveraging these capabilities, we can catch bugs and vulnerabilities early, improve code presentation, and even enhance documentation—all before issues become problems.

How It Works

Our solution uses Git hooks to integrate Oracle Generative AI into the development workflow. Git hooks are scripts that run automatically at key points in the Git lifecycle, such as before a commit or push. For this implementation, we’ll use the pre-commit hook to intercept staged files, send them to Oracle Generative AI for analysis, and save the feedback in a markdown file.

Step 1: Setting Up the Pre-Commit Hook

Within the .git/hooks directory of your Git repository, create a file named pre-commit with the following content:

#!/bin/bash

STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)
OUTPUT_DIR="oracle_ai_peer_review"
mkdir -p $OUTPUT_DIR

for FILE in $STAGED_FILES; do
    if [[ "$FILE" == *.py || "$FILE" == *.js ]]; then
        CONTENT=$(git show :$FILE)
        python oracle_ai_peer_review.py "$CONTENT" "$FILE" "$OUTPUT_DIR"
    fi
done

This script identifies staged files (e.g., .py or .js files), extracts their content, and passes it to a Python script for analysis. Save the script and make it executable:

chmod +x .git/hooks/pre-commit

Step 2: Writing the Python Script

Create a Python script named oracle_ai_peer_review.py. This script connects to Oracle Generative AI, sends the code for review, and saves the feedback in a markdown file.

import os
import sys
import oci

compartment_id = os.getenv("ORACLE_COMPARTMENT_ID")
CONFIG_PROFILE = "DEFAULT"
config = oci.config.from_file('~/.oci/config', CONFIG_PROFILE)

endpoint = "https://inference.generativeai.uk-london-1.oci.oraclecloud.com"



def review_code(content, filename):
    generative_ai_inference_client = oci.generative_ai_inference.GenerativeAiInferenceClient(config=config, service_endpoint=endpoint, retry_strategy=oci.retry.NoneRetryStrategy(), timeout=(10,240))
    chat_detail = oci.generative_ai_inference.models.ChatDetails()

    chat_request = oci.generative_ai_inference.models.CohereChatRequest()
    chat_request.message = f"You are an expert developer that needs to peer review code in a file. Please provide feedback with a focus on performance, security and presentation. Include the new code for the complete file in your response and include comments were possible. Please review the file called {filename}: ```{content}```"
    chat_request.max_tokens = 4000
    chat_request.temperature = 1
    chat_request.frequency_penalty = 0
    chat_request.top_p = 0.75
    chat_request.top_k = 0


    chat_detail.serving_mode = oci.generative_ai_inference.models.OnDemandServingMode(model_id="ocid1.generativeaimodel.oc1.uk-london-1.amaaaaaask7dceyahpidcahiiyhcdmnvicfxo7suq3pxcimkyik75mbxziqq")
    chat_detail.chat_request = chat_request
    chat_detail.compartment_id = compartment_id
    chat_response = generative_ai_inference_client.chat(chat_detail)
    print(type(chat_response.data.chat_response.text))
    print(dir(chat_response.data.chat_response.text))
    return chat_response.data.chat_response.text

def write_feedback(content, filename, output_dir):
    feedback = review_code(content, filename)
    output_path = f"{output_dir}/{filename.replace('/', '_')}.md"
    with open(output_path, 'w') as f:
        f.write(feedback)

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: oracle_ai_peer_review.py <content> <filename> <output_dir>")
        sys.exit(1)
    content = sys.argv[1]
    filename = sys.argv[2]
    output_dir = sys.argv[3]
    print(f"Reviewing {filename} and storing in {output_dir}/{filename}")
    write_feedback(content, filename, output_dir)

Step 3: Testing the Workflow

Once everything is set up, use your normal Git workflow to test the solution:

$ git add oracle_ai_peer_review.py
$ git commit -m "Testing AI-based peer review"
Reviewing oracle_ai_peer_review.py and storing feedback in oracle_ai_peer_review/oracle_ai_peer_review.py.md

The feedback is saved in the oracle_ai_peer_review/ directory as a markdown file, leaving your repository files untouched.

Benefits in Action

In this example, Oracle Generative AI flagged potential improvements in the Python script, such as adding a retry mechanism for robustness, enhancing security with better environment variable handling, and improving the readability of feedback files with better formatting.

Here is the output from the model.

Markdown Response

The code you provided is a script that utilises the Oracle Cloud Infrastructure (OCI) services to review code and generate feedback. Here is a peer review with a focus on performance, security, and presentation:

import os
import sys
import oci

# Ensure environment variables are set
if not os.getenv("ORACLE_COMPARTMENT_ID"):
    raise EnvironmentError("ORACLE_COMPARTMENT_ID environment variable not set")

# Define constants
CONFIG_PROFILE = "DEFAULT"
endpoint = "https://inference.generativeai.uk-london-1.oci.oraclecloud.com"

def review_code(content, filename):
    """
    Generate code review feedback using Oracle AI services.

    Args:
        content (str): The code content to be reviewed.
        filename (str): The name of the file being reviewed.

    Returns:
        str: The generated feedback text.
    """
    config = oci.config.from_file('~/.oci/config', CONFIG_PROFILE)
    generative_ai_inference_client = oci.generative_ai_inference.GenerativeAiInferenceClient(config=config, service_endpoint=endpoint, retry_strategy=oci.retry.NoneRetryStrategy(), timeout=(10,240))

    # Prepare the chat request
    chat_request = oci.generative_ai_inference.models.CohereChatRequest()
    chat_request.message = f"You are an expert developer. Review the following code with a focus on performance, security, and presentation. Provide feedback and suggestions for improvement. Code: ```{content}```"
    chat_request.max_tokens = 4000
    chat_request.temperature = 1
    chat_request.frequency_penalty = 0
    chat_request.top_p = 0.75
    chat_request.top_k = 0

    # Set up the chat details
    compartment_id = os.getenv("ORACLE_COMPARTMENT_ID")
    chat_detail = oci.generative_ai_inference.models.ChatDetails(
        serving_mode=oci.generative_ai_inference.models.OnDemandServingMode(model_id="ocid1.generativeaimodel.oc1.uk-london-1.amaaaaaask7dceyahpidcahiiyhcdmnvicfxo7suq3pxcimkyik75mbxziqq"),
        chat_request=chat_request,
        compartment_id=compartment_id
    )

    # Send the chat request and get the response
    chat_response = generative_ai_inference_client.chat(chat_detail)
    return chat_response.data.chat_response.text

def write_feedback(content, filename, output_dir):
    """
    Write the generated feedback to a Markdown file.

    Args:
        content (str): The code content.
        filename (str): The name of the file.
        output_dir (str): The directory to store the feedback file.
    """
    feedback = review_code(content, filename)
    output_path = f"{output_dir}/{filename.replace('/', '_')}.md"
    with open(output_path, 'w') as f:
        f.write(f"# Code Review for {filename}\n\n{feedback}")

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: oracle_ai_peer_review.py <content> <filename> <output_dir>")
        sys.exit(1)

    content = sys.argv[1]
    filename = sys.argv[2]
    output_dir = sys.argv[3]

    print(f"Reviewing {filename} and storing in {output_dir}/{filename}")
    write_feedback(content, filename, output_dir)

Performance:

  • The script uses the oci.retry.NoneRetryStrategy for the client, which might be appropriate for simple, non-critical tasks. However, for more robust and reliable performance, consider implementing a retry mechanism with exponential backoff to handle transient errors.
  • The timeout is set to (10, 240), which seems reasonable for most use cases. Ensure that this value is appropriate for your specific use case and network conditions.

Security:

  • The script relies on environment variables (ORACLE_COMPARTMENT_ID) for sensitive information. Ensure that these variables are properly secured and not exposed in any logs or error messages.
  • The script uses the oci.config.from_file function to load configuration settings from a file. Make sure that the configuration file is stored securely and not accessible to unauthorised users.

Presentation:

  • The feedback generated by the Oracle AI services is directly returned and printed. Consider structuring the feedback with appropriate headers, sections, and formatting to make it more readable and organised.
  • The write_feedback function writes the feedback to a Markdown file. Ensure that the filename is properly sanitised to prevent potential security issues (e.g., path traversal).

Overall, the script provides a basic framework for utilising Oracle AI services for code review. By addressing the performance and security considerations mentioned above and enhancing the presentation of the feedback, you can further improve the reliability and usability of this code review process.

Conclusion

By integrating Oracle Generative AI into your Git workflow, you can automate peer reviews, improve code quality, and catch issues early. This approach not only saves time, but also ensures consistent and actionable feedback. Give it a try in your next project, and see how it transforms your development process!