ci: build + anchors + inline-js guard
Some checks failed
CI / build-and-anchors (push) Failing after 5m4s
Some checks failed
CI / build-and-anchors (push) Failing after 5m4s
This commit is contained in:
35
.gitea/workflows/ci.yml
Normal file
35
.gitea/workflows/ci.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["**"]
|
||||||
|
pull_request:
|
||||||
|
branches: ["master"]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-anchors:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: node:20-bookworm-slim
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install git (needed by checkout)
|
||||||
|
run: |
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y --no-install-recommends git ca-certificates
|
||||||
|
git --version
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install deps
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Inline scripts syntax check
|
||||||
|
run: node scripts/check-inline-js.mjs
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Anchors contract
|
||||||
|
run: npm run test:anchors
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"postbuild": "npx pagefind --site dist",
|
"postbuild": "npx pagefind --site dist",
|
||||||
"import": "node scripts/import-docx.mjs",
|
"import": "node scripts/import-docx.mjs",
|
||||||
"apply:ticket": "node scripts/apply-ticket.mjs",
|
"apply:ticket": "node scripts/apply-ticket.mjs",
|
||||||
|
"test": "npm run build && npm run test:anchors && node scripts/check-inline-js.mjs",
|
||||||
"test:anchors": "node scripts/check-anchors.mjs",
|
"test:anchors": "node scripts/check-anchors.mjs",
|
||||||
"test:anchors:update": "node scripts/check-anchors.mjs --update"
|
"test:anchors:update": "node scripts/check-anchors.mjs --update"
|
||||||
},
|
},
|
||||||
|
|||||||
70
scripts/check-inline-js.mjs
Normal file
70
scripts/check-inline-js.mjs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import fs from "node:fs/promises";
|
||||||
|
import path from "node:path";
|
||||||
|
import os from "node:os";
|
||||||
|
import { spawnSync } from "node:child_process";
|
||||||
|
|
||||||
|
const ROOT = process.cwd();
|
||||||
|
const SRC = path.join(ROOT, "src");
|
||||||
|
|
||||||
|
async function* walk(dir) {
|
||||||
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
for (const e of entries) {
|
||||||
|
const full = path.join(dir, e.name);
|
||||||
|
if (e.isDirectory()) yield* walk(full);
|
||||||
|
else yield full;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractInlineScripts(astroText) {
|
||||||
|
// capture <script ... is:inline ...> ... </script>
|
||||||
|
const re = /<script\b[^>]*\bis:inline\b[^>]*>([\s\S]*?)<\/script>/gi;
|
||||||
|
const out = [];
|
||||||
|
let m;
|
||||||
|
while ((m = re.exec(astroText))) out.push(m[1] ?? "");
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkSyntax(js, label) {
|
||||||
|
const tmp = path.join(os.tmpdir(), `inline-js-check-${Date.now()}-${Math.random().toString(16).slice(2)}.mjs`);
|
||||||
|
const payload = `// ${label}\n${js}\n`;
|
||||||
|
return fs.writeFile(tmp, payload, "utf-8").then(() => {
|
||||||
|
const r = spawnSync(process.execPath, ["--check", tmp], { encoding: "utf-8" });
|
||||||
|
fs.unlink(tmp).catch(() => {});
|
||||||
|
if (r.status !== 0) {
|
||||||
|
const msg = (r.stderr || r.stdout || "").trim();
|
||||||
|
throw new Error(`${label}\n${msg}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const targets = [];
|
||||||
|
for await (const f of walk(SRC)) {
|
||||||
|
if (f.endsWith(".astro")) targets.push(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
let checked = 0;
|
||||||
|
|
||||||
|
for (const file of targets) {
|
||||||
|
const txt = await fs.readFile(file, "utf-8");
|
||||||
|
const scripts = extractInlineScripts(txt);
|
||||||
|
if (!scripts.length) continue;
|
||||||
|
|
||||||
|
for (let i = 0; i < scripts.length; i++) {
|
||||||
|
const js = (scripts[i] || "").trim();
|
||||||
|
if (!js) continue;
|
||||||
|
const label = `${path.relative(ROOT, file)} :: <script is:inline> #${i + 1}`;
|
||||||
|
await checkSyntax(js, label);
|
||||||
|
checked++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`OK inline-js: scripts checked=${checked}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch((e) => {
|
||||||
|
console.error("❌ inline-js syntax check failed");
|
||||||
|
console.error(e?.message || e);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user