1. 创建 GitHub Actions
在项目中创建文件:.github/workflows/release.yml
name: Release
on:
push:
tags:
- "v*" # 识别推送 v 开头的 tag 时触发
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Get version from tag
id: get_version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT
- name: Install dependencies
run: npm install
- name: Build
run: npm run build
# 生成需要上传的 release 文件
- name: Rename and Compress dist
run: |
mv dist timeline-todolist-v${{ steps.get_version.outputs.VERSION }}
tar -czf timeline-todolist-v${{ steps.get_version.outputs.VERSION }}.tar.gz timeline-todolist-v${{ steps.get_version.outputs.VERSION }}
zip -r timeline-todolist-v${{ steps.get_version.outputs.VERSION }}.zip timeline-todolist-v${{ steps.get_version.outputs.VERSION }}
- name: Create Release
uses: softprops/action-gh-release@v1
with:
# token 尤其需要注意,否则会出现 GitHub release failed with status: 403 undefined
# token 的生成可以详见 tips
token: ${{ secrets.GITHUBTOKEN }}
name: "Version ${{ steps.get_version.outputs.VERSION }} 🚀"
draft: false
prerelease: false
generate_release_notes: true
# release 中的信息,一般为 changelog
body_path: changelog/v${{ steps.get_version.outputs.VERSION }}.md
# 你上传的 release 文件路径
files: |
timeline-todolist-v${{ steps.get_version.outputs.VERSION }}.tar.gz
timeline-todolist-v${{ steps.get_version.outputs.VERSION }}.zip
2. 创建发布脚本
2.1 publish 脚本
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const { generateChangelog } = require("./generate-changelog");
// 读取 package.json
const packagePath = path.resolve(__dirname, "../package.json");
const packageJson = fs.readFileSync(packagePath, "utf8");
let packageObj = JSON.parse(packageJson);
// 解析当前版本号
const [major, minor, patch] = packageObj.version.split(".").map(Number);
// 增加补丁版本号
const newVersion = `${major}.${minor}.${patch + 1}`;
// 根据你的 git 记录生成对应的 changlog
generateChangelog(newVersion);
// 更新 package.json
packageObj.version = newVersion;
fs.writeFileSync(packagePath, JSON.stringify(packageObj, null, 2) + "\n");
console.log("✨ Successfully create version " + newVersion);
try {
// 提交更改
execSync("git add package.json changelog/");
execSync(`git commit -m "chore: bump version to ${newVersion}"`);
// 创建新的 tag
execSync(`git tag v${newVersion}`);
// 推送更改和 tag
execSync("git push");
execSync("git push --tags");
console.log(`✨ Successfully published version ${newVersion}`);
} catch (error) {
console.error("❌ Failed to publish:", error.message);
process.exit(1);
}
2.2 生成 changelog 脚本
generate-changelog.js 根据 git 记录,自动生成 changlog 脚本
const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");
function getLatestTag() {
try {
return execSync("git describe --tags --abbrev=0").toString().trim();
} catch (error) {
console.log("No tags found");
return null;
}
}
function getCommitsSinceLastTag() {
const latestTag = getLatestTag();
if (!latestTag) {
return execSync('git log --pretty=format:"%h - %s (%an)"').toString();
}
return execSync(
`git log ${latestTag}..HEAD --pretty=format:"%h - %s (%an)"`
).toString();
}
function generateChangelog(version) {
const changelogDir = path.join(__dirname, "../changelog");
// 确保 changelog 目录存在
if (!fs.existsSync(changelogDir)) {
fs.mkdirSync(changelogDir);
}
const commits = getCommitsSinceLastTag();
const date = new Date().toISOString().split("T")[0];
const filename = path.join(changelogDir, `v${version}.md`);
const content = `# V${version} Changelog (${date})\n\n${commits}`;
fs.writeFileSync(filename, content);
console.log(`Changelog has been generated at: changelog/${filename}`);
}
module.exports = {
generateChangelog,
};
3. 发布
package.json
增加 "pub": "node scripts/publish.js"
命令
执行 pnpm pub
命令
等 Actions 跑完 github releases 就会生成对应的记录
4. tips:
4.1 secrets.GITHUBTOKEN 的生成和使用
-
生成
- 进入 github.com/settings/to…
- Generate new token (classic) For general use
- 设置对应的权限和过期时间,生成完要保存好,之后不会明文显示。忘记只能重新生成
-
使用