diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 7349e79..6473529 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -3,7 +3,17 @@ name: PROMPT Docker CI and deployment on: push: branches: [main] + paths: + - '**' + - '!docs/**' + - '!**/*.md' + - 'public/**' pull_request: + paths: + - '**' + - '!docs/**' + - '!**/*.md' + - 'public/**' workflow_dispatch: jobs: @@ -17,15 +27,12 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 - - name: Prepare Docker Engine and Compose + - name: Check preinstalled Docker Engine and Compose run: | set -eu - if [ "$(id -u)" -eq 0 ]; then SUDO=""; else SUDO="sudo -n"; fi - if ! command -v docker >/dev/null || ! docker compose version >/dev/null 2>&1; then - $SUDO apt-get update -qq - $SUDO apt-get install -y docker.io docker-compose-v2 - fi - $SUDO systemctl enable --now docker + command -v docker + docker compose version + docker info >/dev/null - name: Validate the Compose configuration run: docker compose --env-file .env.example config --quiet - name: Type check, unit tests, production build and smoke test inside Docker diff --git a/Dockerfile b/Dockerfile index fa858ba..1d3bc65 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,7 +10,14 @@ COPY package.json package-lock.json ./ RUN npm ci FROM dependencies AS build -COPY . . +# Only build inputs belong here: docs and operational notes must not bust this layer. +COPY tsconfig.json next-env.d.ts next.config.ts postcss.config.mjs ./ +COPY src/ ./src/ +COPY public/ ./public/ +COPY scripts/ ./scripts/ +COPY tests/ ./tests/ +COPY db/ ./db/ +COPY seed/ ./seed/ RUN npm run typecheck && npm test && npm run build && npm run test:smoke FROM build AS integration diff --git a/docs/ci-and-entrypoints.md b/docs/ci-and-entrypoints.md new file mode 100644 index 0000000..195928d --- /dev/null +++ b/docs/ci-and-entrypoints.md @@ -0,0 +1,9 @@ +# 构建与入口 + +人类默认从 `/` 进入;Agent 从 `/agent` 或 `/agent/index.md` 读取 `text/markdown` 索引,根目录 `/llms.txt` 提供发现链接。索引复用技能目录,技能继续使用 `/skills//SKILL.md` 和现有子文档 URL,避免复制文档。 + +`ces-control` 必须预装 Docker、Compose,并允许 Runner 访问持久 Docker daemon。CI 只检查环境,不安装系统包、不启停主机服务。当前服务器没有 buildx,先继续使用 daemon 自带层缓存;不要直接粘贴依赖 GitHub cache 服务的 `type=gha` 参数。后续若换 Docker daemon 或清理缓存,会重新冷构建。 + +Dockerfile 显式复制构建输入;根 Markdown 和 docs 不再使应用构建层失效。push 和 PR 对纯文档改动使用 paths,但 public 下的 Markdown 属于产品资源,必须构建部署。新添根级构建配置时,需同步 Dockerfile COPY。仍保留类型检查、单元测试、smoke 与完整隔离栈集成测试。 + +当前页面为 Next.js SSR 与编译组件,改 TSX 仍需 next build。把 HTML 的 COPY 移到最后不能避免编译。独立挂载静态文件会破坏镜像版本与回滚的一致性;只有真正独立、无需编译的内容才适合后续拆成单独发布渠道。 diff --git a/next.config.ts b/next.config.ts index d252ad8..b8200eb 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,7 +2,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { serverExternalPackages: ["playwright-core"], - async rewrites(){return [{source:"/skills/street-people/:doc.md",destination:"/api/skill-docs/street-people/:doc"}]}, + async rewrites(){return [{source:"/agent",destination:"/api/agent-index"},{source:"/agent/index.md",destination:"/api/agent-index"},{source:"/skills/street-people/:doc.md",destination:"/api/skill-docs/street-people/:doc"}]}, output: "standalone", outputFileTracingIncludes: {"/*":["./node_modules/playwright-core/**/*"]}, poweredByHeader: false, diff --git a/public/llms.txt b/public/llms.txt new file mode 100644 index 0000000..b5c1356 --- /dev/null +++ b/public/llms.txt @@ -0,0 +1,6 @@ +# PROMPT + +> 素材与创作技能网站。 + +- [Agent 默认入口](/agent/index.md): Markdown 技能索引与任务导航。 +- [人类入口](/): 网页浏览与素材管理。 diff --git a/src/pages/api/agent-index.ts b/src/pages/api/agent-index.ts new file mode 100644 index 0000000..180fa3f --- /dev/null +++ b/src/pages/api/agent-index.ts @@ -0,0 +1,28 @@ +import type { NextApiRequest, NextApiResponse } from "next"; +import { skillCatalog } from "@/content/skills/catalog"; + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (req.method !== "GET" && req.method !== "HEAD") { + res.setHeader("Allow", "GET, HEAD"); + return res.status(405).end(); + } + const markdown = [ + "# PROMPT — Agent 入口", + "", + "人类入口:[/](/)。Agent 默认入口:[/agent/index.md](/agent/index.md)。", + "", + "按任务选择技能,先阅读 SKILL.md,再按其中链接读取子文档、参考图片与上传协议。所有相对链接均以当前网站根地址解析。", + "不要从 HTML 页面猜测上传协议;生成由你自己的工具完成,网站提供文档、校验与素材存储。执行上传前遵循用户授权和对应技能的要求。", + "", + "## 技能目录", + ...skillCatalog.map(skill => `- [${skill.title}](/skills/${skill.id}/SKILL.md) — ${skill.description}`), + "", + "## 网站导航", + "- [人类首页](/)", + "- [技能浏览](/tools/skills)", + "", + ].join("\n"); + res.setHeader("Content-Type", "text/markdown; charset=utf-8"); + res.setHeader("Cache-Control", "no-cache"); + return req.method === "HEAD" ? res.status(200).end() : res.status(200).send(markdown); +}