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
14 changes: 7 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up yq
uses: mikefarah/yq@b534aa9ee5d38001fba3cd8fe254a037e4847b37 # v4.44.6
uses: mikefarah/yq@1b9b4ac5187171d2e5e3129be0cfa827c7f9d53d # v4.53.3
- name: Parse YAML
run: yq eval . config.yaml > /dev/null
- name: Required keys present
Expand Down Expand Up @@ -57,7 +57,7 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install check-jsonschema
Expand All @@ -76,7 +76,7 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install
Expand All @@ -97,9 +97,9 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "20"
node-version: "22"
- name: Run markdownlint-cli2
run: npx --yes markdownlint-cli2@0.18.1 "**/*.md" "!**/node_modules/**" "!LICENSE"

Expand All @@ -117,9 +117,9 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 10.33.2
version: 10.34.4
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
cache: "pnpm"
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/scan.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install
Expand All @@ -56,7 +56,7 @@ jobs:
- name: Checkout scanner
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install scanner
Expand Down Expand Up @@ -141,7 +141,7 @@ jobs:
--skillspector-json out/skillspector.json \
--output out/skill.json
- name: Upload skill artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v5.1.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: skill-${{ matrix.namespace }}-${{ matrix.slug }}
path: out/
Expand All @@ -158,15 +158,15 @@ jobs:
- name: Checkout scanner
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Download all skill artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v5.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: scans
pattern: skill-*
Expand All @@ -178,7 +178,7 @@ jobs:
run: |
python -c "import json; r=json.load(open('latest.json')); print(json.dumps(r['summary'], indent=2))"
- name: Upload scan-index artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v5.1.0
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: scan-index
path: latest.json
Expand All @@ -194,12 +194,12 @@ jobs:
- name: Checkout
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Download scan-index
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v5.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: scan-index
path: .
- name: Download all skill artifacts
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v5.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: skills
pattern: skill-*
Expand Down Expand Up @@ -266,23 +266,23 @@ jobs:
- name: Install pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
version: 10.33.2
version: 10.34.4
- name: Set up Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.0.0
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: "22"
cache: "pnpm"
cache-dependency-path: site/pnpm-lock.yaml
- name: Set up Python
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
with:
python-version: "3.12"
- name: Install scanner
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Download scan-index
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v5.0.0
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: scan-index
path: .
Expand Down Expand Up @@ -328,7 +328,7 @@ jobs:
path: pages
- name: Deploy Pages
id: deploy
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0

open-issue-on-failure:
name: Open or update tracker issue
Expand Down
2 changes: 1 addition & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ scanners:
# the version in two places. Dependabot does not parse this file,
# so a bumper bot lives outside the loop until the upstream
# publishes to PyPI and the pin can move into pyproject.toml.
pin: "skillspector @ git+https://github.com/NVIDIA/SkillSpector.git@2eb844780ab163f01468ecf142c40a2ec0fcaec0"
pin: "skillspector @ git+https://github.com/NVIDIA/SkillSpector.git@7bc9c0feb663375ced6e7436008d082e6e3486ea"
# Empty so .github/workflows/scan.yaml can append --no-llm
# dynamically based on whether the LLM credential secret is set.
flags: []
Expand Down
2 changes: 1 addition & 1 deletion mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
[tools]
python = "3.12"
node = "22"
pnpm = "10.33.2"
pnpm = "10.34.4"
4 changes: 2 additions & 2 deletions site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
/>

<link href="./src/styles.css" rel="stylesheet" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/svg+xml" href="%BASE_URL%favicon.svg" />
</head>
<body class="size-full bg-coder-neutral-black text-coder-neutral-100">
<div id="root" class="size-full">
<noscript class="mx-auto block max-w-prose p-8">
The Coder Skill Scanner site uses JavaScript to render scan reports.
Please enable JavaScript, or open the
<a href="/latest.json">raw JSON report</a> directly.
<a href="%BASE_URL%latest.json">raw JSON report</a> directly.
</noscript>
</div>
<script type="module" src="/src/main.tsx"></script>
Expand Down
11 changes: 8 additions & 3 deletions site/public/404.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
<title>Coder Skill Scanner</title>
<script>
// GitHub Pages SPA fallback: capture the original path in a query
// parameter and bounce to index.html, which restores it before React
// Router boots. See site/src/main.tsx for the restore step.
var target = "/?p=" + encodeURIComponent(
// parameter and bounce to the SPA index, which restores it before
// React Router boots. See site/src/main.tsx for the restore step.
//
// `%BASE_URL%` is substituted at build time by the
// `rewrite-public-base-url` Vite plugin (see site/vite.config.ts),
// so the bounce lands on the correct base prefix for both apex
// sites (`/`) and project pages (`/<repo>/`).
var target = "%BASE_URL%?p=" + encodeURIComponent(
window.location.pathname + window.location.search
) + window.location.hash;
window.location.replace(target);
Expand Down
12 changes: 6 additions & 6 deletions site/src/components/Layout/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,16 @@ type UtilityLink = {
};

const utilityNav: UtilityLink[] = [
{ href: "/latest.json", label: "Raw JSON" },
{ href: "/schema.json", label: "Schema" },
{ href: `${import.meta.env.BASE_URL}latest.json`, label: "Raw JSON" },
{ href: `${import.meta.env.BASE_URL}schema.json`, label: "Schema" },
{ href: "https://github.com/coder/coder-skill-scanner", label: "GitHub", external: true },
{ href: "https://registry.coder.com", label: "Registry", external: true },
];

const footerLinks: UtilityLink[] = [
{ href: "/latest.json", label: "Raw JSON" },
{ href: "/schema.json", label: "Schema (v1)" },
{ href: "/history", label: "History" },
{ href: `${import.meta.env.BASE_URL}latest.json`, label: "Raw JSON" },
{ href: `${import.meta.env.BASE_URL}schema.json`, label: "Schema (v1)" },
{ href: `${import.meta.env.BASE_URL}history`, label: "History" },
{ href: "https://github.com/coder/coder-skill-scanner", label: "Source", external: true },
{
href: "https://github.com/coder/coder-skill-scanner/blob/main/LICENSE",
Expand Down Expand Up @@ -62,7 +62,7 @@ export const Layout: FC = () => {
aria-label="Coder Skill Scanner home"
>
<img
src="/logo.png"
src={`${import.meta.env.BASE_URL}logo.png`}
alt="Coder Skill Scanner"
/* The source image is 2048x139 (aspect ~14.7). Without a
max-width it renders ~412px wide at h-7, overflowing
Expand Down
4 changes: 3 additions & 1 deletion site/src/lib/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type { HistoryIndex, Report } from "../types/report";

async function fetchJson<T>(path: string, signal?: AbortSignal): Promise<T> {
const url = path.startsWith("/") ? path : `/${path}`;
const url = path.startsWith("/")
? path
: `${import.meta.env.BASE_URL}${path}`;
const res = await fetch(url, { cache: "no-cache", signal });
if (!res.ok) {
throw new Error(`HTTP ${res.status} fetching ${path}`);
Expand Down
5 changes: 4 additions & 1 deletion site/src/pages/HistoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export const HistoryPage: FC = () => {
<div className="mt-2 text-xs text-coder-neutral-400">
History begins populating after the first scheduled scan. The latest
snapshot is always available as the{" "}
<a className="text-coder-sky hover:underline" href="/latest.json">
<a
className="text-coder-sky hover:underline"
href={`${import.meta.env.BASE_URL}latest.json`}
>
raw JSON report
</a>
.
Expand Down
5 changes: 4 additions & 1 deletion site/src/pages/OverviewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ export const OverviewPage: FC = () => {
<ErrorState error={error}>
<div className="mt-2 text-xs text-coder-neutral-400">
Try fetching the{" "}
<a className="text-coder-sky hover:underline" href="/latest.json">
<a
className="text-coder-sky hover:underline"
href={`${import.meta.env.BASE_URL}latest.json`}
>
raw JSON report
</a>{" "}
directly.
Expand Down
3 changes: 3 additions & 0 deletions site/src/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ export const router = createBrowserRouter(
<Route path="*" element={<NotFoundPage />} />
</Route>,
),
// basename mirrors Vite's `base` config so SPA routes resolve correctly
// when the site is served under a project-page prefix (e.g. /coder-skill-scanner/).
{ basename: import.meta.env.BASE_URL },
Comment thread
DevelopmentCats marked this conversation as resolved.
);
58 changes: 55 additions & 3 deletions site/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineConfig, loadEnv } from "vite";
import { defineConfig, loadEnv, type PluginOption } from "vite";
import react from "@vitejs/plugin-react-swc";
import fs from "node:fs";
import path from "node:path";

/**
* The React app expects to fetch `latest.json`, `schema.json`, and
Expand All @@ -14,12 +16,62 @@ import react from "@vitejs/plugin-react-swc";
*/
const REPORT_REGEX = /^\/(latest\.json|schema\.json|history\/.+\.json)$/;

export default defineConfig(({ mode }) => {
/**
* Resolve the production `base` path. Lookup priority:
* 1. `VITE_BASE_PATH` env (explicit override; useful for local prod
* builds when you want to mimic a specific Pages deployment).
* 2. The repo name parsed from `GITHUB_REPOSITORY` (CI default; a fork
* named `<owner>/<repo>` gets `/<repo>/` automatically with zero
* config).
* 3. `/` (apex / local-build fallback).
*
* Always returns a value with leading and trailing slashes so Vite's
* own asset URL logic does not have to special-case the input.
*/
function resolveProductionBase(): string {
const explicit = process.env.VITE_BASE_PATH?.trim();
if (explicit) {
const prefixed = explicit.startsWith("/") ? explicit : `/${explicit}`;
return prefixed.endsWith("/") ? prefixed : `${prefixed}/`;
}
const repo = process.env.GITHUB_REPOSITORY?.split("/")[1]?.trim();
if (repo) return `/${repo}/`;
return "/";
}

/**
* Vite already substitutes `%BASE_URL%` in `index.html`, but it copies
* everything under `public/` verbatim. This plugin runs after the build
* finishes and substitutes the same placeholder in `dist/404.html` so
* the GitHub Pages SPA-fallback redirect targets the right base prefix
* regardless of which fork is publishing.
*/
function rewritePublicBaseUrl(base: string): PluginOption {
return {
name: "rewrite-public-base-url",
apply: "build",
writeBundle() {
const targets = ["404.html"];
for (const name of targets) {
const file = path.resolve("dist", name);
if (!fs.existsSync(file)) continue;
const content = fs.readFileSync(file, "utf8");
fs.writeFileSync(file, content.replace(/%BASE_URL%/g, base));
}
},
};
}

export default defineConfig(({ mode, command }) => {
const env = loadEnv(mode, process.cwd(), "");
const upstream = env.VITE_REPORT_UPSTREAM || "http://localhost:8765";
const base = command === "build" ? resolveProductionBase() : "/";

return {
plugins: [react()],
// See `resolveProductionBase` above. Dev keeps `/` so the local Vite
// server and its report proxy keep working without env juggling.
base,
plugins: [react(), rewritePublicBaseUrl(base)],
server: {
host: "0.0.0.0",
port: 5173,
Expand Down