SuperAPI AI Directory

kubo-publish-e2e

Frontend & websites

View repository

Updated 10-15 20:12

About this skill

Kubo publishing pipeline e2e / demo runbook

Verify "Agent publishing pipelineis correct":token write endpoint gate → publish.sh single-file/directory publish → share link rendering → default expiry/permanent. All real curl / publish.sh / ipfs-cluster-ctl assertions.

This ispublishing e2e. Clusterinfrastructure(3 peers formed, multi-replica, gateway, node-stop fault tolerance) e2e see kubo-deploy-e2e skill / make e2e。

Conventions and prerequisites

REPO=$(git rev-parse --show-toplevel)
ENDPOINT=http://localhost:9097   # token 写入口(仅 POST /add)—— Agent 发布打这里
BASE=http://localhost:8088       # 读网关 base —— /artifact/<CID>
PUBLISH="$REPO/skills/publish-artifact/publish.sh"
TOKEN=$(grep '^IPFS_PUBLISH_TOKEN=' "$REPO/.env" | cut -d= -f2)
  • Image pinned versions:kubo v0.42.0 / ipfs-cluster v1.1.6 / caddy:2-alpine。
  • Secrets:.env(CLUSTER_SECRET + IPFS_PUBLISH_TOKEN) and runtime/private/swarm.key, both gitignored.make secrets idempotently generated.
  • Publishing skill contract: 3 env IPFS_PUBLISH_ENDPOINT / IPFS_PUBLISH_TOKEN / IPFS_BASE_URL。
  • Docs: write endpoint and publishing see docs/SINGLE_HOST_DEPLOYMENT.md §5、docs/AGENT_INTEGRATION_GUIDE.md。

1. One-click e2e (recommended)

Coverage: ① write endpoint gate (no token→401, token+GET /add→403, token+DELETE /pins→403) ② single-file publish rendering ③ directory site rendering (index+css) ④ default 1-week expiry set ⑤ --permanent no expiry.

make publish-e2e        # = ./e2e/run-publish.sh(自起栈,跑完自动 down)
make publish-e2e-keep   # = ./e2e/run-publish.sh --keep(保留集群继续手测)

Non-zero exit code means failure; at the end prints PASS=N FAIL=M, and generates a self-contained HTML report runtime/e2e/<时间戳>-publish/report.html. On failure do not tear down the stack; troubleshoot per §3.

2. Manual step-by-step (for demo / troubleshooting)

cd "$REPO"
export IPFS_PUBLISH_ENDPOINT="$ENDPOINT" IPFS_PUBLISH_TOKEN="$TOKEN" IPFS_BASE_URL="$BASE"

# ① 写入口闸门
curl -s -o /dev/null -w 'no-token: %{http_code}\n' -X POST "$ENDPOINT/add"                                   # 401
curl -s -o /dev/null -w 'GET /add: %{http_code}\n' -H "Authorization: Bearer $TOKEN" "$ENDPOINT/add"          # 403
curl -s -o /dev/null -w 'DELETE pins: %{http_code}\n' -H "Authorization: Bearer $TOKEN" -X DELETE "$ENDPOINT/pins/x"  # 403

# ② 单文件发布 → 链接渲染
echo '<!doctype html><meta charset=utf-8><h1>HELLO_PUBLISH</h1>' > /tmp/p.html
link=$("$PUBLISH" /tmp/p.html); echo "link=$link"
curl -fsS "$link"                                    # 应见正文

# ③ 目录站点(相对资源)
mkdir -p /tmp/site/css
echo '<!doctype html><meta charset=utf-8><link rel=stylesheet href="./css/app.css"><h1>DIR</h1>' > /tmp/site/index.html
echo 'h1{color:green}' > /tmp/site/css/app.css
dlink=$("$PUBLISH" /tmp/site); echo "dlink=$dlink"
curl -fsSI "${dlink}index.html" | grep -i 'HTTP/'    # 200
curl -fsSI "${dlink}css/app.css" | grep -i 'HTTP/'   # 200

# ④ 默认 1 周过期:pin 应有 expire_at
cid=$(printf '%s' "$link" | sed "s#$BASE/artifact/##; s#/\$##")
docker exec cl-cluster0 ipfs-cluster-ctl --enc=json pin ls "$cid" | grep expire_at

# ⑤ 永久发布:无 expire_at
plink=$("$PUBLISH" --permanent /tmp/p.html)          # 注意 --permanent 应少量使用

Browser demo: directly open $link(single file) or $dlink(directory site).

3. Troubleshooting

docker compose -f docker-compose.cluster.yml ps              # 容器状态
docker exec cl-caddy caddy validate --config /etc/caddy/Caddyfile
docker logs cl-caddy 2>&1 | tail -30                         # 写入口/反代日志
# 改了 caddy/Caddyfile 后 bind-mount 不会自动热更:
docker exec cl-caddy caddy reload --config /etc/caddy/Caddyfile
docker exec cl-cluster0 ipfs-cluster-ctl pin ls <CID>        # 看 pin 期望态/过期

Pitfalls (must know)

  • Write endpoint only allows POST /add:caddy/Caddyfile of :9097 first validates the Bearer token (otherwise 401), then requires method POST + path /add(otherwise 403). GET /add, DELETE /pins, etc. all return 403 — the Agent cannot get management capabilities such as unpin/peers.
  • Must go through :9097 + token, not direct :9095/:9094: native ports are not exposed to the host; publishing only goes through the authenticated write endpoint.
  • Default 1-week expiry:publish.sh default expire-in=168h; on expiry the cluster automatically unpins.--permanent only then is it permanent (use sparingly to prevent buildup). There is no owner concept, the skill does not provide unpublish, cleanup relies on expiry + admin ipfs-cluster-ctl。
  • Single CID pin ls <cid> is pretty-printed JSON("expire_at": "..." with a space after the colon), while the full pin ls is compact — write assertion grep to tolerate spaces; permanent pin has no expire_at field.
  • Directory links have a trailing slash: single file …/artifact/<cid>, directory …/artifact/<root>/; directory upload filenames use the path relative to the site root + wrap-with-directory=true, the root CID is the response line "name":"" .
  • After changing Caddyfile, reload is required:docker compose up -d will not rebuild the container due to a bind-mounted Caddyfile change; need docker exec cl-caddy caddy reload。

Related:kubo-deploy-e2e(deployment e2e) · skills/publish-artifact/(publishing skill itself) · docs/SINGLE_HOST_DEPLOYMENT.md §5 · docs/CLUSTER_CTL_REFERENCE.md