Claude Skills Collection Logo
CreateSun-code-js-bin-with-issue

issue-pages

帮用户把 Issue Pages(用 GitHub Issue 当内容源的静态发布工具)部署成一套自己的站点:fork 仓库、开通 Actions 与 Pages、建 publish 标签、发布第一张页面,并验证最终网址真的能打开。当用户说「帮我部署一套 Issue Pages」「fork 这个仓库跑起来」「把这几个 HTML 发布到我自己的 GitHub Pages」「用 issue 发布网页」时使用。
stars0
forks0
watches0
updated2026-10-16 18:43:48

Issue Pages 部署

帮用户把自己的一份 Issue Pages 跑起来。上游仓库默认是 CreateSun/code-js-bin-with-issue,用户要 fork 的是它。

发布内容的唯一来源是 issue

这条是硬规则,任何一步都不能绕开:

  • 页面的每一个字节都来自 issue 正文。 构建脚本只读 issue(scripts/build.mjs 调 Issues API),生成 dist/ 后发布。
  • 不要在仓库里另建发布通道:public/、assets/、docs/ 里放页面 HTML、或让构建去拷贝仓库里的静态文件,都会让"站点上的内容"多出一个来源,代码和 issue 立刻开始分叉,审批门(publish 标签)也管不到它。需要新页面就开 issue。
  • 单页上限 65536 字符(GitHub 对 issue 正文的硬限制)。发布前先量:node -e 'console.log(require("fs").readFileSync("body.html","utf8").length)',超了就必须让页面变轻,而不是换通道:
    1. 裁掉装饰性细节(细网格、刻度、齿纹、螺线、小零件的面色带);
    2. 坐标量化(四舍五入到 1–2 个单位,1× 分辨率看不出);
    3. 体积还大就把矢量/文本用 gzip + base64 内联,页面里用 DecompressionStream("gzip") 解压后再挂载(bambu-a1-mini 这个 issue 就是这么做的,正文 64 KB 装下一张约 34000 个坐标的等距图)。
    4. 一个页面实在装不下就拆成几个 issue 分别发布,不要拼出第二种发布方式。
  • 用户明确要求"把某个仓库文件发布到站点"时,也要走 issue:把内容贴进 issue 正文,而不是加旁路。

先确认三件事

  1. gh auth status 显示已登录,且 token 有 repo scope(没有就先让用户 gh auth login,不要代替用户登录)。
  2. 部署到哪个账号/仓库:默认是当前登录用户 fork 上游仓库;用户已有 fork 时直接用它,不要重复创建。
  3. 是否要保留发布审批:默认保留(ISSUE_AUTHOR = 仓库 owner,PUBLISH_LABEL = publish)。用户说「不用审批」就让他把工作流里的 PUBLISH_LABEL 改成空字符串。

下面的命令把 $OWNER 换成用户的账号名、$REPO 换成 fork 出来的仓库名。

部署步骤

1. Fork 并克隆

gh repo fork CreateSun/code-js-bin-with-issue --clone --default-branch-only

gh 已经 fork 过会报错,此时改成克隆已有的那个 fork。克隆目录里 git remote origin 就是用户的 fork。

2. 打开工作流开关

GitHub 不会在新 fork 上自动运行工作流,必须显式打开:

gh api -X PUT "repos/$OWNER/$REPO/actions/permissions" -f enabled=true

失败(403 等)就告诉用户在仓库 Actions 页点 “I understand my workflows, go ahead and enable them”,不要跳过这步——跳过会表现为「部署一直没跑」。

3. 启用 GitHub Pages(构建源 = GitHub Actions)

gh api -X POST "repos/$OWNER/$REPO/pages" -f build_type=workflow

已存在会返回 409,可以忽略。不要依赖工作流自己开通 Pages:GITHUB_TOKEN 没有创建 Pages 站点的权限,没启用就运行会以 “先打开 …/settings/pages” 的报错失败——这是预期行为,不是配置坏了。

4. 建发布标签

gh label create publish --repo "$OWNER/$REPO" --color 0E8A16 \
  --description "打上这个标签才发布到站点(审批通过)"

标签名要和 PUBLISH_LABEL 一致。没有这个标签时所有 issue 都会被跳过,站点会是空的——这是最常见的「部署成功但页面 404」原因。

5. 换成用户自己的信息

  • src/footer.html:把博客链接和源码链接换成用户自己的,或整段删掉。
  • 首页标题默认取仓库名,想改就设工作流里的 SITE_NAME。
  • 想改站点样式:src/style.css。

改完提交推送:

git add -A && git commit -m "chore: 改成我自己的站点信息" && git push

推送会触发一次构建,你也可以顺便确认工作流能跑通。

6. 发布第一张页面

把页面源码写进一个文件(HTML 片段、完整 HTML 或纯 JS 都可以),然后:

gh issue create --repo "$OWNER/$REPO" --title hello --body-file /tmp/hello.html --label publish

--title 就是访问路径,用英文小写和连字符。

7. 等部署完成并验证网址真的能打开

gh run list --repo "$OWNER/$REPO" --limit 3
run=$(gh run list --repo "$OWNER/$REPO" --limit 1 --json databaseId --jq '.[0].databaseId')
gh run watch "$run" --repo "$OWNER/$REPO" --exit-status

工作流成功不等于网站可访问。必须再验证一次,直到拿到 200 或超时:

host="$(printf '%s' "$OWNER" | tr '[:upper:]' '[:lower:]')"
url="https://$host.github.io/$REPO/hello/"
for i in $(seq 1 20); do
  code=$(curl -s -o /tmp/page.html -w '%{http_code}' "$url")
  [ "$code" = "200" ] && break
  sleep 10
done
echo "$code $url"
grep -q "页面正文里的某个特征字符串" /tmp/page.html && echo "内容已上线"

首次部署 Pages 可能有几十秒到几分钟的传播延迟,属正常。最后把 url 报给用户。

排查

现象原因与处理
完全没有工作流运行fork 的 Actions 没开(步骤 2);或 issue 事件没触发,手动 gh workflow run deploy-pages.yml --repo "$OWNER/$REPO"
运行失败并提示「先打开 …/settings/pages」Pages 还没启用,按步骤 3 做完再重跑;如果是在启用 Pages 之前推的代码,这次失败属正常
构建日志里全是「跳过 #N … 还没有 publish 标签」标签名与 PUBLISH_LABEL 不一致,或 issue 没打标签
构建日志里「作者 xxx 不在发布名单内」ISSUE_AUTHOR 是别人;要放开发布就把它设为空字符串
构建成功但访问 404Pages 没启用 / 构建源不是 GitHub Actions(步骤 3);或路径拼错、大小写不符
发布时 gh 报 Body is too long (maximum is 65536 characters)页面超过单页上限,按上文压体积,不要在仓库里加旁路
页面是旧的Pages 对 HTML 有 cache-control: max-age=600,强刷一次
gh: Not Found / Resource not accessibletoken 缺 repo scope 或不是仓库 admin

不要做的事

  • 不要在没 curl 到 200 的情况下告诉用户「已经部署好了」。工作流 success 只说明构建和部署动作完成。
  • 不要替用户改仓库名、转让或删除仓库;改名会让全部旧链接失效,要由用户决定。
  • 不要把 token、密码写进任何文件或命令参数里让用户看到。
  • 只有在用户明确要求时才关闭审批门或放开作者名单——这两项是防止别人往他的域名上发内容的主要手段。
  • 不要在仓库里为页面内容另开通道(public/、资产目录、构建期拷贝静态文件)。内容的唯一来源是 issue;页面太大就压小它,见开头那节。