From 8ecd61e003e736448fe6847a1b116f17fb505d60 Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Tue, 27 Aug 2024 00:39:53 +0200 Subject: [PATCH 1/8] Refactor and extend dependency update logic Refactored how dependencies are processed, leveraging the new `DependencyDetails` structure. Added support to manage version update types (Major, Minor, Patch) by introducing `VersionUpdateType` enum and enhancing the project configuration. Made robust error handling for missing configurations and streamlined the parsing logic for the project files. --- DependencyUpdated.Core/Config/Project.cs | 14 +-- DependencyUpdated.Core/Version.cs | 8 ++ .../DotNetUpdater.cs | 111 +++++++++++------- DependencyUpdated/config.json | 1 + 4 files changed, 83 insertions(+), 51 deletions(-) create mode 100644 DependencyUpdated.Core/Version.cs diff --git a/DependencyUpdated.Core/Config/Project.cs b/DependencyUpdated.Core/Config/Project.cs index 20d7b95..be31cb3 100644 --- a/DependencyUpdated.Core/Config/Project.cs +++ b/DependencyUpdated.Core/Config/Project.cs @@ -4,21 +4,17 @@ namespace DependencyUpdated.Core.Config; public sealed class Project : IValidatableObject { - private string[] _groups = ["*"]; - public ProjectType Type { get; set; } + + public VersionUpdateType Version { get; set; } public string Name { get; set; } = default!; - - public string[] DependencyConfigurations { get; set; } = ArraySegment.Empty.ToArray(); + + public string[] DependencyConfigurations { get; set; } = ["https://api.nuget.org/v3/index.json"]; public string[] Directories { get; set; } = ArraySegment.Empty.ToArray(); - public string[] Groups - { - get => _groups; - set => _groups = value; - } + public string[] Groups { get; set; } = ["*"]; public IEnumerable Validate(ValidationContext validationContext) { diff --git a/DependencyUpdated.Core/Version.cs b/DependencyUpdated.Core/Version.cs new file mode 100644 index 0000000..3c15c2a --- /dev/null +++ b/DependencyUpdated.Core/Version.cs @@ -0,0 +1,8 @@ +namespace DependencyUpdated.Core; + +public enum VersionUpdateType +{ + Major = 1, + Minor = 2, + Patch = 3, +} \ No newline at end of file diff --git a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs index cddf4a9..c82a6dd 100644 --- a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs +++ b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs @@ -39,19 +39,16 @@ public async Task> ExtractAllPackagesThatNeedToBe var returnList = new List(); foreach (var nuget in nugets) { - logger.Verbose("Processing {PackageName}:{PackageVersion}", nuget.Key, nuget.Value); - var latestVersion = await GetLatestVersion(nuget.Key, projectConfiguration); + logger.Verbose("Processing {PackageName}:{PackageVersion}", nuget.Name, nuget.Version); + var latestVersion = await GetLatestVersion(nuget, projectConfiguration); if (latestVersion is null) { - logger.Warning("{PacakgeName} unable to find in sources", nuget.Key); + logger.Warning("{PacakgeName} unable to find in sources", nuget.Name); continue; } - if (latestVersion.Version > nuget.Value.Version) - { - logger.Information("{PacakgeName} new version {Version} available", nuget.Key, latestVersion); - returnList.Add(new DependencyDetails(nuget.Key, latestVersion.Version)); - } + logger.Information("{PacakgeName} new version {Version} available", nuget.Name, latestVersion); + returnList.Add(nuget with { Version = latestVersion.Version }); } return returnList; @@ -108,30 +105,28 @@ private IReadOnlyCollection UpdateCsProj(string fullPath, ICollect return results; } - private async Task GetLatestVersion(string packageId, Project projectConfiguration) + private async Task GetLatestVersion(DependencyDetails package, Project projectConfiguration) { - var existsInCache = memoryCache.TryGetValue(packageId, out var cachedVersion); + var existsInCache = memoryCache.TryGetValue(package.Name, out var cachedVersion); if (existsInCache) { return cachedVersion; } - var packageSources = new List + if (!projectConfiguration.DependencyConfigurations.Any()) { - new("https://api.nuget.org/v3/index.json"), - }; - - if (projectConfiguration.DependencyConfigurations.Any()) + throw new InvalidOperationException( + $"Missing {nameof(projectConfiguration.DependencyConfigurations)} in config."); + } + + var packageSources = new List(); + foreach (var projectConfigurationPath in projectConfiguration.DependencyConfigurations) { - packageSources = new List(); - foreach (var projectConfigurationPath in projectConfiguration.DependencyConfigurations) - { - var setting = Settings.LoadSpecificSettings(Path.GetDirectoryName(projectConfigurationPath)!, - Path.GetFileName(projectConfigurationPath)); - var packageSourceProvider = new PackageSourceProvider(setting); - var sources = packageSourceProvider.LoadPackageSources(); - packageSources.AddRange(sources); - } + var setting = Settings.LoadSpecificSettings(Path.GetDirectoryName(projectConfigurationPath)!, + Path.GetFileName(projectConfigurationPath)); + var packageSourceProvider = new PackageSourceProvider(setting); + var sources = packageSourceProvider.LoadPackageSources(); + packageSources.AddRange(sources); } var providers = Repository.Provider.GetCoreV3(); @@ -140,24 +135,48 @@ private IReadOnlyCollection UpdateCsProj(string fullPath, ICollect var version = default(NuGetVersion?); foreach (var repository in repositories) { - var findPackageByIdResource = await repository.GetResourceAsync(); - var versions = await findPackageByIdResource.GetAllVersionsAsync( - packageId, - new SourceCacheContext(), - NullLogger.Instance, - CancellationToken.None); - var maxVersion = versions.Where(x => !x.IsPrerelease).Max(); - if (version is null || (maxVersion is not null && maxVersion >= version)) - { - version = maxVersion; - } + var findPackageByIdResource = await repository.GetResourceAsync(); + var versions = await findPackageByIdResource.GetAllVersionsAsync( + package.Name, + new SourceCacheContext(), + NullLogger.Instance, + CancellationToken.None); + var maxVersion = GetMaxVersion(versions, package.Version, projectConfiguration); + if (version is null || (maxVersion is not null && maxVersion >= version)) + { + version = maxVersion; + } } - memoryCache.Set(packageId, version); + memoryCache.Set(package.Name, version); return version; } - private static Dictionary ParseCsproj(string path) + private static NuGetVersion? GetMaxVersion(IEnumerable versions, Version currentVersion, Project projectConfiguration) + { + var baseQuery = versions.Where(x => !x.IsPrerelease); + if (projectConfiguration.Version == VersionUpdateType.Major) + { + return baseQuery.Max(); + } + + if (projectConfiguration.Version == VersionUpdateType.Minor) + { + return baseQuery.Where(x => + x.Version.Major == currentVersion.Major && x.Version.Minor > currentVersion.Minor).Max(); + } + + if (projectConfiguration.Version == VersionUpdateType.Patch) + { + return baseQuery.Where(x => + x.Version.Major == currentVersion.Major && x.Version.Minor == currentVersion.Minor && + x.Version.Build > currentVersion.Build).Max(); + } + + throw new NotSupportedException($"Version configuration {projectConfiguration.Version} is not supported"); + } + + private static ICollection ParseCsproj(string path) { var document = XDocument.Load(path); if (document.Root is null) @@ -167,18 +186,26 @@ private static Dictionary ParseCsproj(string path) var packageReferences = document.Root.Elements("ItemGroup") .Elements("PackageReference"); - var nugets = new Dictionary(); + var nugets = new List(); foreach (var packageReference in packageReferences) { var includeAttribute = packageReference.Attribute("Include"); var versionAttribute = packageReference.Attribute("Version"); - if (includeAttribute != null && versionAttribute != null) + if (includeAttribute == null || versionAttribute == null) { - var version = NuGetVersion.Parse(versionAttribute.Value).Version; - nugets[includeAttribute.Value] = - new DependencyDetails(includeAttribute.Value, version); + continue; } + + var name = includeAttribute.Value; + + if (nugets.Any(x => x.Name == name)) + { + continue; + } + + var version = NuGetVersion.Parse(versionAttribute.Value).Version; + nugets.Add(new DependencyDetails(name, version)); } return nugets; diff --git a/DependencyUpdated/config.json b/DependencyUpdated/config.json index 05c6d6a..6659b28 100644 --- a/DependencyUpdated/config.json +++ b/DependencyUpdated/config.json @@ -15,6 +15,7 @@ { "Type": "DotNet", "Name": "DotNetProjects", + "Version": "Major", "DependencyConfigurations": [ ], "Directories": [ From c446401699fa35a74aac2f8556ad8979afb4fa79 Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Tue, 27 Aug 2024 00:53:02 +0200 Subject: [PATCH 2/8] Change ParseCsproj to use HashSet for dependency details Updated the ParseCsproj method to return a HashSet instead of a List, ensuring unique entries for dependency details. This change eliminates previously required code to check for duplicates, streamlining the logic and enhancing performance. --- DependencyUpdated.Projects.DotNet/DotNetUpdater.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs index c82a6dd..1c5ea56 100644 --- a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs +++ b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs @@ -176,7 +176,7 @@ private IReadOnlyCollection UpdateCsProj(string fullPath, ICollect throw new NotSupportedException($"Version configuration {projectConfiguration.Version} is not supported"); } - private static ICollection ParseCsproj(string path) + private static HashSet ParseCsproj(string path) { var document = XDocument.Load(path); if (document.Root is null) @@ -186,7 +186,7 @@ private static ICollection ParseCsproj(string path) var packageReferences = document.Root.Elements("ItemGroup") .Elements("PackageReference"); - var nugets = new List(); + var nugets = new HashSet(); foreach (var packageReference in packageReferences) { var includeAttribute = packageReference.Attribute("Include"); @@ -198,12 +198,6 @@ private static ICollection ParseCsproj(string path) } var name = includeAttribute.Value; - - if (nugets.Any(x => x.Name == name)) - { - continue; - } - var version = NuGetVersion.Parse(versionAttribute.Value).Version; nugets.Add(new DependencyDetails(name, version)); } From 18d6b13507733adc77b9d15973fafd8e63c1c4f6 Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:18:33 +0200 Subject: [PATCH 3/8] Add unit tests and update project structure Introduced unit tests for `DotNetUpdater` and reorganized project files, including new directories and `directory.build.props` files for better project management. Also refactored some methods and updated `csproj` files to enable documentation generation. --- .editorconfig | 247 ++++++++++++++++++ .../Config/AzureDevOpsConfig.cs | 18 +- .../DependencyUpdated.Core.csproj | 1 + DependencyUpdated.Core/IProjectUpdater.cs | 14 +- .../{Version.cs => VersionUpdateType.cs} | 0 .../DependencyUpdated.Projects.DotNet.csproj | 1 + .../DotNetUpdater.cs | 152 ++++++----- .../AzureDevOps.cs | 62 ++--- ...ncyUpdated.Repositories.AzureDevOps.csproj | 1 + DependencyUpdated.sln | 16 +- DependencyUpdated/DependencyUpdated.csproj | 1 + DependencyUpdated/Program.cs | 194 +++++++------- directory.build.props | 34 +++ stylecop.json | 19 ++ ...cyUpdated.Projects.DotNet.UnitTests.csproj | 22 ++ .../DotNetUpdaterTests.cs | 106 ++++++++ .../Projects/SampleProject.csproj | 13 + tests/directory.build.props | 21 ++ 18 files changed, 700 insertions(+), 222 deletions(-) create mode 100644 .editorconfig rename DependencyUpdated.Core/{Version.cs => VersionUpdateType.cs} (100%) create mode 100644 directory.build.props create mode 100644 stylecop.json create mode 100644 tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj create mode 100644 tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs create mode 100644 tests/DependencyUpdated.Projects.DotNet.UnitTests/Projects/SampleProject.csproj create mode 100644 tests/directory.build.props diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..dd0fff9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,247 @@ +# Remove the line below if you want to inherit .editorconfig settings from higher directories +root = true + +# C# files +[*.cs] + +#### Core EditorConfig Options #### + +# Indentation and spacing +indent_size = 4 +indent_style = space +tab_width = 4 + +# New line preferences +end_of_line = crlf +insert_final_newline = false + +#### .NET Coding Conventions #### + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = false +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:warning +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_property = false:warning + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:warning +dotnet_style_predefined_type_for_member_access = true:warning + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning +dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# Expression-level preferences +dotnet_style_coalesce_expression = true:warning +dotnet_style_collection_initializer = true:warning +dotnet_style_explicit_tuple_names = true:warning +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true:warning +dotnet_style_object_initializer = true:warning +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:warning +dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_prefer_conditional_expression_over_assignment = false:warning +dotnet_style_prefer_conditional_expression_over_return = false:warning +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning +dotnet_style_prefer_inferred_tuple_names = true:warning +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +dotnet_style_prefer_simplified_boolean_expressions = true:warning +dotnet_style_prefer_simplified_interpolation = true + +# Field preferences +dotnet_style_readonly_field = true:none + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:warning + +# Suppression preferences +dotnet_remove_unnecessary_suppression_exclusions = none + +# New line preferences +dotnet_style_allow_multiple_blank_lines_experimental = false:warning +dotnet_style_allow_statement_immediately_after_block_experimental = false:warning + +#### C# Coding Conventions #### + +# var preferences +csharp_style_var_elsewhere = true:warning +csharp_style_var_for_built_in_types = true:warning +csharp_style_var_when_type_is_apparent = true:warning + +# Expression-bodied members +csharp_style_expression_bodied_accessors = when_on_single_line:warning +csharp_style_expression_bodied_constructors = false:warning +csharp_style_expression_bodied_indexers = when_on_single_line:warning +csharp_style_expression_bodied_lambdas = when_on_single_line:warning +csharp_style_expression_bodied_local_functions = when_on_single_line:warning +csharp_style_expression_bodied_methods = false:warning +csharp_style_expression_bodied_operators = false:warning +csharp_style_expression_bodied_properties = when_on_single_line:warning + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:warning +csharp_style_pattern_matching_over_is_with_cast_check = true:warning +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true:warning +csharp_style_prefer_pattern_matching = true:warning +csharp_style_prefer_switch_expression = true:warning + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:warning + +# Modifier preferences +csharp_prefer_static_local_function = true:warning +csharp_preferred_modifier_order = public, private, protected, internal, file, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, required, volatile, async +csharp_style_prefer_readonly_struct = true:warning +csharp_style_prefer_readonly_struct_member = true + +# Code-block preferences +csharp_prefer_braces = true:warning +csharp_prefer_simple_using_statement = true:warning +csharp_style_namespace_declarations = file_scoped:warning +csharp_style_prefer_method_group_conversion = true:warning +csharp_style_prefer_top_level_statements = false:warning + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:warning +csharp_style_deconstructed_variable_declaration = false:warning +csharp_style_implicit_object_creation_when_type_is_apparent = true:warning +csharp_style_inlined_variable_declaration = true:warning +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_local_over_anonymous_function = true:warning +csharp_style_prefer_null_check_over_type_check = true:warning +csharp_style_prefer_range_operator = true:warning +csharp_style_prefer_tuple_swap = true:warning +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true:warning +csharp_style_unused_value_assignment_preference = discard_variable:silent +csharp_style_unused_value_expression_statement_preference = discard_variable:warning + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:warning + +# New line preferences +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:warning +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning +csharp_style_allow_embedded_statements_on_same_line_experimental = false:warning + +#### C# Formatting Rules #### + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false + +#### Naming styles #### + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +# Rules +dotnet_diagnostic.SA1101.severity = none +dotnet_diagnostic.SA1309.severity = none +dotnet_diagnostic.SA1413.severity = none +dotnet_diagnostic.SA1633.severity = none +dotnet_diagnostic.CS1591.severity = none +dotnet_diagnostic.S3925.severity = none +dotnet_diagnostic.S4035.severity = none +dotnet_diagnostic.S1133.severity = none +dotnet_diagnostic.SA1028.severity = none +dotnet_diagnostic.SA1124.severity = none +dotnet_diagnostic.SA1117.severity = none +dotnet_diagnostic.SA1116.severity = none + +dotnet_diagnostic.IDE0005.severity = warning +dotnet_diagnostic.IDE0058.severity = none +dotnet_diagnostic.IDE0130.severity = warning \ No newline at end of file diff --git a/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs b/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs index 923da54..7f654c6 100644 --- a/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs +++ b/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs @@ -7,15 +7,15 @@ public class AzureDevOpsConfig : IValidatableObject public string? Username { get; set; } public string? Email { get; set; } - + public string? PAT { get; set; } - + public string? Organization { get; set; } - + public string? Project { get; set; } public string? Repository { get; set; } - + public int? WorkItemId { get; set; } public string TargetBranchName { get; set; } = "dev"; @@ -23,29 +23,29 @@ public class AzureDevOpsConfig : IValidatableObject public string BranchName { get; set; } = "updateDependencies"; public bool AutoComplete { get; set; } = true; - + public IEnumerable Validate(ValidationContext validationContext) { if (string.IsNullOrEmpty(Username)) { yield return new ValidationResult($"{nameof(Username)} must be provided in {nameof(AzureDevOpsConfig)}"); } - + if (string.IsNullOrEmpty(Email)) { yield return new ValidationResult($"{nameof(Email)} must be provided in {nameof(AzureDevOpsConfig)}"); } - + if (string.IsNullOrEmpty(Organization)) { yield return new ValidationResult($"{nameof(Organization)} must be provided in {nameof(AzureDevOpsConfig)}"); } - + if (string.IsNullOrEmpty(Project)) { yield return new ValidationResult($"{nameof(Project)} must be provided in {nameof(AzureDevOpsConfig)}"); } - + if (string.IsNullOrEmpty(Repository)) { yield return new ValidationResult($"{nameof(Repository)} must be provided in {nameof(AzureDevOpsConfig)}"); diff --git a/DependencyUpdated.Core/DependencyUpdated.Core.csproj b/DependencyUpdated.Core/DependencyUpdated.Core.csproj index de6abfc..78862bc 100644 --- a/DependencyUpdated.Core/DependencyUpdated.Core.csproj +++ b/DependencyUpdated.Core/DependencyUpdated.Core.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true diff --git a/DependencyUpdated.Core/IProjectUpdater.cs b/DependencyUpdated.Core/IProjectUpdater.cs index 24b0063..aef8b9a 100644 --- a/DependencyUpdated.Core/IProjectUpdater.cs +++ b/DependencyUpdated.Core/IProjectUpdater.cs @@ -3,10 +3,12 @@ namespace DependencyUpdated.Core; public interface IProjectUpdater -{ - Task> ExtractAllPackagesThatNeedToBeUpdated(string fullPath, Project projectConfiguration); - - IEnumerable GetAllProjectFiles(string searchPath); - - IReadOnlyCollection HandleProjectUpdate(string fullPath, ICollection dependenciesToUpdate); +{ + Task> ExtractAllPackagesThatNeedToBeUpdated(string fullPath, + Project projectConfiguration); + + IReadOnlyCollection GetAllProjectFiles(string searchPath); + + IReadOnlyCollection HandleProjectUpdate(string fullPath, + ICollection dependenciesToUpdate); } \ No newline at end of file diff --git a/DependencyUpdated.Core/Version.cs b/DependencyUpdated.Core/VersionUpdateType.cs similarity index 100% rename from DependencyUpdated.Core/Version.cs rename to DependencyUpdated.Core/VersionUpdateType.cs diff --git a/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj b/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj index 5c39326..7cc2ad5 100644 --- a/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj +++ b/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true diff --git a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs index 1c5ea56..6f3899c 100644 --- a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs +++ b/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs @@ -1,12 +1,12 @@ -using System.Xml; -using System.Xml.Linq; -using DependencyUpdated.Core; +using DependencyUpdated.Core; using DependencyUpdated.Core.Config; using Microsoft.Extensions.Caching.Memory; using NuGet.Common; using NuGet.Configuration; using NuGet.Protocol.Core.Types; using NuGet.Versioning; +using System.Xml; +using System.Xml.Linq; using ILogger = Serilog.ILogger; namespace DependencyUpdated.Projects.DotNet; @@ -19,20 +19,22 @@ internal sealed class DotNetUpdater(ILogger logger, IMemoryCache memoryCache) : "*.nfproj", "directory.build.props" ]; - - public IEnumerable GetAllProjectFiles(string searchPath) + + public IReadOnlyCollection GetAllProjectFiles(string searchPath) { return ValidDotnetPatterns.SelectMany(dotnetPattern => - Directory.GetFiles(searchPath, dotnetPattern, SearchOption.AllDirectories)); + Directory.GetFiles(searchPath, dotnetPattern, SearchOption.AllDirectories)).ToList(); } - public IReadOnlyCollection HandleProjectUpdate(string fullPath, ICollection dependenciesToUpdate) + public IReadOnlyCollection HandleProjectUpdate(string fullPath, + ICollection dependenciesToUpdate) { logger.Information("Processing: {FullPath} project", fullPath); return UpdateCsProj(fullPath, dependenciesToUpdate); } - public async Task> ExtractAllPackagesThatNeedToBeUpdated(string fullPath, Project projectConfiguration) + public async Task> ExtractAllPackagesThatNeedToBeUpdated(string fullPath, + Project projectConfiguration) { var nugets = ParseCsproj(fullPath); @@ -54,55 +56,59 @@ public async Task> ExtractAllPackagesThatNeedToBe return returnList; } - private IReadOnlyCollection UpdateCsProj(string fullPath, ICollection packagesToUpdate) + private static NuGetVersion? GetMaxVersion(IEnumerable versions, Version currentVersion, + Project projectConfiguration) { - var results = new List(); - var document = XDocument.Load(fullPath, LoadOptions.PreserveWhitespace); + var baseQuery = versions.Where(x => !x.IsPrerelease); + if (projectConfiguration.Version == VersionUpdateType.Major) + { + return baseQuery.Max(); + } - var nugetsToUpdate = packagesToUpdate.ToDictionary(x => x.Name, x => x.Version); - + if (projectConfiguration.Version == VersionUpdateType.Minor) + { + return baseQuery.Where(x => + x.Version.Major == currentVersion.Major && x.Version.Minor > currentVersion.Minor).Max(); + } + + if (projectConfiguration.Version == VersionUpdateType.Patch) + { + return baseQuery.Where(x => + x.Version.Major == currentVersion.Major && x.Version.Minor == currentVersion.Minor && + x.Version.Build > currentVersion.Build).Max(); + } + + throw new NotSupportedException($"Version configuration {projectConfiguration.Version} is not supported"); + } + + private static HashSet ParseCsproj(string path) + { + var document = XDocument.Load(path); if (document.Root is null) { throw new InvalidOperationException("Root object is null"); } - + var packageReferences = document.Root.Elements("ItemGroup") .Elements("PackageReference"); + var nugets = new HashSet(); foreach (var packageReference in packageReferences) { var includeAttribute = packageReference.Attribute("Include"); var versionAttribute = packageReference.Attribute("Version"); - if (includeAttribute is null || versionAttribute is null) - { - continue; - } - - var packageName = includeAttribute.Value; - var exists = nugetsToUpdate.TryGetValue(packageName, out var newVersion); - if (!exists || newVersion is null) + + if (includeAttribute == null || versionAttribute == null) { continue; } - - versionAttribute.SetValue(newVersion.ToString()); - results.Add(new UpdateResult(packageName, versionAttribute.Value, newVersion.ToString())); - } - - var settings = new XmlWriterSettings - { - OmitXmlDeclaration = true, - Indent = true, - }; - if (results.Count == 0) - { - return results; + var name = includeAttribute.Value; + var version = NuGetVersion.Parse(versionAttribute.Value).Version; + nugets.Add(new DependencyDetails(name, version)); } - using var xmlWriter = XmlWriter.Create(fullPath, settings); - document.Save(xmlWriter); - return results; + return nugets; } private async Task GetLatestVersion(DependencyDetails package, Project projectConfiguration) @@ -112,25 +118,32 @@ private IReadOnlyCollection UpdateCsProj(string fullPath, ICollect { return cachedVersion; } - + if (!projectConfiguration.DependencyConfigurations.Any()) { throw new InvalidOperationException( $"Missing {nameof(projectConfiguration.DependencyConfigurations)} in config."); } - + var packageSources = new List(); foreach (var projectConfigurationPath in projectConfiguration.DependencyConfigurations) { + if (projectConfigurationPath.StartsWith("http")) + { + packageSources.Add(new PackageSource(projectConfigurationPath)); + continue; + } + var setting = Settings.LoadSpecificSettings(Path.GetDirectoryName(projectConfigurationPath)!, Path.GetFileName(projectConfigurationPath)); var packageSourceProvider = new PackageSourceProvider(setting); var sources = packageSourceProvider.LoadPackageSources(); packageSources.AddRange(sources); } - + var providers = Repository.Provider.GetCoreV3(); - var sourceRepositoryProvider = new SourceRepositoryProvider(new PackageSourceProvider(NullSettings.Instance, packageSources), providers); + var sourceRepositoryProvider = + new SourceRepositoryProvider(new PackageSourceProvider(NullSettings.Instance, packageSources), providers); var repositories = sourceRepositoryProvider.GetRepositories(); var version = default(NuGetVersion?); foreach (var repository in repositories) @@ -152,56 +165,51 @@ private IReadOnlyCollection UpdateCsProj(string fullPath, ICollect return version; } - private static NuGetVersion? GetMaxVersion(IEnumerable versions, Version currentVersion, Project projectConfiguration) + private IReadOnlyCollection UpdateCsProj(string fullPath, + ICollection packagesToUpdate) { - var baseQuery = versions.Where(x => !x.IsPrerelease); - if (projectConfiguration.Version == VersionUpdateType.Major) - { - return baseQuery.Max(); - } - - if (projectConfiguration.Version == VersionUpdateType.Minor) - { - return baseQuery.Where(x => - x.Version.Major == currentVersion.Major && x.Version.Minor > currentVersion.Minor).Max(); - } - - if (projectConfiguration.Version == VersionUpdateType.Patch) - { - return baseQuery.Where(x => - x.Version.Major == currentVersion.Major && x.Version.Minor == currentVersion.Minor && - x.Version.Build > currentVersion.Build).Max(); - } + var results = new List(); + var document = XDocument.Load(fullPath, LoadOptions.PreserveWhitespace); - throw new NotSupportedException($"Version configuration {projectConfiguration.Version} is not supported"); - } + var nugetsToUpdate = packagesToUpdate.ToDictionary(x => x.Name, x => x.Version); - private static HashSet ParseCsproj(string path) - { - var document = XDocument.Load(path); if (document.Root is null) { throw new InvalidOperationException("Root object is null"); } + var packageReferences = document.Root.Elements("ItemGroup") .Elements("PackageReference"); - var nugets = new HashSet(); foreach (var packageReference in packageReferences) { var includeAttribute = packageReference.Attribute("Include"); var versionAttribute = packageReference.Attribute("Version"); + if (includeAttribute is null || versionAttribute is null) + { + continue; + } - if (includeAttribute == null || versionAttribute == null) + var packageName = includeAttribute.Value; + var exists = nugetsToUpdate.TryGetValue(packageName, out var newVersion); + if (!exists || newVersion is null) { continue; } - var name = includeAttribute.Value; - var version = NuGetVersion.Parse(versionAttribute.Value).Version; - nugets.Add(new DependencyDetails(name, version)); + versionAttribute.SetValue(newVersion.ToString()); + results.Add(new UpdateResult(packageName, versionAttribute.Value, newVersion.ToString())); } - return nugets; + var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, }; + + if (results.Count == 0) + { + return results; + } + + using var xmlWriter = XmlWriter.Create(fullPath, settings); + document.Save(xmlWriter); + return results; } } \ No newline at end of file diff --git a/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs b/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs index 59a0f76..a78d66e 100644 --- a/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs +++ b/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs @@ -1,41 +1,37 @@ -using System.Net; -using System.Net.Http.Headers; -using System.Text; -using System.Text.Json; using DependencyUpdated.Core; using DependencyUpdated.Core.Config; using DependencyUpdated.Repositories.AzureDevOps.Dto; using LibGit2Sharp; using Microsoft.Extensions.Options; using Serilog; +using System.Net; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; namespace DependencyUpdated.Repositories.AzureDevOps; -internal sealed class AzureDevOps(TimeProvider timeProvider, IOptions config, ILogger logger) : IRepositoryProvider +internal sealed class AzureDevOps(TimeProvider timeProvider, IOptions config, ILogger logger) + : IRepositoryProvider { private const string GitCommitMessage = "Bump dependencies"; - + public void SwitchToDefaultBranch(string repositoryPath) { var branchName = config.Value.AzureDevOps.TargetBranchName; logger.Information("Switching {Repository} to branch {Branch}", repositoryPath, branchName); - using (var repo = new Repository(repositoryPath)) - { - var branch = repo.Branches[branchName]; - if (branch == null) - { - throw new Exception($"Branch {branchName} doesn't exists"); - } + using var repo = new Repository(repositoryPath); + var branch = repo.Branches[branchName] ?? + throw new Exception($"Branch {branchName} doesn't exists"); - Commands.Checkout(repo, branch); - } + Commands.Checkout(repo, branch); } public void SwitchToUpdateBranch(string repositoryPath, string projectName, string group) { var gitBranchName = CreateGitBranchName(projectName, config.Value.AzureDevOps.BranchName, group); logger.Information("Switching {Repository} to branch {Branch}", repositoryPath, gitBranchName); - using (var repo = new Repository(repositoryPath)) + using (var repo = new Repository(repositoryPath)) { var branch = repo.Branches[gitBranchName]; if (branch == null) @@ -53,7 +49,6 @@ public void SwitchToUpdateBranch(string repositoryPath, string projectName, stri } } - public void CommitChanges(string repositoryPath, string projectName, string group) { var gitBranchName = CreateGitBranchName(projectName, config.Value.AzureDevOps.BranchName, group); @@ -98,29 +93,26 @@ public async Task SubmitPullRequest(IReadOnlyCollection updates, s client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes($":{configValue.PAT}"))); var pr = new PullRequest(sourceBranch, targetBranch, prTitile, prDescription); - + var jsonString = JsonSerializer.Serialize(pr); var content = new StringContent(jsonString, Encoding.UTF8, "application/json"); - + var result = await client.PostAsync(baseUrl, content); result.EnsureSuccessStatusCode(); - + if (result.StatusCode == HttpStatusCode.NonAuthoritativeInformation) { throw new Exception("Invalid PAT token provided"); } - - var response = await result.Content.ReadAsStringAsync(); + + var response = await result.Content.ReadAsStringAsync(); var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, }; - var responseObject = JsonSerializer.Deserialize(response, options); - if (responseObject is null) - { - throw new Exception("Missing response from API"); - } - + var responseObject = JsonSerializer.Deserialize(response, options) ?? + throw new Exception("Missing response from API"); + logger.Information("New PR created {Id}", responseObject.PullRequestId); if (configValue.AutoComplete) { @@ -134,7 +126,7 @@ public async Task SubmitPullRequest(IReadOnlyCollection updates, s result = await client.PatchAsync(baseUrl, content); result.EnsureSuccessStatusCode(); } - + if (configValue.WorkItemId.HasValue) { logger.Information("Setting work item {ConfigValueWorkItemId} relation to {PullRequestId}", @@ -162,6 +154,11 @@ public async Task SubmitPullRequest(IReadOnlyCollection updates, s result.EnsureSuccessStatusCode(); } } + + private static string CreateGitBranchName(string projectName, string branchName, string group) + { + return $"{projectName.ToLower()}/{branchName.ToLower()}/{group.ToLower().Replace("*", "-asterix-")}"; + } private string CreatePrDescription(IReadOnlyCollection updates) { @@ -173,12 +170,7 @@ private string CreatePrDescription(IReadOnlyCollection updates) { stringBuilder.AppendLine($"Bump {update.PackageName}: {update.OldVersion} -> {update.NewVersion}"); } - - return stringBuilder.ToString(); - } - private static string CreateGitBranchName(string projectName, string branchName, string group) - { - return $"{projectName.ToLower()}/{branchName.ToLower()}/{group.ToLower().Replace("*","-asterix-")}"; + return stringBuilder.ToString(); } } \ No newline at end of file diff --git a/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj b/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj index 0a5f1ef..815071d 100644 --- a/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj +++ b/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true diff --git a/DependencyUpdated.sln b/DependencyUpdated.sln index 2dffeb0..ac0b822 100644 --- a/DependencyUpdated.sln +++ b/DependencyUpdated.sln @@ -11,11 +11,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Core", "D EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet", "DependencyUpdated.Projects.DotNet\DependencyUpdated.Projects.DotNet.csproj", "{D10799F8-DCBB-442E-85C0-2F473C716D01}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Projects", "Projects", "{3B80A93A-ED38-4221-B96F-2EF927AA6CEE}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Repositories.AzureDevOps", "DependencyUpdated.Repositories.AzureDevOps\DependencyUpdated.Repositories.AzureDevOps.csproj", "{A9181ADC-801D-45BE-B091-CF6C14E6F702}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Repositories", "Repositories", "{39D82538-18BD-4D04-AD5D-D2A55B43C14A}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35DCECB9-4FF1-4277-8C84-B905A5D1E693}" + ProjectSection(SolutionItems) = preProject + tests\directory.build.props = tests\directory.build.props + EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Repositories.AzureDevOps", "DependencyUpdated.Repositories.AzureDevOps\DependencyUpdated.Repositories.AzureDevOps.csproj", "{A9181ADC-801D-45BE-B091-CF6C14E6F702}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet.UnitTests", "tests\DependencyUpdated.Projects.DotNet.UnitTests\DependencyUpdated.Projects.DotNet.UnitTests.csproj", "{0F4B408D-9B4A-4621-BD67-AB80EB74E14B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,9 +42,12 @@ Global {A9181ADC-801D-45BE-B091-CF6C14E6F702}.Debug|Any CPU.Build.0 = Debug|Any CPU {A9181ADC-801D-45BE-B091-CF6C14E6F702}.Release|Any CPU.ActiveCfg = Release|Any CPU {A9181ADC-801D-45BE-B091-CF6C14E6F702}.Release|Any CPU.Build.0 = Release|Any CPU + {0F4B408D-9B4A-4621-BD67-AB80EB74E14B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F4B408D-9B4A-4621-BD67-AB80EB74E14B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F4B408D-9B4A-4621-BD67-AB80EB74E14B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F4B408D-9B4A-4621-BD67-AB80EB74E14B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution - {D10799F8-DCBB-442E-85C0-2F473C716D01} = {3B80A93A-ED38-4221-B96F-2EF927AA6CEE} - {A9181ADC-801D-45BE-B091-CF6C14E6F702} = {39D82538-18BD-4D04-AD5D-D2A55B43C14A} + {0F4B408D-9B4A-4621-BD67-AB80EB74E14B} = {35DCECB9-4FF1-4277-8C84-B905A5D1E693} EndGlobalSection EndGlobal diff --git a/DependencyUpdated/DependencyUpdated.csproj b/DependencyUpdated/DependencyUpdated.csproj index 4df4342..5232e2c 100644 --- a/DependencyUpdated/DependencyUpdated.csproj +++ b/DependencyUpdated/DependencyUpdated.csproj @@ -5,6 +5,7 @@ net8.0 enable enable + true DependencyUpdaterTool true diff --git a/DependencyUpdated/Program.cs b/DependencyUpdated/Program.cs index 853ff5b..29ea647 100644 --- a/DependencyUpdated/Program.cs +++ b/DependencyUpdated/Program.cs @@ -1,6 +1,4 @@ -using System.ComponentModel.DataAnnotations; -using System.IO.Enumeration; -using CommandLine; +using CommandLine; using DependencyUpdated.Core; using DependencyUpdated.Core.Config; using DependencyUpdated.Projects.DotNet; @@ -9,125 +7,131 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using Serilog; +using System.ComponentModel.DataAnnotations; +using System.IO.Enumeration; using ILogger = Serilog.ILogger; -namespace DependencyUpdated +namespace DependencyUpdated; + +public static class Program { - public static class Program + private static IConfiguration _configuration = default!; + private static IServiceProvider _serviceProvider = default!; + + public static async Task Main(string[] args) + { + await Parser.Default.ParseArguments(args) + .WithParsedAsync(RunApplication); + } + + private static async Task RunApplication(Options options) { - private static IConfiguration _configuration = default!; - private static IServiceProvider _serviceProvider = default!; + Configure(options); + ConfigureServices(); - public static async Task Main(string[] args) + var config = _serviceProvider.GetRequiredService>(); + var validationResult = config.Value.Validate(new ValidationContext(config.Value)).ToList(); + if (validationResult.Count != 0) { - await Parser.Default.ParseArguments(args) - .WithParsedAsync(RunApplication); + throw new OptionsValidationException(nameof(UpdaterConfig), typeof(UpdaterConfig), + validationResult.Where(x => !string.IsNullOrEmpty(x.ErrorMessage)).Select(x => x.ErrorMessage!)); } - private static async Task RunApplication(Options options) + var repositoryProvider = + _serviceProvider.GetRequiredKeyedService(config.Value.RepositoryType); + var repositoryPath = string.IsNullOrEmpty(options.RepositoryPath) + ? Environment.CurrentDirectory + : options.RepositoryPath; + + Directory.SetCurrentDirectory(repositoryPath); + + foreach (var configEntry in config.Value.Projects) { - Configure(options); - ConfigureServices(); + var updater = _serviceProvider.GetRequiredKeyedService(configEntry.Type); - var config = _serviceProvider.GetRequiredService>(); - var validationResult = config.Value.Validate(new ValidationContext(config.Value)).ToList(); - if (validationResult.Count != 0) + foreach (var project in configEntry.Directories) { - throw new OptionsValidationException(nameof(UpdaterConfig), typeof(UpdaterConfig), - validationResult.Where(x => !string.IsNullOrEmpty(x.ErrorMessage)).Select(x => x.ErrorMessage!)); - } + if (!Path.Exists(project)) + { + throw new FileNotFoundException("Search path not found", project); + } - var repositoryProvider = - _serviceProvider.GetRequiredKeyedService(config.Value.RepositoryType); - var repositoryPath = string.IsNullOrEmpty(options.RepositoryPath) - ? Environment.CurrentDirectory - : options.RepositoryPath; - - Directory.SetCurrentDirectory(repositoryPath); + var allDepencenciesToUpdate = new List(); + var projectFiles = updater.GetAllProjectFiles(project).ToArray(); - foreach (var configEntry in config.Value.Projects) - { - var updater = _serviceProvider.GetRequiredKeyedService(configEntry.Type); - - foreach (var project in configEntry.Directories) + foreach (var projectFile in projectFiles) { - if (!Path.Exists(project)) + var dependencyToUpdate = + await updater.ExtractAllPackagesThatNeedToBeUpdated(projectFile, configEntry); + allDepencenciesToUpdate.AddRange(dependencyToUpdate); + } + + if (allDepencenciesToUpdate.Count == 0) + { + continue; + } + + var uniqueListOfDependencies = allDepencenciesToUpdate.DistinctBy(x => x.Name).ToList(); + + foreach (var group in configEntry.Groups) + { + var matchesForGroup = uniqueListOfDependencies + .Where(x => FileSystemName.MatchesSimpleExpression(group, x.Name)).ToArray(); + uniqueListOfDependencies.RemoveAll(x => FileSystemName.MatchesSimpleExpression(group, x.Name)); + + if (matchesForGroup.Length == 0) { - throw new FileNotFoundException("Search path not found", project); + continue; } - var allDepencenciesToUpdate = new List(); - var projectFiles = updater.GetAllProjectFiles(project).ToArray(); - + + var projectName = configEntry.Name; + repositoryProvider.SwitchToDefaultBranch(repositoryPath); + repositoryProvider.SwitchToUpdateBranch(repositoryPath, projectName, group); + + var allUpdates = new List(); foreach (var projectFile in projectFiles) { - var dependencyToUpdate = await updater.ExtractAllPackagesThatNeedToBeUpdated(projectFile, configEntry); - allDepencenciesToUpdate.AddRange(dependencyToUpdate); + var updateResults = updater.HandleProjectUpdate(projectFile, matchesForGroup); + allUpdates.AddRange(updateResults); } - if (allDepencenciesToUpdate.Count == 0) + if (allUpdates.Count == 0) { continue; } - var uniqueListOfDependencies = allDepencenciesToUpdate.DistinctBy(x => x.Name).ToList(); - - foreach (var group in configEntry.Groups) - { - var matchesForGroup = uniqueListOfDependencies - .Where(x => FileSystemName.MatchesSimpleExpression(group, x.Name)).ToArray(); - uniqueListOfDependencies.RemoveAll(x => FileSystemName.MatchesSimpleExpression(group, x.Name)); - - if (matchesForGroup.Length == 0) - { - continue; - } - - var projectName = configEntry.Name; - repositoryProvider.SwitchToDefaultBranch(repositoryPath); - repositoryProvider.SwitchToUpdateBranch(repositoryPath, projectName, group); - - var allUpdates = new List(); - foreach (var projectFile in projectFiles) - { - var updateResults = updater.HandleProjectUpdate(projectFile, matchesForGroup); - allUpdates.AddRange(updateResults); - } - - if (allUpdates.Count != 0) - { - repositoryProvider.CommitChanges(repositoryPath, projectName, group); - repositoryProvider.SubmitPullRequest(allUpdates.DistinctBy(x=>x.PackageName).ToArray(), projectName, group).Wait(); - } - } + repositoryProvider.CommitChanges(repositoryPath, projectName, group); + repositoryProvider.SubmitPullRequest( + allUpdates.DistinctBy(x => x.PackageName).ToArray(), projectName, group).Wait(); } - } + } } + } - private static void Configure(Options appOptions) - { - var configPath = string.IsNullOrEmpty(appOptions.ConfigPath) ? "config.json" : appOptions.ConfigPath; - _configuration = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile(configPath, false) - .AddEnvironmentVariables() - .Build(); - } + private static void Configure(Options appOptions) + { + var configPath = string.IsNullOrEmpty(appOptions.ConfigPath) ? "config.json" : appOptions.ConfigPath; + _configuration = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile(configPath, false) + .AddEnvironmentVariables() + .Build(); + } - private static void ConfigureServices() - { - var services = new ServiceCollection(); - var logger = new LoggerConfiguration() - .WriteTo.Console() - .CreateLogger(); - services - .AddSingleton(logger) - .AddSingleton(TimeProvider.System) - .AddMemoryCache() - .RegisterDotNetServices() - .RegisterGithub() - .AddOptions().Bind(_configuration.GetSection("UpdaterConfig")); - - _serviceProvider = services.BuildServiceProvider(); - } + private static void ConfigureServices() + { + var services = new ServiceCollection(); + var logger = new LoggerConfiguration() + .WriteTo.Console() + .CreateLogger(); + services + .AddSingleton(logger) + .AddSingleton(TimeProvider.System) + .AddMemoryCache() + .RegisterDotNetServices() + .RegisterGithub() + .AddOptions().Bind(_configuration.GetSection("UpdaterConfig")); + + _serviceProvider = services.BuildServiceProvider(); } } \ No newline at end of file diff --git a/directory.build.props b/directory.build.props new file mode 100644 index 0000000..54fcecf --- /dev/null +++ b/directory.build.props @@ -0,0 +1,34 @@ + + + + true + + + + + + + + + <_Parameter1>$(MSBuildProjectName).UnitTests + + + <_Parameter1>$(MSBuildProjectName).IntegrationTests + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file diff --git a/stylecop.json b/stylecop.json new file mode 100644 index 0000000..fd51867 --- /dev/null +++ b/stylecop.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + "documentationRules": { + "xmlHeader": false, + "documentExposedElements": false, + "documentInterfaces": false, + "documentInternalElements": false, + "documentPrivateElements": false, + "documentPrivateFields": false + }, + "orderingRules": { + "usingDirectivesPlacement": "outsideNamespace" + }, + "layoutRules": { + "newlineAtEndOfFile": "allow" + }, + } +} \ No newline at end of file diff --git a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj new file mode 100644 index 0000000..aa5bbde --- /dev/null +++ b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + + false + true + + + + + Always + + + + + + + + diff --git a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs new file mode 100644 index 0000000..076329d --- /dev/null +++ b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs @@ -0,0 +1,106 @@ +using DependencyUpdated.Core; +using DependencyUpdated.Core.Config; +using FluentAssertions; +using FluentAssertions.Execution; +using Microsoft.Extensions.Caching.Memory; +using NSubstitute; +using Serilog; +using Xunit; + +namespace DependencyUpdated.Projects.DotNet.UnitTests; + +public class DotNetUpdaterTests +{ + private readonly DotNetUpdater _target; + private readonly ILogger _logger; + private readonly IMemoryCache _memoryCahce; + private readonly string _searchPath; + + public DotNetUpdaterTests() + { + _logger = Substitute.For(); + _memoryCahce = Substitute.For(); + _target = new DotNetUpdater(_logger, _memoryCahce); + _searchPath = "Projects"; + } + + [Fact] + public void GetAllProjectFiles_Should_ReturnAllProjects() + { + // Arrange + var expectedResult = new[] { "Projects\\SampleProject.csproj" }; + + // Act + var result = _target.GetAllProjectFiles(_searchPath); + + // Assert + using (new AssertionScope()) + { + result.Count.Should().Be(1); + result.Should().ContainInOrder(expectedResult); + } + } + + [Fact] + public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdatePatchVersion() + { + // Arrange + var path = "Projects\\SampleProject.csproj"; + var config = new Project() { Version = VersionUpdateType.Patch, }; + var expectedResult = new List() + { + new("Serilog", new Version(3,0,1, 0)) + }; + + // Act + var packages = await _target.ExtractAllPackagesThatNeedToBeUpdated(path, config); + + // Assert + using (new AssertionScope()) + { + packages.Should().BeEquivalentTo(expectedResult); + } + } + + [Fact] + public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdateMinorVersion() + { + // Arrange + var path = "Projects\\SampleProject.csproj"; + var config = new Project() { Version = VersionUpdateType.Minor, }; + var expectedResult = new List() + { + new("Serilog", new Version(3,1,1, 0)) + }; + + // Act + var packages = await _target.ExtractAllPackagesThatNeedToBeUpdated(path, config); + + // Assert + using (new AssertionScope()) + { + packages.Should().BeEquivalentTo(expectedResult); + } + } + + [Fact] + public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdateMajorVersion() + { + // Arrange + var path = "Projects\\SampleProject.csproj"; + var config = new Project() { Version = VersionUpdateType.Major, }; + var expectedResult = new List() + { + new("Serilog", new Version(4,0,1, 0)) + }; + + // Act + var packages = await _target.ExtractAllPackagesThatNeedToBeUpdated(path, config); + + // Assert + using (new AssertionScope()) + { + packages.Should().BeEquivalentTo(expectedResult); + } + } +} diff --git a/tests/DependencyUpdated.Projects.DotNet.UnitTests/Projects/SampleProject.csproj b/tests/DependencyUpdated.Projects.DotNet.UnitTests/Projects/SampleProject.csproj new file mode 100644 index 0000000..9423c8c --- /dev/null +++ b/tests/DependencyUpdated.Projects.DotNet.UnitTests/Projects/SampleProject.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + enable + enable + + + + + + + diff --git a/tests/directory.build.props b/tests/directory.build.props new file mode 100644 index 0000000..ccd7c89 --- /dev/null +++ b/tests/directory.build.props @@ -0,0 +1,21 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file From d52027d498c8f905e6ddb6dd1a8aebff05fa0706 Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:20:44 +0200 Subject: [PATCH 4/8] Move to src folder --- DependencyUpdated.sln | 16 ++++++++++++---- .../Config/AzureDevOpsConfig.cs | 0 .../DependencyUpdated.Core}/Config/Project.cs | 0 .../Config/UpdaterConfig.cs | 0 .../DependencyUpdated.Core}/DependencyDetails.cs | 0 .../DependencyUpdated.Core.csproj | 0 .../DependencyUpdated.Core}/IProjectUpdater.cs | 0 .../IRepositoryProvider.cs | 0 .../DependencyUpdated.Core}/ProjectType.cs | 0 .../DependencyUpdated.Core}/RepositoryType.cs | 0 .../DependencyUpdated.Core}/UpdateResult.cs | 0 .../DependencyUpdated.Core}/VersionUpdateType.cs | 0 .../ConfigureServices.cs | 0 .../DependencyUpdated.Projects.DotNet.csproj | 0 .../DotNetUpdater.cs | 0 .../AzureDevOps.cs | 0 .../ConfigureServices.cs | 0 ...ndencyUpdated.Repositories.AzureDevOps.csproj | 0 .../Dto/GitPullRequestCompletionOptions.cs | 0 .../Dto/GitPullRequestMergeStrategy.cs | 0 .../Dto/PullRequest.cs | 0 .../Dto/PullRequestResponse.cs | 0 .../Dto/PullRequestUpdate.cs | 0 .../Dto/User.cs | 0 .../DependencyUpdated}/DependencyUpdated.csproj | 0 .../DependencyUpdated}/Options.cs | 0 .../DependencyUpdated}/Program.cs | 0 .../DependencyUpdated}/config.json | 0 28 files changed, 12 insertions(+), 4 deletions(-) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/Config/AzureDevOpsConfig.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/Config/Project.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/Config/UpdaterConfig.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/DependencyDetails.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/DependencyUpdated.Core.csproj (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/IProjectUpdater.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/IRepositoryProvider.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/ProjectType.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/RepositoryType.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/UpdateResult.cs (100%) rename {DependencyUpdated.Core => src/DependencyUpdated.Core}/VersionUpdateType.cs (100%) rename {DependencyUpdated.Projects.DotNet => src/DependencyUpdated.Projects.DotNet}/ConfigureServices.cs (100%) rename {DependencyUpdated.Projects.DotNet => src/DependencyUpdated.Projects.DotNet}/DependencyUpdated.Projects.DotNet.csproj (100%) rename {DependencyUpdated.Projects.DotNet => src/DependencyUpdated.Projects.DotNet}/DotNetUpdater.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/AzureDevOps.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/ConfigureServices.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/DependencyUpdated.Repositories.AzureDevOps.csproj (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/GitPullRequestCompletionOptions.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/GitPullRequestMergeStrategy.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/PullRequest.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/PullRequestResponse.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/PullRequestUpdate.cs (100%) rename {DependencyUpdated.Repositories.AzureDevOps => src/DependencyUpdated.Repositories.AzureDevOps}/Dto/User.cs (100%) rename {DependencyUpdated => src/DependencyUpdated}/DependencyUpdated.csproj (100%) rename {DependencyUpdated => src/DependencyUpdated}/Options.cs (100%) rename {DependencyUpdated => src/DependencyUpdated}/Program.cs (100%) rename {DependencyUpdated => src/DependencyUpdated}/config.json (100%) diff --git a/DependencyUpdated.sln b/DependencyUpdated.sln index ac0b822..16f162d 100644 --- a/DependencyUpdated.sln +++ b/DependencyUpdated.sln @@ -1,17 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated", "DependencyUpdated\DependencyUpdated.csproj", "{8F92D3D1-EB23-4CA3-BCE9-ACC6327993E1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated", "src/DependencyUpdated\DependencyUpdated.csproj", "{8F92D3D1-EB23-4CA3-BCE9-ACC6327993E1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{BC1D92B0-5DBD-4BAA-9741-B61B1A1DD8C2}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore + stylecop.json = stylecop.json + directory.build.props = directory.build.props EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Core", "DependencyUpdated.Core\DependencyUpdated.Core.csproj", "{F346E159-924F-4206-B2BA-D5B34F91B9C0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Core", "src/DependencyUpdated.Core\DependencyUpdated.Core.csproj", "{F346E159-924F-4206-B2BA-D5B34F91B9C0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet", "DependencyUpdated.Projects.DotNet\DependencyUpdated.Projects.DotNet.csproj", "{D10799F8-DCBB-442E-85C0-2F473C716D01}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet", "src/DependencyUpdated.Projects.DotNet\DependencyUpdated.Projects.DotNet.csproj", "{D10799F8-DCBB-442E-85C0-2F473C716D01}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Repositories.AzureDevOps", "DependencyUpdated.Repositories.AzureDevOps\DependencyUpdated.Repositories.AzureDevOps.csproj", "{A9181ADC-801D-45BE-B091-CF6C14E6F702}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Repositories.AzureDevOps", "src/DependencyUpdated.Repositories.AzureDevOps\DependencyUpdated.Repositories.AzureDevOps.csproj", "{A9181ADC-801D-45BE-B091-CF6C14E6F702}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35DCECB9-4FF1-4277-8C84-B905A5D1E693}" ProjectSection(SolutionItems) = preProject @@ -20,6 +22,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35DCECB9 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet.UnitTests", "tests\DependencyUpdated.Projects.DotNet.UnitTests\DependencyUpdated.Projects.DotNet.UnitTests.csproj", "{0F4B408D-9B4A-4621-BD67-AB80EB74E14B}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0D271967-C5D2-425F-883E-FFCDC51A62A2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,5 +53,9 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {0F4B408D-9B4A-4621-BD67-AB80EB74E14B} = {35DCECB9-4FF1-4277-8C84-B905A5D1E693} + {8F92D3D1-EB23-4CA3-BCE9-ACC6327993E1} = {0D271967-C5D2-425F-883E-FFCDC51A62A2} + {F346E159-924F-4206-B2BA-D5B34F91B9C0} = {0D271967-C5D2-425F-883E-FFCDC51A62A2} + {D10799F8-DCBB-442E-85C0-2F473C716D01} = {0D271967-C5D2-425F-883E-FFCDC51A62A2} + {A9181ADC-801D-45BE-B091-CF6C14E6F702} = {0D271967-C5D2-425F-883E-FFCDC51A62A2} EndGlobalSection EndGlobal diff --git a/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs b/src/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs similarity index 100% rename from DependencyUpdated.Core/Config/AzureDevOpsConfig.cs rename to src/DependencyUpdated.Core/Config/AzureDevOpsConfig.cs diff --git a/DependencyUpdated.Core/Config/Project.cs b/src/DependencyUpdated.Core/Config/Project.cs similarity index 100% rename from DependencyUpdated.Core/Config/Project.cs rename to src/DependencyUpdated.Core/Config/Project.cs diff --git a/DependencyUpdated.Core/Config/UpdaterConfig.cs b/src/DependencyUpdated.Core/Config/UpdaterConfig.cs similarity index 100% rename from DependencyUpdated.Core/Config/UpdaterConfig.cs rename to src/DependencyUpdated.Core/Config/UpdaterConfig.cs diff --git a/DependencyUpdated.Core/DependencyDetails.cs b/src/DependencyUpdated.Core/DependencyDetails.cs similarity index 100% rename from DependencyUpdated.Core/DependencyDetails.cs rename to src/DependencyUpdated.Core/DependencyDetails.cs diff --git a/DependencyUpdated.Core/DependencyUpdated.Core.csproj b/src/DependencyUpdated.Core/DependencyUpdated.Core.csproj similarity index 100% rename from DependencyUpdated.Core/DependencyUpdated.Core.csproj rename to src/DependencyUpdated.Core/DependencyUpdated.Core.csproj diff --git a/DependencyUpdated.Core/IProjectUpdater.cs b/src/DependencyUpdated.Core/IProjectUpdater.cs similarity index 100% rename from DependencyUpdated.Core/IProjectUpdater.cs rename to src/DependencyUpdated.Core/IProjectUpdater.cs diff --git a/DependencyUpdated.Core/IRepositoryProvider.cs b/src/DependencyUpdated.Core/IRepositoryProvider.cs similarity index 100% rename from DependencyUpdated.Core/IRepositoryProvider.cs rename to src/DependencyUpdated.Core/IRepositoryProvider.cs diff --git a/DependencyUpdated.Core/ProjectType.cs b/src/DependencyUpdated.Core/ProjectType.cs similarity index 100% rename from DependencyUpdated.Core/ProjectType.cs rename to src/DependencyUpdated.Core/ProjectType.cs diff --git a/DependencyUpdated.Core/RepositoryType.cs b/src/DependencyUpdated.Core/RepositoryType.cs similarity index 100% rename from DependencyUpdated.Core/RepositoryType.cs rename to src/DependencyUpdated.Core/RepositoryType.cs diff --git a/DependencyUpdated.Core/UpdateResult.cs b/src/DependencyUpdated.Core/UpdateResult.cs similarity index 100% rename from DependencyUpdated.Core/UpdateResult.cs rename to src/DependencyUpdated.Core/UpdateResult.cs diff --git a/DependencyUpdated.Core/VersionUpdateType.cs b/src/DependencyUpdated.Core/VersionUpdateType.cs similarity index 100% rename from DependencyUpdated.Core/VersionUpdateType.cs rename to src/DependencyUpdated.Core/VersionUpdateType.cs diff --git a/DependencyUpdated.Projects.DotNet/ConfigureServices.cs b/src/DependencyUpdated.Projects.DotNet/ConfigureServices.cs similarity index 100% rename from DependencyUpdated.Projects.DotNet/ConfigureServices.cs rename to src/DependencyUpdated.Projects.DotNet/ConfigureServices.cs diff --git a/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj b/src/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj similarity index 100% rename from DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj rename to src/DependencyUpdated.Projects.DotNet/DependencyUpdated.Projects.DotNet.csproj diff --git a/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs b/src/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs similarity index 100% rename from DependencyUpdated.Projects.DotNet/DotNetUpdater.cs rename to src/DependencyUpdated.Projects.DotNet/DotNetUpdater.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs b/src/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/AzureDevOps.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/ConfigureServices.cs b/src/DependencyUpdated.Repositories.AzureDevOps/ConfigureServices.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/ConfigureServices.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/ConfigureServices.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj b/src/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj rename to src/DependencyUpdated.Repositories.AzureDevOps/DependencyUpdated.Repositories.AzureDevOps.csproj diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestCompletionOptions.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestCompletionOptions.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestCompletionOptions.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestCompletionOptions.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestMergeStrategy.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestMergeStrategy.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestMergeStrategy.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/GitPullRequestMergeStrategy.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequest.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequest.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequest.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequest.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestResponse.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestResponse.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestResponse.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestResponse.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestUpdate.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestUpdate.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestUpdate.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/PullRequestUpdate.cs diff --git a/DependencyUpdated.Repositories.AzureDevOps/Dto/User.cs b/src/DependencyUpdated.Repositories.AzureDevOps/Dto/User.cs similarity index 100% rename from DependencyUpdated.Repositories.AzureDevOps/Dto/User.cs rename to src/DependencyUpdated.Repositories.AzureDevOps/Dto/User.cs diff --git a/DependencyUpdated/DependencyUpdated.csproj b/src/DependencyUpdated/DependencyUpdated.csproj similarity index 100% rename from DependencyUpdated/DependencyUpdated.csproj rename to src/DependencyUpdated/DependencyUpdated.csproj diff --git a/DependencyUpdated/Options.cs b/src/DependencyUpdated/Options.cs similarity index 100% rename from DependencyUpdated/Options.cs rename to src/DependencyUpdated/Options.cs diff --git a/DependencyUpdated/Program.cs b/src/DependencyUpdated/Program.cs similarity index 100% rename from DependencyUpdated/Program.cs rename to src/DependencyUpdated/Program.cs diff --git a/DependencyUpdated/config.json b/src/DependencyUpdated/config.json similarity index 100% rename from DependencyUpdated/config.json rename to src/DependencyUpdated/config.json From e9bdb8e3319110ac5b66a8f29c5f6d6139b4921b Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:25:18 +0200 Subject: [PATCH 5/8] Fix --- directory.build.props | 2 +- src/DependencyUpdated/DependencyUpdated.csproj | 4 ++-- .../DependencyUpdated.Projects.DotNet.UnitTests.csproj | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/directory.build.props b/directory.build.props index 54fcecf..db2e32a 100644 --- a/directory.build.props +++ b/directory.build.props @@ -5,7 +5,7 @@ - + diff --git a/src/DependencyUpdated/DependencyUpdated.csproj b/src/DependencyUpdated/DependencyUpdated.csproj index 5232e2c..8580d05 100644 --- a/src/DependencyUpdated/DependencyUpdated.csproj +++ b/src/DependencyUpdated/DependencyUpdated.csproj @@ -33,8 +33,8 @@ Always - - + + diff --git a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj index aa5bbde..bc4025a 100644 --- a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj +++ b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DependencyUpdated.Projects.DotNet.UnitTests.csproj @@ -16,7 +16,7 @@ - + From e4a1504f058f22a9e3631c0f74b9da39b4b9066f Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:33:37 +0200 Subject: [PATCH 6/8] fix --- DependencyUpdated.sln | 4 ++-- ...ctory.build.props => Directory.Build.props | 0 tests/directory.build.props | 21 ------------------- 3 files changed, 2 insertions(+), 23 deletions(-) rename directory.build.props => Directory.Build.props (100%) delete mode 100644 tests/directory.build.props diff --git a/DependencyUpdated.sln b/DependencyUpdated.sln index 16f162d..f359c9b 100644 --- a/DependencyUpdated.sln +++ b/DependencyUpdated.sln @@ -6,7 +6,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFi ProjectSection(SolutionItems) = preProject .gitignore = .gitignore stylecop.json = stylecop.json - directory.build.props = directory.build.props + Directory.Build.props = Directory.Build.props EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Core", "src/DependencyUpdated.Core\DependencyUpdated.Core.csproj", "{F346E159-924F-4206-B2BA-D5B34F91B9C0}" @@ -17,7 +17,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Repositor EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{35DCECB9-4FF1-4277-8C84-B905A5D1E693}" ProjectSection(SolutionItems) = preProject - tests\directory.build.props = tests\directory.build.props + tests\Directory.Build.props = tests\Directory.Build.props EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependencyUpdated.Projects.DotNet.UnitTests", "tests\DependencyUpdated.Projects.DotNet.UnitTests\DependencyUpdated.Projects.DotNet.UnitTests.csproj", "{0F4B408D-9B4A-4621-BD67-AB80EB74E14B}" diff --git a/directory.build.props b/Directory.Build.props similarity index 100% rename from directory.build.props rename to Directory.Build.props diff --git a/tests/directory.build.props b/tests/directory.build.props deleted file mode 100644 index ccd7c89..0000000 --- a/tests/directory.build.props +++ /dev/null @@ -1,21 +0,0 @@ - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - \ No newline at end of file From 3b7e13a8331e546d949e8e1a1b07e1692db2725d Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:33:53 +0200 Subject: [PATCH 7/8] missing file --- tests/Directory.Build.props | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/Directory.Build.props diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props new file mode 100644 index 0000000..ccd7c89 --- /dev/null +++ b/tests/Directory.Build.props @@ -0,0 +1,21 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + \ No newline at end of file From 752a992c07f890eca434fa6a4395e7910bedff60 Mon Sep 17 00:00:00 2001 From: Marcin Torba Date: Wed, 28 Aug 2024 23:38:57 +0200 Subject: [PATCH 8/8] fix --- .../DotNetUpdaterTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs index 076329d..eb32705 100644 --- a/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs +++ b/tests/DependencyUpdated.Projects.DotNet.UnitTests/DotNetUpdaterTests.cs @@ -28,7 +28,7 @@ public DotNetUpdaterTests() public void GetAllProjectFiles_Should_ReturnAllProjects() { // Arrange - var expectedResult = new[] { "Projects\\SampleProject.csproj" }; + var expectedResult = new[] { Path.Combine("Projects", "SampleProject.csproj") }; // Act var result = _target.GetAllProjectFiles(_searchPath); @@ -45,7 +45,7 @@ public void GetAllProjectFiles_Should_ReturnAllProjects() public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdatePatchVersion() { // Arrange - var path = "Projects\\SampleProject.csproj"; + var path = Path.Combine("Projects", "SampleProject.csproj"); var config = new Project() { Version = VersionUpdateType.Patch, }; var expectedResult = new List() { @@ -66,7 +66,7 @@ public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdatePatchVersio public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdateMinorVersion() { // Arrange - var path = "Projects\\SampleProject.csproj"; + var path = Path.Combine("Projects", "SampleProject.csproj"); var config = new Project() { Version = VersionUpdateType.Minor, }; var expectedResult = new List() { @@ -87,7 +87,7 @@ public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdateMinorVersio public async Task ExtractAllPackagesThatNeedToBeUpdated_Should_UpdateMajorVersion() { // Arrange - var path = "Projects\\SampleProject.csproj"; + var path = Path.Combine("Projects", "SampleProject.csproj"); var config = new Project() { Version = VersionUpdateType.Major, }; var expectedResult = new List() {