diff --git a/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs b/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
index c72ca461c..73cb06ffa 100644
--- a/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
+++ b/src/services/Elastic.Changelog/Bundling/ChangelogBundlingService.cs
@@ -24,7 +24,10 @@ namespace Elastic.Changelog.Bundling;
///
public record BundleChangelogsArguments
{
- public required string Directory { get; init; }
+ ///
+ /// Directory containing changelog YAML files. null = use config default.
+ ///
+ public string? Directory { get; init; }
public string? Output { get; init; }
public bool All { get; init; }
public IReadOnlyList? InputProducts { get; init; }
@@ -137,16 +140,19 @@ public async Task BundleChangelogs(IDiagnosticsCollector collector, Bundle
issuesToMatch = issueFilterResult.IssuesToMatch;
}
+ // Directory is resolved by ApplyConfigDefaults (never null at this point)
+ var directory = input.Directory!;
+
// Determine output path
- var outputPath = input.Output ?? _fileSystem.Path.Combine(input.Directory, "changelog-bundle.yaml");
+ var outputPath = input.Output ?? _fileSystem.Path.Combine(directory, "changelog-bundle.yaml");
// Discover changelog files
var fileDiscovery = new ChangelogFileDiscovery(_fileSystem, _logger);
- var yamlFiles = await fileDiscovery.DiscoverChangelogFilesAsync(input.Directory, outputPath, ctx);
+ var yamlFiles = await fileDiscovery.DiscoverChangelogFilesAsync(directory, outputPath, ctx);
if (yamlFiles.Count == 0)
{
- collector.EmitError(input.Directory, "No YAML files found in directory");
+ collector.EmitError(directory, "No YAML files found in directory");
return false;
}
@@ -269,7 +275,7 @@ public async Task BundleChangelogs(IDiagnosticsCollector collector, Bundle
string? outputPath = null;
if (!string.IsNullOrWhiteSpace(outputPattern))
{
- var outputDir = config.Bundle.OutputDirectory ?? input.OutputDirectory ?? input.Directory;
+ var outputDir = config.Bundle.OutputDirectory ?? input.OutputDirectory ?? input.Directory ?? _fileSystem.Directory.GetCurrentDirectory();
outputPath = _fileSystem.Path.Combine(outputDir, outputPattern);
}
@@ -324,16 +330,11 @@ private static List ParseProfileProducts(string pattern)
private static BundleChangelogsArguments ApplyConfigDefaults(BundleChangelogsArguments input, ChangelogConfiguration? config)
{
- if (config?.Bundle == null)
- return input;
+ // Apply directory: CLI takes precedence. Only use config when --directory not specified.
+ var directory = input.Directory ?? config?.Bundle?.Directory ?? Directory.GetCurrentDirectory();
- // Apply directory default if not specified
- var directory = input.Directory;
- if ((string.IsNullOrWhiteSpace(directory) || directory == Directory.GetCurrentDirectory())
- && !string.IsNullOrWhiteSpace(config.Bundle.Directory))
- {
- directory = config.Bundle.Directory;
- }
+ if (config?.Bundle == null)
+ return input with { Directory = directory };
// Apply output default when --output not specified: use bundle.output_directory if set
var output = input.Output;
diff --git a/src/tooling/docs-builder/Commands/ChangelogCommand.cs b/src/tooling/docs-builder/Commands/ChangelogCommand.cs
index 7329b9651..4c961ca77 100644
--- a/src/tooling/docs-builder/Commands/ChangelogCommand.cs
+++ b/src/tooling/docs-builder/Commands/ChangelogCommand.cs
@@ -627,7 +627,7 @@ public async Task Bundle(
var input = new BundleChangelogsArguments
{
- Directory = directory ?? Directory.GetCurrentDirectory(),
+ Directory = directory,
Output = processedOutput,
All = all,
InputProducts = inputProducts,
diff --git a/tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs b/tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs
index 701091d6f..6fa23d772 100644
--- a/tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs
+++ b/tests/Elastic.Changelog.Tests/Changelogs/BundleChangelogsTests.cs
@@ -2079,11 +2079,10 @@ public async Task BundleChangelogs_WithConfigOutputDirectory_WhenOutputNotSpecif
}
[Fact]
- public async Task BundleChangelogs_WithConfigDirectory_WhenDirectoryIsCurrentDirectory_UsesConfigDirectory()
+ public async Task BundleChangelogs_WithConfigDirectory_WhenDirectoryNotSpecified_UsesConfigDirectory()
{
- // Arrange - When --directory is not specified (current directory), use bundle.directory from config if set
+ // Arrange - When --directory is not specified (null), use bundle.directory from config if set
- var currentDir = Directory.GetCurrentDirectory();
var outputDir = FileSystem.Path.Combine(FileSystem.Path.GetTempPath(), Guid.NewGuid().ToString());
FileSystem.Directory.CreateDirectory(outputDir);
@@ -2116,13 +2115,13 @@ public async Task BundleChangelogs_WithConfigDirectory_WhenDirectoryIsCurrentDir
var input = new BundleChangelogsArguments
{
- Directory = currentDir,
+ Directory = null,
Config = configPath,
Output = null,
All = true
};
- // Act - Directory equals GetCurrentDirectory(), so ApplyConfigDefaults should use config.Bundle.Directory
+ // Act - Directory not specified, so ApplyConfigDefaults uses config.Bundle.Directory
var result = await ServiceWithConfig.BundleChangelogs(Collector, input, TestContext.Current.CancellationToken);
// Assert
@@ -2137,6 +2136,64 @@ public async Task BundleChangelogs_WithConfigDirectory_WhenDirectoryIsCurrentDir
bundleContent.Should().Contain("name: 1755268130-feature.yaml");
}
+ [Fact]
+ public async Task BundleChangelogs_WithExplicitDirectory_OverridesConfigDirectory()
+ {
+ // Arrange - config has directory pointing elsewhere, but CLI passes --directory explicitly.
+ // The explicit CLI value must win (e.g. --directory . when cwd has changelogs).
+
+ var configDir = FileSystem.Path.Combine(FileSystem.Path.GetTempPath(), Guid.NewGuid().ToString());
+ FileSystem.Directory.CreateDirectory(configDir);
+ var outputDir = FileSystem.Path.Combine(FileSystem.Path.GetTempPath(), Guid.NewGuid().ToString());
+ FileSystem.Directory.CreateDirectory(outputDir);
+
+ // language=yaml
+ var configContent =
+ $"""
+ bundle:
+ directory: "{configDir.Replace("\\", "/")}"
+ output_directory: "{outputDir.Replace("\\", "/")}"
+ """;
+
+ var configPath = FileSystem.Path.Combine(FileSystem.Path.GetTempPath(), "config-dir-override", "changelog.yml");
+ FileSystem.Directory.CreateDirectory(FileSystem.Path.GetDirectoryName(configPath)!);
+ await FileSystem.File.WriteAllTextAsync(configPath, configContent, TestContext.Current.CancellationToken);
+
+ // language=yaml
+ var changelog1 =
+ """
+ title: Test feature
+ type: feature
+ products:
+ - product: elasticsearch
+ target: 9.2.0
+ prs:
+ - https://github.com/elastic/elasticsearch/pull/100
+ """;
+
+ var file1 = FileSystem.Path.Combine(_changelogDir, "1755268130-feature.yaml");
+ await FileSystem.File.WriteAllTextAsync(file1, changelog1, TestContext.Current.CancellationToken);
+
+ var input = new BundleChangelogsArguments
+ {
+ Directory = _changelogDir,
+ Config = configPath,
+ Output = FileSystem.Path.Combine(outputDir, "bundle.yaml"),
+ All = true
+ };
+
+ // Act - Explicit Directory overrides config.Bundle.Directory
+ var result = await ServiceWithConfig.BundleChangelogs(Collector, input, TestContext.Current.CancellationToken);
+
+ // Assert - used _changelogDir (CLI), not configDir (config)
+ result.Should().BeTrue($"Expected bundling to succeed. Errors: {string.Join("; ", Collector.Diagnostics.Where(d => d.Severity == Severity.Error).Select(d => d.Message))}");
+ Collector.Errors.Should().Be(0);
+
+ var bundleContent = await FileSystem.File.ReadAllTextAsync(input.Output, TestContext.Current.CancellationToken);
+ bundleContent.Should().Contain("product: elasticsearch");
+ bundleContent.Should().Contain("name: 1755268130-feature.yaml");
+ }
+
[Fact]
public async Task BundleChangelogs_WithProfileHideFeatures_IncludesHideFeaturesInBundle()
{