Skip to content

Commit 4d40922

Browse files
authored
Added monitor app for deps publication (#265)
1 parent 3f6aeba commit 4d40922

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ detekt/reports/**
3737

3838
local.properties
3939
scan-journal.log
40+
41+
monitor/.venv
42+
monitor/.idea

monitor/main.py

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import asyncio
2+
import os
3+
import sys
4+
from typing import List
5+
6+
import httpx
7+
8+
from textual.app import App, ComposeResult
9+
from textual.binding import Binding
10+
from textual.containers import VerticalScroll, Container, HorizontalGroup
11+
from textual.widget import Widget
12+
from textual.widgets import Header, ProgressBar, Static, Footer
13+
14+
REPO_URL = "https://repo.maven.apache.org/maven2"
15+
16+
17+
def read_publications(version, path):
18+
files = [[x[0], list(filter(lambda file: file.endswith(".pom"), x[2]))[0]] for x in os.walk(path) if
19+
version in x[0]]
20+
paths = list(map(lambda tpl: Path(f"{tpl[0].removeprefix(path)}/{tpl[1]}"), files))
21+
return paths
22+
23+
24+
class Path:
25+
def __init__(self, path) -> None:
26+
self.full = path
27+
self.base = os.path.basename(path)
28+
self.calculated_id = str(self.base.replace(".", "_"))
29+
30+
31+
class Dependency(HorizontalGroup):
32+
def __init__(self, path: Path, *children: Widget) -> None:
33+
self.path = path
34+
super().__init__(*children, name=self.path.base)
35+
36+
def compose(self) -> ComposeResult:
37+
yield Static(self.path.base, id=self.path.calculated_id)
38+
39+
40+
class MonitoringApp(App):
41+
CSS = """
42+
Screen {
43+
align: center middle;
44+
}
45+
46+
Header {
47+
text-align: center;
48+
}
49+
50+
.progress-container {
51+
width: 80%;
52+
height: 3;
53+
margin: 1 0;
54+
}
55+
56+
VerticalScroll {
57+
width: 95%;
58+
height: 80%;
59+
border: solid white;
60+
}
61+
62+
.found {
63+
color: green;
64+
}
65+
66+
.hidden {
67+
display: none;
68+
}
69+
"""
70+
71+
BINDINGS = [
72+
Binding(key="q", action="quit", description="Quit the app"),
73+
Binding(key="h", action="hide", description="Hide/Show Uploaded"),
74+
]
75+
76+
def __init__(self, paths: List[Path], version, *children, **kwargs):
77+
super().__init__(*children, **kwargs)
78+
self.paths = paths
79+
self.version = version
80+
81+
def compose(self) -> ComposeResult:
82+
yield Header(show_clock=True, name="Monitoring")
83+
yield Container(
84+
ProgressBar(
85+
total=len(self.paths),
86+
show_percentage=True,
87+
id="progress-bar",
88+
show_eta=False,
89+
),
90+
classes="progress-container",
91+
)
92+
93+
deps = [Dependency(i) for i in self.paths]
94+
yield VerticalScroll(*deps)
95+
yield Footer()
96+
97+
hidden = True
98+
99+
def action_hide(self):
100+
if self.hidden:
101+
self.query(".found").remove_class("hidden")
102+
else:
103+
self.query(".found").add_class("hidden")
104+
105+
self.hidden = not self.hidden
106+
107+
def on_mount(self):
108+
self.title = "Monitoring Dependencies"
109+
self.sub_title = f"Version {self.version}"
110+
111+
def on_load(self) -> None:
112+
self.run_worker(self.gather(), exclusive=True)
113+
114+
async def gather(self):
115+
await asyncio.gather(*[self.update_weather(path) for path in _paths])
116+
117+
lock = asyncio.Lock()
118+
progress = 0
119+
120+
async def update_weather(self, path: Path) -> None:
121+
url = f"{REPO_URL}/{path.full}"
122+
async with httpx.AsyncClient() as client:
123+
response = await client.get(url)
124+
if response.status_code == 200:
125+
weather_widget = self.query_one(f"#{path.calculated_id}", Static)
126+
weather_widget.add_class("found")
127+
if self.hidden:
128+
weather_widget.add_class("hidden")
129+
weather_widget.update(f"{path.base} - UPLOADED")
130+
await self.lock.acquire()
131+
self.progress += 1
132+
self.query_one("#progress-bar", ProgressBar).update(progress=self.progress)
133+
self.lock.release()
134+
else:
135+
await asyncio.sleep(1)
136+
await self.update_weather(path)
137+
138+
139+
if __name__ == "__main__":
140+
if not os.path.exists("../build/repo/"):
141+
print("use ./publishLocal.sh from the repository root")
142+
elif len(sys.argv) != 2:
143+
print("Usage: python main.py <version>")
144+
else:
145+
_version = sys.argv[1]
146+
_paths = read_publications(_version, "../build/repo/")
147+
app = MonitoringApp(_paths, _version)
148+
app.run()

monitor/requirements.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
aiohappyeyeballs==2.4.4
2+
aiohttp==3.11.11
3+
aiohttp-jinja2==1.6
4+
aiosignal==1.3.2
5+
anyio==4.8.0
6+
async-timeout==5.0.1
7+
attrs==25.1.0
8+
certifi==2024.12.14
9+
click==8.1.8
10+
exceptiongroup==1.2.2
11+
frozenlist==1.5.0
12+
h11==0.14.0
13+
httpcore==1.0.7
14+
httpx==0.28.1
15+
idna==3.10
16+
Jinja2==3.1.5
17+
linkify-it-py==2.0.3
18+
markdown-it-py==3.0.0
19+
MarkupSafe==3.0.2
20+
mdit-py-plugins==0.4.2
21+
mdurl==0.1.2
22+
msgpack==1.1.0
23+
multidict==6.1.0
24+
platformdirs==4.3.6
25+
propcache==0.2.1
26+
Pygments==2.19.1
27+
rich==13.9.4
28+
sniffio==1.3.1
29+
textual==1.0.0
30+
textual-dev==1.7.0
31+
textual-serve==1.1.1
32+
typing_extensions==4.12.2
33+
uc-micro-py==1.0.3
34+
yarl==1.18.3

0 commit comments

Comments
 (0)