Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/core/__tests__/format.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ describe("toNotice", () => {
expect(n.url).toBe("https://github.com/acme/api/compare/aaa...bbb");
});

it("doesn't claim '0 commits' when GitHub omits the count", () => {
const n = toNotice(base("PushEvent", { ref: "refs/heads/main", before: "a", head: "b" }))!;
expect(n.body).toBe("en main");
});

it("distinguishes merged from closed PRs", () => {
const pr = { number: 7, title: "Add cache", html_url: "https://github.com/acme/api/pull/7" };
expect(toNotice(base("PullRequestEvent", { action: "closed", number: 7, pull_request: { ...pr, merged: true } }))!.title)
Expand Down
6 changes: 4 additions & 2 deletions src/core/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ export function toNotice(ev: GhEvent, agentsEnabled = true): Notice | null {
switch (ev.type) {
case "PushEvent": {
const branch = shortRef(p.ref);
const n: number = p.size ?? p.commits?.length ?? 0;
const n: number | undefined = p.size ?? (p.commits?.length || undefined);
const msg = firstLine(p.commits?.[0]?.message);
title = t("ev.push.title", { who, repo });
body = t(n === 1 ? "ev.push.body" : "ev.push.bodyPlural", { n, branch }) + (msg ? `: ${clip(msg)}` : "");
body = (n === undefined
? t("ev.push.bodyUnknown", { branch })
: t(n === 1 ? "ev.push.body" : "ev.push.bodyPlural", { n, branch })) + (msg ? `: ${clip(msg)}` : "");
url = p.before && p.head ? `${repoUrl}/compare/${p.before}...${p.head}` : `${repoUrl}/commits/${branch}`;
break;
}
Expand Down
26 changes: 26 additions & 0 deletions src/core/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,29 @@ export async function fetchLatestEvent(target: string, token: string, login: str
const r = await fetchEvents(`${url}?per_page=10`, token, null);
return r.events?.[0] ?? null;
}

/**
* GitHub's Events API stopped including `size` and `commits` in PushEvent
* payloads (only before/head/ref remain). One compare call restores the
* commit count, messages and authors, which the formatter and the agent
* detector need. Mutates the event in place; failures leave it slim.
*/
export async function enrichPushEvent(ev: GhEvent, token: string): Promise<void> {
const p = ev.payload;
if (ev.type !== "PushEvent" || Array.isArray(p.commits) && p.commits.length) return;
if (!p.before || !p.head) return;
try {
const res = await timedFetch(`${API}/repos/${ev.repo.name}/compare/${p.before}...${p.head}?per_page=20`, {
headers: headers(token),
});
if (!res.ok) return;
const data = (await res.json()) as {
total_commits: number;
commits: { sha: string; commit: { message: string; author: { name: string; email: string } } }[];
};
p.size = data.total_commits;
p.commits = data.commits.map((c) => ({ sha: c.sha, message: c.commit.message, author: c.commit.author }));
} catch (e) {
console.warn("enrich push", ev.id, e);
}
}
2 changes: 2 additions & 0 deletions src/core/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ const dict = {
"ev.push.title": "{who} hizo push a {repo}",
"ev.push.body": "{n} commit en {branch}",
"ev.push.bodyPlural": "{n} commits en {branch}",
"ev.push.bodyUnknown": "en {branch}",
"ev.pr.opened": "{who} abrió PR #{num} en {repo}",
"ev.pr.merged": "{who} mergeó PR #{num} en {repo}",
"ev.pr.closed": "{who} cerró PR #{num} en {repo}",
Expand Down Expand Up @@ -275,6 +276,7 @@ const dict = {
"ev.push.title": "{who} pushed to {repo}",
"ev.push.body": "{n} commit on {branch}",
"ev.push.bodyPlural": "{n} commits on {branch}",
"ev.push.bodyUnknown": "on {branch}",
"ev.pr.opened": "{who} opened PR #{num} in {repo}",
"ev.pr.merged": "{who} merged PR #{num} in {repo}",
"ev.pr.closed": "{who} closed PR #{num} in {repo}",
Expand Down
13 changes: 10 additions & 3 deletions src/core/poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// record its newest id and notify nothing, otherwise a fresh install would
// spam you with the last 90 days of activity.

import { endpointFor, fetchEvents, GhError } from "./github";
import { endpointFor, enrichPushEvent, fetchEvents, GhError } from "./github";
import { t } from "./i18n";
import { toNotice } from "./format";
import { markUnread, ringTray, toast } from "../platform/notify";
Expand Down Expand Up @@ -116,7 +116,7 @@ export class Poller {
if (r.remaining !== null) remaining = r.remaining;
if (!r.events) continue; // 304, nothing new

fresh.push(...this.diff(target, r.events));
fresh.push(...(await this.diff(target, r.events, token)));
} catch (e) {
if (e instanceof GhError && e.isRateLimited && e.resetAt) {
this.pausedUntil = e.resetAt * 1000 + 1000;
Expand Down Expand Up @@ -153,7 +153,7 @@ export class Poller {
}

/** Returns notices for events newer than what we've seen for this target. */
private diff(target: string, events: import("./types").GhEvent[]): Notice[] {
private async diff(target: string, events: import("./types").GhEvent[], token: string): Promise<Notice[]> {
if (events.length === 0) return [];
const newest = events[0].id; // API returns newest first
const last = this.lastSeen[target];
Expand All @@ -163,8 +163,15 @@ export class Poller {

const { events: wanted, ignoreOwn, agentsOwn, login } = this.settings;
const out: Notice[] = [];
let enriched = 0;
for (const ev of events) {
if (BigInt(ev.id) <= BigInt(last)) break;
// slim PushEvents: one compare call gives count, messages, authors
// (needed for the body and for agent trailers). Bounded per cycle.
if (ev.type === "PushEvent" && enriched < 10) {
enriched++;
await enrichPushEvent(ev, token);
}
const n = toNotice(ev, wanted.agent);
if (!n || !wanted[n.category]) continue;
// your own activity is noise... unless an agent did it under your name:
Expand Down
Loading