|
23 | 23 |
|
24 | 24 | namespace Elastic.Changelog.Bundling; |
25 | 25 |
|
26 | | -/// <summary> |
27 | | -/// Helper for performing placeholder substitution in bundle descriptions |
28 | | -/// </summary> |
29 | | -internal static class BundleDescriptionSubstitution |
30 | | -{ |
31 | | - /// <summary> |
32 | | - /// Substitutes placeholders in a description string with provided values |
33 | | - /// </summary> |
34 | | - public static string SubstitutePlaceholders(string description, string? version, string? lifecycle, string? owner, string? repo) => |
35 | | - SubstitutePlaceholders(description, version, lifecycle, owner, repo, validateResolvable: false); |
36 | | - |
37 | | - /// <summary> |
38 | | - /// Substitutes placeholders in a description string with provided values |
39 | | - /// </summary> |
40 | | - /// <param name="description">The description string containing placeholders</param> |
41 | | - /// <param name="version">Version value for {version} placeholder</param> |
42 | | - /// <param name="lifecycle">Lifecycle value for {lifecycle} placeholder</param> |
43 | | - /// <param name="owner">Owner value for {owner} placeholder</param> |
44 | | - /// <param name="repo">Repository value for {repo} placeholder</param> |
45 | | - /// <param name="validateResolvable">If true, validates that all used placeholders can be resolved</param> |
46 | | - /// <returns>Description with placeholders substituted</returns> |
47 | | - /// <exception cref="InvalidOperationException">When validateResolvable is true and placeholders cannot be resolved</exception> |
48 | | - public static string SubstitutePlaceholders(string description, string? version, string? lifecycle, string? owner, string? repo, bool validateResolvable) |
49 | | - { |
50 | | - if (string.IsNullOrEmpty(description)) |
51 | | - return description; |
52 | | - |
53 | | - if (validateResolvable) |
54 | | - { |
55 | | - var missingValues = new List<string>(); |
56 | | - if (description.Contains("{version}") && string.IsNullOrEmpty(version)) |
57 | | - missingValues.Add("version"); |
58 | | - if (description.Contains("{lifecycle}") && string.IsNullOrEmpty(lifecycle)) |
59 | | - missingValues.Add("lifecycle"); |
60 | | - if (description.Contains("{owner}") && string.IsNullOrEmpty(owner)) |
61 | | - missingValues.Add("owner"); |
62 | | - if (description.Contains("{repo}") && string.IsNullOrEmpty(repo)) |
63 | | - missingValues.Add("repo"); |
64 | | - |
65 | | - if (missingValues.Count > 0) |
66 | | - throw new InvalidOperationException($"Cannot resolve placeholders: {string.Join(", ", missingValues)}"); |
67 | | - } |
68 | | - |
69 | | - return description |
70 | | - .Replace("{version}", version ?? string.Empty) |
71 | | - .Replace("{lifecycle}", lifecycle ?? string.Empty) |
72 | | - .Replace("{owner}", owner ?? string.Empty) |
73 | | - .Replace("{repo}", repo ?? string.Empty); |
74 | | - } |
75 | | -} |
76 | | - |
77 | 26 | /// <summary> |
78 | 27 | /// Arguments for the BundleChangelogs method |
79 | 28 | /// </summary> |
@@ -385,18 +334,24 @@ public async Task<bool> BundleChangelogs(IDiagnosticsCollector collector, Bundle |
385 | 334 | // Apply description with placeholder substitution |
386 | 335 | if (!string.IsNullOrEmpty(input.Description)) |
387 | 336 | { |
388 | | - // Get version/lifecycle from the first output product or first product in the bundle |
389 | 337 | var version = (input.OutputProducts?.Count > 0 ? input.OutputProducts[0].Target : null) |
390 | 338 | ?? (bundleData.Products.Count > 0 ? bundleData.Products[0].Target : null); |
391 | 339 | var lifecycle = (input.OutputProducts?.Count > 0 ? input.OutputProducts[0].Lifecycle : null) |
392 | 340 | ?? (bundleData.Products.Count > 0 ? bundleData.Products[0].Lifecycle?.ToStringFast(true) : null); |
393 | 341 | var owner = input.Owner ?? "elastic"; |
394 | 342 | var repo = input.Repo ?? (bundleData.Products.Count > 0 ? bundleData.Products[0].ProductId : null) ?? "unknown"; |
395 | 343 |
|
396 | | - var substitutedDescription = BundleDescriptionSubstitution.SubstitutePlaceholders( |
397 | | - input.Description, version, lifecycle, owner, repo); |
398 | | - |
399 | | - bundleData = bundleData with { Description = substitutedDescription }; |
| 344 | + try |
| 345 | + { |
| 346 | + var substitutedDescription = BundleDescriptionSubstitution.SubstitutePlaceholders( |
| 347 | + input.Description, version, lifecycle, owner, repo, validateResolvable: true); |
| 348 | + bundleData = bundleData with { Description = substitutedDescription }; |
| 349 | + } |
| 350 | + catch (InvalidOperationException ex) |
| 351 | + { |
| 352 | + collector.EmitError(string.Empty, $"Description placeholder substitution failed: {ex.Message}"); |
| 353 | + return false; |
| 354 | + } |
400 | 355 | } |
401 | 356 |
|
402 | 357 | // Write bundle file |
@@ -674,7 +629,6 @@ private bool ValidateInput(IDiagnosticsCollector collector, BundleChangelogsArgu |
674 | 629 |
|
675 | 630 | private static bool ValidatePlaceholderUsage(IDiagnosticsCollector collector, BundleChangelogsArguments input) |
676 | 631 | { |
677 | | - // Only validate in option-based mode (profile mode has separate validation) |
678 | 632 | if (!string.IsNullOrEmpty(input.Profile)) |
679 | 633 | return true; |
680 | 634 |
|
|
0 commit comments