mirror of
https://github.com/redwoodjs/local-ci.git
synced 2026-09-19 07:54:29 +08:00
e2fe5761ba
* feat(compat): make compatibility.json the source of truth Flip the compatibility matrix so packages/cli/compatibility.json is authoritative. scripts/gen-compatibility-md.mjs renders the .md from it, pnpm check runs a drift check, and the website imports the JSON directly and renders inline markdown in keys/notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test: add compat smoke coverage for secrets, working-dir defaults, runner image Fill three audit gaps identified against packages/cli/compatibility.json: - smoke-secrets-env-file: secrets resolved from .env.agent-ci and from the shell environment fallback - smoke-defaults-workdir: workflow- and job-level defaults.run.working-directory plus a step-level override - smoke-runner-image: .github/agent-ci.Dockerfile is picked up and the resulting image is used at job start Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(workflow): propagate defaults.run.working-directory to steps Parse defaults.run.working-directory at workflow and job level and merge it into each run-step's inputs with step > job > workflow precedence. Step-level working-directory already worked; the defaults blocks were silently ignored. Closes #290. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(compat): add proof field to compatibility.json rows Every `supported`/`partial` row now lists the smoke workflows that exercise it end-to-end. `pnpm compat:gen`/`compat:check` fails if a listed path does not resolve, catching renames. Rows with an empty `proof: []` are the audit gaps tracked in #292. Refs #292. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dtu): attach step env per-step so it does not leak to siblings Step-level env was being aggregated into the job-wide EnvironmentVariables map (last-wins), so a later step's `env: FOO=x` would override an earlier step's effective FOO at runtime. Emit step.Env as the mapped step's own `environment` instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(compat): fill audit gaps #292 — env, expressions, local action Three smokes covering eight of the ten gaps listed in #292: - smoke-env-scoping: workflow + job + step `env:` precedence - smoke-expressions: hashFiles, format, join, runner.arch, type literals, startsWith/endsWith - smoke-local-action: `steps[*].uses: ./.github/actions/...` (verified via marker file rather than steps.<id>.outputs.*) Proof fields updated for every row these smokes cover. hashFiles downgraded to ⚠️ partial — agent-ci emits SHA-1, GitHub Actions emits SHA-256 (tracked by #294). Two gaps remain open as filed issues: - #293 defaults.run.shell / steps[*].shell not applied - #295 ${{ steps.<id>.outputs.<name> }} leaks literal text in run scripts Refs #292. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
82 lines
2.9 KiB
JavaScript
82 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
// Copy the public CLI docs into the website's static assets so they are
|
|
// reachable at https://agent-ci.dev/docs/... and regenerate the Agent Skills
|
|
// discovery index with fresh sha256 digests.
|
|
//
|
|
// This script is idempotent and safe to run repeatedly. It is hooked into
|
|
// `predev` and `prebuild` so the website's `public/docs/` tree and
|
|
// `public/.well-known/agent-skills/index.json` never drift from the CLI.
|
|
|
|
import { createHash } from "node:crypto";
|
|
import { readFile, mkdir, writeFile, rm } from "node:fs/promises";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const websiteDir = resolve(__dirname, "..");
|
|
const cliDir = resolve(websiteDir, "../../packages/cli");
|
|
const publicDir = resolve(websiteDir, "public");
|
|
const docsOut = resolve(publicDir, "docs");
|
|
const skillsOut = resolve(publicDir, ".well-known/agent-skills");
|
|
|
|
// Source files from the CLI that should be published as public docs.
|
|
// Keep `SKILL.md` in this list so the Agent Skills index can link to it.
|
|
const docs = [
|
|
{ src: "README.md", dest: "README.md" },
|
|
{ src: "compatibility.md", dest: "compatibility.md" },
|
|
{ src: "compatibility.json", dest: "compatibility.json" },
|
|
{ src: "runner-image.md", dest: "runner-image.md" },
|
|
{ src: "SKILL.md", dest: "SKILL.md" },
|
|
];
|
|
|
|
const sha256 = (buf) => createHash("sha256").update(buf).digest("hex");
|
|
|
|
async function copyDocs() {
|
|
await rm(docsOut, { recursive: true, force: true });
|
|
await mkdir(docsOut, { recursive: true });
|
|
|
|
const copied = [];
|
|
for (const { src, dest } of docs) {
|
|
const bytes = await readFile(resolve(cliDir, src));
|
|
await writeFile(resolve(docsOut, dest), bytes);
|
|
copied.push({ dest, digest: sha256(bytes) });
|
|
console.log(` copied ${src} → public/docs/${dest}`);
|
|
}
|
|
return copied;
|
|
}
|
|
|
|
async function writeAgentSkillsIndex(copied) {
|
|
await mkdir(skillsOut, { recursive: true });
|
|
|
|
const skillDigest = copied.find((c) => c.dest === "SKILL.md")?.digest;
|
|
if (!skillDigest) {
|
|
throw new Error("SKILL.md was not copied; cannot build agent-skills index");
|
|
}
|
|
|
|
// Agent Skills Discovery RFC v0.2.0
|
|
// https://github.com/cloudflare/agent-skills-discovery-rfc
|
|
const index = {
|
|
$schema:
|
|
"https://raw.githubusercontent.com/cloudflare/agent-skills-discovery-rfc/main/schema/index.schema.json",
|
|
version: "0.2.0",
|
|
skills: [
|
|
{
|
|
name: "agent-ci",
|
|
type: "skill",
|
|
description:
|
|
"Run GitHub Actions workflows locally with pause-on-failure for AI-agent-driven CI iteration.",
|
|
url: "https://agent-ci.dev/docs/SKILL.md",
|
|
sha256: skillDigest,
|
|
},
|
|
],
|
|
};
|
|
|
|
const path = resolve(skillsOut, "index.json");
|
|
await writeFile(path, JSON.stringify(index, null, 2) + "\n");
|
|
console.log(` wrote public/.well-known/agent-skills/index.json`);
|
|
}
|
|
|
|
const copied = await copyDocs();
|
|
await writeAgentSkillsIndex(copied);
|
|
console.log("docs synced.");
|