Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

Commit

A work item's activity counts for every repository it links

Projects grow more active on work_item.opened, .closed and .reopened, and on comments, in each repository the work item is linked to.

G1T-Session:
ses_01m566357hejh9yeqjbetx23f3
syntaqxcommitted Parentbe06371Browse files
3 files+28−90/3 viewed
+10−1
11 import { test } from "node:test";
22 import assert from "node:assert/strict";
33
4−import { ACTIVE, decayed, raised } from "./activity.ts";
4+import { ACTIVE, activeRepos, decayed, raised } from "./activity.ts";
55
66 const DAY = 24 * 60 * 60 * 1000;
77 const at = (days: number) => new Date(Date.UTC(2026, 9, 1) + days * DAY).toISOString();
3939 assert.ok(ACTIVE.has("git.push"));
4040 assert.ok(ACTIVE.has("pull.merged"));
4141 assert.ok(!ACTIVE.has("repo.created"));
42+ assert.ok(ACTIVE.has("work_item.opened"));
43+});
44+
45+test("a work item's activity counts for every repository it is linked to", () => {
46+ assert.deepEqual(activeRepos("rep_1", { itemId: "wki_1", repoIds: ["rep_1", "rep_2"] }), ["rep_1", "rep_2"]);
47+ // Filed in the workspace and linked nowhere: no project's.
48+ assert.deepEqual(activeRepos(null, { itemId: "wki_2", repoIds: [] }), []);
49+ assert.deepEqual(activeRepos(null, { repoId: "rep_3", number: 4 }), ["rep_3"]);
50+ assert.deepEqual(activeRepos("rep_4", {}), ["rep_4"]);
4251 });
+16−5
11 /**
22 * How active a project is lately, for sorting a workspace's projects: each
3− * push, issue or pull request opened or closed, review, comment and
4− * deployment adds one, and what came before counts for half as much every
3+ * push, work item or pull request opened or closed, review, comment and
4+ * deployment adds one (a work item's, to every repository it is linked to), and what came before counts for half as much every
55 * week. Kept as a score and the time it was last raised, so raising it is
66 * one row's update. Pure, so it is tested apart from the service.
77 */
1111 /** What happens to a project's code and work that counts as activity. */
1212 export const ACTIVE: ReadonlySet<EventType> = new Set<EventType>([
1313 "git.push",
14− "issue.opened",
15− "issue.closed",
16− "issue.reopened",
14+ "work_item.opened",
15+ "work_item.closed",
16+ "work_item.reopened",
1717 "pull.opened",
1818 "pull.updated",
1919 "pull.merged",
2424 "deployment.failed",
2525 ]);
2626
27+/**
28+ * The repositories an event's activity counts for: every repository a work
29+ * item (or a comment on one) is linked to, else the one it names.
30+ */
31+export function activeRepos(repoId: string | null | undefined, data: unknown): string[] {
32+ const linked = (data as { repoIds?: unknown } | null)?.repoIds;
33+ if (Array.isArray(linked) && linked.length > 0) return linked.filter((id): id is string => typeof id === "string" && id !== "");
34+ const named = repoId ?? (data as { repoId?: unknown } | null)?.repoId;
35+ return typeof named === "string" && named !== "" ? [named] : [];
36+}
37+
2738 /** How long until activity counts for half. */
2839 export const HALF_LIFE_MS = 7 * 24 * 60 * 60 * 1000;
2940
+2−3
2929 runsSetting,
3030 } from "./kind";
3131 import { cleanLinks, cleanUrl, projectLinks } from "./links";
32−import { ACTIVE, decayed, raised } from "./activity";
32+import { ACTIVE, activeRepos, decayed, raised } from "./activity";
3333 import { MAX_PINS, MAX_RECENT, MAX_VISITS, placePin, recentAfterPins, reorderPins } from "./pins";
3434 import { renameStatements } from "./rename";
3535 import { moveStatements, slugOf, strandedQuery } from "./transfer";
984984
985985 async onEvent(event: G1tEvent): Promise<void> {
986986 if (ACTIVE.has(event.type)) {
987− const repoId = event.repoId ?? ("repoId" in event.data ? (event.data as { repoId?: string }).repoId : undefined);
988− if (repoId) await this.active(repoId, event.time, event.type === "git.push");
987+ for (const repoId of activeRepos(event.repoId, event.data)) await this.active(repoId, event.time, event.type === "git.push");
989988 }
990989 if (event.type === "deployment_status.created") {
991990 await this.productionReported(event.data);

Comments

Sign in to comment.