From 641cf22abbc373026f40963f93aab01073097391 Mon Sep 17 00:00:00 2001 From: AdmiringWorm Date: Thu, 8 Feb 2024 18:08:18 +0100 Subject: [PATCH] (#476) Add validation of input file path handler This updates how arguments are parsed when attempting to create a new release. This disallows explicitly the use of a milestone, and an input file path in the same call. This is done as there was confusion on why specifying a input file path was not using the release notes specified. This should make it clearer to the caller what the issue is. --- .../Commands/CreateCommandTests.cs | 24 +++++++++++++++++++ .../Commands/CreateCommand.cs | 6 +++++ .../Options/CreateSubOptions.cs | 4 ++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/GitReleaseManager.Core.Tests/Commands/CreateCommandTests.cs b/src/GitReleaseManager.Core.Tests/Commands/CreateCommandTests.cs index 6853253c..feca58cd 100644 --- a/src/GitReleaseManager.Core.Tests/Commands/CreateCommandTests.cs +++ b/src/GitReleaseManager.Core.Tests/Commands/CreateCommandTests.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Threading.Tasks; using GitReleaseManager.Core.Commands; @@ -106,5 +107,28 @@ public async Task Should_Create_Release_From_InputFile() _logger.Received(1).Information(Arg.Any(), _release.HtmlUrl); _logger.Received(1).Verbose(Arg.Any(), _release.Body); } + + [Test] + public async Task Throws_Exception_When_Both_Milestone_And_Input_File_Specified() + { + var options = new CreateSubOptions + { + RepositoryName = "repository", + RepositoryOwner = "owner", + InputFilePath = "file.path", + TargetCommitish = "target commitish", + AssetPaths = new List(), + Prerelease = false, + Milestone = "0.5.0", + }; + + Func action = async () => await _command.ExecuteAsync(options).ConfigureAwait(false); + + var ex = await action.ShouldThrowAsync().ConfigureAwait(false); + ex.Message.ShouldBe("Both a milestone and an input file path have been specified. Only one of these arguments may be used at the same time when creating a release!"); + + _vcsService.ReceivedCalls().ShouldBeEmpty(); + _logger.ReceivedCalls().ShouldHaveSingleItem(); + } } } \ No newline at end of file diff --git a/src/GitReleaseManager.Core/Commands/CreateCommand.cs b/src/GitReleaseManager.Core/Commands/CreateCommand.cs index cd9a9bd7..ce37b9d4 100644 --- a/src/GitReleaseManager.Core/Commands/CreateCommand.cs +++ b/src/GitReleaseManager.Core/Commands/CreateCommand.cs @@ -1,3 +1,4 @@ +using System; using System.Threading.Tasks; using GitReleaseManager.Core.Model; using GitReleaseManager.Core.Options; @@ -29,6 +30,11 @@ public async Task ExecuteAsync(CreateSubOptions options) } else if (!string.IsNullOrEmpty(options.Milestone)) { + if (!string.IsNullOrWhiteSpace(options.InputFilePath)) + { + throw new InvalidOperationException("Both a milestone and an input file path have been specified. Only one of these arguments may be used at the same time when creating a release!"); + } + _logger.Verbose("Milestone {Milestone} was specified", options.Milestone); var releaseName = options.Name; diff --git a/src/GitReleaseManager.Core/Options/CreateSubOptions.cs b/src/GitReleaseManager.Core/Options/CreateSubOptions.cs index 2f4a9004..34d0d7c5 100644 --- a/src/GitReleaseManager.Core/Options/CreateSubOptions.cs +++ b/src/GitReleaseManager.Core/Options/CreateSubOptions.cs @@ -12,13 +12,13 @@ public class CreateSubOptions : BaseVcsOptions [Option('c', "targetcommitish", HelpText = "The commit to tag. Can be a branch or SHA. Defaults to repository's default branch.", Required = false)] public string TargetCommitish { get; set; } - [Option('m', "milestone", HelpText = "The milestone to use.", Required = false)] + [Option('m', "milestone", HelpText = "The milestone to use. (Can't be used together with a release notes file path).", Required = false)] public string Milestone { get; set; } [Option('n', "name", HelpText = "The name of the release (Typically this is the generated SemVer Version Number).", Required = false)] public string Name { get; set; } - [Option('i', "inputFilePath", HelpText = "The path to the file to be used as the content of the release notes.", Required = false)] + [Option('i', "inputFilePath", HelpText = "The path to the file to be used as the content of the release notes. (Can't be used together with a milestone)", Required = false)] public string InputFilePath { get; set; } [Option('t', "template", HelpText = "The name of the template file to use. Can also be a relative or absolute path (relative paths are resolved from yaml template-dir configuration). Defaults to 'default'")]