fn_b/docs/maintenance/EDITORIAL_RELEASE.md

48 lines
6.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 经白色机的固定文章发布流程
## 设计
维护脚本:`tools/editorial/release.py`(本机传输)、`tools/editorial/ssh_askpass.py`(只向OpenSSH认证组件提供登记密码)、`editorial:release`(业务服务器命令)。现有文章API负责资产、草稿、版本、链接校验、原子发布、回执和搜索缓存同步,契约见[EDITORIAL_API.md](EDITORIAL_API.md)。本封装不另写文章SQL,不经ATOM。
固定路线:本机SSH→VPS-001白色机→VPS-003 `/www/wwwroot/clashfreenode-new.com`。SSH强制ProxyCommand、既有主机密钥核验,禁用配置文件和已有连接复用,不接受自定义目标/命令,也没有直连回退。白色机仅转发SSH,不保存稿件、凭据或运行定时器。
远端固定以nginx运行`php artisan editorial:release`,命令校验production环境、真实项目路径和base_url。JSON由stdin传递。服务器内通过Laravel HTTP Kernel调用原有API路由,经过原认证、校验和控制器;无需本机或公网HTTP。运行身份使用现有服务器权限,不改SSH策略或管理员凭据。
进程内临时API认证值只保存在内存,寿命10分钟,每次内部请求后恢复原配置,结束/断开杀进程即消失;不写.env或公用credential.json,不重载配置、不启用公网编辑入口。签名预览也在同一命令内渲染,公网API关闭时这些预览URL不可从外部打开。旧API的手动操作契约仍保留,周期发布改用本封装。
## 调用
本机在项目目录执行,输出文件包含私有预览,权限600,不提交Git:
```sh
python3 tools/editorial/release.py catalog --input /私有目录/empty.json --output /私有目录/catalog.json
python3 tools/editorial/release.py source --input /私有目录/source.json --output /私有目录/source-result.json
python3 tools/editorial/release.py prepare --input /私有目录/bundle.json --output /私有目录/prepared.json
python3 tools/editorial/release.py review --input /私有目录/id.json --output /私有目录/review.json
python3 tools/editorial/release.py publish --input /私有目录/publish.json --output /私有目录/published.json
python3 tools/editorial/release.py status --input /私有目录/id.json --output /私有目录/status.json
```
- empty.json为`{}`;source.json为`{"article_id":真实整数ID}`。catalog/source只读,不创建release。
- bundle.json含`release_id`(UUID)、`articles`(原API字段)及可选`assets`。每个asset为`{"name":"diagram","base64":"实际PNG/JPEG/WebP/GIF字节的base64"}`,正文/封面用`file:diagram`占位;程序上传后替换为asset引用。单图≤8MiB、最多10图、总输入≤48MiB;不接收SVG,既有本站SVG可以按真实路径引用。新画的技术SVG可在本地渲染为PNG后通过资产API上传,无需为了配图部署程序。
- id.json仅`{"release_id":"原UUID"}`。服务器先保存稳定草稿ID/发布UUID,再调用API;相同bundle重复prepare不新建版本或重新抽取参数,相同release_id改正文拒绝409。改稿应显式创建新release并使用当前版本。
- review.json的`data.previews`含原模板渲染的HTML,`data.review`含hash和digest。先阅读及检查冻结版本;程序渲染通过不等于人类/浏览器视觉验收。正式HTML内含线上资源链接,禁止直接在本机浏览器打开加载;视觉检查在本地对应稿件完成。必须线上页面验收时仍按项目访问批准规则到Windows,不以取预览为由越界。
- publish.json为`{"release_id":"原UUID","expected_hash":"review中hash","review_digest":"review中digest"}`,不得盲填或以另一份稿件替换。程序先查回执;已发表则只重试后处理,草稿版本冲突返回失败。
- status会从API重新查询并核对公开正文,不只读本地台账。`phase=complete`要求内容/版本/上传图哈希和缓存/搜索/sitemap/IndexNow状态通过(无需通知的IndexNow skipped视为完成),且IndexNow通知为done或明确skipped;`published_pending`代表正文已提交但后续仍待处理,退出码2,不能据此另发正文。返回`published_at`来自服务器真实发布事务时间。
本机工具只输出结果文件路径及状态,不回显SSH认证、正文或预览。SSH断开、超时或非JSON输出都保存未知/失败状态,不自动重放写入;用原release_id查status。不存在草稿时沿原bundle恢复prepare。
## 状态与恢复
服务器台账`storage/app/private/editorial-releases/UUID.json`,权限600;原子替换并fsync,文件锁防并发,系统会在进程退出时释放锁。保存IDs先于写入API。台账记录prepared/reviewed/publishing/complete或published_pending;唯一发表事实仍以API事务回执为准。服务器台账损坏/丢失时须从原请求UUID和API回执恢复,不能另起ID重发。
回读校验包括真实版本、标题、摘要、slug、栏目、封面、正文哈希及内容寻址图文件SHA;点赞参数随结果返回供确认。文章完整HTTP页面及外部链接状态按任务另外验证,不能把内部Kernel渲染说成外部网络/浏览器验收。没有真实新稿时不向正式站发布演练文章。
上线前仅执行`2026_10_31_150000_add_article_display_timestamp.php`迁移(新增可空`sDisplayPublishedAt`);旧文显示回退原时间。新文草稿冻结0~21600秒偏移,首次发布计算展示时间;保留created_at、实际回执、点赞起点,旧文改稿不改展示日期。回滚程序保留新增可空列和历史发布记录,不删业务数据。
验证与当前部署状态见[2026-10-31发布记录](EDITORIAL_RELEASE_2026-10-31.md)。周期调度和额度唯一见[WEEKLY_TUTORIALS.md](WEEKLY_TUTORIALS.md)。
IndexNow的结果、环境开关及服务器延时重试见[教程SEO通知](EDITORIAL_INDEXNOW.md)。通知pending只重试后处理,不再次发表正文。
2026-10-31编辑发布已接入[IndexNow通知与重试](EDITORIAL_INDEXNOW.md),复用发布回执effects;通知pending不表示正文未发布,禁止为通知重发正文。