Skip to content

Commit c8cf05f

Browse files
committed
fix ci failures
1 parent 245396c commit c8cf05f

11 files changed

Lines changed: 93 additions & 35 deletions

File tree

‎.github/workflows/container.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
--tmpfs /tmp:rw,noexec,nosuid,nodev,size=16m,uid=10001,gid=10001 \
2626
--entrypoint python feedback:${{ github.sha }} \
2727
-c 'import os; assert os.getuid() == 10001; import feedback'
28-
- uses: aquasecurity/trivy-action@0.33.1
28+
- uses: aquasecurity/trivy-action@v0.36.0
2929
with:
3030
image-ref: feedback:${{ github.sha }}
3131
format: table

‎runtime/src/api/client.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ export class FeedbackClient {
276276
id: cached?.id ?? null,
277277
up: result.up,
278278
down: result.down,
279+
upvotes: cached?.upvotes ?? 0,
280+
reactions: cached?.reactions ?? {},
279281
age: 0,
280282
stale: true,
281283
viewer: result.viewer,

‎runtime/src/example/page.ts‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,20 @@ async function render(): Promise<void> {
5858
const root = required("thread");
5959
root.replaceChildren();
6060
appendText(root, "h2", string(content.title) || key);
61+
const category = record(content.category);
62+
if (category) appendText(root, "span", `Category: ${string(category.name)}`, "tag");
63+
renderLabels(root, content.labels);
6164
appendText(root, "p", string(content.body));
65+
if (state) {
66+
appendText(
67+
root,
68+
"span",
69+
`Thumbs up: ${String(state.reactions.THUMBS_UP ?? state.up)} ` +
70+
`Thumbs down: ${String(state.reactions.THUMBS_DOWN ?? state.down)} ` +
71+
`Upvotes: ${String(state.upvotes)}`,
72+
"tag",
73+
);
74+
}
6275
renderPoll(root, record(content.poll));
6376
const reactions = document.createElement("div");
6477
reactions.className = "reactions";
@@ -86,6 +99,15 @@ async function render(): Promise<void> {
8699
}
87100
}
88101

102+
function renderLabels(parent: HTMLElement, value: unknown): void {
103+
const nodes = record(value)?.nodes;
104+
if (!Array.isArray(nodes)) return;
105+
for (const label of nodes) {
106+
const item = record(label);
107+
if (item) appendText(parent, "span", `Label: ${string(item.name)}`, "tag");
108+
}
109+
}
110+
89111
function renderPoll(parent: HTMLElement, poll: Record<string, unknown> | null): void {
90112
if (!poll) return;
91113
appendText(parent, "h3", string(poll.question));

‎src/feedback/api/routes.py‎

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
from feedback.api.http import (
1414
ApiError,
15+
add_comment_request,
1516
cors,
1617
ensure_discussion_request,
17-
add_comment_request,
1818
error_response,
1919
json_strings,
2020
preflight,
@@ -55,16 +55,17 @@ async def reactions(request: Request) -> Response:
5555
item = cached.get(key)
5656
if item is None:
5757
items[key] = {
58-
"id": None, "up": 0, "down": 0, "upvotes": 0,
58+
"id": None,
59+
"up": 0,
60+
"down": 0,
61+
"upvotes": 0,
5962
"reactions": {name: 0 for name in site.reaction_counters},
60-
"age": 0, "stale": False,
63+
"age": 0,
64+
"stale": False,
6165
}
6266
continue
6367
age = max(0, now - item.fetched_at)
64-
reactions = {
65-
name: item.reactions.get(name, 0)
66-
for name in site.reaction_counters
67-
}
68+
reactions = {name: item.reactions.get(name, 0) for name in site.reaction_counters}
6869
thumbsup = item.thumbsup
6970
thumbsdown = item.thumbsdown
7071
up = item.thumbsup if site.upvote_source == "thumbsup" else item.upvotes
@@ -224,9 +225,7 @@ async def discussion_content(request: Request) -> Response:
224225
raise ApiError("service_unavailable", "Discussion content is unavailable.", 503)
225226
keys = resource_keys(request.query_params, 1)
226227
try:
227-
content = await container.discussions.content(
228-
site, container.databases[site.id], keys[0]
229-
)
228+
content = await container.discussions.content(site, container.databases[site.id], keys[0])
230229
except DiscussionError as exc:
231230
raise ApiError("discussion_not_found", str(exc), 404) from exc
232231
except GitHubError as exc:
@@ -259,7 +258,9 @@ async def add_comment(request: Request) -> Response:
259258
except GitHubError as exc:
260259
status = 401 if exc.status == 401 else 502
261260
raise ApiError("github_comment_failed", "GitHub rejected the comment.", status) from exc
262-
return cors(JSONResponse({"v": 1, "comment": result}, headers={"Cache-Control": "no-store"}), origin)
261+
return cors(
262+
JSONResponse({"v": 1, "comment": result}, headers={"Cache-Control": "no-store"}), origin
263+
)
263264

264265

265266
async def submit_vote(request: Request) -> Response:

‎src/feedback/app.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616
from feedback.api.http import ApiError
1717
from feedback.api.middleware import SecurityHeadersMiddleware
1818
from feedback.api.routes import (
19+
add_comment,
1920
api_error,
2021
discussion_content,
21-
add_comment,
2222
homepage,
2323
oauth_authorize,
2424
oauth_exchange,

‎src/feedback/config.py‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,17 @@ class ConfigError(ValueError):
1818
_MAPPINGS = frozenset({"key", "title", "url", "pathname", "custom", "number"})
1919
_UPVOTE_SOURCES = frozenset({"thumbsup", "native", "both"})
2020
_REACTIONS = frozenset({"LAUGH", "HOORAY", "CONFUSED", "HEART", "ROCKET", "EYES"})
21-
_FEATURES = frozenset({
22-
"counters", "viewer_reactions", "voting", "discussion", "comments", "labels", "github_link",
23-
})
21+
_FEATURES = frozenset(
22+
{
23+
"counters",
24+
"viewer_reactions",
25+
"voting",
26+
"discussion",
27+
"comments",
28+
"labels",
29+
"github_link",
30+
}
31+
)
2432
_SERVICE_KEYS = frozenset(
2533
{
2634
"public_origin",
@@ -157,7 +165,8 @@ def load_config(path: Path | str, *, data_directory: Path | None = None) -> Conf
157165
raise ConfigError(f"sites.{site_id}.upvote_source is unsupported")
158166
reaction_counters = (
159167
tuple(item.upper() for item in _string_list(value, "reaction_counters"))
160-
if "reaction_counters" in value else tuple(sorted(_REACTIONS))
168+
if "reaction_counters" in value
169+
else tuple(sorted(_REACTIONS))
161170
)
162171
if not reaction_counters or any(item not in _REACTIONS for item in reaction_counters):
163172
raise ConfigError(f"sites.{site_id}.reaction_counters contains an unsupported reaction")

‎src/feedback/database/sqlite.py‎

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ def reactions(self, resource_ids: Iterable[str]) -> dict[str, ReactionCounts]:
7474
rows = connection.execute(REACTIONS, (json.dumps(keys),)).fetchall()
7575
return {
7676
row[0]: ReactionCounts(
77-
node_id=row[1], thumbsup=row[2], thumbsdown=row[3], upvotes=row[4], fetched_at=row[5],
77+
node_id=row[1],
78+
thumbsup=row[2],
79+
thumbsdown=row[3],
80+
upvotes=row[4],
81+
fetched_at=row[5],
7882
reactions=json.loads(row[6]),
7983
)
8084
for row in rows
@@ -96,15 +100,20 @@ def comment_belongs_to(self, comment_id: str, discussion_id: str) -> bool:
96100
def comment_can_receive_reply(self, comment_id: str, discussion_id: str) -> bool:
97101
with self.connect() as connection:
98102
row = connection.execute(
99-
"SELECT 1 FROM comments WHERE id = ? AND discussion_id = ? "
100-
"AND parent_id IS NULL",
103+
"SELECT 1 FROM comments WHERE id = ? AND discussion_id = ? AND parent_id IS NULL",
101104
(comment_id, discussion_id),
102105
).fetchone()
103106
return row is not None
104107

105108
def put_comment(
106-
self, *, comment_id: str, discussion_id: str, parent_id: str | None,
107-
body: str, url: str | None, fetched_at: int,
109+
self,
110+
*,
111+
comment_id: str,
112+
discussion_id: str,
113+
parent_id: str | None,
114+
body: str,
115+
url: str | None,
116+
fetched_at: int,
108117
) -> None:
109118
with self.connect() as connection:
110119
connection.execute(
@@ -124,10 +133,17 @@ def tracked_reactions(
124133
with self.connect() as connection:
125134
rows = connection.execute(TRACKED_REACTIONS, (after, fetched_before, limit)).fetchall()
126135
return [
127-
(row[0], ReactionCounts(
128-
node_id=row[1], thumbsup=row[2], thumbsdown=row[3], upvotes=row[4], fetched_at=row[5],
129-
reactions=json.loads(row[6]),
130-
))
136+
(
137+
row[0],
138+
ReactionCounts(
139+
node_id=row[1],
140+
thumbsup=row[2],
141+
thumbsdown=row[3],
142+
upvotes=row[4],
143+
fetched_at=row[5],
144+
reactions=json.loads(row[6]),
145+
),
146+
)
131147
for row in rows
132148
]
133149

‎src/feedback/protocol/github/discussions.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,9 @@ async def create(self, site: SiteConfig, *, title: str, body: str) -> GitHubDisc
8686
raise GitHubError("github_malformed_response")
8787
return discussion
8888

89-
async def content(self, site: SiteConfig, discussion_id: str, comments: int = 100) -> dict[str, Any]:
89+
async def content(
90+
self, site: SiteConfig, discussion_id: str, comments: int = 100
91+
) -> dict[str, Any]:
9092
return await self._client.graphql(
9193
site.installation_id,
9294
load("discussion"),
@@ -137,7 +139,9 @@ def _parse(value: object, site: SiteConfig) -> GitHubDiscussion | None:
137139
upvotes = value.get("upvoteCount", 0)
138140
if isinstance(upvotes, bool) or not isinstance(upvotes, int) or upvotes < 0:
139141
raise GitHubError("github_malformed_response")
140-
return GitHubDiscussion(node_id, number, title, url, locked, thumbsup, thumbsdown, upvotes, reactions)
142+
return GitHubDiscussion(
143+
node_id, number, title, url, locked, thumbsup, thumbsdown, upvotes, reactions
144+
)
141145

142146

143147
def _vote_counts(value: object) -> tuple[int, int, dict[str, int]]:

‎src/feedback/service/discussions.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ async def find(self, site: SiteConfig, lookup_term: str) -> GitHubDiscussion | N
2323

2424
async def create(self, site: SiteConfig, *, title: str, body: str) -> GitHubDiscussion: ...
2525

26-
async def content(self, site: SiteConfig, discussion_id: str, comments: int = 100) -> dict[str, Any]: ...
26+
async def content(
27+
self, site: SiteConfig, discussion_id: str, comments: int = 100
28+
) -> dict[str, Any]: ...
2729

2830
async def add_comment(
2931
self, token: str, discussion_id: str, body: str, reply_to_id: str | None
@@ -81,7 +83,9 @@ async def ensure(
8183
)
8284
return result
8385

84-
async def content(self, site: SiteConfig, database: SiteDatabase, resource_id: str) -> dict[str, Any]:
86+
async def content(
87+
self, site: SiteConfig, database: SiteDatabase, resource_id: str
88+
) -> dict[str, Any]:
8589
discussion = database.discussion(resource_id)
8690
if discussion is None:
8791
raise DiscussionError("discussion does not exist")

‎src/feedback/service/reaction_cache.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ def _parse_node(
9393
if not isinstance(nodes, list):
9494
raise GitHubError("github_malformed_response")
9595
accounts = tuple(
96-
node["id"] for node in nodes
96+
node["id"]
97+
for node in nodes
9798
if isinstance(node, dict) and isinstance(node.get("id"), str)
9899
)
99100
if len(accounts) != len(nodes):
@@ -116,5 +117,6 @@ def _parse_node(
116117
counts.get("THUMBS_DOWN", (0, ()))[0],
117118
upvotes,
118119
counts,
119-
locked, updated_at,
120+
locked,
121+
updated_at,
120122
)

0 commit comments

Comments
 (0)