Skip to content

Commit 5489ab6

Browse files
committed
fix: pass process variables at runtime, and log errors
1 parent f8929ae commit 5489ab6

File tree

4 files changed

+192
-103
lines changed

4 files changed

+192
-103
lines changed

webapp/github.py

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import json
2+
import logging
23
from pathlib import Path
34

45
import flask
56
import requests
67

7-
from webapp.tasks import save_github_file
8+
from webapp.settings import BASE_DIR, GH_TOKEN
9+
from webapp.tasks import register_task
10+
11+
# Configure logger
12+
logging.basicConfig(
13+
level=logging.INFO,
14+
format="%(levelname)s [%(name)s] %(message)s",
15+
)
16+
logger = logging.getLogger(__name__)
817

918

1019
class Tree:
@@ -24,18 +33,14 @@ class GithubError(Exception):
2433

2534

2635
class GitHub:
27-
def __init__(
28-
self,
29-
app: flask.Flask = None,
30-
):
36+
logger = logger
37+
38+
def __init__(self) -> None:
3139
"""
3240
Initialize the Github object.
33-
34-
Args:
35-
app (Flask): The Flask application instance.
3641
"""
37-
self.REPOSITORY_PATH = Path(app.config["BASE_DIR"]) / "repositories"
38-
token = app.config["GH_TOKEN"]
42+
self.REPOSITORY_PATH = Path(BASE_DIR) / "repositories"
43+
token = GH_TOKEN
3944
self.headers = {
4045
"Accept": "application/vnd.github.raw+json",
4146
"Authorization": f"Bearer {token}",
@@ -46,18 +51,19 @@ def __request__(
4651
self,
4752
method: str,
4853
url: str,
49-
data: dict = {},
50-
params: dict = {},
54+
data: dict | None = None,
55+
params: dict | None = None,
5156
blob=False,
52-
):
53-
if data:
54-
data = json.dumps(data)
57+
) -> bytes | dict:
58+
req_data = json.dumps(data) if data else data
59+
5560
response = requests.request(
5661
method,
5762
GITHUB_API_URL + url,
58-
data=data,
63+
data=req_data,
5964
headers=self.headers,
6065
params=params,
66+
timeout=10,
6167
)
6268

6369
if blob:
@@ -66,14 +72,12 @@ def __request__(
6672
if response.status_code == 200:
6773
return response.json()
6874

69-
raise GithubError(
75+
err = (
7076
"Failed to make a request to GitHub. Status code:"
7177
f" {url} {method} {data} {params}"
7278
f" {response.status_code}. Response: {response.text}",
7379
)
74-
75-
def _url_path(self, url: str):
76-
return url.split(self.URL)[-1]
80+
raise GithubError(err)
7781

7882
def get_file_content(self, repository: str, path: str) -> bytes:
7983
"""
@@ -103,18 +107,53 @@ def get_repository_tree(self, repository: str, branch: str = "main"):
103107
"""
104108
tree_file_path = self.REPOSITORY_PATH / repository
105109
tree_file_path.mkdir(parents=True, exist_ok=True)
106-
data = self.__request__(
107-
"GET",
108-
f"repos/canonical/{repository}/git/trees/{branch}?recursive=1",
109-
)
110+
111+
try:
112+
data = self.__request__(
113+
"GET",
114+
f"repos/canonical/{repository}/git/trees/{branch}?recursive=1",
115+
)
116+
except Exception as e:
117+
print(f"Failed to get repository tree: {e}")
118+
raise
110119
for item in data["tree"]:
111120
if item["type"] == "blob" and item["path"].startswith("templates"):
112-
save_github_file.delay(
121+
task = async_save_file(
113122
tree_file_path=str(tree_file_path),
114123
repository=repository,
115124
path=item["path"],
116125
)
126+
task()
127+
128+
129+
@register_task()
130+
def async_save_file(
131+
repository: str = "",
132+
path: str = "",
133+
tree_file_path: str = "",
134+
) -> None:
135+
"""
136+
Download a file to a given repository.
137+
138+
Args:
139+
repository (str): The repository name.
140+
path (str): The remote path to the file inside the repository.
141+
tree_file_path (str): The local path where the file will be saved.
142+
"""
143+
try:
144+
github = GitHub()
145+
github.logger.info(f"File path {path}")
146+
content = github.get_file_content(repository, path)
147+
github.logger.info(f"File {path} downloaded")
148+
149+
file_path = Path(tree_file_path) / path
150+
file_path.parent.mkdir(parents=True, exist_ok=True)
151+
152+
with file_path.open("wb") as file:
153+
file.write(content)
154+
except Exception as e:
155+
github.logger.exception(f"Failed to save file: {e}")
117156

118157

119158
def init_github(app: flask.Flask) -> None:
120-
app.config["github"] = GitHub(app=app)
159+
app.config["github"] = GitHub()

webapp/site_repository.py

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
import re
33
import subprocess
44
import time
5-
from typing import Callable, TypedDict
5+
from collections.abc import Callable
6+
from typing import TypedDict
67

78
from flask import Flask
89
from flask_sqlalchemy import SQLAlchemy
@@ -84,7 +85,9 @@ def __exec__(self, command_str: str):
8485
"""
8586
command = command_str.strip("").split(" ")
8687
process = subprocess.Popen(
87-
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
88+
command,
89+
stdout=subprocess.PIPE,
90+
stderr=subprocess.PIPE,
8891
)
8992
# Wait for the process to finish
9093
process.wait()
@@ -141,7 +144,8 @@ def setup_site_repository(self):
141144
# Download files from the repository
142145
github = self.app.config["github"]
143146
github.get_repository_tree(
144-
repository=self.repository_uri, branch=self.branch
147+
repository=self.repository_uri,
148+
branch=self.branch,
145149
)
146150

147151
def repository_exists(self):
@@ -195,7 +199,7 @@ def get_tree_from_disk(self):
195199
if not folder_exists:
196200
raise SiteRepositoryError(
197201
"Templates folder 'templates' not found for "
198-
f"repository {self.repo_path}"
202+
f"repository {self.repo_path}",
199203
)
200204

201205
# Change directory to the templates folder
@@ -244,8 +248,8 @@ def get_tree_from_db(self):
244248
webpages = (
245249
self.db.session.execute(
246250
select(Webpage).where(
247-
Webpage.project_id == get_project_id(self.repository_uri)
248-
)
251+
Webpage.project_id == get_project_id(self.repository_uri),
252+
),
249253
)
250254
.scalars()
251255
.all()
@@ -259,7 +263,7 @@ def get_tree_from_db(self):
259263
# If the tree is empty, load from the repository
260264
if not tree.get("children") and not tree.get("parent_id"):
261265
self.logger.info(
262-
f"Reloading incomplete tree root {self.repository_uri}."
266+
f"Reloading incomplete tree root {self.repository_uri}.",
263267
)
264268
tree = self.get_new_tree()
265269
return tree
@@ -319,22 +323,35 @@ def __create_webpage_for_node__(
319323
return {**node, **webpage_dict}
320324

321325
def __create_webpages_for_children__(
322-
self, db, children, project, owner, parent_id
326+
self,
327+
db,
328+
children,
329+
project,
330+
owner,
331+
parent_id,
323332
):
324333
"""
325334
Recursively create webpages for each child in the tree.
326335
"""
327336
for child in children:
328337
# Create a webpage for the root node
329338
webpage_dict = self.__create_webpage_for_node__(
330-
db, child, project, owner, parent_id
339+
db,
340+
child,
341+
project,
342+
owner,
343+
parent_id,
331344
)
332345
# Update the child node with the webpage fields
333346
child.update(webpage_dict)
334347
if child.get("children"):
335348
# Create webpages for the children recursively
336349
self.__create_webpages_for_children__(
337-
db, child["children"], project, owner, webpage_dict["id"]
350+
db,
351+
child["children"],
352+
project,
353+
owner,
354+
webpage_dict["id"],
338355
)
339356

340357
def __remove_webpages_to_delete__(self, db, tree):
@@ -343,14 +360,14 @@ def __remove_webpages_to_delete__(self, db, tree):
343360
self.add_pages_to_list(tree, webpages)
344361

345362
webpages_to_delete = db.session.execute(
346-
select(Webpage).where(Webpage.status == WebpageStatus.TO_DELETE)
363+
select(Webpage).where(Webpage.status == WebpageStatus.TO_DELETE),
347364
)
348365

349366
for row in webpages_to_delete:
350367
page_to_delete = row[0]
351368
if page_to_delete.name not in webpages:
352369
db.session.execute(
353-
delete(Webpage).where(Webpage.id == page_to_delete.id)
370+
delete(Webpage).where(Webpage.id == page_to_delete.id),
354371
)
355372

356373
def create_webpages_for_tree(self, db: SQLAlchemy, tree: Tree):
@@ -360,18 +377,28 @@ def create_webpages_for_tree(self, db: SQLAlchemy, tree: Tree):
360377
self.logger.info(f"Existing tree {tree}")
361378
# Get the default project and owner for new webpages
362379
project, _ = get_or_create(
363-
db.session, Project, name=self.repository_uri
380+
db.session,
381+
Project,
382+
name=self.repository_uri,
364383
)
365384
owner, _ = get_or_create(db.session, User, name="Default")
366385

367386
# Create a webpage for the root node
368387
webpage_dict = self.__create_webpage_for_node__(
369-
db, tree, project, owner, None
388+
db,
389+
tree,
390+
project,
391+
owner,
392+
None,
370393
)
371394

372395
# Create webpages for the children recursively
373396
self.__create_webpages_for_children__(
374-
db, webpage_dict["children"], project, owner, webpage_dict["id"]
397+
db,
398+
webpage_dict["children"],
399+
project,
400+
owner,
401+
webpage_dict["id"],
375402
)
376403

377404
# Remove pages that don't exist in the repository anymore

0 commit comments

Comments
 (0)