Skip to content

Commit 82dc4fb

Browse files
Merge pull request #13 from coder/cat/custom-domain
fix(pages): publish to scanner.registry.coder.com
2 parents f58f4ef + 6cee1c2 commit 82dc4fb

4 files changed

Lines changed: 57 additions & 21 deletions

File tree

README.md

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,17 @@ The registry's deploys are not gated on the scan result.
3131

3232
Stable URLs, no auth required:
3333

34-
+ Public site: `https://coder.github.io/coder-skill-scanner/`
35-
+ Per-skill detail: `https://coder.github.io/coder-skill-scanner/skills/<namespace>/<slug>`
36-
+ Run history: `https://coder.github.io/coder-skill-scanner/history`
37-
+ CDN-cached JSON: `https://coder.github.io/coder-skill-scanner/latest.json`
34+
+ Public site: `https://scanner.registry.coder.com/`
35+
+ Per-skill detail: `https://scanner.registry.coder.com/skills/<namespace>/<slug>`
36+
+ Run history: `https://scanner.registry.coder.com/history`
37+
+ CDN-cached JSON: `https://scanner.registry.coder.com/latest.json`
3838
+ Tagged release: `https://github.com/coder/coder-skill-scanner/releases/latest/download/latest.json`
39-
+ Schema: `https://coder.github.io/coder-skill-scanner/schema.json` (v1)
40-
+ Per-scan history (JSON): `https://coder.github.io/coder-skill-scanner/history/index.json`
39+
+ Schema: `https://scanner.registry.coder.com/schema.json` (v1)
40+
+ Per-scan history (JSON): `https://scanner.registry.coder.com/history/index.json`
41+
42+
The custom domain is configured via `site/public/CNAME`; the legacy
43+
project-page URL (`https://coder.github.io/coder-skill-scanner/`) is
44+
still redirected by GitHub Pages but should not be used in new code.
4145

4246
## Public API (v1)
4347

@@ -68,19 +72,23 @@ Two badges per skill:
6872
Embed a status badge in a README:
6973

7074
```markdown
71-
![skill scan](https://coder.github.io/coder-skill-scanner/api/v1/skills/coder/setup/badge/status.svg)
75+
![skill scan](https://scanner.registry.coder.com/api/v1/skills/coder/setup/badge/status.svg)
7276
```
7377

7478
Or via shields.io if you want their renderer:
7579

7680
```markdown
77-
![skill scan](https://img.shields.io/endpoint?url=https://coder.github.io/coder-skill-scanner/api/v1/skills/coder/setup/badge/status.json)
81+
![skill scan](https://img.shields.io/endpoint?url=https://scanner.registry.coder.com/api/v1/skills/coder/setup/badge/status.json)
7882
```
7983

80-
For a fork, swap the host: `https://<owner>.github.io/<repo>/api/v1/...`.
81-
The scanner derives the public base URL from `$GITHUB_REPOSITORY` at
82-
publish time, so the same URL pattern is correct for any fork without
83-
config changes.
84+
For a fork, swap the host: `https://<your-host>/api/v1/...`. The scanner
85+
picks the public base URL at publish time in this order:
86+
87+
1. `site/public/CNAME` (the custom Pages domain, if set),
88+
2. otherwise `$GITHUB_REPOSITORY` -> `https://<owner>.github.io/<repo>`.
89+
90+
So a fork that just sets a CNAME gets the right URLs everywhere without
91+
touching workflow code.
8492

8593
## Running locally
8694

@@ -114,6 +122,7 @@ as `/skills/coder/setup` stay client-side.
114122
|-- scanner/ # Python module (CLI + enumerate + combine + aggregate + history)
115123
|-- tests/ # pytest, no on-disk fixtures
116124
|-- site/ # React SPA (Vite + Tailwind + Radix + react-router-dom)
125+
| `-- public/CNAME # custom Pages domain (drop or change for a fork)
117126
|-- pyproject.toml
118127
|-- Makefile
119128
|-- mise.toml # pinned Python + Node versions
@@ -140,15 +149,19 @@ This scanner is data-driven. To run it against a different registry:
140149
2. Edit `config.yaml`'s `catalogue.registry_repo` block.
141150
3. Configure GitHub Pages on your fork (Settings, Pages, source:
142151
"GitHub Actions").
143-
4. Set Actions workflow permissions to "Read and write" so the
152+
4. Optional: set a custom domain by editing `site/public/CNAME` (one
153+
line, the bare host). Delete the file to publish at the github.io
154+
project-page URL instead. Whichever you choose, DNS for the host
155+
needs to point at `<owner>.github.io` separately.
156+
5. Set Actions workflow permissions to "Read and write" so the
144157
publish-release job can create releases.
145-
5. To enable the LLM semantic pass, set the credential secret matching
158+
6. To enable the LLM semantic pass, set the credential secret matching
146159
`config.yaml`'s `scanners.skillspector.llm.provider` on your fork
147160
(for the default `anthropic` provider, `ANTHROPIC_API_KEY`), AND
148161
confirm `.github/workflows/scan.yaml` exports that secret into the
149162
SkillSpector step. Static-only mode (without the secret) is the
150163
default and works out of the box.
151-
6. Enable Actions.
164+
7. Enable Actions.
152165

153166
No source changes required for catalogue changes.
154167

scanner/_carry_history.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,33 @@
1818
import urllib.request
1919
from pathlib import Path
2020

21-
DEFAULT_BASE = "https://coder.github.io/coder-skill-scanner"
21+
DEFAULT_BASE_FALLBACK = "https://coder.github.io/coder-skill-scanner"
2222
MAX_SNAPSHOTS = 120 # roughly 30 days at a 6h cadence.
2323

2424

25+
def _default_base() -> str:
26+
"""Return the canonical Pages URL for this repo.
27+
28+
Prefer ``site/public/CNAME`` when present so a custom-domain deploy
29+
fetches prior history from the same origin it will publish to. Fall
30+
back to the github.io project-page URL otherwise.
31+
"""
32+
cname = Path("site/public/CNAME")
33+
if cname.is_file():
34+
for line in cname.read_text(encoding="utf-8").splitlines():
35+
host = line.strip()
36+
if host:
37+
return f"https://{host}"
38+
return DEFAULT_BASE_FALLBACK
39+
40+
2541
def _fetch(url: str, dest: Path) -> None:
2642
dest.parent.mkdir(parents=True, exist_ok=True)
2743
urllib.request.urlretrieve(url, dest)
2844

2945

3046
def main(out_dir: str = "prior-history") -> int:
31-
base = os.environ.get("PAGES_URL") or DEFAULT_BASE
47+
base = os.environ.get("PAGES_URL") or _default_base()
3248
base = base.rstrip("/")
3349
out = Path(out_dir)
3450
out.mkdir(parents=True, exist_ok=True)

site/public/CNAME

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
scanner.registry.coder.com

site/vite.config.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@ const REPORT_REGEX = /^\/(latest\.json|schema\.json|history\/.+\.json)$/;
2020
* Resolve the production `base` path. Lookup priority:
2121
* 1. `VITE_BASE_PATH` env (explicit override; useful for local prod
2222
* builds when you want to mimic a specific Pages deployment).
23-
* 2. The repo name parsed from `GITHUB_REPOSITORY` (CI default; a fork
24-
* named `<owner>/<repo>` gets `/<repo>/` automatically with zero
25-
* config).
26-
* 3. `/` (apex / local-build fallback).
23+
* 2. A `public/CNAME` file. When the site is published to a custom
24+
* Pages domain, GitHub serves it at the apex of that domain so
25+
* assets must resolve at `/`, not under `/<repo>/`.
26+
* 3. The repo name parsed from `GITHUB_REPOSITORY` (CI default; a fork
27+
* named `<owner>/<repo>` without a custom domain gets `/<repo>/`
28+
* automatically with zero config).
29+
* 4. `/` (apex / local-build fallback).
2730
*
2831
* Always returns a value with leading and trailing slashes so Vite's
2932
* own asset URL logic does not have to special-case the input.
@@ -34,6 +37,9 @@ function resolveProductionBase(): string {
3437
const prefixed = explicit.startsWith("/") ? explicit : `/${explicit}`;
3538
return prefixed.endsWith("/") ? prefixed : `${prefixed}/`;
3639
}
40+
if (fs.existsSync(path.resolve("public", "CNAME"))) {
41+
return "/";
42+
}
3743
const repo = process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
3844
if (repo) return `/${repo}/`;
3945
return "/";

0 commit comments

Comments
 (0)