kedar-bhumkar's picture
Upload 5 files
3d833be verified
import streamlit as st
import tempfile
import json
from backend import (
clone_repository,
read_code_files,
analyze_code,
check_api_keys
)
def get_severity_color(severity):
"""Get color based on severity level."""
colors = {
"LOW": "#FFA500", # Orange
"MEDIUM": "#FF6B6B", # Light Red
"HIGH": "#FF0000" # Red
}
return colors.get(severity.upper(), "#000000")
def render_analysis_results(analysis_text):
"""Render the analysis results according to the Pydantic model schema."""
try:
# Parse the analysis text as JSON
analysis_data = json.loads(analysis_text)
# Custom CSS for styling
st.markdown("""
<style>
.severity-box {
background-color: #f0f2f6;
padding: 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
}
.file-impact {
background-color: #ffffff;
padding: 1rem;
border-radius: 0.5rem;
margin: 0.5rem 0;
border: 1px solid #e1e4e8;
}
.impact-count {
background-color: #e6f3ff;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
margin: 1rem 0;
}
</style>
""", unsafe_allow_html=True)
# Calculate severity level based on number of files impacted
severity_level = analysis_data['severity_level']
if(analysis_data['number_of_files_impacted'] == None or analysis_data['number_of_files_impacted'] == 0):
severity_level = "No Impact"
elif(analysis_data['number_of_files_impacted'] > 0 and analysis_data['number_of_files_impacted'] <= 3):
severity_level = "Low"
elif(analysis_data['number_of_files_impacted'] > 3 and analysis_data['number_of_files_impacted'] <= 8):
severity_level = "Medium"
else:
severity_level = "High"
# Display Severity Level with custom styling
severity_color = get_severity_color(severity_level)
st.markdown(f"""
<div class="severity-box">
<h3 style='color: {severity_color}; margin: 0; font-size: 1.5rem; font-weight: bold;'>
Severity Level: {severity_level}
</h3>
</div>
""", unsafe_allow_html=True)
# Display Number of Files Impacted with custom styling
st.markdown(f"""
<div class="impact-count">
<h3 style='color: #1f77b4; margin: 0; font-size: 1.2rem;'>
Number of Files Impacted: {analysis_data['number_of_files_impacted']}
</h3>
</div>
""", unsafe_allow_html=True)
# Display Files Impacted with custom styling
st.markdown("<h3 style='color: #2c3e50; font-size: 1.3rem;'>Files Impacted</h3>", unsafe_allow_html=True)
for file_impact in analysis_data['files_impacted']:
with st.expander(f"πŸ“„ {file_impact['files_impacted']}", expanded=False):
st.markdown(f"""
<div class="file-impact">
<p style='color: #34495e; font-size: 1rem; line-height: 1.6;'>
{file_impact['impact_details']}
</p>
</div>
""", unsafe_allow_html=True)
except json.JSONDecodeError:
# If the response is not valid JSON, display it as plain text
st.markdown(analysis_text)
except Exception as e:
st.error(f"Error rendering analysis results: {str(e)}")
st.markdown(analysis_text)
def main():
st.title("Git Repository Code Analyzer")
st.write("Enter a Git repository URL and a prompt to analyze the code.")
# Example data
examples = [
{
"Git URL": "https://github.com/kedar-bhumkar/SFRoutingFramework",
"Code/Config Changes": "Enum USER_INTERFACE removed from file: BaseAppLiterals.cls"
},
{
"Git URL": "https://github.com/kedar-bhumkar/SFDynamicFields",
"Code/Config Changes": "Removed a field Value__c from DynamicFieldTable__c.object"
}
]
# Initialize session state if not exists
if 'selected_example' not in st.session_state:
st.session_state.selected_example = None
if 'openai_key' not in st.session_state:
st.session_state.openai_key = ""
# API Key input section
with st.expander("πŸ”‘ API Key Settings", expanded=False):
st.markdown("""
<style>
.api-key-section {
background-color: #f8f9fa;
padding: 1rem;
border-radius: 0.5rem;
margin: 0.5rem 0;
}
</style>
""", unsafe_allow_html=True)
st.markdown("""
<div class="api-key-section">
<p style='color: #2c3e50; font-size: 0.9rem;'>
Enter your OpenAI API key to use the GPT-4 model. The key will be stored in the session and not saved permanently.
</p>
</div>
""", unsafe_allow_html=True)
openai_key = st.text_input(
"OpenAI API Key",
value=st.session_state.openai_key,
type="password",
help="Enter your OpenAI API key to use GPT-4"
)
if openai_key:
st.session_state.openai_key = openai_key
st.success("API key saved for this session")
# Display examples table with Select buttons
st.subheader("Example Cases")
# Create columns for the table
col1, col2, col3 = st.columns([2, 2, 1])
# Table header
with col1:
st.write("**Git URL**")
with col2:
st.write("**Code/Config Changes**")
with col3:
st.write("**Action**")
# Table rows
for idx, example in enumerate(examples):
with col1:
st.write(example["Git URL"])
with col2:
st.write(example["Code/Config Changes"])
with col3:
if st.button("Select", key=f"select_{idx}"):
st.session_state.selected_example = idx
st.session_state.repo_url = example["Git URL"]
st.session_state.prompt = example["Code/Config Changes"]
st.experimental_rerun()
# Get user inputs
repo_url = st.text_input("Git Repository URL",
value=st.session_state.get("repo_url", ""))
# Model selection
model = st.selectbox(
"Select AI Model",
["gpt-4", "claude-sonnet (coming soon)"],
help="Choose the AI model to analyze the code"
)
prompt = st.text_area("Code or configuration changes",
value=st.session_state.get("prompt", "List down the code/configuration changes to be performed"))
# Clear button
if st.button("Clear Selection"):
st.session_state.selected_example = None
st.session_state.repo_url = ""
st.session_state.prompt = "List down the code/configuration changes to be performed"
st.experimental_rerun()
if st.button("Analyze"):
if not repo_url:
st.error("Please enter a Git repository URL")
return
# Check API keys
api_keys_status = check_api_keys()
if model == "gpt-4":
# First check session state for OpenAI key
if st.session_state.openai_key:
# Use the key from session state
api_keys_status["gpt-4"] = True
elif not api_keys_status["gpt-4"]:
st.error("OpenAI API key not found. Please enter your key in the API Key Settings section or set the OPENAI_API_KEY environment variable.")
return
elif model == "claude-sonnet" and not api_keys_status["claude-sonnet"]:
st.error("Anthropic API key not found. Please set the ANTHROPIC_API_KEY environment variable.")
return
with st.spinner("Cloning repository and analyzing code..."):
# Create a temporary directory
with tempfile.TemporaryDirectory() as temp_dir:
# Clone the repository
success, error = clone_repository(repo_url, temp_dir)
if not success:
st.error(f"Error cloning repository: {error}")
return
# Read code files
code_files, warnings = read_code_files(temp_dir)
# Display any warnings from reading files
for warning in warnings:
st.warning(warning)
if not code_files:
st.warning("No code files found in the repository.")
return
# Analyze the code
analysis, error = analyze_code(code_files, prompt, model)
if error:
st.error(f"Error during analysis: {error}")
return
if analysis:
st.subheader("Analysis Results")
render_analysis_results(analysis)
if __name__ == "__main__":
main()