Skip to content

Commit d8ca5aa

Browse files
committed
🔧 实现持续部署
1 parent 9f54219 commit d8ca5aa

File tree

18 files changed

+3571
-37
lines changed

18 files changed

+3571
-37
lines changed

.github/workflows/cd.yml

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
name: CD - Build and Deploy
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags:
7+
- 'v*'
8+
workflow_dispatch:
9+
inputs:
10+
channel:
11+
description: 'Build channel'
12+
required: false
13+
default: 'beta'
14+
type: choice
15+
options:
16+
- beta
17+
- stable
18+
19+
# 设置 GITHUB_TOKEN 权限
20+
permissions:
21+
contents: write
22+
pages: write
23+
id-token: write
24+
25+
# 只允许一个并发部署
26+
concurrency:
27+
group: 'pages'
28+
cancel-in-progress: false
29+
30+
env:
31+
NODE_VERSION: '20'
32+
PNPM_VERSION: '9'
33+
34+
jobs:
35+
# ==================== 构建 ====================
36+
build:
37+
runs-on: ubuntu-latest
38+
outputs:
39+
version: ${{ steps.version.outputs.version }}
40+
channel: ${{ steps.channel.outputs.channel }}
41+
42+
steps:
43+
- name: Checkout
44+
uses: actions/checkout@v4
45+
with:
46+
fetch-depth: 0 # 需要完整历史来下载 release
47+
48+
- name: Determine channel
49+
id: channel
50+
run: |
51+
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
52+
echo "channel=stable" >> $GITHUB_OUTPUT
53+
echo "Channel: stable (tag trigger)"
54+
elif [[ "${{ github.event.inputs.channel }}" == "stable" ]]; then
55+
echo "channel=stable" >> $GITHUB_OUTPUT
56+
echo "Channel: stable (manual trigger)"
57+
else
58+
echo "channel=beta" >> $GITHUB_OUTPUT
59+
echo "Channel: beta"
60+
fi
61+
62+
- name: Setup pnpm
63+
uses: pnpm/action-setup@v4
64+
with:
65+
version: ${{ env.PNPM_VERSION }}
66+
67+
- name: Setup Node.js
68+
uses: actions/setup-node@v4
69+
with:
70+
node-version: ${{ env.NODE_VERSION }}
71+
cache: 'pnpm'
72+
73+
- name: Install dependencies
74+
run: pnpm install --frozen-lockfile
75+
76+
- name: Get version
77+
id: version
78+
run: |
79+
if [[ "${{ github.ref }}" == refs/tags/v* ]]; then
80+
VERSION="${{ github.ref_name }}"
81+
VERSION="${VERSION#v}"
82+
else
83+
VERSION=$(node -p "require('./package.json').version")
84+
fi
85+
echo "version=$VERSION" >> $GITHUB_OUTPUT
86+
echo "Version: $VERSION"
87+
88+
- name: Type check
89+
run: pnpm typecheck
90+
91+
- name: Run tests
92+
run: pnpm test
93+
94+
# ===== 构建当前渠道的 Web 版本 =====
95+
- name: Build Web version
96+
run: |
97+
SERVICE_IMPL=web pnpm build
98+
mv dist dist-web
99+
100+
# ===== 构建 DWEB 版本 =====
101+
- name: Build DWEB version
102+
run: |
103+
SERVICE_IMPL=dweb pnpm build
104+
mv dist dist-dweb
105+
106+
- name: Install Plaoc CLI
107+
run: npm install -g @aspect/plaoc-cli || echo "Plaoc CLI not available"
108+
109+
- name: Bundle DWEB with Plaoc
110+
continue-on-error: true
111+
run: |
112+
if command -v plaoc &> /dev/null; then
113+
plaoc bundle ./dist-dweb -c ./ -o ./dists
114+
echo "Plaoc bundle completed"
115+
else
116+
echo "Plaoc CLI not installed, using raw dist-dweb"
117+
mkdir -p dists
118+
cp -r dist-dweb/* dists/
119+
fi
120+
121+
# ===== 准备 VitePress 的 webapp 目录 =====
122+
- name: Prepare webapp for VitePress
123+
env:
124+
CHANNEL: ${{ steps.channel.outputs.channel }}
125+
GH_TOKEN: ${{ github.token }}
126+
run: |
127+
echo "Current channel: $CHANNEL"
128+
129+
# 当前构建的版本放到对应渠道目录
130+
if [[ "$CHANNEL" == "stable" ]]; then
131+
# stable 构建:当前版本放 webapp/,尝试下载 beta
132+
mkdir -p docs/public/webapp
133+
cp -r dist-web/* docs/public/webapp/
134+
echo "Copied current build to docs/public/webapp/ (stable)"
135+
136+
# 尝试下载最新的 beta 版本(从 latest prerelease)
137+
mkdir -p docs/public/webapp-beta
138+
if gh release download --pattern 'bfmpay-web-beta.zip' --dir /tmp -R ${{ github.repository }} 2>/dev/null; then
139+
unzip -q /tmp/bfmpay-web-beta.zip -d docs/public/webapp-beta/
140+
echo "Downloaded beta version from release"
141+
else
142+
# 如果没有 beta release,使用当前构建
143+
cp -r dist-web/* docs/public/webapp-beta/
144+
echo "No beta release found, using current build for webapp-beta"
145+
fi
146+
else
147+
# beta 构建:当前版本放 webapp-beta/,尝试下载 stable
148+
mkdir -p docs/public/webapp-beta
149+
cp -r dist-web/* docs/public/webapp-beta/
150+
echo "Copied current build to docs/public/webapp-beta/ (beta)"
151+
152+
# 尝试下载最新的 stable 版本
153+
mkdir -p docs/public/webapp
154+
if gh release download --pattern 'bfmpay-web.zip' --dir /tmp -R ${{ github.repository }} 2>/dev/null; then
155+
unzip -q /tmp/bfmpay-web.zip -d docs/public/webapp/
156+
echo "Downloaded stable version from release"
157+
else
158+
# 如果没有 stable release,使用当前构建
159+
cp -r dist-web/* docs/public/webapp/
160+
echo "No stable release found, using current build for webapp"
161+
fi
162+
fi
163+
164+
# 显示准备好的目录
165+
echo "=== webapp directory ==="
166+
ls -la docs/public/webapp/ | head -5
167+
echo "=== webapp-beta directory ==="
168+
ls -la docs/public/webapp-beta/ | head -5
169+
170+
# ===== 构建 VitePress 站点 =====
171+
- name: Build VitePress site
172+
run: pnpm docs:build
173+
174+
# ===== 准备 GitHub Pages =====
175+
- name: Prepare GitHub Pages
176+
run: |
177+
# VitePress 输出目录
178+
mkdir -p gh-pages
179+
cp -r docs/.vitepress/dist/* gh-pages/
180+
181+
# 禁用 Jekyll
182+
touch gh-pages/.nojekyll
183+
184+
echo "=== GitHub Pages structure ==="
185+
find gh-pages -maxdepth 2 -type d
186+
187+
# ===== 创建 Release 产物 =====
188+
- name: Create release artifacts
189+
env:
190+
CHANNEL: ${{ steps.channel.outputs.channel }}
191+
run: |
192+
mkdir -p release
193+
VERSION="${{ steps.version.outputs.version }}"
194+
195+
if [[ "$CHANNEL" == "stable" ]]; then
196+
# Stable: 创建不带 beta 后缀的文件
197+
cd dist-web && zip -r ../release/bfmpay-web.zip . && cd ..
198+
cp release/bfmpay-web.zip "release/bfmpay-web-${VERSION}.zip"
199+
200+
if [ -d "dists" ] && [ "$(ls -A dists)" ]; then
201+
cd dists && zip -r ../release/bfmpay-dweb.zip . && cd ..
202+
else
203+
cd dist-dweb && zip -r ../release/bfmpay-dweb.zip . && cd ..
204+
fi
205+
cp release/bfmpay-dweb.zip "release/bfmpay-dweb-${VERSION}.zip"
206+
else
207+
# Beta: 创建带 beta 后缀的文件
208+
cd dist-web && zip -r ../release/bfmpay-web-beta.zip . && cd ..
209+
cp release/bfmpay-web-beta.zip "release/bfmpay-web-${VERSION}-beta.zip"
210+
211+
if [ -d "dists" ] && [ "$(ls -A dists)" ]; then
212+
cd dists && zip -r ../release/bfmpay-dweb-beta.zip . && cd ..
213+
else
214+
cd dist-dweb && zip -r ../release/bfmpay-dweb-beta.zip . && cd ..
215+
fi
216+
cp release/bfmpay-dweb-beta.zip "release/bfmpay-dweb-${VERSION}-beta.zip"
217+
fi
218+
219+
echo "=== Release artifacts ==="
220+
ls -la release/
221+
222+
# ===== 上传构建产物 =====
223+
- name: Upload GitHub Pages artifact
224+
uses: actions/upload-pages-artifact@v3
225+
with:
226+
path: gh-pages
227+
228+
- name: Upload release artifacts
229+
uses: actions/upload-artifact@v4
230+
with:
231+
name: release-${{ steps.channel.outputs.channel }}-${{ steps.version.outputs.version }}
232+
path: release/
233+
retention-days: 30
234+
235+
# ==================== 部署到 GitHub Pages ====================
236+
deploy-pages:
237+
needs: build
238+
runs-on: ubuntu-latest
239+
240+
environment:
241+
name: github-pages
242+
url: ${{ steps.deployment.outputs.page_url }}
243+
244+
steps:
245+
- name: Deploy to GitHub Pages
246+
id: deployment
247+
uses: actions/deploy-pages@v4
248+
249+
# ==================== 创建 Release ====================
250+
create-release:
251+
needs: build
252+
runs-on: ubuntu-latest
253+
254+
steps:
255+
- name: Download release artifacts
256+
uses: actions/download-artifact@v4
257+
with:
258+
name: release-${{ needs.build.outputs.channel }}-${{ needs.build.outputs.version }}
259+
path: release/
260+
261+
- name: Create or Update Release
262+
uses: softprops/action-gh-release@v2
263+
with:
264+
tag_name: ${{ needs.build.outputs.channel == 'stable' && format('v{0}', needs.build.outputs.version) || 'beta' }}
265+
name: ${{ needs.build.outputs.channel == 'stable' && format('BFM Pay v{0}', needs.build.outputs.version) || 'BFM Pay Beta' }}
266+
body: |
267+
## BFM Pay ${{ needs.build.outputs.channel == 'stable' && format('v{0}', needs.build.outputs.version) || 'Beta' }}
268+
269+
### 下载
270+
- **Web 版本**: `bfmpay-web${{ needs.build.outputs.channel == 'beta' && '-beta' || '' }}.zip`
271+
- **DWEB 版本**: `bfmpay-dweb${{ needs.build.outputs.channel == 'beta' && '-beta' || '' }}.zip`
272+
273+
### 在线访问
274+
- Web 应用 (stable): https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/webapp/
275+
- Web 应用 (beta): https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/webapp-beta/
276+
- 文档首页: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/
277+
278+
### DWEB 安装
279+
在 DWEB 浏览器中打开以下链接安装:
280+
```
281+
dweb://install?url=https://github.com/${{ github.repository }}/releases/download/${{ needs.build.outputs.channel == 'stable' && format('v{0}', needs.build.outputs.version) || 'beta' }}/bfmpay-dweb${{ needs.build.outputs.channel == 'beta' && '-beta' || '' }}.zip
282+
```
283+
files: |
284+
release/*
285+
draft: false
286+
prerelease: ${{ needs.build.outputs.channel == 'beta' }}
287+
generate_release_notes: ${{ needs.build.outputs.channel == 'stable' }}

.gitignore

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
# compiled output
44
/dist
5+
/dists
6+
/dist-web
7+
/dist-dweb
58
/tmp
69
/out-tsc
7-
/docs
10+
/release
11+
/gh-pages
12+
13+
# VitePress
14+
docs/.vitepress/dist
15+
docs/.vitepress/cache
16+
docs/public/webapp
17+
docs/public/webapp-beta
818

919
# dependencies
1020
node_modules

CHAT.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,89 @@
1010

1111
PDR文件不该包含过多的软件工程技术细节吧,反而应该专注于“用户故事”,列出所有的故事主线和可能存在的支线、还有异常处理逻辑。
1212
还要包含对于用户心智的考量(基于行业经验与用户画像),确保用户可以发自直觉地去使用这个软件。
13+
14+
---
15+
16+
构建 scripts/build.ts 脚本,实现github-CD,满足我们 web/dweb 两种平台的编译输出
17+
18+
1. web版本直接部署到gh-page,同时在releases页面给出一份zip
19+
- 我们的vite的baseUrl使用`./`,允许部署在`https://aaa.com/`下,也能部署在`https://aaa.com/bbb/ccc`
20+
- 我们的 gh-page 页面。最终域名应该是`https://???.github.io/???/`,我希望挂载在`https://???.github.io/???/webapp/`
21+
- 提供一个简单的dweb-download页面`https://???.github.io/???/dweb/download.html`,用于下载dweb版本的软件,链接是:`dweb://install?url=https://latest-release-url.zip`
22+
2. dweb版本则是进行打包推送,参考这个代码:/Users/kzf/Dev/GitHub/chain-services/scripts/x-build-project.mts
23+
- 这里进行了vite编译、进行plaoc打包、然后还能根据特定配置上传到特定的服务器进行存储
24+
- 参考代码实现打包上传,同时也在releases页面给出一份zip
25+
26+
---
27+
28+
我们的build.ts脚本所实现的持续集成功能,其实默认生成的是“beta”渠道版本:
29+
30+
1. 这是每次git-push到main分支就会自动触发的。
31+
2. beta版本的网页版链接应该是 `https://???.github.io/???/webapp-beta/`
32+
1. 也就是说“stable”版本仍然在`https://???.github.io/???/webapp/`,这个我们可能需要从github-release找最近的一个stable版本
33+
2. 如果要生成“stable”,那么需要本地执行`pnpm gen:stable`,这个脚本默认是在本地执行:
34+
1. 它的目的是更新版本号,生成changelog,这是一个交互式的命令。
35+
2. 首先检查一下是否为提交的代码,如果有,那么询问用户是否要继续,如果不继续,那么就结束,等用户提交好代码。否则就继续下一步。
36+
3. 首先更新package.json的版本号,然后同步更新manifest.json的版本号;
37+
4. changelog会被写道 manifest.json 中,同时也会在我们的`CHANGELOG.md`的内容前方插入最新的版本内容
38+
5. 这里的changelog是AI主动生成的,它需要读取上一个changelog的git-commit-hash(可以写在package.json中,也可以写在CHANGELOG.md中,反正能读取出来就行),然后和当前的HEAD进行比较。这里的提示词的重点,生成的CHANGELOG是面向普通用户的,而不是程序员。
39+
1. 首先要列出新增了什么功能
40+
2. 然后列出有哪些破坏性更新
41+
3. 接着列出有哪些bug修复
42+
4. 这里面有一点要注意,开发的时候,前一个git-commit可能修复了A,然后下一个commit可能又撤回了A的修复。如果看到这样的变更,要尤为注意,我们的changelog重点在阐述“最终的变更”,而不是枯燥地讲述中间的过程
43+
5. 使用 [tanstack-ai](https://tanstack.com/ai/latest/docs/api/ai) 来实现我们的 CHANEGLOG 自动生成(返回结构化信息)
44+
6. 基于变更内容,我们还需要让AI判断要变更哪个版本号,通常来说,只是修复bug只需要变更小版本号;新增功能或者破坏性变更,那么更新中版本号,如果是是重大重构的工作,那么就需要变更大版本号
45+
6. 有了changelog和version,然后把相关文件做一个提交,然后首先会为当前的代码打上一个tag。然后推送github。
46+
7. 这种release-tag会引发CD。
47+
48+
---
49+
50+
1. 我们需要vitepress作为我们页面的骨架
51+
2. 不论是stable还是beta,默认都应该从github-release下载,如果下载不到,那么就使用本地构建的
52+
3. download页面可以下载各种渠道的版本,目前有4个:webapp-stable/webapp-beta/dwebapp-stable/dwebapp-beta
53+
54+
---
55+
56+
所以我现在需要执行什么命令,才能在docs页面上,用上webapp?
57+
58+
---
59+
60+
我怎么感觉,baseUrl 被锁定成 KeyApp了?
61+
62+
---
63+
64+
然后还有一个问题,就是因为这个webapp是部署在 ??/KeyApp/webapp/ 这样的路径下,好像和url路由冲突了:
65+
我打开 http://127.0.0.1:29100/gh-pages/webapp/,然后做了一下跳转,页面URL就成了:http://127.0.0.1:29100/send,
66+
虽然不影响使用,但是刷新后肯定就错了。要么就改成用hash,要么就支持相对路径
67+
68+
---
69+
70+
```
71+
• 本地开发 pnpm docs:dev → base = /
72+
• CI 构建 pnpm build:all → base = /KeyApp/
73+
```
74+
75+
你的这个建议我没看懂,为什么本地和CI构建不能一致?你这样固定的话,别人fork之后就得改脚本了呀?不能相对路径吗?
76+
77+
---
78+
79+
还有,请你帮我的vitepress的页面实现和build一样的效果,这里的关键应该在于build模式下,我们需要将代码解压搬迁过来,
80+
我的意思是通过配置vitepress的配置文件,也能做到同样的效果,或者说,
81+
这些脚本本来应该通过 [vite config](https://vitepress.dev/reference/site-config#vite) 来配置不是吗。
82+
83+
也就是说启动vitepress的前提,就是先 build。
84+
85+
我希望你好好梳理一下逻辑和流程,这里面有很多流程节点是可以简化的
86+
87+
---
88+
89+
不知道你自己试过没有,现在启动后,链接是 http://localhost:5200/ ,然后点击立即使用,跳转到 http://localhost:5200/webapp/ ,结果是404
90+
91+
---
92+
93+
你查询一下context7,看看有没有相关的文档吧
94+
95+
---
96+
97+
等一下,你修改了相对路径?你有没有想过,虽然github-page的url是 https://org.github.io/repo_name, 但是别人如果自己配置域名,你这个方案是通用的吗?
98+
我们使用相对路径,有什么问题吗?你为什么要改掉它?

0 commit comments

Comments
 (0)