Skip to content

Commit

Permalink
envoy.ci.report(0.0.3): Improve schema and cleanups (#2348)
Browse files Browse the repository at this point in the history
Signed-off-by: Ryan Northey <ryan@synca.io>
  • Loading branch information
phlax authored Oct 12, 2024
1 parent 6f02f6c commit 5759d4c
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 114 deletions.
2 changes: 1 addition & 1 deletion envoy.ci.report/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.0.3-dev
0.0.3
1 change: 1 addition & 0 deletions envoy.ci.report/envoy/ci/report/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ toolshed_library(
"exceptions.py",
"interface.py",
"runner.py",
"typing.py",
"abstract/__init__.py",
"abstract/filters.py",
"abstract/format.py",
Expand Down
5 changes: 3 additions & 2 deletions envoy.ci.report/envoy/ci/report/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

from . import abstract, exceptions, interface
from . import abstract, exceptions, interface, typing
from .ci import CIRuns
from .runner import (
CreationTimeFilter, JSONFormat, MarkdownFormat,
Expand All @@ -18,4 +18,5 @@
"main",
"MarkdownFormat",
"ReportRunner",
"StatusFilter")
"StatusFilter",
"typing")
68 changes: 41 additions & 27 deletions envoy.ci.report/envoy/ci/report/abstract/format.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import json
import textwrap
from datetime import datetime

import abstracts
Expand Down Expand Up @@ -28,36 +29,49 @@ def out(self, data: dict) -> None:
class AMarkdownFormat(AFormat):

def out(self, data: dict) -> None:
for commit, events in data.items():
self._handle_commit(commit, events)

def _handle_commit(self, commit: str, events: list[dict]) -> None:
outcome = (
"failed"
if any(event["workflow"]["conclusion"] == "failure"
for event
in events)
else "succeeded")
target_branch = events[0]["request"]["target-branch"]
for commit, info in data.items():
self._handle_commit(commit, info)

def _handle_commit(self, commit: str, info: dict) -> None:
target_branch = info["head"]["target_branch"]
commit_url = f"https://github.com/envoyproxy/envoy/commit/{commit}"
print(f"[{target_branch}@{commit[:7]}]({commit_url}): {outcome}")
for event in events:
self._handle_event(event)
print(f"### [{target_branch}@{commit[:7]}]({commit_url})")
self._handle_commit_message(info['head']['message'])
for request_id, request in info["requests"].items():
self._handle_event(request_id, request)

def _handle_commit_message(self, message):
lines = message.splitlines()
if len(lines) == 1:
print(message)
return
summary = lines[0]
details = textwrap.indent(
"\n".join(lines[1:]),
" ",
lambda line: True)
print("<details>")
print(f" <summary>{summary}</summary>")
print(" <blockquote>")
print(details)
print(" </blockquote>")
print("</details>")
print()

def _handle_event(self, event: dict) -> None:
event_type = event["event"]
def _handle_event(self, request_id, request) -> None:
event_type = request["event"]
request_started = datetime.utcfromtimestamp(
int(event["request"]["started"])).isoformat()
workflow_name = event["workflow"]["name"]
conclusion = event["workflow"]["conclusion"]
workflow_id = event["workflow_id"]
request_id = event["request_id"]
workflow_url = (
"https://github.com/envoyproxy/envoy/"
f"actions/runs/{workflow_id}")
int(request["started"])).isoformat()
request_url = (
"https://github.com/envoyproxy/envoy/"
f"actions/runs/{request_id}")
print(
f" -> [[{event_type}@{request_started}]({request_url})]: "
f"[{workflow_name} ({conclusion})]({workflow_url})")
print(f"#### [{event_type}@{request_started}]({request_url}):")
for workflow_id, workflow in request["workflows"].items():
workflow_url = (
"https://github.com/envoyproxy/envoy/"
f"actions/runs/{workflow_id}")
print(
f"- [{workflow['name']} "
f"({workflow['conclusion']})]({workflow_url})")
print()
print("----")
4 changes: 2 additions & 2 deletions envoy.ci.report/envoy/ci/report/abstract/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os
import pathlib
from functools import cached_property
from typing import Callable, Type
from typing import Callable

import aiohttp

Expand Down Expand Up @@ -94,7 +94,7 @@ def runs(self) -> interface.ICIRuns:

@property
@abstracts.interfacemethod
def runs_class(self) -> Type[interface.ICIRuns]:
def runs_class(self) -> type[interface.ICIRuns]:
raise NotImplementedError

@cached_property
Expand Down
75 changes: 46 additions & 29 deletions envoy.ci.report/envoy/ci/report/abstract/runs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from aio.core.functional import async_property
from aio.core.tasks import concurrent

from envoy.ci.report import exceptions
from envoy.ci.report import exceptions, typing

URL_GH_REPO_ACTION_ENV_ARTIFACT = "actions/runs/{wfid}/artifacts?name=env"
URL_GH_REPO_ACTIONS = "actions/runs?per_page=100"
Expand Down Expand Up @@ -41,7 +41,7 @@ def __init__(
else sort_ascending)

@async_property
async def as_dict(self) -> dict:
async def as_dict(self) -> typing.CIRunsDict:
return self._sorted(await self._to_dict())

@async_property(cache=True)
Expand All @@ -57,7 +57,7 @@ async def check_runs(self) -> dict:
return result

@async_property(cache=True)
async def envs(self) -> dict:
async def envs(self) -> typing.CIRequestEnvsDict:
artifacts: dict = {}
async for result in concurrent(self._env_fetches):
if not result:
Expand Down Expand Up @@ -214,40 +214,57 @@ async def _resolve_env_artifact_url(self, wfid: int) -> str | None:
except IndexError:
log.warning(f"Unable to find request artifact: {wfid}")

def _sorted(self, runs: dict) -> dict:
def _sorted(self, runs: typing.CIRunsDict) -> typing.CIRunsDict:
max_or_min = (
min
if self.sort_ascending
else max)
return dict(
sorted(
((k,
sorted(
v,
key=lambda event: event["request"]["started"],
reverse=not self.sort_ascending))
for k, v in runs.items()),
runs.items(),
key=lambda item: max_or_min(
x["request"]["started"]
for x in item[1]),
request["started"]
for request
in item[1]["requests"].values()),
reverse=not self.sort_ascending))

async def _to_dict(self) -> dict:
return {
commit: requests
for commit, request in (await self.workflow_requests).items()
if (requests := await self._to_list_request(commit, request))}
async def _to_dict(self) -> typing.CIRunsDict:
wf_requests = await self.workflow_requests
result: dict = {}
for commit, _requests in wf_requests.items():
requests = await self._to_list_request(commit, _requests)
if not requests:
continue
result[commit] = {}
result[commit]["head"] = dict(
message=requests[0]["request"]["message"],
target_branch=requests[0]["request"]["target-branch"])
result[commit]["requests"] = {}
for request in requests:
result[commit]["requests"][request["request_id"]] = result[
commit]["requests"].get(
request["request_id"],
dict(event=request["event"],
started=request["request"]["started"],
workflows={}))
result[commit]["requests"][
request["request_id"]]["workflows"][
request["workflow_id"]] = request["workflow"]
return result

async def _to_list_request(self, commit: str, request: dict) -> list[dict]:
return [
{"event": event,
"request": (await self.envs)[commit][event][req]["request"],
"request_id": req,
"check_name": check_run["name"],
"workflow_id": check_run["external_id"],
"workflow": (await self.workflows)[int(check_run["external_id"])]}
for event, requests in request.items()
for check_run in (
await self.check_runs).get(
commit, {}).get(event, [])
for req in requests]
return sorted(
[{"event": event,
"request": (await self.envs)[commit][event][req]["request"],
"request_id": req,
"check_name": check_run["name"],
"workflow_id": check_run["external_id"],
"workflow": (await self.workflows)[
int(check_run["external_id"])]}
for event, requests in request.items()
for check_run in (
await self.check_runs).get(
commit, {}).get(event, [])
for req in requests],
key=lambda item: item["request"]["started"],
reverse=not self.sort_ascending)
3 changes: 1 addition & 2 deletions envoy.ci.report/envoy/ci/report/cmd.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@

import sys
from typing import Optional

from .runner import ReportRunner


def main(*args: str) -> Optional[int]:
def main(*args: str) -> int | None:
return ReportRunner(*args)()


Expand Down
3 changes: 1 addition & 2 deletions envoy.ci.report/envoy/ci/report/runner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@

from functools import cached_property
from typing import Type

import abstracts

Expand Down Expand Up @@ -29,7 +28,7 @@ class ReportRunner(abstract.AReportRunner):
about Envoy's CI."""

@property
def runs_class(self) -> Type[interface.ICIRuns]:
def runs_class(self) -> type[interface.ICIRuns]:
return ci.CIRuns

@cached_property
Expand Down
36 changes: 36 additions & 0 deletions envoy.ci.report/envoy/ci/report/typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

from typing import TypedDict


class CIWorkflowDict(TypedDict):
name: str
status: str
event: str
conclusion: str


class CICommitHeadDict(TypedDict):
message: str
target_branch: str


class CIRequestDict(TypedDict):
event: str
started: float
workflows: list[dict[str, CIWorkflowDict]]


class CIRunsCommitDict(TypedDict):
head: CICommitHeadDict
requests: dict[int, CIRequestDict]


class CIRequestWorkflowDict(TypedDict):
checks: dict
request: dict


CIRunsDict = dict[str, CIRunsCommitDict]
CIRequestWorkflowsDict = dict[int, list[CIRequestWorkflowDict]]
CIRequestEventDict = dict[str, CIRequestWorkflowsDict]
CIRequestEnvsDict = dict[str, CIRequestEventDict]
Loading

0 comments on commit 5759d4c

Please sign in to comment.