init repo

This commit is contained in:
2026-02-25 14:07:37 +08:00
commit 4ea6a8ad46
4 changed files with 241 additions and 0 deletions

45
.gitignore vendored Normal file
View File

@@ -0,0 +1,45 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
!.idea/icon.png
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
# Maven ignore
.flattened-pom.xml
### Temp ###
*.log
*.logs
*.cache
*.diff
*.patch
*.tmp

23
README.md Normal file
View File

@@ -0,0 +1,23 @@
# CHANGELOG 生成器
将提交信息转换成 CHANGELOG Markdown。
## 快速开始
- `BASIC_PATH`:项目基础路径
- `PROJECT_NAME`:项目名称
- `LAST_TAG_NAME`:上一个版本名称
- `SHOW_MODULE_NAME`:是否显示模块名称
## 示例
```text
feat(core): ServletUtils 新增 isMultipart、isForm、isStream 方法
```
转换如下:
```text
新特性:
- 【core】ServletUtils 新增 isMultipart、isForm、isStream 方法 ([580aa00a](https://github.com/continew-org/continew-starter/commit/580aa00af920acb3f66fbd835378a802741d18d6))
```

30
pom.xml Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.charles7c</groupId>
<artifactId>changelog-generator</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>7.2.1.202505142326-r</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.40</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,143 @@
package top.charles7c.app;
import cn.hutool.core.util.StrUtil;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* Git Changelog 生成器
*
* @author Charles7c
*/
public class App {
private static final String BASIC_PATH = "D:\\Projects\\charles7c\\";
private static final String PROJECT_NAME = "continew-starter";
// private static final String PROJECT_NAME = "continew-admin";
// private static final String PROJECT_NAME = "continew-admin-ui";
//
private static final String LAST_TAG_NAME = "release: v2.15.0";
// private static final String LAST_TAG_NAME = "release: v4.1.0";
private static final boolean SHOW_MODULE_NAME = true;
public static void main(String[] args) throws IOException, GitAPIException {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.setGitDir(new File(BASIC_PATH + PROJECT_NAME + "\\.git"))
.readEnvironment()
.findGitDir()
.build();
Map<String, List<RevCommit>> commitListMap = new LinkedHashMap<>();
// 根据类型汇总提交记录
try (Git git = new Git(repository)) {
// 倒序遍历所有提交记录
Iterable<RevCommit> logs = git.log().call();
for (RevCommit commit : logs) {
// 直到上次发布标签,停止遍历
if (LAST_TAG_NAME.equals(commit.getShortMessage())) {
break;
}
logChangeCommit(commit, commitListMap);
}
} finally {
repository.close();
}
// 转换为 CHANGELOG Markdown
Set<Map.Entry<String, List<RevCommit>>> entrySet = commitListMap.entrySet();
for (Map.Entry<String, List<RevCommit>> entry : entrySet) {
String changeType = entry.getKey();
System.out.printf("%n%n%s%n", changeType);
printChangelog(entry.getValue());
}
}
/**
* 添加变更记录
*
* @param commit 提交记录
* @param commitListMap 提交记录列表
*/
private static void logChangeCommit(RevCommit commit, Map<String, List<RevCommit>> commitListMap) {
String shortMessage = commit.getShortMessage();
// 忽略合并
if (shortMessage.startsWith("Merge ")) {
return;
}
// e.g. feat(core): ServletUtils 新增 isMultipart、isForm、isStream 方法
String changeType = getChangeType(shortMessage);
String changeTypeName = getChangeTypeName(changeType);
List<RevCommit> commitList = commitListMap.get(changeTypeName);
if (null == commitList) {
commitList = new ArrayList<>();
}
// 正序添加
commitList.add(0, commit);
commitListMap.put(changeTypeName, commitList);
}
/**
* 转换为 CHANGELOG Markdown
*
* @param commitList 提交记录列表
*/
private static void printChangelog(List<RevCommit> commitList) {
for (RevCommit commit : commitList) {
String shortMessage = commit.getShortMessage();
String commitId = commit.getId().getName();
String moduleName = getModuleName(shortMessage);
List<String> changelogTemplateVarList = new ArrayList<>(List.of(StrUtil.subAfter(shortMessage, ": ", false), StrUtil.subPre(commitId, 8), PROJECT_NAME, commitId));
String changelogTemplate = "- ";
if (SHOW_MODULE_NAME && StrUtil.isNotBlank(moduleName)) {
changelogTemplate += "【%s】";
changelogTemplateVarList.add(0, moduleName);
}
changelogTemplate += "%s ([%s](https://github.com/continew-org/%s/commit/%s))%n";
System.out.printf(changelogTemplate, changelogTemplateVarList.toArray());
}
}
/**
* 获取变更类型
*
* @param shortMessage {@link RevCommit#getShortMessage()}
* @return 变更类型
*/
private static String getChangeType(String shortMessage) {
return StrUtil.subBefore(StrUtil.subBefore(shortMessage, ":", false), "(", false);
}
/**
* 获取变更类型名称
*
* @param changeType 变更类型
* @return 变更类型名称
*/
private static String getChangeTypeName(String changeType) {
return switch (changeType) {
case "feat" -> "新特性";
case "fix" -> "问题修复";
case "style", "refactor", "perf", "chore" -> "功能优化";
default -> "其他";
};
}
/**
* 获取模块名称
*
* @param shortMessage {@link RevCommit#getShortMessage()}
* @return 模块名称
*/
private static String getModuleName(String shortMessage) {
return StrUtil.subBetween(StrUtil.subBefore(shortMessage, ":", false), "(", ")");
}
}