diff --git a/frontend/src/content/config.ts b/frontend/src/content/config.ts index 40afc1f..aacf66b 100644 --- a/frontend/src/content/config.ts +++ b/frontend/src/content/config.ts @@ -1,9 +1,9 @@ -import { RepoSummary } from '@lib/repo-summaries'; +import { RepoSummaryInContent } from '@lib/repo-summaries'; import { defineCollection } from 'astro:content'; const githubCollection = defineCollection({ type: "data", - schema: RepoSummary, + schema: RepoSummaryInContent, }); export const collections = { diff --git a/frontend/src/lib/repo-summaries.ts b/frontend/src/lib/repo-summaries.ts index 53e6f3b..53f0687 100644 --- a/frontend/src/lib/repo-summaries.ts +++ b/frontend/src/lib/repo-summaries.ts @@ -4,17 +4,23 @@ import { z } from 'zod'; export const SloType = z.enum(["triage", "urgent", "important", "none"]); export type SloType = z.infer; +const checkInstant = z.string().refine(val => { + try { Temporal.Instant.from(val); return true; } catch { return false; } +}); +const checkDuration = z.string().refine(val => { + try { Temporal.Duration.from(val); return true; } catch { return false; } +}); const duration = z.string().transform(val => Temporal.Duration.from(val)); const instant = z.string().transform(val => Temporal.Instant.from(val)); -export const IssueSummary = z.object({ +export const IssueSummaryInContent = z.object({ url: z.string().url(), title: z.string(), author: z.string().optional(), - createdAt: instant, + createdAt: checkInstant, pull_request: z.object({ draft: z.boolean().default(false) }).optional(), labels: z.array(z.string()), - sloTimeUsed: duration, + sloTimeUsed: checkDuration, whichSlo: SloType, stats: z.object({ numTimelineItems: z.number(), @@ -22,13 +28,19 @@ export const IssueSummary = z.object({ numLabels: z.number(), }).optional(), }) +export type IssueSummaryInContent = z.infer; + +export const IssueSummary = IssueSummaryInContent.extend({ + createdAt: instant, + sloTimeUsed: duration, +}); export type IssueSummary = z.infer; -export const RepoSummary = z.object({ - cachedAt: instant, +export const RepoSummaryInContent = z.object({ + cachedAt: checkInstant, org: z.string(), repo: z.string(), - issues: IssueSummary.array(), + issues: IssueSummaryInContent.array(), labelsPresent: z.boolean(), stats: z.object({ numLabels: z.number(), @@ -36,4 +48,10 @@ export const RepoSummary = z.object({ numPRs: z.number(), }).optional(), }); +export type RepoSummaryInContent = z.infer; + +export const RepoSummary = RepoSummaryInContent.extend({ + cachedAt: instant, + issues: IssueSummary.array(), +}); export type RepoSummary = z.infer; diff --git a/frontend/src/pages/[org]/[repo].astro b/frontend/src/pages/[org]/[repo].astro index 0fc1924..c14911d 100644 --- a/frontend/src/pages/[org]/[repo].astro +++ b/frontend/src/pages/[org]/[repo].astro @@ -1,6 +1,7 @@ --- import Issue from "@components/Issue.astro"; import Layout from "@layouts/Layout.astro"; +import { IssueSummary } from "@lib/repo-summaries"; import { cmpByTimeUsed, groupBySlo } from "@lib/slo"; import type { GetStaticPaths, @@ -30,7 +31,7 @@ const { importantViolations, urgent, urgentViolations, -} = groupBySlo(details.issues); +} = groupBySlo(IssueSummary.array().parse(details.issues)); urgent.push(...urgentViolations); urgent.sort(cmpByTimeUsed); important.push(...importantViolations); diff --git a/frontend/src/pages/index.astro b/frontend/src/pages/index.astro index 00a06fc..374ab44 100644 --- a/frontend/src/pages/index.astro +++ b/frontend/src/pages/index.astro @@ -4,6 +4,7 @@ import { groupBySlo } from "@lib/slo"; import * as ghLabels from "@lib/triage-labels"; import { getCollection } from "astro:content"; import Layout from "../layouts/Layout.astro"; +import { IssueSummary } from "@lib/repo-summaries"; const repos = await getCollection("github"); @@ -21,7 +22,7 @@ const andFormatter = new Intl.ListFormat("en", { }); const repoSummaries = repos.map((repo) => { - const groups = groupBySlo(repo.data.issues); + const groups = groupBySlo(IssueSummary.array().parse(repo.data.issues)); const triageViolations = groups.triageViolations.length; const urgentViolations = groups.urgentViolations.length;