fn_b/docs/maintenance/EDITORIAL_RELEASE.md

6.4 KiB
Raw Permalink Blame History

经白色机的固定文章发布流程

设计

维护脚本:tools/editorial/release.py(本机传输)、tools/editorial/ssh_askpass.py(只向OpenSSH认证组件提供登记密码)、editorial:release(业务服务器命令)。现有文章API负责资产、草稿、版本、链接校验、原子发布、回执和搜索缓存同步,契约见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:

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发布记录。周期调度和额度唯一见WEEKLY_TUTORIALS.md。

IndexNow的结果、环境开关及服务器延时重试见教程SEO通知。通知pending只重试后处理,不再次发表正文。

2026-10-31编辑发布已接入IndexNow通知与重试,复用发布回执effects;通知pending不表示正文未发布,禁止为通知重发正文。

图片发布目录

2026-10-31首篇真实上传配图时发现正式 public/images/editorial 缺失。用户明确批准创建该专用目录并设为nginx所有、0755;已实施并完成真实文章发布。上级public/images权限未改变。以后部署预检该目录存在且执行身份nginx可写,禁止临时以root执行文章发布来绕过。回执见首篇周期教程。