auto-version-tool
Version:
根据git commit历史自动修改版本号并生成changelog的CLI工具 (Automatically bump version & generate changelog based on git commits)
199 lines • 6.63 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitService = void 0;
const simple_git_1 = __importDefault(require("simple-git"));
class GitService {
constructor(config) {
this.config = config;
this.git = (0, simple_git_1.default)();
}
async isGitRepository() {
try {
await this.git.status();
return true;
}
catch {
return false;
}
}
async isWorkingDirectoryClean() {
const status = await this.git.status();
return status.files.length === 0;
}
async checkoutBranch(branch) {
const branches = await this.git.branchLocal();
if (branches.all.includes(branch)) {
await this.git.checkout(branch);
}
else {
// 尝试检出远程分支
try {
await this.git.checkout(["-b", branch, `origin/${branch}`]);
}
catch {
throw new Error(`分支 '${branch}' 不存在`);
}
}
}
async getCurrentBranch() {
const status = await this.git.status();
return status.current || "unknown";
}
async getLatestTag() {
try {
const tags = await this.git.tags(["--sort=-version:refname"]);
const tagList = tags.all.filter((tag) => tag.startsWith(this.config.git.tagPrefix));
return tagList[0] || null;
}
catch {
return null;
}
}
async getCommitsSinceLastTag(branch) {
const latestTag = await this.getLatestTag();
try {
if (latestTag) {
// 获取从最新标签(不含)到当前分支HEAD(含)的提交
const log = await this.git.log({ from: latestTag, to: branch });
return log.all
.filter((c) => c.hash !== log.latest?.hash || log.latest?.hash !== latestTag) // 保守过滤
.map((commit) => ({
hash: commit.hash,
date: commit.date,
message: commit.message,
author_name: commit.author_name,
author_email: commit.author_email,
refs: commit.refs,
}));
}
// 没有标签时,返回除首次提交外的全部提交以避免把初始化提交也当成“待发布”
const allLog = await this.git.log();
return allLog.all.map((commit) => ({
hash: commit.hash,
date: commit.date,
message: commit.message,
author_name: commit.author_name,
author_email: commit.author_email,
refs: commit.refs,
}));
}
catch (error) {
console.error("获取提交历史失败:", error);
return [];
}
}
async getCommitsBetweenTags(from, to) {
try {
const log = await this.git.log({
from,
to,
format: {
hash: "%H",
date: "%ai",
message: "%s",
author_name: "%an",
author_email: "%ae",
},
});
return log.all.map((commit) => ({
hash: commit.hash,
date: commit.date,
message: commit.message,
author_name: commit.author_name,
author_email: commit.author_email,
}));
}
catch {
return [];
}
}
async getAllTags() {
try {
const tags = await this.git.tags([
"--sort=-version:refname",
"-l",
"--format=%(refname:short)|%(objectname)|%(creatordate:iso8601)|%(contents:lines=1)",
]);
return tags.all
.filter((tag) => tag.startsWith(this.config.git.tagPrefix))
.map((tagInfo) => {
const [name, hash, date, message] = tagInfo.split("|");
return {
name,
hash,
date,
message: message || undefined,
};
});
}
catch {
return [];
}
}
async commitVersionBump(version) {
// 添加更改的文件
await this.git.add([
this.config.files.packageJson,
this.config.files.changelogFile,
]);
// 提交更改
const commitMessage = `chore(release): bump version to ${version}`;
await this.git.commit(commitMessage);
}
async createTag(version, message) {
const tagName = `${this.config.git.tagPrefix}${version}`;
const tagMessage = message || `Release version ${version}`;
await this.git.addAnnotatedTag(tagName, tagMessage);
}
async pushChanges(branch, withTags = true) {
await this.git.push("origin", branch);
if (withTags) {
await this.git.pushTags("origin");
}
}
async getBranches() {
const branches = await this.git.branchLocal();
return branches.all.map((name) => ({
name,
current: name === branches.current,
commit: "", // 可以进一步获取每个分支的最新提交
}));
}
async getRemoteUrl() {
try {
const remotes = await this.git.getRemotes(true);
const origin = remotes.find((remote) => remote.name === "origin");
return origin?.refs?.fetch || null;
}
catch {
return null;
}
}
async hasUncommittedChanges() {
const status = await this.git.status();
return status.files.length > 0 || status.staged.length > 0;
}
async getLastCommit() {
try {
const log = await this.git.log({ maxCount: 1 });
const commit = log.latest;
if (!commit)
return null;
return {
hash: commit.hash,
date: commit.date,
message: commit.message,
author_name: commit.author_name,
author_email: commit.author_email,
};
}
catch {
return null;
}
}
}
exports.GitService = GitService;
//# sourceMappingURL=GitService.js.map
;