Skip to content

Commit ce5604b

Browse files
LeeJimclaude
andcommitted
feat: add checkin fix, CI auto-upload, and changelog
- Fix checkin user isolation bug (cloud function _openid filtering) - Add CI workflow for auto upload and submit audit on push to main - Auto-generate changelog from commit messages in CI pipeline - Add changelog entry in personal center (my page) - Update version to 3.1.2 - Add recent version history to changelog data Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 74b5c7f commit ce5604b

8 files changed

Lines changed: 273 additions & 3 deletions

File tree

.github/workflows/upload.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: UPLOAD
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
jobs:
8+
upload-and-submit:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
13+
- uses: actions/setup-node@v4
14+
with:
15+
node-version: '18'
16+
17+
- name: Install miniprogram dependencies
18+
run: cd miniprogram && npm install
19+
20+
- name: Install miniprogram-ci
21+
run: npm install miniprogram-ci@latest
22+
23+
- name: Upload and Submit Audit
24+
run: node script/ci-upload.js
25+
env:
26+
MINI_APP_ID: ${{ secrets.APP_ID }}
27+
MINI_APP_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
28+
COMMIT_MESSAGE: ${{ github.event.head_commit.message }}
29+
30+
- name: Update changelog
31+
run: node script/update-changelog.js
32+
env:
33+
PUSH_COMMITS: ${{ toJson(github.event.commits) }}
34+
35+
- name: Commit changelog
36+
run: |
37+
git config user.name "github-actions[bot]"
38+
git config user.email "github-actions[bot]@users.noreply.github.com"
39+
git add miniprogram/pages/changelog/log.js
40+
if git diff --staged --quiet; then
41+
echo "No changelog changes to commit."
42+
else
43+
git commit -m "chore: update changelog [skip ci]"
44+
git push
45+
fi

cloudfunctions/checkin/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ exports.main = async (event) => {
3939
const coll = db.collection('checkins');
4040

4141
try {
42-
const { data: records } = await coll.get();
42+
const { data: records } = await coll.where({ _openid: OPENID }).get();
4343
const record = records[0] || { streak: 0, lastDate: '' };
4444

4545
if (action === 'status') {
@@ -80,7 +80,7 @@ exports.main = async (event) => {
8080
});
8181
} else {
8282
await coll.add({
83-
data: { streak: newStreak, lastDate: today, updateTime: Date.now() }
83+
data: { _openid: OPENID, streak: newStreak, lastDate: today, updateTime: Date.now() }
8484
});
8585
}
8686

miniprogram/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "HowToCookOnMiniprogram",
3-
"version": "0.2.1",
3+
"version": "3.1.2",
44
"description": "",
55
"main": "app.js",
66
"scripts": {

miniprogram/pages/changelog/log.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,63 @@
11
export default [{
2+
version: '3.1.2',
3+
detail: [{
4+
type: 'bug',
5+
value: '修复打卡数据用户隔离问题'
6+
}, {
7+
type: 'feature',
8+
value: '新增 CI 自动上传审核'
9+
}],
10+
date: '2026-06-01'
11+
}, {
12+
version: '3.1.0',
13+
detail: [{
14+
type: 'feature',
15+
value: '新增 AI 智能做菜'
16+
}, {
17+
type: 'feature',
18+
value: '新增每日打卡和等级系统'
19+
}, {
20+
type: 'feature',
21+
value: '重构首页 UI(分类侧边栏 + 滑动切换)'
22+
}, {
23+
type: 'feature',
24+
value: '新增仓储管理(食材库存、条码扫描)'
25+
}, {
26+
type: 'feature',
27+
value: '优化菜谱搜索和收藏'
28+
}],
29+
date: '2026-05-24'
30+
}, {
31+
version: '3.0.0',
32+
detail: [{
33+
type: 'feature',
34+
value: '全新 3.0 版本发布'
35+
}, {
36+
type: 'feature',
37+
value: '菜谱数据全面升级'
38+
}],
39+
date: '2026-05-24'
40+
}, {
41+
version: '2.0.0',
42+
detail: [{
43+
type: 'feature',
44+
value: '新增仓储管理模块'
45+
}, {
46+
type: 'feature',
47+
value: '新增条码扫描功能'
48+
}],
49+
date: '2024-10-06'
50+
}, {
51+
version: '1.2.0',
52+
detail: [{
53+
type: 'feature',
54+
value: '优化首页 UI 和交互'
55+
}, {
56+
type: 'bug',
57+
value: '修复页面标题问题'
58+
}],
59+
date: '2023-01-26'
60+
}, {
261
version: '1.1.1',
362
detail: [{
463
type: 'feature',

miniprogram/pages/my/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ Page({
147147
wx.navigateTo({ url: '/pages/myStarred/index' })
148148
},
149149

150+
handleToChangelog() {
151+
wx.navigateTo({ url: '/pages/changelog/index' })
152+
},
153+
150154
handleToggleAd({ detail }) {
151155
const adFlag = detail.value
152156
wx.setStorageSync('ad-flag', adFlag)

miniprogram/pages/my/index.wxml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,16 @@
5656
</view>
5757
</view>
5858

59+
<view class="menu-card">
60+
<view class="menu-item" bind:tap="handleToChangelog">
61+
<view class="menu-left">
62+
<text class="menu-icon">📋</text>
63+
<text class="menu-label">更新日志</text>
64+
</view>
65+
<t-icon name="chevron-right" size="36rpx" color="#c0c0c0" />
66+
</view>
67+
</view>
68+
5969
<view class="menu-card">
6070
<view class="menu-item">
6171
<view class="menu-left">

script/ci-upload.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const ci = require('miniprogram-ci');
2+
const fs = require('fs');
3+
const path = require('path');
4+
const os = require('os');
5+
6+
// 从 miniprogram/package.json 读取版本号
7+
const pkgPath = path.join(__dirname, '..', 'miniprogram', 'package.json');
8+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
9+
const version = pkg.version;
10+
11+
// 将私钥写入临时文件(miniprogram-ci 只能读文件路径,不能直接传内容)
12+
const keyPath = path.join(os.tmpdir(), `mp-private-key-${Date.now()}.key`);
13+
fs.writeFileSync(keyPath, process.env.MINI_APP_PRIVATE_KEY, 'utf8');
14+
15+
// project.config.json 在仓库根目录,其中 miniprogramRoot 指向 miniprogram/
16+
const project = new ci.Project({
17+
appid: process.env.MINI_APP_ID,
18+
type: 'miniProgram',
19+
projectPath: path.join(__dirname, '..'),
20+
privateKeyPath: keyPath,
21+
});
22+
23+
// 取 commit message 第一行作为版本描述
24+
const desc = (process.env.COMMIT_MESSAGE || 'CI auto upload').split('\n')[0].trim().slice(0, 200);
25+
26+
async function main() {
27+
console.log(`📦 Version: ${version}`);
28+
console.log(`📝 Description: ${desc}`);
29+
30+
// Step 1: 上传体验版
31+
console.log('⬆️ Uploading...');
32+
const uploadResult = await ci.upload({
33+
project,
34+
version,
35+
desc,
36+
setting: {
37+
es6: true,
38+
es7: true,
39+
minify: true,
40+
autoPrefixWXSS: true,
41+
},
42+
onProgressUpdate: (info) => {
43+
if (info.status === 'uploading') {
44+
console.log(` Uploading: ${info.progress}%`);
45+
} else {
46+
console.log(` ${info.status}: ${info.message || ''}`);
47+
}
48+
},
49+
});
50+
console.log('✅ Upload success');
51+
52+
// Step 2: 提交审核
53+
console.log('📤 Submitting audit...');
54+
try {
55+
const auditResult = await ci.submitAudit({
56+
project,
57+
version,
58+
});
59+
console.log('✅ Submit audit success:', JSON.stringify(auditResult));
60+
} catch (err) {
61+
// 提交审核失败不一定是 bug(比如有审核中的版本),记录后继续
62+
console.warn('⚠️ Submit audit failed:', err.message);
63+
}
64+
65+
// 清理临时私钥文件
66+
fs.unlinkSync(keyPath);
67+
}
68+
69+
main().catch(err => {
70+
console.error('❌ CI upload failed:', err.message);
71+
try { fs.unlinkSync(keyPath); } catch {}
72+
process.exit(1);
73+
});

script/update-changelog.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
// ── 读取版本号 ──
5+
const pkgPath = path.join(__dirname, '..', 'miniprogram', 'package.json');
6+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
7+
const version = pkg.version;
8+
9+
// ── 解析 push 携带的 commit 信息 ──
10+
let commits = [];
11+
try {
12+
commits = JSON.parse(process.env.PUSH_COMMITS || '[]');
13+
} catch {
14+
console.warn('Failed to parse PUSH_COMMITS, using default entry.');
15+
}
16+
17+
// ── commit → changelog detail ──
18+
const details = commits
19+
.filter(c => c.message && !/^Merge/i.test(c.message))
20+
.map(c => {
21+
let msg = c.message.trim();
22+
let type = 'feature';
23+
24+
// 解析 Conventional Commits 格式
25+
if (/^fix[:(]/.test(msg)) {
26+
type = 'bug';
27+
msg = msg.replace(/^fix[:(]\s*/, '').replace(/\)\s*$/, '').replace(/\):/, ':');
28+
} else if (/^feat[:(]/.test(msg)) {
29+
type = 'feature';
30+
msg = msg.replace(/^feat[:(]\s*/, '').replace(/\)\s*$/, '').replace(/\):/, ':');
31+
} else if (/^chore[:(]/.test(msg) || /^build[:(]/.test(msg) || /^ci[:(]/.test(msg)) {
32+
// skip chore/build/ci commits — not user-facing
33+
return null;
34+
}
35+
36+
return { type, value: msg.slice(0, 200) };
37+
})
38+
.filter(Boolean);
39+
40+
// 没有任何有效 commit 时给一个占位
41+
if (details.length === 0) {
42+
details.push({ type: 'feature', value: '版本更新' });
43+
}
44+
45+
// 去重:相同 value 只保留一条
46+
const seen = new Set();
47+
const unique = details.filter(d => {
48+
if (seen.has(d.value)) return false;
49+
seen.add(d.value);
50+
return true;
51+
});
52+
53+
// ── 生成日期 ──
54+
const today = new Date().toISOString().slice(0, 10);
55+
56+
// ── 更新 log.js ──
57+
const logPath = path.join(
58+
__dirname, '..', 'miniprogram', 'pages', 'changelog', 'log.js'
59+
);
60+
let content = fs.readFileSync(logPath, 'utf8');
61+
62+
// 避免重复插入
63+
if (content.includes(`version: '${version}'`)) {
64+
console.log(`⚠️ v${version} already in log.js, skipped.`);
65+
process.exit(0);
66+
}
67+
68+
const entry = `{
69+
version: '${version}',
70+
detail: ${JSON.stringify(unique, null, 4)},
71+
date: '${today}'
72+
},
73+
`;
74+
75+
content = content.replace('export default [', `export default [\n ${entry}`);
76+
fs.writeFileSync(logPath, content, 'utf8');
77+
78+
console.log(`✅ Added changelog entry for v${version}`);
79+
console.log(JSON.stringify(unique, null, 2));

0 commit comments

Comments
 (0)