bluenevus commited on
Commit
785cb50
·
verified ·
1 Parent(s): 266767f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +181 -69
app.py CHANGED
@@ -1,4 +1,6 @@
1
- import gradio as gr
 
 
2
  from datetime import datetime, timedelta
3
  import google.generativeai as genai
4
  from github import Github, GithubException
@@ -6,25 +8,39 @@ import gitlab
6
  import docx
7
  import tempfile
8
  import requests
 
 
 
9
 
10
- def generate_release_notes(git_provider, repo_url, personal_access_token, gemini_api_key, start_date, end_date):
 
 
 
 
 
 
 
 
 
 
 
11
  try:
12
  start_date = datetime.strptime(start_date, "%Y-%m-%d")
13
  end_date = datetime.strptime(end_date, "%Y-%m-%d")
14
 
15
  if git_provider == "GitHub":
16
- g = Github(personal_access_token)
17
  repo = g.get_repo(repo_url)
18
  commits = list(repo.get_commits(since=start_date, until=end_date))
19
  commit_messages = [commit.commit.message for commit in commits]
20
  elif git_provider == "GitLab":
21
- gl = gitlab.Gitlab(url='https://gitlab.com', private_token=personal_access_token)
22
  project = gl.projects.get(repo_url)
23
  commits = project.commits.list(since=start_date.isoformat(), until=end_date.isoformat())
24
  commit_messages = [commit.message for commit in commits]
25
  elif git_provider == "Gitea":
26
  base_url = "https://gitea.com/api/v1"
27
- headers = {"Authorization": f"token {personal_access_token}"}
28
  response = requests.get(f"{base_url}/repos/{repo_url}/commits", headers=headers, params={
29
  "since": start_date.isoformat(),
30
  "until": end_date.isoformat()
@@ -33,14 +49,14 @@ def generate_release_notes(git_provider, repo_url, personal_access_token, gemini
33
  commits = response.json()
34
  commit_messages = [commit['commit']['message'] for commit in commits]
35
  else:
36
- return "Unsupported Git provider", None, None
37
 
38
  commit_text = "\n".join(commit_messages)
39
 
40
  if not commit_text:
41
- return "No commits found in the specified date range.", None, None
42
-
43
- genai.configure(api_key=gemini_api_key)
44
  model = genai.GenerativeModel('gemini-2.0-flash-lite')
45
 
46
  prompt = f"""Based on the following commit messages, generate comprehensive release notes:
@@ -61,26 +77,6 @@ def generate_release_notes(git_provider, repo_url, personal_access_token, gemini
61
 
62
  response = model.generate_content(prompt)
63
  release_notes = response.text
64
-
65
- # Create DOCX file
66
- doc = docx.Document()
67
- doc.add_heading('Release Notes', 0)
68
-
69
- current_section = None
70
- for line in release_notes.split('\n'):
71
- line = line.strip()
72
- if line.endswith(':'):
73
- doc.add_heading(line, level=1)
74
- current_section = None
75
- elif line:
76
- if current_section is None:
77
- current_section = doc.add_paragraph().style
78
- current_section.name = 'List Bullet'
79
- doc.add_paragraph(line, style=current_section)
80
-
81
- with tempfile.NamedTemporaryFile(delete=False, suffix='.docx') as temp_docx:
82
- doc.save(temp_docx.name)
83
- docx_path = temp_docx.name
84
 
85
  # Create Markdown file
86
  markdown_content = "# Release Notes\n\n"
@@ -91,49 +87,165 @@ def generate_release_notes(git_provider, repo_url, personal_access_token, gemini
91
  elif line:
92
  markdown_content += f"- {line}\n"
93
 
94
- with tempfile.NamedTemporaryFile(delete=False, suffix='.md', mode='w', encoding='utf-8') as temp_md:
95
- temp_md.write(markdown_content)
96
- md_path = temp_md.name
97
 
98
- return release_notes, docx_path, md_path
 
 
 
 
 
 
 
 
99
 
100
  except Exception as e:
101
- return f"An error occurred: {str(e)}", None, None
102
-
103
- default_end_date = datetime.now()
104
- default_start_date = default_end_date - timedelta(days=30)
105
-
106
- iface = gr.Interface(
107
- fn=generate_release_notes,
108
- inputs=[
109
- gr.Dropdown(
110
- choices=["GitHub", "GitLab", "Gitea"],
111
- label="Git Provider"
112
- ),
113
- gr.Textbox(label="Repository URL", placeholder="owner/repo"),
114
- gr.Textbox(label="Personal Access Token", type="password"),
115
- gr.Textbox(label="Gemini API Key", type="password"),
116
- gr.Textbox(
117
- label="Start Date",
118
- placeholder="YYYY-MM-DD",
119
- value=default_start_date.strftime("%Y-%m-%d"),
120
- ),
121
- gr.Textbox(
122
- label="End Date",
123
- placeholder="YYYY-MM-DD",
124
- value=default_end_date.strftime("%Y-%m-%d"),
 
 
 
 
 
 
 
 
 
125
  )
126
- ],
127
- outputs=[
128
- gr.Textbox(label="Generated Release Notes"),
129
- gr.File(label="Download Release Notes (DOCX)"),
130
- gr.File(label="Download Release Notes (Markdown)")
131
- ],
132
- title="Automated Release Notes Generator",
133
- description="Generate release notes based on Git commits using Gemini AI. Select a Git provider, enter repository details, and specify the date range for commits.",
134
- allow_flagging="never",
135
- theme="default",
136
- analytics_enabled=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
139
- iface.launch()
 
 
 
 
1
+ import dash
2
+ from dash import dcc, html, Input, Output, State
3
+ import dash_bootstrap_components as dbc
4
  from datetime import datetime, timedelta
5
  import google.generativeai as genai
6
  from github import Github, GithubException
 
8
  import docx
9
  import tempfile
10
  import requests
11
+ import os
12
+ import threading
13
+ import io
14
 
15
+ # Initialize the Dash app
16
+ app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
17
+
18
+ # Hugging Face variables
19
+ HF_GEMINI_API_KEY = os.environ.get('HF_GEMINI_API_KEY')
20
+ HF_GITHUB_TOKEN = os.environ.get('HF_GITHUB_TOKEN')
21
+
22
+ # Global variable to store generated files
23
+ generated_file = None
24
+
25
+ def generate_release_notes(git_provider, repo_url, start_date, end_date, folder_location):
26
+ global generated_file
27
  try:
28
  start_date = datetime.strptime(start_date, "%Y-%m-%d")
29
  end_date = datetime.strptime(end_date, "%Y-%m-%d")
30
 
31
  if git_provider == "GitHub":
32
+ g = Github(HF_GITHUB_TOKEN)
33
  repo = g.get_repo(repo_url)
34
  commits = list(repo.get_commits(since=start_date, until=end_date))
35
  commit_messages = [commit.commit.message for commit in commits]
36
  elif git_provider == "GitLab":
37
+ gl = gitlab.Gitlab(url='https://gitlab.com', private_token=HF_GITHUB_TOKEN)
38
  project = gl.projects.get(repo_url)
39
  commits = project.commits.list(since=start_date.isoformat(), until=end_date.isoformat())
40
  commit_messages = [commit.message for commit in commits]
41
  elif git_provider == "Gitea":
42
  base_url = "https://gitea.com/api/v1"
43
+ headers = {"Authorization": f"token {HF_GITHUB_TOKEN}"}
44
  response = requests.get(f"{base_url}/repos/{repo_url}/commits", headers=headers, params={
45
  "since": start_date.isoformat(),
46
  "until": end_date.isoformat()
 
49
  commits = response.json()
50
  commit_messages = [commit['commit']['message'] for commit in commits]
51
  else:
52
+ return "Unsupported Git provider", None
53
 
54
  commit_text = "\n".join(commit_messages)
55
 
56
  if not commit_text:
57
+ return "No commits found in the specified date range.", None
58
+
59
+ genai.configure(api_key=HF_GEMINI_API_KEY)
60
  model = genai.GenerativeModel('gemini-2.0-flash-lite')
61
 
62
  prompt = f"""Based on the following commit messages, generate comprehensive release notes:
 
77
 
78
  response = model.generate_content(prompt)
79
  release_notes = response.text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
 
81
  # Create Markdown file
82
  markdown_content = "# Release Notes\n\n"
 
87
  elif line:
88
  markdown_content += f"- {line}\n"
89
 
90
+ # Generate file name based on the current date
91
+ file_name = f"{datetime.now().strftime('%m-%d-%Y')}.md"
 
92
 
93
+ # Store the generated file content
94
+ generated_file = io.BytesIO(markdown_content.encode())
95
+ generated_file.seek(0)
96
+
97
+ # Update SUMMARY.md
98
+ summary_url = "https://github.com/MicroHealthLLC/maiko-assistant/blob/main/documentation%2Freleases%2FSUMMARY.md"
99
+ update_summary(summary_url, file_name)
100
+
101
+ return release_notes, file_name
102
 
103
  except Exception as e:
104
+ return f"An error occurred: {str(e)}", None
105
+
106
+ def update_summary(summary_url, new_file_name):
107
+ try:
108
+ g = Github(HF_GITHUB_TOKEN)
109
+ repo = g.get_repo("MicroHealthLLC/maiko-assistant")
110
+ summary_content = repo.get_contents("documentation/releases/SUMMARY.md").decoded_content.decode()
111
+
112
+ # Add new file to the top of the Releases section
113
+ new_entry = f"{datetime.now().strftime('%b %d, %Y')}\n"
114
+ updated_content = summary_content.replace("Releases\n", f"Releases\n{new_entry}")
115
+
116
+ # Create a new branch for the PR
117
+ base_branch = repo.default_branch
118
+ new_branch = f"update-summary-{datetime.now().strftime('%Y%m%d%H%M%S')}"
119
+ ref = repo.get_git_ref(f"heads/{base_branch}")
120
+ repo.create_git_ref(ref=f"refs/heads/{new_branch}", sha=ref.object.sha)
121
+
122
+ # Update SUMMARY.md in the new branch
123
+ repo.update_file(
124
+ "documentation/releases/SUMMARY.md",
125
+ f"Update SUMMARY.md with new release notes {new_file_name}",
126
+ updated_content,
127
+ repo.get_contents("documentation/releases/SUMMARY.md").sha,
128
+ branch=new_branch
129
+ )
130
+
131
+ # Create a pull request
132
+ pr = repo.create_pull(
133
+ title=f"Update SUMMARY.md with new release notes {new_file_name}",
134
+ body="Automatically generated PR to update SUMMARY.md with new release notes.",
135
+ head=new_branch,
136
+ base=base_branch
137
  )
138
+
139
+ return f"Pull request created: {pr.html_url}"
140
+ except Exception as e:
141
+ return f"Error updating SUMMARY.md: {str(e)}"
142
+
143
+ # App layout
144
+ app.layout = dbc.Container([
145
+ html.H1("Automated Release Notes Generator", className="mb-4"),
146
+ dbc.Card([
147
+ dbc.CardBody([
148
+ dbc.Form([
149
+ dbc.Row([
150
+ dbc.Col([
151
+ dcc.Dropdown(
152
+ id='git-provider',
153
+ options=[
154
+ {'label': 'GitHub', 'value': 'GitHub'},
155
+ {'label': 'GitLab', 'value': 'GitLab'},
156
+ {'label': 'Gitea', 'value': 'Gitea'}
157
+ ],
158
+ placeholder="Select Git Provider"
159
+ )
160
+ ], width=12, className="mb-3"),
161
+ ]),
162
+ dbc.Row([
163
+ dbc.Col([
164
+ dbc.Input(id='repo-url', placeholder="Repository URL (owner/repo)", type="text")
165
+ ], width=12, className="mb-3"),
166
+ ]),
167
+ dbc.Row([
168
+ dbc.Col([
169
+ dbc.Input(id='start-date', placeholder="Start Date (YYYY-MM-DD)", type="text")
170
+ ], width=12, className="mb-3"),
171
+ ]),
172
+ dbc.Row([
173
+ dbc.Col([
174
+ dbc.Input(id='end-date', placeholder="End Date (YYYY-MM-DD)", type="text")
175
+ ], width=12, className="mb-3"),
176
+ ]),
177
+ dbc.Row([
178
+ dbc.Col([
179
+ dbc.Input(id='folder-location', placeholder="Folder Location", type="text")
180
+ ], width=12, className="mb-3"),
181
+ ]),
182
+ dbc.Row([
183
+ dbc.Col([
184
+ dbc.Button("Generate Release Notes", id="generate-button", color="primary", className="mr-2"),
185
+ dbc.Button("Download Markdown", id="download-button", color="secondary", className="mr-2", disabled=True),
186
+ dbc.Button("Create PR", id="pr-button", color="info", disabled=True)
187
+ ], width=12, className="mb-3"),
188
+ ]),
189
+ ]),
190
+ ])
191
+ ], className="mb-4"),
192
+ dbc.Card([
193
+ dbc.CardBody([
194
+ html.H4("Generated Release Notes"),
195
+ html.Pre(id="output-notes", style={"white-space": "pre-wrap"})
196
+ ])
197
+ ]),
198
+ dcc.Download(id="download-markdown")
199
+ ])
200
+
201
+ @app.callback(
202
+ [Output("output-notes", "children"),
203
+ Output("download-button", "disabled"),
204
+ Output("pr-button", "disabled")],
205
+ [Input("generate-button", "n_clicks")],
206
+ [State("git-provider", "value"),
207
+ State("repo-url", "value"),
208
+ State("start-date", "value"),
209
+ State("end-date", "value"),
210
+ State("folder-location", "value")]
211
  )
212
+ def update_output(n_clicks, git_provider, repo_url, start_date, end_date, folder_location):
213
+ if n_clicks is None:
214
+ return "", True, True
215
+
216
+ notes, file_name = generate_release_notes(git_provider, repo_url, start_date, end_date, folder_location)
217
+ return notes, False, False
218
+
219
+ @app.callback(
220
+ Output("download-markdown", "data"),
221
+ Input("download-button", "n_clicks"),
222
+ prevent_initial_call=True
223
+ )
224
+ def download_markdown(n_clicks):
225
+ if n_clicks is None:
226
+ return dash.no_update
227
+
228
+ global generated_file
229
+ if generated_file is None:
230
+ return dash.no_update
231
+
232
+ return dcc.send_bytes(generated_file.getvalue(), f"release_notes_{datetime.now().strftime('%Y%m%d%H%M%S')}.md")
233
+
234
+ @app.callback(
235
+ Output("pr-button", "children"),
236
+ Input("pr-button", "n_clicks"),
237
+ [State("folder-location", "value")],
238
+ prevent_initial_call=True
239
+ )
240
+ def create_pr(n_clicks, folder_location):
241
+ if n_clicks is None:
242
+ return dash.no_update
243
+
244
+ # Implement PR creation logic here
245
+ # For now, we'll just return a placeholder message
246
+ return "PR Created"
247
 
248
+ if __name__ == '__main__':
249
+ print("Starting the Dash application...")
250
+ app.run(debug=True, host='0.0.0.0', port=7860)
251
+ print("Dash application has finished running.")