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
6 changes: 1 addition & 5 deletions src/lib/components/HowItWorks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@
<div class="step">
<span class="num mono">{s.num}</span>
<h3 class="mono">{s.title}</h3>
<p>
{s.body}
{#if s.code}<br /><code class="mono">{s.code}</code>{/if}
</p>
<p>{s.body}</p>
</div>
{/each}
</div>
Expand All @@ -50,7 +47,6 @@
.num { font-size: 13px; font-weight: 700; color: var(--primary); border-top: 2px solid var(--primary); padding-top: 14px; display: inline-block; }
.step h3 { font-size: 17px; font-weight: 600; margin: 14px 0 8px; }
.step p { font-size: 13.5px; line-height: 1.6; color: var(--muted); margin: 0; }
.step code { display: inline-block; margin-top: 8px; font-size: 12px; background: var(--elevated); padding: 4px 8px; border-radius: 5px; color: var(--text); }

@media (max-width: 760px) { .steps { grid-template-columns: 1fr; gap: 28px; } }
</style>
14 changes: 4 additions & 10 deletions src/lib/components/docs/DocsContent.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
<script lang="ts">
import type { Component } from 'svelte';

const mods = import.meta.glob('/src/lib/docs-content/*.svx', { eager: true });
const sections = Object.values(mods) as Array<{
default: Component;
metadata: { id: string };
}>;
import { sections } from '$lib/docs-content/index';
</script>

<main class="content">
{#each sections as mod}
<section id={mod.metadata.id}>
<mod.default />
{#each sections as s}
<section id={s.id}>
<s.component />
</section>
{/each}

Expand Down
42 changes: 1 addition & 41 deletions src/lib/components/docs/DocsSidebar.svelte
Original file line number Diff line number Diff line change
@@ -1,46 +1,6 @@
<script lang="ts">
import { onMount } from 'svelte';

type Item = { id: string; label: string };
type Group = { head: string; items: Item[] };

const groups: Group[] = [
{
head: 'Getting started',
items: [
{ id: 'overview', label: 'Overview' },
{ id: 'how-it-works', label: 'How it works' },
{ id: 'quick-start', label: 'Quick start' }
]
},
{
head: 'Installation',
items: [
{ id: 'prerequisites', label: 'Prerequisites' },
{ id: 'domain-database', label: 'Domain & database' },
{ id: 'github-app', label: 'GitHub App' },
{ id: 'cloudflare-access', label: 'Cloudflare Access' },
{ id: 'secrets', label: 'Secrets' },
{ id: 'deploy', label: 'Deploy the Worker' },
{ id: 'verify', label: 'Install & verify' }
]
},
{
head: 'Usage',
items: [
{ id: 'ingest', label: 'Ingest from CI' },
{ id: 'badges', label: 'Status badges' },
{ id: 'dashboard', label: 'Dashboard' }
]
},
{
head: 'Reference',
items: [
{ id: 'api', label: 'API reference' },
{ id: 'ingest-payload', label: 'Ingest payload' }
]
}
];
import { sidebarGroups as groups } from '$lib/docs-content/index';

let active = $state('overview');
let open = $state(false);
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/01-overview.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: overview
kicker: getting started
title: Overview
group: getting started
---

Coverage Tracker is a **self-hosted** dashboard that tracks code coverage, cyclomatic complexity, and code duplication across your GitHub repositories — with trend charts, per-PR diff checks, and README badges.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/02-how-it-works.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: how-it-works
kicker: architecture
title: How it works
group: getting started
---

The flow is four moving parts: your CI pushes metrics, the Worker validates and stores them, D1 keeps the history, and the dashboard reads trends back.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/03-quick-start.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: quick-start
kicker: the short version
title: Quick start
group: getting started
---

If you already run on Cloudflare, the whole setup is six moves. Each links to its full section below.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/04-prerequisites.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: prerequisites
kicker: installation
title: Prerequisites
group: installation
---

- A **Cloudflare account** (free tier is sufficient).
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/05-domain-database.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: domain-database
kicker: installation
title: Domain & database
group: installation
---

Create your D1 database, then wire its id into `wrangler.jsonc` and apply the schema migration.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/06-github-app.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: github-app
kicker: installation
title: GitHub App
group: installation
---

> [!WARNING] Two separate integrations
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/07-cloudflare-access.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: cloudflare-access
kicker: installation
title: Cloudflare Access
group: installation
---

In **Zero Trust**, choose a team name (becomes `myteam.cloudflareaccess.com`). Then create a **GitHub OAuth App** for dashboard login with callback URL `https://myteam.cloudflareaccess.com/cdn-cgi/access/callback`, and add GitHub as an identity provider in **Settings → Authentication** using that OAuth App's client id and secret.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/08-secrets.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: secrets
kicker: installation
title: Secrets
group: installation
---

Set every value with `wrangler secret put` — secrets are never committed. `wrangler.json` references names only.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/09-deploy.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: deploy
kicker: installation
title: Deploy the Worker
group: installation
---

Make sure dashboard dependencies are installed, then deploy. The command applies pending D1 migrations and compiles the SvelteKit dashboard before uploading.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/10-verify.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: verify
kicker: installation
title: Install & verify
group: installation
---

From the GitHub App's settings page → **Install App** → choose the account or org → select repos. This fires an `installation: created` webhook that populates the `owners` and `projects` tables.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/11-ingest.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: ingest
kicker: usage
title: Ingest from CI
group: usage
---

Add a workflow step that runs after your test suite and posts coverage to `/api/ci/coverage` using a GitHub Actions OIDC token. There is **no static ingest secret**: the Worker verifies the token signature and checks the `repository` claim against your registered projects, so only your repos can push data. Re-running CI for the same commit is a safe no-op.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/12-badges.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: badges
kicker: usage
title: Status badges
group: usage
---

Badge numbers are opt-in per repo. Find the project id, enable it, then paste the snippet into your README. Available metrics: `coverage`, `complexity`, `duplication`.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/13-dashboard.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: dashboard
kicker: usage
title: Dashboard
group: usage
---

The SvelteKit dashboard is compiled by `wrangler deploy` automatically and served as static assets by the same Worker — there is no separate Pages project. After first deploy, visit `https://coverage-tracker.yourdomain.com`; Cloudflare Access prompts you to log in with the identity provider you configured. Once authenticated, the dashboard shows all registered repos and their per-metric, per-branch trend charts.
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/14-api.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: api
kicker: reference
title: API reference
group: reference
---

<table class="deftable">
Expand Down
1 change: 1 addition & 0 deletions src/lib/docs-content/15-ingest-payload.svx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
id: ingest-payload
kicker: reference
title: Ingest payload
group: reference
---

`line_coverage` is required; all other fields are optional. `repository`, `branch`, and `commit_sha` are derived from the OIDC token claims — they are not accepted in the body.
Expand Down
28 changes: 28 additions & 0 deletions src/lib/docs-content/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Component } from 'svelte';

const mods = import.meta.glob('/src/lib/docs-content/*.svx', { eager: true });

export type DocSection = {
id: string;
title: string;
group: string;
component: Component;
};

export type SidebarGroup = { head: string; items: { id: string; label: string }[] };

export const sections: DocSection[] = Object.entries(mods)
.sort(([a], [b]) => a.localeCompare(b))
.map(([, mod]: [string, any]) => ({
id: mod.metadata.id,
title: mod.metadata.title,
group: mod.metadata.group,
component: mod.default,
}));

export const sidebarGroups: SidebarGroup[] = sections.reduce<SidebarGroup[]>((acc, s) => {
const existing = acc.find((g) => g.head === s.group);
if (existing) existing.items.push({ id: s.id, label: s.title });
else acc.push({ head: s.group, items: [{ id: s.id, label: s.title }] });
return acc;
}, []);
Loading