Skip to content

Commit 555aa32

Browse files
tobenotcursoragent
andauthored
Implement version management with manual update workflow and scripts (#3)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
1 parent c6d17b9 commit 555aa32

File tree

6 files changed

+260
-13
lines changed

6 files changed

+260
-13
lines changed

.github/workflows/publish-contract.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ on:
55
push:
66
branches:
77
- main
8+
paths-ignore:
9+
- 'package.json'
810

911
jobs:
1012
publish:
@@ -31,17 +33,7 @@ jobs:
3133
env:
3234
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3335

34-
- name: Update version and publish
35-
run: |
36-
npm version patch --no-git-tag-version
37-
npm publish
36+
- name: Publish package
37+
run: npm publish
3838
env:
3939
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40-
41-
- name: Commit and push version update
42-
run: |
43-
git config --local user.email "action@github.com"
44-
git config --local user.name "GitHub Action"
45-
git add package.json
46-
git commit -m "Auto update version for npm publish"
47-
git push
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# .github/workflows/update-version.yml
2+
name: Update Version
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
version_type:
8+
description: 'Version type to increment'
9+
required: true
10+
default: 'patch'
11+
type: choice
12+
options:
13+
- patch
14+
- minor
15+
- major
16+
17+
jobs:
18+
update-version:
19+
runs-on: ubuntu-latest
20+
permissions:
21+
contents: write
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
token: ${{ secrets.GITHUB_TOKEN }}
26+
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: '20'
30+
31+
- name: Install dependencies
32+
run: npm install
33+
34+
- name: Update version
35+
run: npm run version:${{ github.event.inputs.version_type }}
36+
37+
- name: Commit and push version update
38+
run: |
39+
git config --local user.email "action@github.com"
40+
git config --local user.name "GitHub Action"
41+
git add package.json
42+
git commit -m "Update version to ${{ github.event.inputs.version_type }}"
43+
git push

VERSION_MANAGEMENT.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# 版本管理说明
2+
3+
## 问题背景
4+
5+
之前的GitHub Action会在每次推送到main分支时自动更新版本号并发布,这会导致:
6+
1. 循环触发Vercel构建
7+
2. 每次提交后都需要拉取最新代码
8+
3. 不必要的版本更新
9+
10+
## 新的版本管理方式
11+
12+
### 1. 本地版本更新
13+
14+
您可以在本地使用以下命令来更新版本号:
15+
16+
```bash
17+
# 更新补丁版本 (1.0.10 -> 1.0.11)
18+
npm run version:patch
19+
20+
# 更新次要版本 (1.0.10 -> 1.1.0)
21+
npm run version:minor
22+
23+
# 更新主要版本 (1.0.10 -> 2.0.0)
24+
npm run version:major
25+
26+
# 查看下一个版本号(不更新文件)
27+
npm run get-next-version
28+
```
29+
30+
### 2. 手动触发版本更新
31+
32+
在GitHub仓库的Actions页面,您可以手动触发"Update Version"工作流:
33+
1. 进入Actions页面
34+
2. 选择"Update Version"工作流
35+
3. 点击"Run workflow"
36+
4. 选择版本类型(patch/minor/major)
37+
5. 点击"Run workflow"
38+
39+
### 3. 版本号获取逻辑
40+
41+
脚本会按以下顺序获取版本号:
42+
1. 首先尝试从npm registry获取最新版本
43+
2. 如果失败,则使用本地package.json中的版本
44+
3. 根据选择的类型(patch/minor/major)计算下一个版本号
45+
46+
### 4. 发布流程
47+
48+
修改后的发布流程:
49+
1. 手动更新版本号(本地或GitHub Action)
50+
2. 推送到main分支
51+
3. 自动触发发布到npm包(不会更新版本号)
52+
53+
### 5. 避免循环触发
54+
55+
- 发布工作流添加了`paths-ignore: ['package.json']`,避免版本更新触发发布
56+
- 版本更新工作流只在手动触发时运行
57+
58+
## 使用建议
59+
60+
1. **开发阶段**:使用本地命令更新版本号
61+
2. **发布阶段**:使用GitHub Action手动触发版本更新
62+
3. **紧急修复**:直接使用`npm run version:patch`快速更新
63+
64+
## 脚本文件
65+
66+
- `scripts/get-next-version.js` - 获取下一个版本号
67+
- `scripts/update-version.js` - 更新package.json中的版本号
68+
- `.github/workflows/update-version.yml` - 手动版本更新工作流
69+
- `.github/workflows/publish-contract.yml` - 发布工作流(已优化)

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@tobenot/basic-web-game-backend-contract",
3-
"version": "1.0.10",
3+
"version": "1.1.1",
44
"description": "",
55
"main": "dist/server.js",
66
"types": "dist/server.d.ts",
@@ -16,6 +16,10 @@
1616
"migrate:prod": "npx dotenv -e .env.publish -- npm run prisma:generate:schema && npx prisma migrate deploy",
1717
"studio": "npx dotenv -e .env -- npm run prisma:generate:schema && npx prisma studio",
1818
"copy-templates": "node scripts/copy-templates.js",
19+
"version:patch": "node scripts/update-version.js patch",
20+
"version:minor": "node scripts/update-version.js minor",
21+
"version:major": "node scripts/update-version.js major",
22+
"get-next-version": "node scripts/get-next-version.js",
1923
"test": "echo \"Error: no test specified\" && exit 1"
2024
},
2125
"repository": {

scripts/get-next-version.js

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
const https = require('https');
2+
const { execSync } = require('child_process');
3+
4+
async function getPackageInfo(packageName) {
5+
return new Promise((resolve, reject) => {
6+
const url = `https://registry.npmjs.org/${packageName}`;
7+
8+
https.get(url, (res) => {
9+
let data = '';
10+
11+
res.on('data', (chunk) => {
12+
data += chunk;
13+
});
14+
15+
res.on('end', () => {
16+
try {
17+
const packageInfo = JSON.parse(data);
18+
resolve(packageInfo);
19+
} catch (error) {
20+
reject(error);
21+
}
22+
});
23+
}).on('error', (error) => {
24+
reject(error);
25+
});
26+
});
27+
}
28+
29+
function incrementVersion(version, type = 'patch') {
30+
const parts = version.split('.').map(Number);
31+
32+
switch (type) {
33+
case 'major':
34+
parts[0]++;
35+
parts[1] = 0;
36+
parts[2] = 0;
37+
break;
38+
case 'minor':
39+
parts[1]++;
40+
parts[2] = 0;
41+
break;
42+
case 'patch':
43+
default:
44+
parts[2]++;
45+
break;
46+
}
47+
48+
return parts.join('.');
49+
}
50+
51+
async function getNextVersion(packageName, versionType = 'patch') {
52+
try {
53+
const packageInfo = await getPackageInfo(packageName);
54+
const currentVersion = packageInfo['dist-tags'].latest;
55+
const nextVersion = incrementVersion(currentVersion, versionType);
56+
57+
console.log(`Current version: ${currentVersion}`);
58+
console.log(`Next version: ${nextVersion}`);
59+
60+
return nextVersion;
61+
} catch (error) {
62+
console.error('Error fetching package info:', error.message);
63+
64+
// Fallback: read from local package.json
65+
try {
66+
const packageJson = require('../package.json');
67+
const currentVersion = packageJson.version;
68+
const nextVersion = incrementVersion(currentVersion, versionType);
69+
70+
console.log(`Using local package.json version: ${currentVersion}`);
71+
console.log(`Next version: ${nextVersion}`);
72+
73+
return nextVersion;
74+
} catch (fallbackError) {
75+
console.error('Error reading local package.json:', fallbackError.message);
76+
process.exit(1);
77+
}
78+
}
79+
}
80+
81+
// If run directly
82+
if (require.main === module) {
83+
const packageName = process.argv[2] || '@tobenot/basic-web-game-backend-contract';
84+
const versionType = process.argv[3] || 'patch';
85+
86+
getNextVersion(packageName, versionType)
87+
.then(nextVersion => {
88+
console.log(nextVersion);
89+
})
90+
.catch(error => {
91+
console.error('Error:', error.message);
92+
process.exit(1);
93+
});
94+
}
95+
96+
module.exports = { getNextVersion, incrementVersion };

scripts/update-version.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const { getNextVersion } = require('./get-next-version');
4+
5+
async function updateVersion(versionType = 'patch') {
6+
const packageJsonPath = path.join(__dirname, '../package.json');
7+
8+
try {
9+
// Get the next version
10+
const nextVersion = await getNextVersion('@tobenot/basic-web-game-backend-contract', versionType);
11+
12+
// Read current package.json
13+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
14+
15+
// Update version
16+
packageJson.version = nextVersion;
17+
18+
// Write back to package.json
19+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
20+
21+
console.log(`✅ Version updated to ${nextVersion}`);
22+
return nextVersion;
23+
} catch (error) {
24+
console.error('❌ Error updating version:', error.message);
25+
process.exit(1);
26+
}
27+
}
28+
29+
// If run directly
30+
if (require.main === module) {
31+
const versionType = process.argv[2] || 'patch';
32+
33+
updateVersion(versionType)
34+
.then(() => {
35+
console.log('Version update completed successfully');
36+
})
37+
.catch(error => {
38+
console.error('Error:', error.message);
39+
process.exit(1);
40+
});
41+
}
42+
43+
module.exports = { updateVersion };

0 commit comments

Comments
 (0)