feat(devops): 发版拆分为 client/site/server 三条独立流水线
将单一 CI/CD 流水线拆成三条互不影响的发布流水线,各有 tag 前缀、独立版本
序列与独立 CHANGELOG:
- client(client-v*):Flutter 全平台 + version.yaml 自更新清单
- site(site-v*):web/ Eleventy 营销站,不含 web 版 app
- server(server-v*):backend Go 服务 + 共享基建 nginx/systemd
新增 3 个 workflow(deploy-client/site/server.yml)替换 deploy.yml;CI 脚本
按 part 拆分为 compile-/release-/deploy-{client,site,server}.sh,抽出公共函数
lib-forgejo.sh;compile-{macos,android,ios,windows}.sh 改去 client-v 前缀;
manual.yml 按前缀路由回滚。
跨流水线解耦:version.yaml 归 client,后端每请求实时读取(不重启、不触发
server 流水线);官网下载页的版本徽章/下载链接/更新日志时间线运行时经
/api/v1/public/release 动态拉取(API 不可达回退构建时静态内容)。为此一次性
扩展后端 changelog 字段(version.go/public.go)与 download.njk 动态渲染。
CHANGELOG.md 重命名为 CHANGELOG-client.md,新增 CHANGELOG-site/server.md;
重写 /release 命令为 /release <part> [version];同步更新 CLAUDE.md 与部署文档。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+43
-2
@@ -390,9 +390,9 @@ pageStyle: |
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<h2 class="fs-3xl fw-6 text-brand-900 m-0 mb-6" style="letter-spacing: var(--tracking-cn-display);">版本更新日志</h2>
|
||||
<p class="fs-md text-muted m-0">最近 {{ changelog | length }} 个版本。</p>
|
||||
<p class="fs-md text-muted m-0" id="changelog-count">最近 {{ changelog | length }} 个版本。</p>
|
||||
|
||||
<div class="changelog">
|
||||
<div class="changelog" id="changelog-list">
|
||||
{% for entry in changelog %}
|
||||
<div class="changelog-entry{% if loop.first %} current{% endif %}">
|
||||
<div class="changelog-meta">
|
||||
@@ -499,6 +499,46 @@ pageStyle: |
|
||||
});
|
||||
}
|
||||
|
||||
// 用 /api/v1/public/release 返回的 changelog 重渲染更新日志时间线,使客户端
|
||||
// 发版无需重建官网即可同步。结构与构建时 web/_data/changelog.js 一致;接口
|
||||
// 不可达或字段缺失时保留构建时静态时间线作 fallback。
|
||||
function renderChangelog(entries) {
|
||||
if (!Array.isArray(entries) || entries.length === 0) return;
|
||||
var dotClass = { '新功能': 'dot-feature', '改进': 'dot-improve', '修复': 'dot-fix' };
|
||||
var label = { '修复': '问题修复' };
|
||||
function esc(s) {
|
||||
return String(s == null ? '' : s).replace(/[&<>"]/g, function(c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"' }[c];
|
||||
});
|
||||
}
|
||||
var html = '';
|
||||
entries.forEach(function(entry, i) {
|
||||
var current = i === 0;
|
||||
html += '<div class="changelog-entry' + (current ? ' current' : '') + '">';
|
||||
html += '<div class="changelog-meta">';
|
||||
html += '<div class="changelog-version">v' + esc(entry.version) + '</div>';
|
||||
html += '<div class="changelog-date">' + esc(entry.date) + '</div>';
|
||||
if (current) html += '<span class="changelog-tag">当前版本</span>';
|
||||
html += '</div><div class="changelog-body">';
|
||||
if (entry.intro) html += '<p class="changelog-intro">' + esc(entry.intro) + '</p>';
|
||||
(entry.sections || []).forEach(function(section) {
|
||||
var dot = dotClass[section.type] || 'dot-improve';
|
||||
var name = label[section.type] || section.type;
|
||||
html += '<div class="changelog-cat"><div class="changelog-cat-label">';
|
||||
html += '<span class="dot ' + dot + '"></span>' + esc(name) + '</div><ul>';
|
||||
(section.items || []).forEach(function(item) {
|
||||
html += '<li>' + esc(item) + '</li>';
|
||||
});
|
||||
html += '</ul></div>';
|
||||
});
|
||||
html += '</div></div>';
|
||||
});
|
||||
var list = document.getElementById('changelog-list');
|
||||
if (list) list.innerHTML = html;
|
||||
var count = document.getElementById('changelog-count');
|
||||
if (count) count.textContent = '最近 ' + entries.length + ' 个版本。';
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var detected = detectPlatform();
|
||||
updateDetectCard(detected);
|
||||
@@ -508,6 +548,7 @@ pageStyle: |
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
if (data && data.version) updateVersionBadges(data.version);
|
||||
if (data && data.changelog) renderChangelog(data.changelog);
|
||||
if (data && data.download_urls && data.download_urls.macos) {
|
||||
platforms.macos.btnHref = data.download_urls.macos;
|
||||
var macBtn = document.getElementById('macos-dl-btn');
|
||||
|
||||
Reference in New Issue
Block a user