Skip to content

Commit 03a0283

Browse files
CopilotMalcolmnixon
andcommitted
Implement Version.TryCreate and make Version.Create non-nullable
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
1 parent f01d4d5 commit 03a0283

File tree

7 files changed

+78
-81
lines changed

7 files changed

+78
-81
lines changed

src/DemaConsulting.BuildMark/RepoConnectors/GitHubRepoConnector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ public override async Task<List<Version>> GetTagHistoryAsync()
8484
.ToList();
8585
// Filter out non-version tags
8686
return tagNames
87-
.Select(Version.Create)
87+
.Select(Version.TryCreate)
8888
.Where(t => t != null)
8989
.Cast<Version>()
9090
.ToList();

src/DemaConsulting.BuildMark/RepoConnectors/MockRepoConnector.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public Task<List<Version>> GetTagHistoryAsync()
6969
{
7070
// Use dictionary keys to avoid duplication, filter out non-version tags
7171
var tagInfoList = _tagHashes.Keys
72-
.Select(Version.Create)
72+
.Select(Version.TryCreate)
7373
.Where(t => t != null)
7474
.Cast<Version>()
7575
.ToList();

src/DemaConsulting.BuildMark/Version.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@ public partial record Version(string Tag, string FullVersion, string SemanticVer
4646
private static partial Regex TagPattern();
4747

4848
/// <summary>
49-
/// Creates a Version from a tag string, or returns null if the tag doesn't match version format.
49+
/// Tries to create a Version from a tag string.
5050
/// </summary>
5151
/// <param name="tag">Tag name to parse.</param>
5252
/// <returns>Version instance if tag matches version format, null otherwise.</returns>
53-
public static Version? Create(string tag)
53+
public static Version? TryCreate(string tag)
5454
{
5555
var match = TagPattern().Match(tag);
5656
if (!match.Success)
@@ -83,4 +83,20 @@ public partial record Version(string Tag, string FullVersion, string SemanticVer
8383

8484
return new Version(tag, fullVersion, version, preRelease, metadata, hasPreRelease);
8585
}
86+
87+
/// <summary>
88+
/// Creates a Version from a tag string.
89+
/// </summary>
90+
/// <param name="tag">Tag name to parse.</param>
91+
/// <returns>Version instance.</returns>
92+
/// <exception cref="ArgumentException">Thrown if tag doesn't match version format.</exception>
93+
public static Version Create(string tag)
94+
{
95+
var version = TryCreate(tag);
96+
if (version == null)
97+
{
98+
throw new ArgumentException($"Tag '{tag}' does not match version format", nameof(tag));
99+
}
100+
return version;
101+
}
86102
}

test/DemaConsulting.BuildMark.Tests/BuildInformationTests.cs

Lines changed: 13 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,7 @@ public async Task BuildInformation_CreateAsync_WorksWithExplicitVersion()
6868
var connector = new MockRepoConnector();
6969

7070
// Act
71-
var version = Version.Create("v2.1.0");
72-
Assert.IsNotNull(version);
73-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
71+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("v2.1.0"));
7472

7573
// Assert
7674
Assert.AreEqual("v2.1.0", buildInfo.ToVersion.Tag);
@@ -107,9 +105,7 @@ public async Task BuildInformation_CreateAsync_PreReleaseUsesPreviousTag()
107105
var connector = new MockRepoConnector();
108106

109107
// Act
110-
var version = Version.Create("v2.0.0-beta.1");
111-
Assert.IsNotNull(version);
112-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
108+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("v2.0.0-beta.1"));
113109

114110
// Assert
115111
Assert.AreEqual("v2.0.0-beta.1", buildInfo.ToVersion.Tag);
@@ -126,9 +122,7 @@ public async Task BuildInformation_CreateAsync_ReleaseSkipsPreReleases()
126122
var connector = new MockRepoConnector();
127123

128124
// Act
129-
var version = Version.Create("v2.0.0");
130-
Assert.IsNotNull(version);
131-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
125+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("v2.0.0"));
132126

133127
// Assert
134128
Assert.AreEqual("v2.0.0", buildInfo.ToVersion.Tag);
@@ -145,9 +139,7 @@ public async Task BuildInformation_CreateAsync_CollectsIssuesCorrectly()
145139
var connector = new MockRepoConnector();
146140

147141
// Act
148-
var version = Version.Create("ver-1.1.0");
149-
Assert.IsNotNull(version);
150-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
142+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("ver-1.1.0"));
151143

152144
// Assert
153145
Assert.HasCount(1, buildInfo.ChangeIssues);
@@ -173,9 +165,7 @@ public async Task BuildInformation_CreateAsync_SeparatesBugAndChangeIssues()
173165
var connector = new MockRepoConnector();
174166

175167
// Act
176-
var version = Version.Create("v2.0.0");
177-
Assert.IsNotNull(version);
178-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
168+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("v2.0.0"));
179169

180170
// Assert
181171
Assert.HasCount(2, buildInfo.ChangeIssues);
@@ -194,9 +184,7 @@ public async Task BuildInformation_CreateAsync_HandlesFirstReleaseCorrectly()
194184
var connector = new MockRepoConnector();
195185

196186
// Act
197-
var version = Version.Create("v1.0.0");
198-
Assert.IsNotNull(version);
199-
var buildInfo = await BuildInformation.CreateAsync(connector, version);
187+
var buildInfo = await BuildInformation.CreateAsync(connector, Version.Create("v1.0.0"));
200188

201189
// Assert
202190
Assert.IsNull(buildInfo.FromVersion);
@@ -226,12 +214,7 @@ private class MockRepoConnectorMismatch : IRepoConnector
226214
{
227215
public Task<List<Version>> GetTagHistoryAsync()
228216
{
229-
var version = Version.Create("v1.0.0");
230-
if (version == null)
231-
{
232-
throw new InvalidOperationException("Failed to create version");
233-
}
234-
return Task.FromResult(new List<Version> { version });
217+
return Task.FromResult(new List<Version> { Version.Create("v1.0.0") });
235218
}
236219
public Task<List<string>> GetPullRequestsBetweenTagsAsync(Version? from, Version? to) => Task.FromResult(new List<string>());
237220
public Task<List<string>> GetIssuesForPullRequestAsync(string pullRequestId) => Task.FromResult(new List<string>());
@@ -249,14 +232,12 @@ private class MockRepoConnectorMatchingTag : IRepoConnector
249232
{
250233
public Task<List<Version>> GetTagHistoryAsync()
251234
{
252-
var v1 = Version.Create("v1.0.0");
253-
var v2 = Version.Create("ver-1.1.0");
254-
var v3 = Version.Create("v2.0.0");
255-
if (v1 == null || v2 == null || v3 == null)
256-
{
257-
throw new InvalidOperationException("Failed to create version");
258-
}
259-
return Task.FromResult(new List<Version> { v1, v2, v3 });
235+
return Task.FromResult(new List<Version>
236+
{
237+
Version.Create("v1.0.0"),
238+
Version.Create("ver-1.1.0"),
239+
Version.Create("v2.0.0")
240+
});
260241
}
261242
public Task<List<string>> GetPullRequestsBetweenTagsAsync(Version? from, Version? to) => Task.FromResult(new List<string>());
262243
public Task<List<string>> GetIssuesForPullRequestAsync(string pullRequestId) => Task.FromResult(new List<string>());

test/DemaConsulting.BuildMark.Tests/GitHubRepoConnectorTests.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,9 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_ReturnsExp
113113
"abc123 Merge pull request #10 from feature/x\ndef456 Merge pull request #11 from bugfix/y");
114114

115115
// Act
116-
var v1 = Version.Create("v1.0.0");
117-
var v2 = Version.Create("v2.0.0");
118-
Assert.IsNotNull(v1);
119-
Assert.IsNotNull(v2);
120-
var prs = await connector.GetPullRequestsBetweenTagsAsync(v1, v2);
116+
var prs = await connector.GetPullRequestsBetweenTagsAsync(
117+
Version.Create("v1.0.0"),
118+
Version.Create("v2.0.0"));
121119

122120
// Assert
123121
Assert.HasCount(2, prs);
@@ -139,9 +137,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesNul
139137
"abc123 Merge pull request #10 from feature/x");
140138

141139
// Act
142-
var version = Version.Create("v1.0.0");
143-
Assert.IsNotNull(version);
144-
var prs = await connector.GetPullRequestsBetweenTagsAsync(null, version);
140+
var prs = await connector.GetPullRequestsBetweenTagsAsync(null, Version.Create("v1.0.0"));
145141

146142
// Assert
147143
Assert.HasCount(1, prs);
@@ -162,9 +158,7 @@ public async Task GitHubRepoConnector_GetPullRequestsBetweenTagsAsync_HandlesNul
162158
"abc123 Merge pull request #11 from feature/y");
163159

164160
// Act
165-
var version = Version.Create("v1.0.0");
166-
Assert.IsNotNull(version);
167-
var prs = await connector.GetPullRequestsBetweenTagsAsync(version, null);
161+
var prs = await connector.GetPullRequestsBetweenTagsAsync(Version.Create("v1.0.0"), null);
168162

169163
// Assert
170164
Assert.HasCount(1, prs);
@@ -313,9 +307,7 @@ public async Task GitHubRepoConnector_GetHashForTagAsync_ReturnsExpectedHash()
313307
connector.AddCommandResult("git", "rev-parse v1.0.0", "abc123def456789");
314308

315309
// Act
316-
var version = Version.Create("v1.0.0");
317-
Assert.IsNotNull(version);
318-
var hash = await connector.GetHashForTagAsync(version.Tag);
310+
var hash = await connector.GetHashForTagAsync(Version.Create("v1.0.0").Tag);
319311

320312
// Assert
321313
Assert.AreEqual("abc123def456789", hash);

test/DemaConsulting.BuildMark.Tests/MockRepoConnectorTests.cs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,9 @@ public async Task MockRepoConnector_GetPullRequestsBetweenTagsAsync_ReturnsExpec
5757
var connector = new MockRepoConnector();
5858

5959
// Act
60-
var v1 = Version.Create("v1.0.0");
61-
var v2 = Version.Create("ver-1.1.0");
62-
Assert.IsNotNull(v1);
63-
Assert.IsNotNull(v2);
64-
var prs = await connector.GetPullRequestsBetweenTagsAsync(v1, v2);
60+
var prs = await connector.GetPullRequestsBetweenTagsAsync(
61+
Version.Create("v1.0.0"),
62+
Version.Create("ver-1.1.0"));
6563

6664
// Assert
6765
Assert.HasCount(1, prs);
@@ -78,11 +76,9 @@ public async Task MockRepoConnector_GetPullRequestsBetweenTagsAsync_ReturnsExpec
7876
var connector = new MockRepoConnector();
7977

8078
// Act
81-
var v1 = Version.Create("ver-1.1.0");
82-
var v2 = Version.Create("2.0.0");
83-
Assert.IsNotNull(v1);
84-
Assert.IsNotNull(v2);
85-
var prs = await connector.GetPullRequestsBetweenTagsAsync(v1, v2);
79+
var prs = await connector.GetPullRequestsBetweenTagsAsync(
80+
Version.Create("ver-1.1.0"),
81+
Version.Create("2.0.0"));
8682

8783
// Assert
8884
Assert.HasCount(2, prs);
@@ -213,9 +209,7 @@ public async Task MockRepoConnector_GetHashForTagAsync_ReturnsExpectedHash()
213209
var connector = new MockRepoConnector();
214210

215211
// Act
216-
var version = Version.Create("v1.0.0");
217-
Assert.IsNotNull(version);
218-
var hash = await connector.GetHashForTagAsync(version.Tag);
212+
var hash = await connector.GetHashForTagAsync(Version.Create("v1.0.0").Tag);
219213

220214
// Assert
221215
Assert.AreEqual("abc123def456", hash);
@@ -247,9 +241,7 @@ public async Task MockRepoConnector_GetHashForTagAsync_ReturnsUnknownHashForUnkn
247241
var connector = new MockRepoConnector();
248242

249243
// Act
250-
var version = Version.Create("v999.0.0");
251-
Assert.IsNotNull(version);
252-
var hash = await connector.GetHashForTagAsync(version.Tag);
244+
var hash = await connector.GetHashForTagAsync(Version.Create("v999.0.0").Tag);
253245

254246
// Assert
255247
Assert.AreEqual("unknown000hash000", hash);

0 commit comments

Comments
 (0)