feat: add ability to create pre-release tags (#17)
All checks were successful
CD / Release (push) Successful in 40s

Reviewed-on: #17
Co-authored-by: Timo Behrendt <t.behrendt@t00n.de>
Co-committed-by: Timo Behrendt <t.behrendt@t00n.de>
This commit was merged in pull request #17.
This commit is contained in:
2025-09-30 17:29:47 +02:00
committed by t.behrendt
parent 5b2f1fe9d4
commit 0e6aab82a5
6 changed files with 231 additions and 50 deletions

View File

@@ -149,6 +149,16 @@ describe("TagService", () => {
const result = tagService.renderTag(tag, "v");
expect(result).toBe("v1.2.3");
});
it("should render tag with prerelease suffix", () => {
const result = tagService.renderTag(tag, "", "-rc-abc123");
expect(result).toBe("1.2.3-rc-abc123");
});
it("should render tag with prefix and prerelease suffix", () => {
const result = tagService.renderTag(tag, "v", "-rc-abc123");
expect(result).toBe("v1.2.3-rc-abc123");
});
});
describe("parseTag", () => {
@@ -221,7 +231,7 @@ describe("TagIncrementer", () => {
const result = await tagIncrementer.getBaseTag(undefined);
expect(result).toBe("v2.0.0");
expect(mockCoreService.getLogs()).toContain("INFO: Using latest tag: v2.0.0");
expect(mockCoreService.getLogs()).toContain("INFO: Using latest real tag: v2.0.0");
});
it("should default to 0.0.0 when no tags found", async () => {
@@ -234,6 +244,34 @@ describe("TagIncrementer", () => {
"WARNING: No tags found in repository, defaulting to 0.0.0"
);
});
it("should skip pre-release tags and use latest real tag", async () => {
mockGitService.setMockTags([
{ name: "v2.0.0-rc-26035c6e13" },
{ name: "v1.2.3" },
{ name: "v1.1.4-rc-aa512edb16" },
{ name: "v1.0.0" },
]);
const result = await tagIncrementer.getBaseTag(undefined);
expect(result).toBe("v1.2.3");
expect(mockCoreService.getLogs()).toContain("INFO: Using latest real tag: v1.2.3");
});
it("should default to 0.0.0 when only pre-release tags found", async () => {
mockGitService.setMockTags([
{ name: "v2.0.0-rc-26035c6e13" },
{ name: "v1.1.4-rc-aa512edb16" },
]);
const result = await tagIncrementer.getBaseTag(undefined);
expect(result).toBe("0.0.0");
expect(mockCoreService.getWarnings()).toContain(
"WARNING: No real tags found (only pre-release tags), defaulting to 0.0.0"
);
});
});
describe("determineIncrementType", () => {
@@ -302,6 +340,28 @@ describe("TagIncrementer", () => {
expect(result).toBe("2.1.1");
});
it("should create prerelease tag when prerelease is true", async () => {
mockGitService.setMockTags([{ name: "v1.2.3" }]);
mockGitService.setMockCommit({
commit: { message: "feat: new feature" },
});
const result = await tagIncrementer.incrementTag(undefined, "ref", 50, true, "abc123");
expect(result).toBe("1.3.0-rc-abc123");
});
it("should not create prerelease tag when prerelease is false", async () => {
mockGitService.setMockTags([{ name: "v1.2.3" }]);
mockGitService.setMockCommit({
commit: { message: "feat: new feature" },
});
const result = await tagIncrementer.incrementTag(undefined, "ref", 50, false, "abc123");
expect(result).toBe("1.3.0");
});
});
});
@@ -315,14 +375,18 @@ describe("LocalGitService", () => {
describe("listTags", () => {
it("should call git command to list tags", async () => {
mockExecSync.mockReturnValue("v1.0.0\nv1.1.0\n" as any);
mockExecSync.mockReturnValue("v1.0.0\n1.1.0\n2.0.0-rc-26035c6e13\n" as any);
const result = await localGitService.listTags(5);
expect(mockExecSync).toHaveBeenCalledWith("git tag --sort=-version:refname", {
encoding: "utf8",
});
expect(result).toEqual([{ name: "v1.0.0" }, { name: "v1.1.0" }]);
expect(result).toEqual([
{ name: "v1.0.0" },
{ name: "1.1.0" },
{ name: "2.0.0-rc-26035c6e13" },
]);
});
it("should return empty array when no tags exist", async () => {
@@ -391,9 +455,12 @@ describe("LocalCoreService", () => {
// Integration test example
describe("TagIncrementer Integration", () => {
it("should handle complete tag increment flow", async () => {
const mockGitService = new MockGitService([{ name: "v1.2.3" }], {
commit: { message: "feat: new feature" },
});
const mockGitService = new MockGitService(
[{ name: "v2.0.0-rc-26035c6e13" }, { name: "v1.1.4-rc-aa512edb16" }, { name: "v1.2.3" }],
{
commit: { message: "feat: new feature" },
}
);
const mockCoreService = new MockCoreService();
const commitAnalyzer = new ConventionalCommitAnalyzer();
const tagService = new TagService();
@@ -410,5 +477,23 @@ describe("TagIncrementer Integration", () => {
expect(result).toBe("1.3.0");
expect(mockCoreService.getLogs()).toContain("INFO: Determined increment type: minor");
expect(mockCoreService.getLogs()).toContain("INFO: New tag: 1.3.0");
expect(mockCoreService.getLogs()).toContain("INFO: Using latest real tag: v1.2.3");
});
});
describe("Prerelease Validation", () => {
it("should validate prerelease configuration correctly", () => {
// Test cases for prerelease validation logic
const testCases = [
{ prerelease: true, githubSha: "abc123", shouldFail: false },
{ prerelease: true, githubSha: "", shouldFail: true },
{ prerelease: false, githubSha: "abc123", shouldFail: false },
{ prerelease: false, githubSha: "", shouldFail: false },
];
testCases.forEach(({ prerelease, githubSha, shouldFail }) => {
const result = prerelease && !githubSha;
expect(result).toBe(shouldFail);
});
});
});