diff --git a/build/Build.cs b/build/Build.cs index 8c94bf518c..4f4cfb6981 100644 --- a/build/Build.cs +++ b/build/Build.cs @@ -28,8 +28,6 @@ namespace Calamari.Build; partial class Build : NukeBuild { - const string RootProjectName = "Calamari"; - [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; [Required] readonly Solution Solution = SolutionModelTasks.ParseSolution(SourceDirectory / "Calamari.sln"); @@ -62,8 +60,6 @@ partial class Build : NukeBuild [Parameter(Name = "signing_certificate_password")] [Secret] readonly string SigningCertificatePassword = "Password01!"; - [Parameter] readonly string? TargetFramework; - [Parameter] readonly string? TargetRuntime; const string CiBranchNameEnvVariable = "OCTOVERSION_CurrentBranch"; @@ -71,12 +67,14 @@ partial class Build : NukeBuild [Parameter($"The name of the current git branch. OctoVersion will use this to calculate the version number. This can be set via the environment variable {CiBranchNameEnvVariable}.", Name = CiBranchNameEnvVariable)] string? BranchName { get; set; } + [Parameter] readonly string? ProjectToBuild; + //this is instantiated in the constructor readonly Lazy OctoVersionInfo; static readonly List NuGetPackagesToExcludeFromConsolidation = new() { "Octopus.Calamari.CloudAccounts", "Octopus.Calamari.Common", "Octopus.Calamari.ConsolidateCalamariPackages", "Octopus.Calamari.ConsolidatedPackage", "Octopus.Calamari.ConsolidatedPackage.Api" }; - CalamariPackageMetadata[] PackagesToPublish = Array.Empty(); + List PackagesToPublish = new(); List CalamariProjects = new(); readonly List ProjectCompressionTasks = new(); @@ -109,7 +107,6 @@ public Build() static AbsolutePath LocalPackagesDirectory => RootDirectory / ".." / "LocalPackages"; static AbsolutePath ConsolidateCalamariPackagesProject => SourceDirectory / "Calamari.ConsolidateCalamariPackages.Tests" / "Calamari.ConsolidateCalamariPackages.Tests.csproj"; static AbsolutePath ConsolidatedPackageDirectory => ArtifactsDirectory / "consolidated"; - static AbsolutePath LegacyCalamariDirectory => PublishDirectory / "Calamari.Legacy"; Lazy NugetVersion { get; } @@ -140,156 +137,82 @@ public Build() Target Clean => d => - d.Executes(() => + d.DependsOn(CheckForbiddenWords) + .Executes(() => { SourceDirectory.GlobDirectories("**/bin", "**/obj", "**/TestResults").ForEach(d => d.DeleteDirectory()); ArtifactsDirectory.CreateOrCleanDirectory(); PublishDirectory.CreateOrCleanDirectory(); }); - Target Restore => + Target RestoreSolution => d => d.DependsOn(Clean) .Executes(() => { - var localRuntime = FixedRuntimes.Windows; + //Do one big, default restore + DotNetRestore(s => s.SetProjectFile(Solution)); - if (!OperatingSystem.IsWindows()) - localRuntime = FixedRuntimes.Linux; - - DotNetRestore(s => s.SetProjectFile(Solution) - .SetRuntime(localRuntime) - .SetProperty("DisableImplicitNuGetFallbackFolder", true)); - }); - - Target Compile => - d => - d.DependsOn(CheckForbiddenWords) - .DependsOn(Restore) - .Executes(() => - { - Log.Information("Compiling Calamari v{CalamariVersion}", NugetVersion.Value); - - DotNetBuild(s => s.SetProjectFile(Solution) - .SetConfiguration(Configuration) - .EnableNoRestore() - .SetVersion(NugetVersion.Value) - .SetInformationalVersion(OctoVersionInfo.Value?.InformationalVersion)); - }); - - Target Publish => - d => - d.DependsOn(Compile) - .DependsOn(PublishAzureWebAppNetCoreShim) - .Executes(() => - { - var nugetVersion = NugetVersion.Value; - if (OperatingSystem.IsWindows()) - { - var outputDirectory = DoPublish(RootProjectName, Frameworks.Net462, nugetVersion); - outputDirectory.Copy(LegacyCalamariDirectory / RootProjectName, ExistsPolicy.DirectoryMerge | ExistsPolicy.FileFail); - DoPublish(RootProjectName, Frameworks.Net462, nugetVersion, FixedRuntimes.Cloud); - } - else + var allRuntimeIds = ListAllRuntimeIdentifiersInSolution(); + //we restore for all individual runtimes + foreach (var runtimeId in allRuntimeIds) { - Log.Warning("Building Calamari on a non-windows machine will result " - + "in the {DefaultNugetPackageName} and {CloudNugetPackageName} " - + "nuget packages being built as .Net Core 8.0 packages " - + "instead of as .Net Framework. " - + "This can cause compatibility issues when running certain " - + "deployment steps in Octopus Server", - RootProjectName, $"{RootProjectName}.{FixedRuntimes.Cloud}"); - - DoPublish(RootProjectName, Frameworks.Net80, nugetVersion); - - Log.Warning($"Skipping the bundling of {RootProjectName} into the Calamari.Legacy bundle. " - + "This is required for providing .Net Framework executables for legacy Target Operating Systems"); - - DoPublish(RootProjectName, Frameworks.Net80, nugetVersion, FixedRuntimes.Cloud); + DotNetRestore(s => s.SetProjectFile(Solution).SetRuntime(runtimeId)); } - - foreach (var rid in GetRuntimeIdentifiers(Solution.GetProject(RootProjectName)!)) - DoPublish(RootProjectName, Frameworks.Net80, nugetVersion, rid); }); Target GetCalamariFlavourProjectsToPublish => d => - d.DependsOn(Compile) + d.DependsOn(RestoreSolution) .Executes(() => { - var flavours = GetCalamariFlavours(); - var migratedCalamariFlavoursTests = flavours.Select(f => $"{f}.Tests"); - var calamariFlavourProjects = Solution.Projects - .Where(project => flavours.Contains(project.Name) - || migratedCalamariFlavoursTests.Contains(project.Name)); + var projectNames = GetCalamariFlavours(); // Calamari.Scripting is a library that other calamari flavours depend on; not a flavour on its own right. // Unlike other *Calamari* tests, we would still want to produce Calamari.Scripting.Zip and its tests, like its flavours. - var calamariScripting = "Calamari.Scripting"; - var calamariScriptingProjectAndTest = Solution.Projects.Where(project => project.Name == calamariScripting || project.Name == $"{calamariScripting}.Tests"); + //We put this at the front of the list so they build in the correct order? + projectNames = [..projectNames, "Calamari.Scripting"]; - var calamariProjects = calamariFlavourProjects - .Concat(calamariScriptingProjectAndTest) - .ToList(); + //its assumed each project has a corresponding test project + var testProjectNames = projectNames.Select(f => $"{f}.Tests"); + var allProjectNames = projectNames.Concat(testProjectNames).ToHashSet(); - CalamariProjects = calamariProjects; + var calamariProjects = Solution.Projects + .Where(project => allProjectNames.Contains(project.Name)) + .ToList(); - // All cross-platform Target Frameworks contain dots, all NetFx Target Frameworks don't - // eg: net40, net452, net48 vs netcoreapp3.1, net5.0, net8.0 - bool IsCrossPlatform(string targetFramework) => targetFramework.Contains('.'); - - var calamariPackages = - calamariProjects.SelectMany(project => project.GetTargetFrameworks()!, (p, f) => new - { - Project = p, - Framework = f, - CrossPlatform = IsCrossPlatform(f) - }) - .ToList(); - - // for NetFx target frameworks, we use "netfx" as the architecture, and ignore defined runtime identifiers - var netFxPackages = - calamariPackages.Where(p => !p.CrossPlatform) - .Select(packageToBuild => new CalamariPackageMetadata( - project: packageToBuild.Project, - framework: packageToBuild.Framework, - architecture: null, - isCrossPlatform: packageToBuild.CrossPlatform - )); - - // for cross-platform frameworks, we combine each runtime identifier with each target framework - var crossPlatformPackages = - calamariPackages.Where(p => p.CrossPlatform) - .Where(p => string.IsNullOrWhiteSpace(TargetFramework) || p.Framework == TargetFramework) - .SelectMany(packageToBuild => GetRuntimeIdentifiers(packageToBuild.Project), - (packageToBuild, runtimeIdentifier) => new CalamariPackageMetadata( - project: packageToBuild.Project, - framework: packageToBuild.Framework, - architecture: runtimeIdentifier, - isCrossPlatform: packageToBuild.CrossPlatform - )) - .Distinct(t => new { t.Project.Name, t.Architecture, t.Framework }); - - PackagesToPublish = crossPlatformPackages.Concat(netFxPackages).ToArray(); - }); + //if this is not + if (!string.IsNullOrEmpty(ProjectToBuild)) + { + calamariProjects = calamariProjects.Where(p => p.Name == ProjectToBuild || p.Name == $"{ProjectToBuild}.Tests").ToList(); + } - Target RestoreCalamariProjects => - d => - d.DependsOn(GetCalamariFlavourProjectsToPublish) - .Executes(() => - { - PackagesToPublish - .Select(p => p.Architecture) - .Distinct() - .ForEach(rid => DotNetRestore(s => - s.SetProjectFile(Solution) - .SetProperty("DisableImplicitNuGetFallbackFolder", true) - .SetRuntime(rid))); + CalamariProjects = calamariProjects; + + //all packages are cross-platform + var packages = calamariProjects + .SelectMany(project => GetRuntimeIdentifiers(project) + .Select(rid => + { + //we are making the bold assumption all projects only have a single target framework + var framework = project.GetTargetFrameworks()?.Single() ?? Frameworks.Net80; + return new CalamariPackageMetadata(project, framework, rid); + })) + .ToList(); + + PackagesToPublish = packages; + + Log.Information("Packages to publish:"); + foreach (var calamariPackageMetadata in packages) + { + Log.Information("Project: {Project}, Framework: {Framework}, Arch: {Architecture}", calamariPackageMetadata.Project.Name, calamariPackageMetadata.Framework, calamariPackageMetadata.Architecture); + } }); Target BuildCalamariProjects => d => - d.DependsOn(RestoreCalamariProjects) + d.DependsOn(GetCalamariFlavourProjectsToPublish) + .DependsOn(PublishAzureWebAppNetCoreShim) .Executes(async () => { var globalSemaphore = new SemaphoreSlim(3); @@ -297,33 +220,23 @@ public Build() var buildTasks = PackagesToPublish.Select(async calamariPackageMetadata => { - if (!OperatingSystem.IsWindows() && !calamariPackageMetadata.IsCrossPlatform) - { - Log.Warning("Not Building {Framework}: can only publish netfx on a Windows OS", calamariPackageMetadata.Framework); - return; - } - var projectName = calamariPackageMetadata.Project.Name; var projectSemaphore = semaphores.GetOrAdd(projectName, _ => new SemaphoreSlim(1, 1)); - - // for NetFx target frameworks, we use "netfx" as the architecture, and ignore defined runtime identifiers, here we'll just block on all netfx - var architectureSemaphore = semaphores.GetOrAdd(calamariPackageMetadata.Architecture ?? "Unknown Architecture", _ => new SemaphoreSlim(1, 1)); + var architectureSemaphore = semaphores.GetOrAdd(calamariPackageMetadata.Architecture, _ => new SemaphoreSlim(1, 1)); await globalSemaphore.WaitAsync(); await projectSemaphore.WaitAsync(); await architectureSemaphore.WaitAsync(); try { - Log.Information("Building {ProjectName} for framework '{Framework}' and arch '{Architecture}'", calamariPackageMetadata.Project.Name, calamariPackageMetadata.Framework, calamariPackageMetadata.Architecture); - - await Task.Run(() => - DotNetBuild(s => - s.SetProjectFile(calamariPackageMetadata.Project) - .SetConfiguration(Configuration) - .SetFramework(calamariPackageMetadata.Framework) - .EnableNoRestore() - .SetRuntime(calamariPackageMetadata.Architecture) - .EnableSelfContained())); + Log.Information($"Building {calamariPackageMetadata.Project.Name} for framework '{calamariPackageMetadata.Framework}' and arch '{calamariPackageMetadata.Architecture}'"); + + await Task.Run(() => DotNetBuild(s => + s.SetProjectFile(calamariPackageMetadata.Project) + .SetConfiguration(Configuration) + .SetFramework(calamariPackageMetadata.Framework) + .SetRuntime(calamariPackageMetadata.Architecture) + .EnableSelfContained())); } finally { @@ -344,6 +257,7 @@ await Task.Run(() => var semaphore = new SemaphoreSlim(4); var outputPaths = new ConcurrentBag(); + Log.Information("Publishing projects..."); var publishTasks = PackagesToPublish.Select(async package => { await semaphore.WaitAsync(); @@ -361,29 +275,25 @@ await Task.Run(() => await Task.WhenAll(publishTasks); // Sign and compress tasks + Log.Information("Signing published binaries..."); var signTasks = outputPaths .Where(output => output != null && !output.ToString().Contains("Tests")) .Select(output => Task.Run(() => SignDirectory(output!))) .ToList(); await Task.WhenAll(signTasks); - StageLegacyCalamariAssemblies(PackagesToPublish); - CalamariProjects.ForEach(CompressCalamariProject); - await Task.WhenAll(ProjectCompressionTasks); + + Log.Information("Compressing published projects..."); + var compressTasks = CalamariProjects.Select(async proj => await CompressCalamariProject(proj)); + await Task.WhenAll(compressTasks); }); async Task PublishPackageAsync(CalamariPackageMetadata calamariPackageMetadata) { - if (!OperatingSystem.IsWindows() && !calamariPackageMetadata.IsCrossPlatform) - { - Log.Warning("Not publishing {Framework}: can only publish netfx on a Windows OS", calamariPackageMetadata.Framework); - return null; - } - Log.Information("Publishing {ProjectName} for framework '{Framework}' and arch '{Architecture}'", calamariPackageMetadata.Project.Name, calamariPackageMetadata.Framework, calamariPackageMetadata.Architecture); var project = calamariPackageMetadata.Project; - var outputDirectory = PublishDirectory / project.Name / (calamariPackageMetadata.IsCrossPlatform ? calamariPackageMetadata.Architecture : "netfx"); + var outputDirectory = PublishDirectory / project.Name / calamariPackageMetadata.Architecture; await Task.Run(() => DotNetPublish(s => @@ -393,7 +303,7 @@ await Task.Run(() => .SetRuntime(calamariPackageMetadata.Architecture) .EnableNoBuild() .EnableNoRestore() - .EnableSelfContained() + .SetSelfContained(OperatingSystem.IsWindows()) // This is here purely to make the local build experience on non-Windows devices workable - Publish breaks on non-Windows platforms with SelfContained = true .SetOutput(outputDirectory))); File.Copy(RootDirectory / "global.json", outputDirectory / "global.json"); @@ -401,44 +311,23 @@ await Task.Run(() => return outputDirectory; } - static void StageLegacyCalamariAssemblies(CalamariPackageMetadata[] packagesToPublish) - { - if (!OperatingSystem.IsWindows()) - { - Log.Warning($"Skipping the bundling of Calamari projects into the Calamari.Legacy bundle - " - + "this is required for providing .Net Framework executables for legacy Target Operating Systems"); - return; - } - - packagesToPublish - //We only need to bundle executable (not tests or libraries) full framework projects - .Where(d => d.Framework == Frameworks.Net462 && d.Project.GetOutputType() == "Exe") - .ForEach(calamariPackageMetadata => - { - Log.Information("Copying {ProjectName} for legacy Calamari '{Framework}' and arch '{Architecture}'", - calamariPackageMetadata.Project.Name, calamariPackageMetadata.Framework, calamariPackageMetadata.Architecture); - var project = calamariPackageMetadata.Project; - var publishedPath = PublishDirectory / project.Name / "netfx"; - publishedPath.Copy(LegacyCalamariDirectory / project.Name, ExistsPolicy.DirectoryMerge | ExistsPolicy.FileFail); - }); - } - - void CompressCalamariProject(Project project) + async Task CompressCalamariProject(Project project) { - Log.Verbose("Compressing Calamari flavour {PublishDirectory}/{ProjectName}", PublishDirectory, project.Name); + Log.Information($"Compressing Calamari flavour {PublishDirectory}/{project.Name}"); var compressionSource = PublishDirectory / project.Name; if (!Directory.Exists(compressionSource)) { - Log.Verbose("Skipping compression for {ProjectName} since nothing was built", project.Name); + Log.Information($"Skipping compression for {project.Name} since nothing was built"); return; } - var compressionTask = Task.Run(() => compressionSource.CompressTo($"{ArtifactsDirectory / project.Name}.zip")); - ProjectCompressionTasks.Add(compressionTask); + await Task.Run(() => compressionSource.CompressTo($"{ArtifactsDirectory / project.Name}.zip")); } Target PublishAzureWebAppNetCoreShim => - _ => _.DependsOn(Restore) + _ => _.DependsOn(RestoreSolution) + //we only build the net core shim when there is the AzureWebApp project is being built + .OnlyWhenDynamic(() => CalamariProjects.Any(p => p.Name == "Calamari.AzureWebApp")) .Executes(() => { if (!OperatingSystem.IsWindows()) @@ -447,15 +336,20 @@ void CompressCalamariProject(Project project) return; } - var project = Solution.GetProject("Calamari.AzureWebApp.NetCoreShim") ?? throw new Exception("Could not find Calamari.AzureWebApp.NetCoreShim project"); + var project = Solution.GetProject("Calamari.AzureWebApp.NetCoreShim"); + if (project is null) + { + Log.Error("Failed to find Calamari.AzureWebApp.NetCoreShim project"); + return; + } var outputPath = PublishDirectory / project.Name; + //as this is the only Net 4.6.2 application left, we do a build and restore here DotNetPublish(s => s .SetConfiguration(Configuration) .SetProject(project.Path) - .SetFramework(Frameworks.Net462) - .EnableNoRestore() + .SetFramework("net462") .SetVersion(NugetVersion.Value) .SetInformationalVersion(OctoVersionInfo.Value?.InformationalVersion) .SetOutput(outputPath)); @@ -466,148 +360,9 @@ void CompressCalamariProject(Project project) outputPath.CompressTo(archivePath); }); - Target PackLegacyCalamari => - d => - d.DependsOn(Publish) - .DependsOn(PublishCalamariProjects) - .Executes(() => - { - if (!OperatingSystem.IsWindows()) - { - return; - } - - Log.Verbose($"Compressing Calamari.Legacy"); - LegacyCalamariDirectory.ZipTo(ArtifactsDirectory / $"Calamari.Legacy.{NugetVersion.Value}.zip"); - }); - - Target PackBinaries => - d => - d.DependsOn(Publish) - .DependsOn(PublishCalamariProjects) - .Executes(async () => - { - var nugetVersion = NugetVersion.Value; - var packageActions = new List - { - () => DoPackage(RootProjectName, - OperatingSystem.IsWindows() ? Frameworks.Net462 : Frameworks.Net80, - nugetVersion), - () => DoPackage(RootProjectName, - OperatingSystem.IsWindows() ? Frameworks.Net462 : Frameworks.Net80, - nugetVersion, - FixedRuntimes.Cloud), - }; - - // Create the self-contained Calamari packages for each runtime ID defined in Calamari.csproj - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var rid in GetRuntimeIdentifiers(Solution.GetProject(RootProjectName)!)) - packageActions.Add(() => DoPackage(RootProjectName, - Frameworks.Net80, - nugetVersion, - rid)); - - var dotNetCorePackSettings = new DotNetPackSettings().SetConfiguration(Configuration) - .SetOutputDirectory(ArtifactsDirectory) - .EnableNoBuild() - .EnableIncludeSource() - .SetVersion(nugetVersion) - .EnableNoRestore(); - - var commonProjects = Directory.GetFiles(SourceDirectory, "*.Common.csproj", - new EnumerationOptions { RecurseSubdirectories = true }); - - // ReSharper disable once LoopCanBeConvertedToQuery - foreach (var project in commonProjects) - packageActions.Add(() => SignAndPack(project.ToString(), dotNetCorePackSettings)); - - // Pack the Consolidation Libraries - var consolidateCalamariPackagesProjectPrefix = "Calamari.ConsolidateCalamariPackages"; - Solution.Projects.Where(project => project.Name.StartsWith(consolidateCalamariPackagesProjectPrefix)).ForEach(p => packageActions.Add(() => SignAndPack(p, dotNetCorePackSettings))); - - var sourceProjectPath = - SourceDirectory / "Calamari.CloudAccounts" / "Calamari.CloudAccounts.csproj"; - packageActions.Add(() => SignAndPack(sourceProjectPath, - dotNetCorePackSettings)); - - await RunPackActions(packageActions); - }); - - Target PackTests => - d => - d.DependsOn(Publish) - .DependsOn(PublishCalamariProjects) - .Executes(async () => - { - var nugetVersion = NugetVersion.Value; - var actions = new List - { - () => - { - //if this is windows, publish a netfx version of the tests project - if (OperatingSystem.IsWindows()) - { - var publishedLocation = DoPublish("Calamari.Tests", Frameworks.Net462, nugetVersion); - var zipName = $"Calamari.Tests.{Frameworks.Net462}.{nugetVersion}.zip"; - publishedLocation.CompressTo(ArtifactsDirectory / zipName); - } - } - }; - - // Create a Zip for each runtime for testing - // ReSharper disable once LoopCanBeConvertedToQuery - actions.Add(() => - { - //run each build in sequence as it's the same project and we get issues - foreach (var rid in GetRuntimeIdentifiers(Solution.GetProject("Calamari.Tests")!)) - { - var publishedLocation = DoPublish("Calamari.Tests", Frameworks.Net80, nugetVersion, rid); - var zipName = $"Calamari.Tests.{rid}.{nugetVersion}.zip"; - File.Copy(RootDirectory / "global.json", publishedLocation / "global.json"); - publishedLocation.CompressTo(ArtifactsDirectory / zipName); - } - }); - - //I don't think this is _actually_ necessary to build... - actions.Add(() => - { - var testingProjectPath = SourceDirectory / "Calamari.Testing" / "Calamari.Testing.csproj"; - DotNetPack(new DotNetPackSettings().SetConfiguration(Configuration) - .SetProject(testingProjectPath) - .SetOutputDirectory(ArtifactsDirectory) - .EnableNoBuild() - .EnableIncludeSource() - .SetVersion(nugetVersion) - .EnableNoRestore()); - }); - - await RunPackActions(actions); - }); - - Target Pack => - d => - d.DependsOn(PackTests) - .DependsOn(PackBinaries) - .DependsOn(PackLegacyCalamari); - - Target CopyToLocalPackages => - d => - d.Requires(() => IsLocalBuild) - .DependsOn(PackBinaries) - .Executes(() => - { - Directory.CreateDirectory(LocalPackagesDirectory); - foreach (AbsolutePath file in Directory.GetFiles(ArtifactsDirectory, "Octopus.Calamari.*.nupkg")) - { - var target = LocalPackagesDirectory / Path.GetFileName(file); - file.Copy(target, ExistsPolicy.FileOverwrite); - } - }); - Target PackageConsolidatedCalamariZip => d => - d.DependsOn(PackBinaries) - .Executes(() => + d.Executes(() => { var artifacts = Directory.GetFiles(ArtifactsDirectory, "*.nupkg") .Where(a => !NuGetPackagesToExcludeFromConsolidation.Any(a.Contains)); @@ -666,13 +421,49 @@ void CompressCalamariProject(Project project) .SetProcessArgumentConfigurator(args => args.Add("--logger:\"console;verbosity=detailed\"") .Add("--") - .Add("NUnit.ShowInternalProperties=true")) - .EnableNoBuild()); + .Add("NUnit.ShowInternalProperties=true"))); }); - Target PackCalamariConsolidatedNugetPackage => + Target PackConsolidationLibrariesNugetPackages => d => d.DependsOn(CalamariConsolidationVerification) + .Executes(() => + { + // Pack the Consolidation Libraries + const string consolidateCalamariPackagesProjectPrefix = "Calamari.ConsolidateCalamariPackages"; + var consolidationLibraryProjects = Solution.Projects.Where(project => project.Name.StartsWith(consolidateCalamariPackagesProjectPrefix)); + + foreach (var project in consolidationLibraryProjects) + { + Log.Information("Packaging {ProjectName}", project.Name); + + var buildDirectory = SourceDirectory / project.Name / "bin" / Configuration; + + //Build the consolidated package libraries + DotNetBuild(s => + s.SetConfiguration(Configuration) + .SetProjectFile(project)); + + File.Copy(RootDirectory / "global.json", buildDirectory / "global.json"); + + //sign the built directory + SignDirectory(buildDirectory); + + //pack the project + DotNetPack(s => s + .SetConfiguration(Configuration) + .SetOutputDirectory(ArtifactsDirectory) + .SetProject(project) + .EnableNoBuild() + .EnableNoRestore() + .EnableIncludeSource() + .SetVersion(NugetVersion.Value)); + } + }); + + Target PackCalamariConsolidatedNugetPackage => + d => + d.DependsOn(PackConsolidationLibrariesNugetPackages) .Executes(() => { NuGetPack(s => s.SetTargetPath(BuildDirectory / "Calamari.Consolidated.nuspec") @@ -681,6 +472,20 @@ void CompressCalamariProject(Project project) .SetOutputDirectory(ArtifactsDirectory)); }); + Target CopyToLocalPackages => + d => + d.Requires(() => IsLocalBuild) + .DependsOn(PublishCalamariProjects) + .Executes(() => + { + Directory.CreateDirectory(LocalPackagesDirectory); + foreach (AbsolutePath file in Directory.GetFiles(ArtifactsDirectory, "Octopus.Calamari.*.nupkg")) + { + var target = LocalPackagesDirectory / Path.GetFileName(file); + file.Copy(target, ExistsPolicy.FileOverwrite); + } + }); + Target UpdateCalamariVersionOnOctopusServer => d => d.OnlyWhenStatic(() => SetOctopusServerVersion) @@ -712,75 +517,32 @@ void CompressCalamariProject(Project project) const string runtime = "win-x64"; var nukeBuildOutputDirectory = BuildDirectory / "outputs" / runtime / "nukebuild"; nukeBuildOutputDirectory.CreateOrCleanDirectory(); - + DotNetPublish(p => p .SetProject(RootDirectory / "build" / "_build.csproj") .SetConfiguration(Configuration) .SetRuntime(runtime) .EnableSelfContained()); - + await Ci.ZipFolderAndUploadArtifact(nukeBuildOutputDirectory, ArtifactsDirectory / $"nukebuild.{runtime}.zip"); }); Target SetTeamCityVersion => d => d.Executes(() => TeamCity.Instance?.SetBuildNumber(NugetVersion.Value)); Target BuildLocal => d => - d.DependsOn(PackCalamariConsolidatedNugetPackage) + d.DependsOn(PublishCalamariProjects) + .DependsOn(PackCalamariConsolidatedNugetPackage) .DependsOn(UpdateCalamariVersionOnOctopusServer); Target BuildCi => d => d.DependsOn(SetTeamCityVersion) - .DependsOn(Pack) + .DependsOn(PublishCalamariProjects) .DependsOn(PackCalamariConsolidatedNugetPackage) .DependsOn(PublishNukeBuild); - public static int Main() => Execute(x => IsServerBuild ? x.BuildCi : x.BuildLocal); - - async Task RunPackActions(List actions) - { - var tasks = actions.Select(Task.Run).ToList(); - await Task.WhenAll(tasks); - } - - AbsolutePath DoPublish(string project, string framework, string version, string? runtimeId = null) - { - var publishedTo = PublishDirectory / project / framework; + Target BuildAndPublishProject => d => d.OnlyWhenDynamic(() => !string.IsNullOrEmpty(ProjectToBuild)).DependsOn(PublishCalamariProjects); - if (!runtimeId.IsNullOrEmpty()) - { - publishedTo /= runtimeId; - runtimeId = runtimeId != "portable" && runtimeId != "Cloud" ? runtimeId : null; - } - - DotNetPublish(s => - s.SetProject(Solution.GetProject(project)) - .SetConfiguration(Configuration) - .SetOutput(publishedTo) - .SetFramework(framework) - .SetVersion(NugetVersion.Value) - .SetVerbosity(BuildVerbosity) - .SetRuntime(runtimeId) - .SetVersion(version) - .SetSelfContained(runtimeId != null) - ); - - if (WillSignBinaries) - { - Signing.SignAndTimestampBinaries(publishedTo, AzureKeyVaultUrl, AzureKeyVaultAppId, - AzureKeyVaultAppSecret, AzureKeyVaultTenantId, AzureKeyVaultCertificateName, - SigningCertificatePath, SigningCertificatePassword); - } - - return publishedTo; - } - - void SignProject(string project) - { - if (!WillSignBinaries) - return; - var binDirectory = $"{Path.GetDirectoryName(project)}/bin/{Configuration}/"; - SignDirectory(binDirectory); - } + public static int Main() => Execute(x => IsServerBuild ? x.BuildCi : x.BuildLocal); void SignDirectory(string directory) { @@ -797,49 +559,6 @@ void SignDirectory(string directory) } } - void SignAndPack(string project, DotNetPackSettings dotNetCorePackSettings) - { - Log.Information("SignAndPack project: {Project}", project); - SignProject(project); - DotNetPack(dotNetCorePackSettings.SetProject(project)); - } - - void DoPackage(string project, string framework, string version, string? runtimeId = null) - { - var publishedTo = PublishDirectory / project / framework; - var projectDir = SourceDirectory / project; - var packageId = project.Equals(RootProjectName) ? $"Octopus.{project}" : $"{project}"; - var nugetPackProperties = new Dictionary(); - - if (!runtimeId.IsNullOrEmpty()) - { - publishedTo /= runtimeId; - packageId = $"Octopus.{project}.{runtimeId}"; - nugetPackProperties.Add("runtimeId", runtimeId!); - } - - if (WillSignBinaries) - Signing.SignAndTimestampBinaries(publishedTo, AzureKeyVaultUrl, AzureKeyVaultAppId, - AzureKeyVaultAppSecret, AzureKeyVaultTenantId, AzureKeyVaultCertificateName, - SigningCertificatePath, SigningCertificatePassword); - - AbsolutePath nuspecSrc = $"{projectDir}/{project}.nuspec"; - AbsolutePath nuspecDest = $"{publishedTo}/{packageId}.nuspec"; - nuspecSrc.Copy(nuspecDest, ExistsPolicy.FileOverwrite); - var text = File.ReadAllText(nuspecDest); - text = text.Replace("$id$", packageId) - .Replace("$version$", version); - File.WriteAllText(nuspecDest, text); - - NuGetPack(s => - s.SetBasePath(publishedTo) - .SetOutputDirectory(ArtifactsDirectory) - .SetTargetPath(nuspecDest) - .SetVersion(NugetVersion.Value) - .SetVerbosity(NuGetVerbosity.Normal) - .SetProperties(nugetPackProperties)); - } - // Sets the Octopus.Server.csproj Calamari.Consolidated package version void SetOctopusServerCalamariVersion(string projectFile) { @@ -860,20 +579,34 @@ string GetNugetVersion() IReadOnlyCollection GetRuntimeIdentifiers(Project? project) { if (project is null) - return Array.Empty(); + return []; var runtimes = project.GetRuntimeIdentifiers(); if (!string.IsNullOrWhiteSpace(TargetRuntime)) runtimes = runtimes?.Where(x => x == TargetRuntime).ToList().AsReadOnly(); - return runtimes ?? Array.Empty(); + return runtimes ?? []; } // Although all libraries/flavours now support .NET Core, ServiceFabric can currently only be built on Windows devices // This is here purely to make the local build experience on non-Windows devices (with testing) workable - static List GetCalamariFlavours() + static string[] GetCalamariFlavours() { - return OperatingSystem.IsWindows() ? CalamariPackages.Flavours : CalamariPackages.CrossPlatformFlavours; + return BuildableCalamariProjects.GetCalamariProjectsToBuild(OperatingSystem.IsWindows()); + } + + HashSet ListAllRuntimeIdentifiersInSolution() + { + var allRuntimes = Solution.AllProjects + .SelectMany(p => p.GetRuntimeIdentifiers() ?? Array.Empty()) + .Distinct() + .Where(rid => rid != "win7-x86") //I have no idea where this is coming from, but let's ignore it. My theory is it's coming from the netstandard libs + .ToHashSet(); + + if (!string.IsNullOrWhiteSpace(TargetRuntime)) + allRuntimes = allRuntimes.Where(x => x == TargetRuntime).ToHashSet(); + + return allRuntimes; } } \ No newline at end of file diff --git a/build/Build.sbom.cs b/build/Build.sbom.cs index 784bdda0a1..893a842eb0 100644 --- a/build/Build.sbom.cs +++ b/build/Build.sbom.cs @@ -32,7 +32,7 @@ partial class Build .Requires(() => DependencyTrackUrl) .Requires(() => DependencyTrackApiKey) .Requires(() => InternalDockerRegistry) - .DependsOn(Publish) + .DependsOn(PublishCalamariProjects) .Executes(async () => { ArgumentNullException.ThrowIfNull(Solution, nameof(Solution)); diff --git a/build/CalamariPackageMetadata.cs b/build/CalamariPackageMetadata.cs index 1af761088d..f824626f58 100644 --- a/build/CalamariPackageMetadata.cs +++ b/build/CalamariPackageMetadata.cs @@ -2,19 +2,9 @@ namespace Calamari.Build; -public class CalamariPackageMetadata +public class CalamariPackageMetadata(Project project, string framework, string architecture) { - public CalamariPackageMetadata(Project project, string framework, string? architecture, bool isCrossPlatform) - { - Project = project; - Framework = framework; - Architecture = architecture; - IsCrossPlatform = isCrossPlatform; - } - - public Project Project { get; } - public string Framework { get; } - public string? Architecture { get; } - public bool IsCrossPlatform { get; } - + public Project Project { get; } = project; + public string Framework { get; } = framework; + public string Architecture { get; } = architecture; } diff --git a/build/Frameworks.cs b/build/Frameworks.cs index dfe16e8345..f5d02a7a0b 100644 --- a/build/Frameworks.cs +++ b/build/Frameworks.cs @@ -4,7 +4,7 @@ namespace Calamari.Build { public static class Frameworks { - public const string Net462 = "net462"; public const string Net80 = "net8.0"; + public const string Net80Windows = "net8.0-windows"; } } \ No newline at end of file diff --git a/source/Calamari.Aws/Calamari.Aws.csproj b/source/Calamari.Aws/Calamari.Aws.csproj index a60f95341f..da7185a30c 100644 --- a/source/Calamari.Aws/Calamari.Aws.csproj +++ b/source/Calamari.Aws/Calamari.Aws.csproj @@ -1,7 +1,6 @@  1.0.0.0 - Exe anycpu Calamari.Aws Library @@ -19,7 +18,8 @@ Calamari.Aws.exe.manifest - net462;netstandard2.1 + net8.0 + default true diff --git a/source/Calamari.Aws/Deployment/AmazonFileUploadException.cs b/source/Calamari.Aws/Deployment/AmazonFileUploadException.cs index 0ed8fb851d..70134e484d 100644 --- a/source/Calamari.Aws/Deployment/AmazonFileUploadException.cs +++ b/source/Calamari.Aws/Deployment/AmazonFileUploadException.cs @@ -8,6 +8,5 @@ public class AmazonFileUploadException : Exception public AmazonFileUploadException(){} public AmazonFileUploadException(string message) : base(message){} public AmazonFileUploadException(string message, Exception innerException) : base(message, innerException){} - protected AmazonFileUploadException(SerializationInfo info, StreamingContext context) : base(info, context){} } } \ No newline at end of file diff --git a/source/Calamari.Azure/Calamari.Azure.csproj b/source/Calamari.Azure/Calamari.Azure.csproj index 9e67e43391..bef28bbf97 100644 --- a/source/Calamari.Azure/Calamari.Azure.csproj +++ b/source/Calamari.Azure/Calamari.Azure.csproj @@ -6,8 +6,8 @@ Octopus Deploy Octopus Deploy Pty Ltd win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - 8.0 - net462;net8.0 + default + net8.0 true diff --git a/source/Calamari.AzureAppService.Tests/Calamari.AzureAppService.Tests.csproj b/source/Calamari.AzureAppService.Tests/Calamari.AzureAppService.Tests.csproj index 3369377f7e..e70a736596 100644 --- a/source/Calamari.AzureAppService.Tests/Calamari.AzureAppService.Tests.csproj +++ b/source/Calamari.AzureAppService.Tests/Calamari.AzureAppService.Tests.csproj @@ -5,8 +5,8 @@ Calamari.AzureAppService.Tests false win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - 8.0 - net462;net8.0 + default + net8.0 true diff --git a/source/Calamari.AzureAppService/Calamari.AzureAppService.csproj b/source/Calamari.AzureAppService/Calamari.AzureAppService.csproj index e1c0d185a4..e3dcac70c0 100644 --- a/source/Calamari.AzureAppService/Calamari.AzureAppService.csproj +++ b/source/Calamari.AzureAppService/Calamari.AzureAppService.csproj @@ -7,9 +7,9 @@ true Exe win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - 8.0 + default NU5104 - net462;net8.0 + net8.0 true diff --git a/source/Calamari.AzureResourceGroup.Tests/Attributes/TestPlatformsAttribute.cs b/source/Calamari.AzureResourceGroup.Tests/Attributes/TestPlatformsAttribute.cs new file mode 100644 index 0000000000..5d8f208351 --- /dev/null +++ b/source/Calamari.AzureResourceGroup.Tests/Attributes/TestPlatformsAttribute.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using Xunit.v3; + +namespace Calamari.AzureResourceGroup.Tests.Attributes; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] +public class TestPlatformsAttribute(string platform) : Attribute, ITraitAttribute +{ + public string Platform { get; } = platform; + + public IReadOnlyCollection> GetTraits() + => [new("Category", Platform)]; +} \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerFixture.cs b/source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerTests.cs similarity index 62% rename from source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerFixture.cs rename to source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerTests.cs index 4400d992cc..568fb19201 100644 --- a/source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerFixture.cs +++ b/source/Calamari.AzureResourceGroup.Tests/AzureResourceGroupActionHandlerTests.cs @@ -1,15 +1,11 @@ using System; using System.IO; -using System.Threading; using System.Threading.Tasks; -using Azure; -using Azure.Core; -using Azure.ResourceManager; -using Azure.ResourceManager.Resources; -using Calamari.Azure; -using Calamari.CloudAccounts; +using Calamari.AzureResourceGroup.Tests.Attributes; +using Calamari.AzureResourceGroup.Tests.Support; using Calamari.Common.Features.Deployment; using Calamari.Common.Features.Scripts; +using Calamari.Common.Plumbing.Extensions; using Calamari.Common.Plumbing.Variables; using Calamari.Testing; using Calamari.Testing.Azure; @@ -17,86 +13,18 @@ using Calamari.Testing.Requirements; using Newtonsoft.Json.Linq; using NUnit.Framework; +using Xunit.Sdk; // ReSharper disable MethodHasAsyncOverload - File.ReadAllTextAsync does not exist for .net framework targets namespace Calamari.AzureResourceGroup.Tests { - [TestFixture] - class AzureResourceGroupActionHandlerFixture + [Collection(nameof(AzureResourceGroupFixture))] + public class AzureResourceGroupActionHandlerTests(AzureResourceGroupFixture resourceGroupFixture): CalamariTest { - string clientId; - string clientSecret; - string tenantId; - string subscriptionId; - static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(); - readonly CancellationToken cancellationToken = CancellationTokenSource.Token; + readonly AzureResourceGroupFixture resourceGroupFixture = resourceGroupFixture; - ArmClient armClient; - SubscriptionResource subscriptionResource; - ResourceGroupResource resourceGroupResource; - string resourceGroupName; - - [OneTimeSetUp] - public async Task Setup() - { - var resourceManagementEndpointBaseUri = - Environment.GetEnvironmentVariable(AccountVariables.ResourceManagementEndPoint) ?? DefaultVariables.ResourceManagementEndpoint; - var activeDirectoryEndpointBaseUri = - Environment.GetEnvironmentVariable(AccountVariables.ActiveDirectoryEndPoint) ?? DefaultVariables.ActiveDirectoryEndpoint; - - clientId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionClientId, cancellationToken); - clientSecret = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionPassword, cancellationToken); - tenantId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionTenantId, cancellationToken); - subscriptionId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionId, cancellationToken); - - var resourceGroupLocation = Environment.GetEnvironmentVariable("AZURE_NEW_RESOURCE_REGION") ?? RandomAzureRegion.GetRandomRegionWithExclusions(); - - resourceGroupName = AzureTestResourceHelpers.GetResourceGroupName(); - - var servicePrincipalAccount = new AzureServicePrincipalAccount(subscriptionId, - clientId, - tenantId, - clientSecret, - "AzureGlobalCloud", - resourceManagementEndpointBaseUri, - activeDirectoryEndpointBaseUri); - - armClient = servicePrincipalAccount.CreateArmClient(retryOptions => - { - retryOptions.MaxRetries = 5; - retryOptions.Mode = RetryMode.Exponential; - retryOptions.Delay = TimeSpan.FromSeconds(2); - retryOptions.NetworkTimeout = TimeSpan.FromSeconds(200); - }); - - //create the resource group - subscriptionResource = armClient.GetSubscriptionResource(SubscriptionResource.CreateResourceIdentifier(subscriptionId)); - - var response = await subscriptionResource - .GetResourceGroups() - .CreateOrUpdateAsync(WaitUntil.Completed, - resourceGroupName, - new ResourceGroupData(new AzureLocation(resourceGroupLocation)) - { - Tags = - { - [AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysKey] = AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysValue, - [AzureTestResourceHelpers.ResourceGroupTags.SourceKey] = AzureTestResourceHelpers.ResourceGroupTags.SourceValue - } - }); - - resourceGroupResource = response.Value; - } - - [OneTimeTearDown] - public async Task Cleanup() - { - await armClient.GetResourceGroupResource(ResourceGroupResource.CreateResourceIdentifier(subscriptionId, resourceGroupName)) - .DeleteAsync(WaitUntil.Started); - } - - [Test] + [Fact] public async Task Deploy_with_template_in_package() { var packagePath = TestEnvironment.GetTestPath("Packages", "AzureResourceGroup"); @@ -113,7 +41,7 @@ await CommandTestBuilder.CreateAsync() .Execute(); } - [Test] + [Fact] public async Task Deploy_with_template_in_git_repository() { // For the purposes of ARM templates in Calamari, a template in a Git Repository @@ -134,7 +62,7 @@ await CommandTestBuilder.CreateAsync() .Execute(); } - [Test] + [Fact] public async Task Deploy_with_template_inline() { var packagePath = TestEnvironment.GetTestPath("Packages", "AzureResourceGroup"); @@ -158,11 +86,15 @@ await CommandTestBuilder.CreateAsync() .Execute(); } - [Test] - [WindowsTest] - [RequiresPowerShell5OrAbove] + [Fact] + [TestPlatforms(TestCategory.CompatibleOS.OnlyWindows)] public async Task Deploy_Ensure_Tools_Are_Configured() { + if (ScriptingEnvironment.SafelyGetPowerShellVersion().Major < 5) + { + throw SkipException.ForSkip("This test requires PowerShell 5 or above."); + } + var packagePath = TestEnvironment.GetTestPath("Packages", "AzureResourceGroup"); var templateFileContent = File.ReadAllText(Path.Combine(packagePath, "azure_website_template.json")); var paramsFileContent = File.ReadAllText(Path.Combine(packagePath, "azure_website_params.json")); @@ -192,19 +124,19 @@ await CommandTestBuilder.CreateAsync() .Execute(); } - private void AddDefaults(CommandTestBuilderContext context) + void AddDefaults(CommandTestBuilderContext context) { context.Variables.Add("Octopus.Account.AccountType", "AzureServicePrincipal"); - context.Variables.Add(AzureAccountVariables.SubscriptionId, subscriptionId); - context.Variables.Add(AzureAccountVariables.TenantId, tenantId); - context.Variables.Add(AzureAccountVariables.ClientId, clientId); - context.Variables.Add(AzureAccountVariables.Password, clientSecret); - context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupName, resourceGroupName); - context.Variables.Add("ResourceGroup", resourceGroupName); + context.Variables.Add(AzureAccountVariables.SubscriptionId, resourceGroupFixture.SubscriptionId); + context.Variables.Add(AzureAccountVariables.TenantId, resourceGroupFixture.TenantId); + context.Variables.Add(AzureAccountVariables.ClientId, resourceGroupFixture.ClientId); + context.Variables.Add(AzureAccountVariables.Password, resourceGroupFixture.ClientSecret); + context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupName, resourceGroupFixture.ResourceGroupName); + context.Variables.Add("ResourceGroup", resourceGroupFixture.ResourceGroupName); context.Variables.Add("SKU", "Shared"); //as we have a single resource group, we need to have unique web app name per test context.Variables.Add("WebSite", $"Calamari-{Guid.NewGuid():N}"); - context.Variables.Add("Location", resourceGroupResource.Data.Location); + context.Variables.Add("Location", resourceGroupFixture.ResourceGroupResource.Data.Location); //this is a storage account prefix, so just make it as random as possible //The names of the storage accounts are a max of 7 chars, so we generate a prefix of 17 chars (storage accounts have a max of 24) context.Variables.Add("AccountPrefix", AzureTestResourceHelpers.RandomName(length: 17)); diff --git a/source/Calamari.AzureResourceGroup.Tests/Calamari.AzureResourceGroup.Tests.csproj b/source/Calamari.AzureResourceGroup.Tests/Calamari.AzureResourceGroup.Tests.csproj index 15226288c6..dd9208b67d 100644 --- a/source/Calamari.AzureResourceGroup.Tests/Calamari.AzureResourceGroup.Tests.csproj +++ b/source/Calamari.AzureResourceGroup.Tests/Calamari.AzureResourceGroup.Tests.csproj @@ -4,16 +4,19 @@ Calamari.AzureResourceGroup.Tests false win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - net462;net8.0 + net8.0 + default true - - - + - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/source/Calamari.AzureResourceGroup.Tests/CalamariTest.cs b/source/Calamari.AzureResourceGroup.Tests/CalamariTest.cs new file mode 100644 index 0000000000..bf09cc5563 --- /dev/null +++ b/source/Calamari.AzureResourceGroup.Tests/CalamariTest.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading; + +namespace Calamari.AzureResourceGroup.Tests; + +public abstract class CalamariTest +{ + readonly CancellationTokenSource cancellationTokenSource; + protected CancellationToken CancellationToken => cancellationTokenSource.Token; + + protected virtual TimeSpan TestTimeout => TimeSpan.FromMilliseconds(int.MaxValue); + + protected CalamariTest() + { + var ctsTimeout = new CancellationTokenSource(TestTimeout); + cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(ctsTimeout.Token, TestContext.Current.CancellationToken); + } +} \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandFixture.cs b/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandFixture.cs deleted file mode 100644 index 1bd5c2213f..0000000000 --- a/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandFixture.cs +++ /dev/null @@ -1,169 +0,0 @@ -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Azure; -using Azure.Core; -using Azure.ResourceManager; -using Azure.ResourceManager.Resources; -using Calamari.Azure; -using Calamari.CloudAccounts; -using Calamari.Testing; -using Calamari.Testing.Azure; -using Calamari.Testing.Helpers; -using Calamari.Testing.Tools; -using NUnit.Framework; - -namespace Calamari.AzureResourceGroup.Tests -{ - [TestFixture] - [Category(TestCategory.CompatibleOS.OnlyWindows)] - class DeployAzureBicepTemplateCommandFixture - { - string clientId; - string clientSecret; - string tenantId; - string subscriptionId; - string resourceGroupName; - string resourceGroupLocation; - ArmClient armClient; - static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5)); - readonly CancellationToken cancellationToken = CancellationTokenSource.Token; - readonly string packagePath = TestEnvironment.GetTestPath("Packages", "Bicep"); - SubscriptionResource subscriptionResource; - - static IDeploymentTool AzureCLI = new InPathDeploymentTool("Octopus.Dependencies.AzureCLI", "AzureCLI\\wbin"); - - [OneTimeSetUp] - public async Task Setup() - { - var resourceManagementEndpointBaseUri = - Environment.GetEnvironmentVariable(AccountVariables.ResourceManagementEndPoint) ?? DefaultVariables.ResourceManagementEndpoint; - var activeDirectoryEndpointBaseUri = - Environment.GetEnvironmentVariable(AccountVariables.ActiveDirectoryEndPoint) ?? DefaultVariables.ActiveDirectoryEndpoint; - - clientId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionClientId, cancellationToken); - clientSecret = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionPassword, cancellationToken); - tenantId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionTenantId, cancellationToken); - subscriptionId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionId, cancellationToken); - - resourceGroupName = AzureTestResourceHelpers.GetResourceGroupName(); - - resourceGroupLocation = Environment.GetEnvironmentVariable("AZURE_NEW_RESOURCE_REGION") ?? RandomAzureRegion.GetRandomRegionWithExclusions(); - - var servicePrincipalAccount = new AzureServicePrincipalAccount(subscriptionId, - clientId, - tenantId, - clientSecret, - "AzureGlobalCloud", - resourceManagementEndpointBaseUri, - activeDirectoryEndpointBaseUri); - - armClient = servicePrincipalAccount.CreateArmClient(retryOptions => - { - retryOptions.MaxRetries = 5; - retryOptions.Mode = RetryMode.Exponential; - retryOptions.Delay = TimeSpan.FromSeconds(2); - retryOptions.NetworkTimeout = TimeSpan.FromSeconds(200); - }); - - //create the resource group - subscriptionResource = armClient.GetSubscriptionResource(SubscriptionResource.CreateResourceIdentifier(subscriptionId)); - - await subscriptionResource - .GetResourceGroups() - .CreateOrUpdateAsync(WaitUntil.Completed, - resourceGroupName, - new ResourceGroupData(new AzureLocation(resourceGroupLocation)) - { - Tags = - { - [AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysKey] = AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysValue, - [AzureTestResourceHelpers.ResourceGroupTags.SourceKey] = AzureTestResourceHelpers.ResourceGroupTags.SourceValue - } - }); - } - - [OneTimeTearDown] - public async Task Cleanup() - { - await armClient.GetResourceGroupResource(ResourceGroupResource.CreateResourceIdentifier(subscriptionId, resourceGroupName)) - .DeleteAsync(WaitUntil.Started); - } - - [Test] - public async Task DeployAzureBicepTemplate_PackageSource() - { - await CommandTestBuilder.CreateAsync() - .WithArrange(context => - { - AddDefaults(context); - context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "Package"); - context.Variables.Add(SpecialVariables.Action.Azure.BicepTemplate, "azure_website_template.bicep"); - context.WithFilesToCopy(packagePath); - }) - .Execute(); - } - - [Test] - public async Task DeployAzureBicepTemplate_GitSource() - { - // For the purposes of Bicep templates in Calamari, a template in a Git Repository - // is equivalent to a template in a package, so we can just re-use the same - // package in the test here, it's just the template source property that is - // different. - await CommandTestBuilder.CreateAsync() - .WithArrange(context => - { - AddDefaults(context); - context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "GitRepository"); - context.Variables.Add(SpecialVariables.Action.Azure.BicepTemplate, "azure_website_template.bicep"); - context.WithFilesToCopy(packagePath); - }) - .Execute(); - } - - [Test] - public async Task DeployAzureBicepTemplate_InlineSource() - { - var templateFileContent = File.ReadAllText(Path.Combine(packagePath, "azure_website_template.bicep")); - var paramsFileContent = File.ReadAllText(Path.Combine(packagePath, "parameters.json")); - - await CommandTestBuilder.CreateAsync() - .WithArrange(context => - { - AddDefaults(context); - context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupDeploymentMode, "Complete"); - context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "Inline"); - AddTemplateFiles(context, templateFileContent, paramsFileContent); - }) - .Execute(); - } - - void AddDefaults(CommandTestBuilderContext context) - { - context.WithTool(AzureCLI); - - context.Variables.Add(AzureScripting.SpecialVariables.Account.AccountType, "AzureServicePrincipal"); - context.Variables.Add(AzureAccountVariables.SubscriptionId, subscriptionId); - context.Variables.Add(AzureAccountVariables.TenantId, tenantId); - context.Variables.Add(AzureAccountVariables.ClientId, clientId); - context.Variables.Add(AzureAccountVariables.Password, clientSecret); - context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupName, resourceGroupName); - context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupLocation, resourceGroupLocation); - context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupDeploymentMode, "Complete"); - context.Variables.Add(SpecialVariables.Action.Azure.TemplateParameters, "parameters.json"); - - context.Variables.Add("SKU", "Standard_LRS"); - context.Variables.Add("Location", resourceGroupLocation); - //storage accounts can be 24 chars long - context.Variables.Add("StorageAccountName", AzureTestResourceHelpers.RandomName(length: 24)); - } - - static void AddTemplateFiles(CommandTestBuilderContext context, string template, string parameters) - { - context.WithDataFile(template, "template.bicep"); - context.WithDataFile(parameters, "parameters.json"); - } - } -} \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandTests.cs b/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandTests.cs new file mode 100644 index 0000000000..7a71f23b11 --- /dev/null +++ b/source/Calamari.AzureResourceGroup.Tests/DeployAzureBicepTemplateCommandTests.cs @@ -0,0 +1,100 @@ +using System; +using System.IO; +using System.Threading.Tasks; +using Calamari.AzureResourceGroup.Tests.Attributes; +using Calamari.AzureResourceGroup.Tests.Support; +using Calamari.Testing; +using Calamari.Testing.Azure; +using Calamari.Testing.Helpers; +using Calamari.Testing.Tools; + +namespace Calamari.AzureResourceGroup.Tests +{ + [TestPlatforms(TestCategory.CompatibleOS.OnlyWindows)] + [Collection(nameof(AzureResourceGroupFixture))] + public class DeployAzureBicepTemplateCommandTests(AzureResourceGroupFixture resourceGroupFixture) : CalamariTest + { + readonly AzureResourceGroupFixture resourceGroupFixture = resourceGroupFixture; + + readonly string packagePath = TestEnvironment.GetTestPath("Packages", "Bicep"); + + static IDeploymentTool AzureCLI = new InPathDeploymentTool("Octopus.Dependencies.AzureCLI", "AzureCLI\\wbin"); + + protected override TimeSpan TestTimeout => TimeSpan.FromMinutes(5); + + [Fact] + public async Task DeployAzureBicepTemplate_PackageSource() + { + await CommandTestBuilder.CreateAsync() + .WithArrange(context => + { + AddDefaults(context); + context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "Package"); + context.Variables.Add(SpecialVariables.Action.Azure.BicepTemplate, "azure_website_template.bicep"); + context.WithFilesToCopy(packagePath); + }) + .Execute(); + } + + [Fact] + public async Task DeployAzureBicepTemplate_GitSource() + { + // For the purposes of Bicep templates in Calamari, a template in a Git Repository + // is equivalent to a template in a package, so we can just re-use the same + // package in the test here, it's just the template source property that is + // different. + await CommandTestBuilder.CreateAsync() + .WithArrange(context => + { + AddDefaults(context); + context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "GitRepository"); + context.Variables.Add(SpecialVariables.Action.Azure.BicepTemplate, "azure_website_template.bicep"); + context.WithFilesToCopy(packagePath); + }) + .Execute(); + } + + [Fact] + public async Task DeployAzureBicepTemplate_InlineSource() + { + var templateFileContent = await File.ReadAllTextAsync(Path.Combine(packagePath, "azure_website_template.bicep"), CancellationToken); + var paramsFileContent = await File.ReadAllTextAsync(Path.Combine(packagePath, "parameters.json"), CancellationToken); + + await CommandTestBuilder.CreateAsync() + .WithArrange(context => + { + AddDefaults(context); + context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupDeploymentMode, "Complete"); + context.Variables.Add(SpecialVariables.Action.Azure.TemplateSource, "Inline"); + AddTemplateFiles(context, templateFileContent, paramsFileContent); + }) + .Execute(); + } + + void AddDefaults(CommandTestBuilderContext context) + { + context.WithTool(AzureCLI); + + context.Variables.Add(AzureScripting.SpecialVariables.Account.AccountType, "AzureServicePrincipal"); + context.Variables.Add(AzureAccountVariables.SubscriptionId, resourceGroupFixture.SubscriptionId); + context.Variables.Add(AzureAccountVariables.TenantId, resourceGroupFixture.TenantId); + context.Variables.Add(AzureAccountVariables.ClientId, resourceGroupFixture.ClientId); + context.Variables.Add(AzureAccountVariables.Password, resourceGroupFixture.ClientSecret); + context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupName, resourceGroupFixture.ResourceGroupName); + context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupLocation, resourceGroupFixture.ResourceGroupLocation); + context.Variables.Add(SpecialVariables.Action.Azure.ResourceGroupDeploymentMode, "Complete"); + context.Variables.Add(SpecialVariables.Action.Azure.TemplateParameters, "parameters.json"); + + context.Variables.Add("SKU", "Standard_LRS"); + context.Variables.Add("Location", resourceGroupFixture.ResourceGroupLocation); + //storage accounts can be 24 chars long + context.Variables.Add("StorageAccountName", AzureTestResourceHelpers.RandomName(length: 24)); + } + + static void AddTemplateFiles(CommandTestBuilderContext context, string template, string parameters) + { + context.WithDataFile(template, "template.bicep"); + context.WithDataFile(parameters, "parameters.json"); + } + } +} \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/DeploymentNameFixture.cs b/source/Calamari.AzureResourceGroup.Tests/DeploymentNameTests.cs similarity index 52% rename from source/Calamari.AzureResourceGroup.Tests/DeploymentNameFixture.cs rename to source/Calamari.AzureResourceGroup.Tests/DeploymentNameTests.cs index 1ec80b6227..6f58985c24 100644 --- a/source/Calamari.AzureResourceGroup.Tests/DeploymentNameFixture.cs +++ b/source/Calamari.AzureResourceGroup.Tests/DeploymentNameTests.cs @@ -1,42 +1,43 @@ -using NUnit.Framework; - -namespace Calamari.AzureResourceGroup.Tests -{ - [TestFixture] - public class DeploymentNameFixture +namespace Calamari.AzureResourceGroup.Tests +{ + public class DeploymentNameTests { - [Test] + [Fact] public void GivenShortStepName_Then_Can_Generate_Deployment_Name_Appropriately() { // Given / When var deploymentName = DeploymentName.FromStepName("StepA"); // Then - Assert.That(deploymentName, Has.Length.LessThanOrEqualTo(64)); - Assert.That(deploymentName, Has.Length.EqualTo(38)); - Assert.That(deploymentName, Does.StartWith("stepa-")); + deploymentName.Should() + .HaveLength(38) + .And + .StartWith("stepa-"); } - [Test] + [Fact] public void GivenNormalStepName_Then_Can_Generate_Deployment_Name_Appropriately() { // Given / When var deploymentName = DeploymentName.FromStepName("1234567890123456789012345678901"); // 31 chars // Then - Assert.That(deploymentName, Has.Length.EqualTo(64)); - Assert.That(deploymentName, Does.StartWith("1234567890123456789012345678901-")); + deploymentName.Should().HaveLength(64) + .And + .StartWith("1234567890123456789012345678901-"); } - [Test] + [Fact] public void GivenLongStepName_Then_Can_Generate_Deployment_Name_Appropriately() { // Given / When var deploymentName = DeploymentName.FromStepName("1234567890123456789012345678901234567890"); // 40 chars // Then - Assert.That(deploymentName, Has.Length.EqualTo(64)); - Assert.That(deploymentName, Does.StartWith("1234567890123456789012345678901-")); // 27 Characters Allow + deploymentName.Should() + .HaveLength(64) + .And + .StartWith("1234567890123456789012345678901-"); // 27 Characters Allow } } } \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/GlobalUsings.cs b/source/Calamari.AzureResourceGroup.Tests/GlobalUsings.cs new file mode 100644 index 0000000000..cbd65c225a --- /dev/null +++ b/source/Calamari.AzureResourceGroup.Tests/GlobalUsings.cs @@ -0,0 +1,4 @@ +global using Xunit; +global using FluentAssertions; +global using FluentAssertions.Execution; +global using TestContext = Xunit.TestContext; \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup.Tests/Support/AzureResourceGroupFixture.cs b/source/Calamari.AzureResourceGroup.Tests/Support/AzureResourceGroupFixture.cs new file mode 100644 index 0000000000..df35052484 --- /dev/null +++ b/source/Calamari.AzureResourceGroup.Tests/Support/AzureResourceGroupFixture.cs @@ -0,0 +1,88 @@ +using System; +using System.Threading.Tasks; +using Azure; +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Resources; +using Calamari.Azure; +using Calamari.CloudAccounts; +using Calamari.Testing; +using Calamari.Testing.Azure; + +namespace Calamari.AzureResourceGroup.Tests.Support; + +public class AzureResourceGroupFixture : IAsyncLifetime +{ + ArmClient armClient; + SubscriptionResource subscriptionResource; + + public string ClientId { get; private set; } + public string ClientSecret { get; private set; } + public string SubscriptionId { get; private set; } + public string TenantId { get; private set; } + + public string ResourceGroupName { get; private set; } + public string ResourceGroupLocation { get; private set; } + public ResourceGroupResource ResourceGroupResource { get; private set; } + + + public async ValueTask InitializeAsync() + { + var resourceManagementEndpointBaseUri = + Environment.GetEnvironmentVariable(AccountVariables.ResourceManagementEndPoint) ?? DefaultVariables.ResourceManagementEndpoint; + var activeDirectoryEndpointBaseUri = + Environment.GetEnvironmentVariable(AccountVariables.ActiveDirectoryEndPoint) ?? DefaultVariables.ActiveDirectoryEndpoint; + + ClientId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionClientId, TestContext.Current.CancellationToken); + ClientSecret = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionPassword, TestContext.Current.CancellationToken); + TenantId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionTenantId, TestContext.Current.CancellationToken); + SubscriptionId = await ExternalVariables.Get(ExternalVariable.AzureSubscriptionId, TestContext.Current.CancellationToken); + + ResourceGroupName = AzureTestResourceHelpers.GetResourceGroupName(); + + ResourceGroupLocation = Environment.GetEnvironmentVariable("AZURE_NEW_RESOURCE_REGION") ?? RandomAzureRegion.GetRandomRegionWithExclusions(); + + var servicePrincipalAccount = new AzureServicePrincipalAccount(SubscriptionId, + ClientId, + TenantId, + ClientSecret, + "AzureGlobalCloud", + resourceManagementEndpointBaseUri, + activeDirectoryEndpointBaseUri); + + armClient = servicePrincipalAccount.CreateArmClient(retryOptions => + { + retryOptions.MaxRetries = 5; + retryOptions.Mode = RetryMode.Exponential; + retryOptions.Delay = TimeSpan.FromSeconds(2); + retryOptions.NetworkTimeout = TimeSpan.FromSeconds(200); + }); + + //create the resource group + subscriptionResource = armClient.GetSubscriptionResource(SubscriptionResource.CreateResourceIdentifier(SubscriptionId)); + + var response = await subscriptionResource + .GetResourceGroups() + .CreateOrUpdateAsync(WaitUntil.Completed, + ResourceGroupName, + new ResourceGroupData(new AzureLocation(ResourceGroupLocation)) + { + Tags = + { + [AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysKey] = AzureTestResourceHelpers.ResourceGroupTags.LifetimeInDaysValue, + [AzureTestResourceHelpers.ResourceGroupTags.SourceKey] = AzureTestResourceHelpers.ResourceGroupTags.SourceValue + } + }); + + ResourceGroupResource = response.Value; + } + + public async ValueTask DisposeAsync() + { + await armClient.GetResourceGroupResource(ResourceGroupResource.CreateResourceIdentifier(SubscriptionId, ResourceGroupResource.Data.Name)) + .DeleteAsync(WaitUntil.Started, cancellationToken: TestContext.Current.CancellationToken); + } +} + +[CollectionDefinition(nameof(AzureResourceGroupFixture))] +public class AzureResourceGroupCollection : ICollectionFixture; \ No newline at end of file diff --git a/source/Calamari.AzureResourceGroup/Calamari.AzureResourceGroup.csproj b/source/Calamari.AzureResourceGroup/Calamari.AzureResourceGroup.csproj index d637a549e1..5240e796d3 100644 --- a/source/Calamari.AzureResourceGroup/Calamari.AzureResourceGroup.csproj +++ b/source/Calamari.AzureResourceGroup/Calamari.AzureResourceGroup.csproj @@ -2,13 +2,13 @@ Calamari.AzureResourceGroup Calamari.AzureResourceGroup - 8 + default enable Exe false false win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - net462;net8.0 + net8.0 diff --git a/source/Calamari.AzureScripting.Tests/Calamari.AzureScripting.Tests.csproj b/source/Calamari.AzureScripting.Tests/Calamari.AzureScripting.Tests.csproj index cc004f8bfd..6c5bae0dc8 100644 --- a/source/Calamari.AzureScripting.Tests/Calamari.AzureScripting.Tests.csproj +++ b/source/Calamari.AzureScripting.Tests/Calamari.AzureScripting.Tests.csproj @@ -3,11 +3,11 @@ Calamari.AzureScripting.Tests Calamari.AzureScripting.Tests - 8 + default enable win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 false - net462;net8.0 + net8.0 true @@ -20,6 +20,7 @@ + @@ -50,7 +51,4 @@ - - - diff --git a/source/Calamari.AzureScripting/Calamari.AzureScripting.csproj b/source/Calamari.AzureScripting/Calamari.AzureScripting.csproj index 1079789115..763bdf055f 100644 --- a/source/Calamari.AzureScripting/Calamari.AzureScripting.csproj +++ b/source/Calamari.AzureScripting/Calamari.AzureScripting.csproj @@ -2,14 +2,14 @@ Calamari.AzureScripting Calamari.AzureScripting - 8 + default enable Exe true win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 true false - net462;net8.0 + net8.0 true @@ -17,9 +17,10 @@ - + + @@ -27,10 +28,6 @@ - - - - diff --git a/source/Calamari.AzureServiceFabric.Tests/Calamari.AzureServiceFabric.Tests.csproj b/source/Calamari.AzureServiceFabric.Tests/Calamari.AzureServiceFabric.Tests.csproj index 16eb7cbbe0..3eccb380df 100644 --- a/source/Calamari.AzureServiceFabric.Tests/Calamari.AzureServiceFabric.Tests.csproj +++ b/source/Calamari.AzureServiceFabric.Tests/Calamari.AzureServiceFabric.Tests.csproj @@ -4,9 +4,9 @@ Calamari.AzureServiceFabric.Tests Calamari.AzureServiceFabric.Tests false - net462;net8.0-windows + net8.0-windows win-x64 - 8.0 + default true diff --git a/source/Calamari.AzureServiceFabric/Calamari.AzureServiceFabric.csproj b/source/Calamari.AzureServiceFabric/Calamari.AzureServiceFabric.csproj index 7fd1cb589f..de226cf0eb 100644 --- a/source/Calamari.AzureServiceFabric/Calamari.AzureServiceFabric.csproj +++ b/source/Calamari.AzureServiceFabric/Calamari.AzureServiceFabric.csproj @@ -5,9 +5,9 @@ true false Exe - net462;net8.0-windows + net8.0-windows win-x64 - 8.0 + default true diff --git a/source/Calamari.AzureWebApp.NetCoreShim/Calamari.AzureWebApp.NetCoreShim.csproj b/source/Calamari.AzureWebApp.NetCoreShim/Calamari.AzureWebApp.NetCoreShim.csproj index ab93ccb1f4..0f104191b8 100644 --- a/source/Calamari.AzureWebApp.NetCoreShim/Calamari.AzureWebApp.NetCoreShim.csproj +++ b/source/Calamari.AzureWebApp.NetCoreShim/Calamari.AzureWebApp.NetCoreShim.csproj @@ -3,7 +3,7 @@ Exe net462 - 8.0 + default CS8632 true diff --git a/source/Calamari.AzureWebApp.Tests/Calamari.AzureWebApp.Tests.csproj b/source/Calamari.AzureWebApp.Tests/Calamari.AzureWebApp.Tests.csproj index 08873b7c92..e35abfbf5a 100644 --- a/source/Calamari.AzureWebApp.Tests/Calamari.AzureWebApp.Tests.csproj +++ b/source/Calamari.AzureWebApp.Tests/Calamari.AzureWebApp.Tests.csproj @@ -2,9 +2,9 @@ Calamari.AzureWebApp.Tests Calamari.AzureWebApp.Tests - net462;net8.0 + net8.0 win-x64 - 8.0 + default false true @@ -27,15 +27,16 @@ - + + - + diff --git a/source/Calamari.AzureWebApp/Calamari.AzureWebApp.csproj b/source/Calamari.AzureWebApp/Calamari.AzureWebApp.csproj index 91a6c6ad47..49025d9a42 100644 --- a/source/Calamari.AzureWebApp/Calamari.AzureWebApp.csproj +++ b/source/Calamari.AzureWebApp/Calamari.AzureWebApp.csproj @@ -5,9 +5,10 @@ true false Exe - net462;net8.0 - win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 8.0 + net8.0 + win-x64 + default true @@ -26,11 +27,7 @@ - - - - - + netcoreshim true @@ -56,13 +53,13 @@ - + - - + + - + @@ -73,11 +70,11 @@ - - - - - - - + + + + + + + diff --git a/source/Calamari.CloudAccounts/Calamari.CloudAccounts.csproj b/source/Calamari.CloudAccounts/Calamari.CloudAccounts.csproj index 1b6fc438a5..2b0eabda77 100644 --- a/source/Calamari.CloudAccounts/Calamari.CloudAccounts.csproj +++ b/source/Calamari.CloudAccounts/Calamari.CloudAccounts.csproj @@ -2,7 +2,8 @@ Calamari.CloudAccounts - net462;netstandard2.1 + net8.0 + default Octopus.Calamari.CloudAccounts Calamari.CloudAccounts Octopus Deploy @@ -13,11 +14,6 @@ git - - - - - diff --git a/source/Calamari.Common/Calamari.Common.csproj b/source/Calamari.Common/Calamari.Common.csproj index 59002bb728..49bfd2c14f 100644 --- a/source/Calamari.Common/Calamari.Common.csproj +++ b/source/Calamari.Common/Calamari.Common.csproj @@ -1,8 +1,8 @@  - net462;netstandard2.1 - 8 + net8.0 + default enable anycpu false @@ -13,36 +13,13 @@ https://github.com/OctopusDeploy/Calamari/ https://github.com/OctopusDeploy/Calamari/blob/main/LICENSE.txt - - $(DefineConstants);USE_ALPHAFS_FOR_LONG_FILE_PATH_SUPPORT;HAS_SSL3 - - - $(DefineConstants);USE_NUGET_V3_LIBS;WORKAROUND_FOR_EMPTY_STRING_BUG;HAS_NULLABLE_REF_TYPES - - - CS8600;CS8601;CS8602;CS8603;CS8604;NU5104 - - - + - - - - - - - - - - - - - diff --git a/source/Calamari.Common/Features/Packages/NuGet/LocalNuGetPackage.cs b/source/Calamari.Common/Features/Packages/NuGet/LocalNuGetPackage.cs index c161f78730..2d81232a91 100644 --- a/source/Calamari.Common/Features/Packages/NuGet/LocalNuGetPackage.cs +++ b/source/Calamari.Common/Features/Packages/NuGet/LocalNuGetPackage.cs @@ -1,8 +1,4 @@ -#if USE_NUGET_V3_LIBS -using NuGet.Packaging; -#else -using NuGet; -#endif +using NuGet.Packaging; using System; using System.IO; using Calamari.Common.Plumbing; diff --git a/source/Calamari.Common/Features/Packages/ZipPackageExtractor.cs b/source/Calamari.Common/Features/Packages/ZipPackageExtractor.cs index 1ac1ad363c..71d7bbe42c 100644 --- a/source/Calamari.Common/Features/Packages/ZipPackageExtractor.cs +++ b/source/Calamari.Common/Features/Packages/ZipPackageExtractor.cs @@ -32,18 +32,7 @@ public int Extract(string packageFile, string directory) var filesExtracted = 0; using var inStream = new FileStream(packageFile, FileMode.Open, FileAccess.Read); - -#if NETFRAMEWORK - var readerOptions = new ReaderOptions(); - if (forceUtf8ZipFiles) - { - readerOptions.ArchiveEncoding.Forced = System.Text.Encoding.UTF8; - } - - using var archive = ZipArchive.Open(inStream, readerOptions); -#else using var archive = ZipArchive.Open(inStream); -#endif foreach (var entry in archive.Entries) { diff --git a/source/Calamari.Common/Features/Processes/CommandLine.cs b/source/Calamari.Common/Features/Processes/CommandLine.cs index 9834ed6d58..a6e4e3f813 100644 --- a/source/Calamari.Common/Features/Processes/CommandLine.cs +++ b/source/Calamari.Common/Features/Processes/CommandLine.cs @@ -12,7 +12,7 @@ public class CommandLine readonly List args = new List(); string? action; bool useDotnet; - private Dictionary? environmentVariables = null; + private Dictionary? environmentVariables = null; private bool outputToLog = true; private string? workingDirectory; @@ -217,15 +217,14 @@ string Escape(string argValue, bool escapeArg) last -= 1; } -#if WORKAROUND_FOR_EMPTY_STRING_BUG -// linux under bash on netcore empty "" gets eaten, hand "\0" -// which gets through as a null string - if(argValue == "") - argValue = "\0"; -#endif + // linux under bash on netcore empty "" gets eaten, hand "\0" + // which gets through as a null string + if (argValue == "") + argValue = "\0"; + // Double-quotes are always escaped. return "\"" + argValue.Replace("\"", "\\\"") + "\""; } } } -} +} \ No newline at end of file diff --git a/source/Calamari.Common/NullableReferenceTypeAttributes.cs b/source/Calamari.Common/NullableReferenceTypeAttributes.cs deleted file mode 100644 index 27fc1f8187..0000000000 --- a/source/Calamari.Common/NullableReferenceTypeAttributes.cs +++ /dev/null @@ -1,50 +0,0 @@ -#if !HAS_NULLABLE_REF_TYPES -using System; - -/// -/// These attributes replicate the ones from System.Diagnostics.CodeAnalysis, and are here so we can still compile against the older frameworks. -/// - -namespace Calamari.Common -{ - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = false)] - public sealed class NotNullIfNotNullAttribute : Attribute - { - public NotNullIfNotNullAttribute(string parameterName) - { - this.ParameterName = parameterName; - } - - public string ParameterName { get; } - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] - public sealed class DisallowNullAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] - public sealed class MaybeNullAttribute : Attribute - { - } - - [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] - public sealed class NotNullAttribute : Attribute - { - } - - /// Specifies that when a method returns , the parameter will not be null even if the corresponding type allows it. - [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] - public sealed class NotNullWhenAttribute : Attribute - { - /// Initializes the attribute with the specified return value condition. - /// - /// The return value condition. If the method returns this value, the associated parameter will not be null. - /// - public NotNullWhenAttribute(bool returnValue) => ReturnValue = returnValue; - - /// Gets the return value condition. - public bool ReturnValue { get; } - } -} -#endif \ No newline at end of file diff --git a/source/Calamari.Common/Plumbing/Extensions/EnumerableExtensions.cs b/source/Calamari.Common/Plumbing/Extensions/EnumerableExtensions.cs deleted file mode 100644 index 0a6b184be1..0000000000 --- a/source/Calamari.Common/Plumbing/Extensions/EnumerableExtensions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Calamari.Common.Plumbing.Extensions -{ - public static class EnumerableExtensions - { - internal static IEnumerable DistinctBy(this IEnumerable source, - Func keySelector) - { - var knownKeys = new HashSet(); - foreach (var element in source) - if (knownKeys.Add(keySelector(element))) - yield return element; - } - } -} \ No newline at end of file diff --git a/source/Calamari.Common/Plumbing/Extensions/ScriptingEnvironment.cs b/source/Calamari.Common/Plumbing/Extensions/ScriptingEnvironment.cs index c4a8a3f08f..de17250510 100644 --- a/source/Calamari.Common/Plumbing/Extensions/ScriptingEnvironment.cs +++ b/source/Calamari.Common/Plumbing/Extensions/ScriptingEnvironment.cs @@ -9,15 +9,6 @@ namespace Calamari.Common.Plumbing.Extensions { public class ScriptingEnvironment { - public static bool IsNetFramework() - { -#if NETFRAMEWORK - return true; -#else - return false; -#endif - } - public static bool IsNet45OrNewer() { // Class "ReflectionContext" exists from .NET 4.5 onwards. diff --git a/source/Calamari.Common/Plumbing/Extensions/VersionExtensions.cs b/source/Calamari.Common/Plumbing/Extensions/VersionExtensions.cs index 01a593ee72..b76bef1d94 100644 --- a/source/Calamari.Common/Plumbing/Extensions/VersionExtensions.cs +++ b/source/Calamari.Common/Plumbing/Extensions/VersionExtensions.cs @@ -1,5 +1,4 @@ -#if USE_NUGET_V3_LIBS -using System; +using System; using NuGet.Versioning; using Octopus.Versioning; @@ -23,5 +22,4 @@ public static NuGetVersion ToNuGetVersion(this IVersion version) version.Metadata); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/source/Calamari.Common/Plumbing/FileSystem/CalamariPhysicalFileSystem.cs b/source/Calamari.Common/Plumbing/FileSystem/CalamariPhysicalFileSystem.cs index 579d4f49b1..e0aa131489 100644 --- a/source/Calamari.Common/Plumbing/FileSystem/CalamariPhysicalFileSystem.cs +++ b/source/Calamari.Common/Plumbing/FileSystem/CalamariPhysicalFileSystem.cs @@ -24,9 +24,7 @@ public abstract class CalamariPhysicalFileSystem : ICalamariFileSystem static CalamariPhysicalFileSystem() { -#if NETSTANDARD Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); // Required to use code pages in .NET Standard -#endif DefaultInputEncodingPrecedence = new List { new UTF8Encoding(false, true), diff --git a/source/Calamari.Common/Plumbing/FileSystem/FileOperations.cs b/source/Calamari.Common/Plumbing/FileSystem/FileOperations.cs index 9aa76bd92f..0e6d09c2f7 100644 --- a/source/Calamari.Common/Plumbing/FileSystem/FileOperations.cs +++ b/source/Calamari.Common/Plumbing/FileSystem/FileOperations.cs @@ -156,125 +156,4 @@ public string GetCurrentDirectory() return Directory.GetCurrentDirectory(); } } - -#if USE_ALPHAFS_FOR_LONG_FILE_PATH_SUPPORT - public class LongPathsFile : IFile - { - public void Delete(string path) - { - Alphaleonis.Win32.Filesystem.File.Delete(path); - } - - public bool Exists(string? path) - { - return Alphaleonis.Win32.Filesystem.File.Exists(path); - } - - public byte[] ReadAllBytes(string path) - { - return Alphaleonis.Win32.Filesystem.File.ReadAllBytes(path); - } - - public void WriteAllBytes(string path, byte[] bytes) - { - Alphaleonis.Win32.Filesystem.File.WriteAllBytes(path, bytes); - } - - public void Move(string source, string destination) - { - Alphaleonis.Win32.Filesystem.File.Move(source, destination); - } - - public void SetAttributes(string path, FileAttributes fileAttributes) - { - Alphaleonis.Win32.Filesystem.File.SetAttributes(path, fileAttributes); - } - - public DateTime GetCreationTime(string path) - { - return Alphaleonis.Win32.Filesystem.File.GetCreationTime(path); - } - - public Stream Open(string path, FileMode mode, FileAccess access, FileShare share) - { - return Alphaleonis.Win32.Filesystem.File.Open(path, mode, access, share); - } - - public void Copy(string source, string destination, bool overwrite) - { - Alphaleonis.Win32.Filesystem.File.Copy(source, destination, overwrite); - } - } - - public class LongPathsDirectory : IDirectory - { - public void CreateDirectory(string path) - { - Alphaleonis.Win32.Filesystem.Directory.CreateDirectory(path); - } - - public void Delete(string path, bool recursive) - { - Alphaleonis.Win32.Filesystem.Directory.Delete(path, recursive); - } - - public bool Exists(string? path) - { - return Alphaleonis.Win32.Filesystem.Directory.Exists(path); - } - - public string[] GetFileSystemEntries(string path) - { - return Alphaleonis.Win32.Filesystem.Directory.GetFileSystemEntries(path); - } - - public IEnumerable EnumerateDirectories(string path) - { - return Alphaleonis.Win32.Filesystem.Directory.EnumerateDirectories(path); - } - - public IEnumerable EnumerateDirectoriesRecursively(string path) - { - return Alphaleonis.Win32.Filesystem.Directory.EnumerateDirectories(path, "*", SearchOption.AllDirectories); - } - - public IEnumerable EnumerateFiles(string parentDirectoryPath, params string[] searchPatterns) - { - return EnumerateFiles(parentDirectoryPath, SearchOption.TopDirectoryOnly, searchPatterns); - } - - public IEnumerable EnumerateFilesRecursively(string parentDirectoryPath, params string[] searchPatterns) - { - return EnumerateFiles(parentDirectoryPath, SearchOption.AllDirectories, searchPatterns); - } - - private IEnumerable EnumerateFiles( - string parentDirectoryPath, - SearchOption searchOption, - string[] searchPatterns) - { - // Note we aren't using Alphaleonis.Win32.Filesystem.Directory.EnumerateFiles which handles long file paths due to performance issues. - var parentDirectoryInfo = new DirectoryInfo(parentDirectoryPath); - - return searchPatterns.Length == 0 - ? parentDirectoryInfo.GetFiles("*", searchOption).Select(fi => fi.FullName) - : searchPatterns.SelectMany(pattern => parentDirectoryInfo.GetFiles(pattern, searchOption).Select(fi => fi.FullName)).Distinct(); - } - - public IEnumerable GetFiles(string path, string searchPattern) - { - return Alphaleonis.Win32.Filesystem.Directory.GetFiles(path, searchPattern); - } - - public IEnumerable GetDirectories(string path) - { - return Alphaleonis.Win32.Filesystem.Directory.GetDirectories(path); - } - - public string GetCurrentDirectory() - { - return Alphaleonis.Win32.Filesystem.Directory.GetCurrentDirectory(); - } - } -#endif } \ No newline at end of file diff --git a/source/Calamari.Common/Plumbing/FileSystem/WindowsPhysicalFileSystem.cs b/source/Calamari.Common/Plumbing/FileSystem/WindowsPhysicalFileSystem.cs index cd21d8f2f9..242cd03a5e 100644 --- a/source/Calamari.Common/Plumbing/FileSystem/WindowsPhysicalFileSystem.cs +++ b/source/Calamari.Common/Plumbing/FileSystem/WindowsPhysicalFileSystem.cs @@ -5,14 +5,6 @@ namespace Calamari.Common.Plumbing.FileSystem { public class WindowsPhysicalFileSystem : CalamariPhysicalFileSystem { - public WindowsPhysicalFileSystem() - { -#if USE_ALPHAFS_FOR_LONG_FILE_PATH_SUPPORT - File = new LongPathsFile(); - Directory = new LongPathsDirectory(); -#endif - } - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, out ulong lpFreeBytesAvailable, out ulong lpTotalNumberOfBytes, out ulong lpTotalNumberOfFreeBytes); diff --git a/source/Calamari.Common/Plumbing/SecurityProtocols.cs b/source/Calamari.Common/Plumbing/SecurityProtocols.cs index 19a07d5d54..7592acf454 100644 --- a/source/Calamari.Common/Plumbing/SecurityProtocols.cs +++ b/source/Calamari.Common/Plumbing/SecurityProtocols.cs @@ -14,23 +14,19 @@ public static void EnableAllSecurityProtocols() // TLS1.1 and below was discontinued on MavenCentral as of 18 June 2018 //https://central.sonatype.org/articles/2018/May/04/discontinue-support-for-tlsv11-and-below/ - var securityProcotolTypes = -#if HAS_SSL3 - SecurityProtocolType.Ssl3 | -#endif - SecurityProtocolType.Tls; + var securityProtocolTypes = SecurityProtocolType.Tls; // Enum.IsDefined is used as even though it may be compiled against net40 which does not have the flag // if at runtime it runs on say net475 the flags are present if (Enum.IsDefined(typeof(SecurityProtocolType), 768)) - securityProcotolTypes = securityProcotolTypes | (SecurityProtocolType)768; + securityProtocolTypes |= (SecurityProtocolType)768; if (Enum.IsDefined(typeof(SecurityProtocolType), 3072)) - securityProcotolTypes = securityProcotolTypes | (SecurityProtocolType)3072; + securityProtocolTypes |= (SecurityProtocolType)3072; else Log.Verbose($"TLS1.2 is not supported, this means that some outgoing connections to third party endpoints will not work as they now only support TLS1.2.{Environment.NewLine}This includes GitHub feeds and Maven feeds."); - ServicePointManager.SecurityProtocol = securityProcotolTypes; + ServicePointManager.SecurityProtocol = securityProtocolTypes; } } } \ No newline at end of file diff --git a/source/Calamari.ConsolidateCalamariPackages.Tests/Calamari.ConsolidateCalamariPackages.Tests.csproj b/source/Calamari.ConsolidateCalamariPackages.Tests/Calamari.ConsolidateCalamariPackages.Tests.csproj index 3b0e227376..d2ff2336b5 100644 --- a/source/Calamari.ConsolidateCalamariPackages.Tests/Calamari.ConsolidateCalamariPackages.Tests.csproj +++ b/source/Calamari.ConsolidateCalamariPackages.Tests/Calamari.ConsolidateCalamariPackages.Tests.csproj @@ -2,6 +2,7 @@ net8.0 + default false true diff --git a/source/Calamari.ConsolidateCalamariPackages.Tests/ConsolidationVerificationTests.cs b/source/Calamari.ConsolidateCalamariPackages.Tests/ConsolidationVerificationTests.cs index 79cd5ce933..f5025f474d 100644 --- a/source/Calamari.ConsolidateCalamariPackages.Tests/ConsolidationVerificationTests.cs +++ b/source/Calamari.ConsolidateCalamariPackages.Tests/ConsolidationVerificationTests.cs @@ -29,47 +29,36 @@ public class ConsolidationVerificationTests IConsolidatedPackageIndex consolidatedPackageIndex; string expectedVersion = ""; + const string WindowsX64Arch = "win-x64"; + static readonly string[] NetCoreArchitectures = { "linux-arm", "linux-arm64", "linux-x64", "osx-x64", - "win-x64" + WindowsX64Arch }; - static readonly string[] WindowsOnlyArchitectures = - { - "netfx" - }; - - static readonly string[] AllArchitectures = NetCoreArchitectures.Concat(WindowsOnlyArchitectures).ToArray(); - - static Dictionary PackagesWithDetails(bool isWindows) + static Dictionary PackagesWithDetails() { return new Dictionary { - { "Calamari", new PackagePropertiesToTest(AllArchitectures , true) }, - { "Calamari.Cloud", new PackagePropertiesToTest(WindowsOnlyArchitectures, true) }, - { "Calamari.AzureServiceFabric", new PackagePropertiesToTest(new[] { "netfx", "win-x64" }, false) }, - { "Calamari.AzureAppService", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) }, - { "Calamari.AzureResourceGroup", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) }, - { "Calamari.GoogleCloudScripting", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) }, - { "Calamari.AzureScripting", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) }, - { "Calamari.AzureWebApp", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) }, - { "Calamari.Terraform", new PackagePropertiesToTest(isWindows ? AllArchitectures : NetCoreArchitectures, false) } + { "Calamari", new PackagePropertiesToTest(NetCoreArchitectures, false /* this is no longer a nuget package */) }, + { "Calamari.AzureServiceFabric", new PackagePropertiesToTest(new[] { WindowsX64Arch }, false) }, + { "Calamari.AzureAppService", new PackagePropertiesToTest(NetCoreArchitectures, false) }, + { "Calamari.AzureResourceGroup", new PackagePropertiesToTest(NetCoreArchitectures, false) }, + { "Calamari.GoogleCloudScripting", new PackagePropertiesToTest(NetCoreArchitectures, false) }, + { "Calamari.AzureScripting", new PackagePropertiesToTest(NetCoreArchitectures, false) }, + { "Calamari.AzureWebApp", new PackagePropertiesToTest(new[] { WindowsX64Arch }, false) }, + { "Calamari.Terraform", new PackagePropertiesToTest(NetCoreArchitectures, false) } }; } static bool PackageSupported(string packageId, bool isWindows) { - if (isWindows) - { - // Windows supports everything - return true; - } - - return CalamariPackages.CrossPlatformFlavours.Contains(packageId) || packageId == "Calamari" || packageId == "Calamari.Cloud"; + var packages = BuildableCalamariProjects.GetCalamariProjectsToBuild(isWindows); + return packages.Contains(packageId); } static IEnumerable ExpectedPackages() @@ -78,7 +67,7 @@ static IEnumerable ExpectedPackages() var isWindows = isWindowsEnvValue == null ? RuntimeInformation.IsOSPlatform(OSPlatform.Windows) : bool.Parse(isWindowsEnvValue); - return PackagesWithDetails(isWindows) + return PackagesWithDetails() .Where(kvp => PackageSupported(kvp.Key, isWindows)) .Select(kvp => kvp.Key); } @@ -89,7 +78,7 @@ static IEnumerable ExpectedPackageArchitectureMappings() var isWindows = isWindowsEnvValue == null ? RuntimeInformation.IsOSPlatform(OSPlatform.Windows) : bool.Parse(isWindowsEnvValue); - return PackagesWithDetails(isWindows) + return PackagesWithDetails() .Where(kvp => PackageSupported(kvp.Key, isWindows)) .Select(kvp => new TestCaseData(kvp.Key, kvp.Value.Architectures).SetName($"Package_{kvp.Key}_HasExpectedArchitectures")); } @@ -100,10 +89,9 @@ static IEnumerable ExpectedPackageNugetStatus() var isWindows = isWindowsEnvValue == null ? RuntimeInformation.IsOSPlatform(OSPlatform.Windows) : bool.Parse(isWindowsEnvValue); - return PackagesWithDetails(isWindows) - .Where(kvp => PackageSupported(kvp.Key, isWindows)) - .Select(kvp => new TestCaseData(kvp.Key, kvp.Value.IsNupkg).SetName($"Package {kvp.Key} Has Expected Nuget PackageFlag")); - + return PackagesWithDetails() + .Where(kvp => PackageSupported(kvp.Key, isWindows)) + .Select(kvp => new TestCaseData(kvp.Key, kvp.Value.IsNupkg).SetName($"Package {kvp.Key} Has Expected Nuget PackageFlag")); } [SetUp] diff --git a/source/Calamari.ConsolidateCalamariPackages/BuildableCalamariProjects.cs b/source/Calamari.ConsolidateCalamariPackages/BuildableCalamariProjects.cs new file mode 100644 index 0000000000..3960b354ea --- /dev/null +++ b/source/Calamari.ConsolidateCalamariPackages/BuildableCalamariProjects.cs @@ -0,0 +1,27 @@ +using System; + +namespace Octopus.Calamari.ConsolidatedPackage +{ + public static class BuildableCalamariProjects + { + public static string[] GetCalamariProjectsToBuild(bool isWindows) + { + return isWindows + ? Windows + : NonWindows; + } + + static readonly string[] NonWindows = + [ + "Calamari", + "Calamari.AzureAppService", + "Calamari.AzureResourceGroup", + "Calamari.GoogleCloudScripting", + "Calamari.AzureScripting", + "Calamari.AzureWebApp", + "Calamari.Terraform" + ]; + + static string[] Windows => [..NonWindows, "Calamari.AzureServiceFabric"]; + } +} \ No newline at end of file diff --git a/source/Calamari.ConsolidateCalamariPackages/CalamariPackages.cs b/source/Calamari.ConsolidateCalamariPackages/CalamariPackages.cs deleted file mode 100644 index e8fcaac811..0000000000 --- a/source/Calamari.ConsolidateCalamariPackages/CalamariPackages.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Octopus.Calamari.ConsolidatedPackage -{ - public static class CalamariPackages - { - public static List Flavours => CrossPlatformFlavours.Concat(WindowsOnlyNetCoreEnabledFlavours).ToList(); - - public static readonly List CrossPlatformFlavours = new() - { - "Calamari.AzureAppService", - "Calamari.AzureResourceGroup", - "Calamari.GoogleCloudScripting", - "Calamari.AzureScripting", - "Calamari.AzureWebApp", - "Calamari.Terraform" - }; - - static readonly List WindowsOnlyNetCoreEnabledFlavours = new() - { - "Calamari.AzureServiceFabric" - }; - } -} \ No newline at end of file diff --git a/source/Calamari.ConsolidateCalamariPackages/Consolidate.cs b/source/Calamari.ConsolidateCalamariPackages/Consolidate.cs index 16416d4416..7d8e36870b 100644 --- a/source/Calamari.ConsolidateCalamariPackages/Consolidate.cs +++ b/source/Calamari.ConsolidateCalamariPackages/Consolidate.cs @@ -17,7 +17,7 @@ public Consolidate(ILogger log) this.log = log; } - public string AssemblyVersion { get; set; } = (((AssemblyInformationalVersionAttribute) typeof(Consolidate).Assembly.GetCustomAttribute(typeof(AssemblyInformationalVersionAttribute))!)!).InformationalVersion; + public string AssemblyVersion { get; set; } = (((AssemblyInformationalVersionAttribute)typeof(Consolidate).Assembly.GetCustomAttribute(typeof(AssemblyInformationalVersionAttribute))!)!).InformationalVersion; public (bool result, string packageFileName) Execute(string outputDirectory, IEnumerable packageReferences) { @@ -52,7 +52,7 @@ public Consolidate(ILogger log) log.Information($"Package creation took {sw.ElapsedMilliseconds:n0}ms"); - foreach (var item in indexEntries.Select(i => new {i.PackageId, i.Platform}).Distinct()) + foreach (var item in indexEntries.Select(i => new { i.PackageId, i.Platform }).Distinct()) log.Information($"Packaged {item.PackageId} for {item.Platform}"); return (true, destination); @@ -61,19 +61,9 @@ public Consolidate(ILogger log) static IReadOnlyList GetPackages(Hasher hasher, IEnumerable packageReferences) { - - var packageReferencesList = packageReferences.ToList(); - - var calamariPackages = packageReferencesList - .Where(p => !CalamariPackages.Flavours.Contains(p.Name)) - .Where(p => p.Name.StartsWith("Calamari")) - .Select(p => new CalamariPackageReference(hasher, p)); - - var calamariFlavourPackages = packageReferencesList - .Where(p => CalamariPackages.Flavours.Contains(p.Name)) - .Select(p => new CalamariFlavourPackageReference(hasher, p)); - - return calamariPackages.Concat(calamariFlavourPackages).ToArray(); + return packageReferences + .Select(p => new CalamariFlavourPackageReference(hasher, p)) + .ToList(); } } -} +} \ No newline at end of file diff --git a/source/Calamari.GoogleCloudAccounts/Calamari.GoogleCloudAccounts.csproj b/source/Calamari.GoogleCloudAccounts/Calamari.GoogleCloudAccounts.csproj index 1126f5d78a..518f285456 100644 --- a/source/Calamari.GoogleCloudAccounts/Calamari.GoogleCloudAccounts.csproj +++ b/source/Calamari.GoogleCloudAccounts/Calamari.GoogleCloudAccounts.csproj @@ -2,18 +2,13 @@ Calamari.GoogleCloudAccounts - net462;netstandard2.1 - latest + net8.0 + default CS8632 true - - - - - diff --git a/source/Calamari.GoogleCloudScripting.Tests/Calamari.GoogleCloudScripting.Tests.csproj b/source/Calamari.GoogleCloudScripting.Tests/Calamari.GoogleCloudScripting.Tests.csproj index f1e08445dc..a94cce45ed 100644 --- a/source/Calamari.GoogleCloudScripting.Tests/Calamari.GoogleCloudScripting.Tests.csproj +++ b/source/Calamari.GoogleCloudScripting.Tests/Calamari.GoogleCloudScripting.Tests.csproj @@ -3,10 +3,10 @@ Calamari.GoogleCloudScripting.Tests win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - 8 + default false enable - net462;net8.0 + net8.0 true diff --git a/source/Calamari.GoogleCloudScripting/Calamari.GoogleCloudScripting.csproj b/source/Calamari.GoogleCloudScripting/Calamari.GoogleCloudScripting.csproj index 3a2216edae..0beec07bdc 100644 --- a/source/Calamari.GoogleCloudScripting/Calamari.GoogleCloudScripting.csproj +++ b/source/Calamari.GoogleCloudScripting/Calamari.GoogleCloudScripting.csproj @@ -4,10 +4,10 @@ Calamari.GoogleCloudScripting Exe win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - 8 + default false false - net462;net8.0 + net8.0 CS8632 true diff --git a/source/Calamari.Scripting/Calamari.Scripting.csproj b/source/Calamari.Scripting/Calamari.Scripting.csproj index 1ce4bfecdc..5fe1e153af 100644 --- a/source/Calamari.Scripting/Calamari.Scripting.csproj +++ b/source/Calamari.Scripting/Calamari.Scripting.csproj @@ -7,8 +7,8 @@ enable win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 true - 9 - net462;net8.0 + default + net8.0 true @@ -19,11 +19,7 @@ - - - CS8600;CS8601;CS8602;CS8603;CS8604 - - + $(DefineConstants);HAS_NULLABLE_REF_TYPES diff --git a/source/Calamari.Shared/Calamari.Shared.csproj b/source/Calamari.Shared/Calamari.Shared.csproj index 2cb6e18649..111c189d01 100644 --- a/source/Calamari.Shared/Calamari.Shared.csproj +++ b/source/Calamari.Shared/Calamari.Shared.csproj @@ -21,19 +21,9 @@ Calamari - 8 + default enable - net462;netstandard2.1 - - - $(DefineConstants);NETFX;USE_NUGET_V2_LIBS;USE_OCTODIFF_EXE; - anycpu - - - $(DefineConstants);USE_NUGET_V3_LIBS - - - CS8600;CS8601;CS8602;CS8603;CS8604;DE0003;DE0004 + net8.0 @@ -56,8 +46,6 @@ - - @@ -68,29 +56,6 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/source/Calamari.Shared/Commands/ApplyDeltaCommand.cs b/source/Calamari.Shared/Commands/ApplyDeltaCommand.cs index 5986e7767c..8ebdbd357a 100644 --- a/source/Calamari.Shared/Commands/ApplyDeltaCommand.cs +++ b/source/Calamari.Shared/Commands/ApplyDeltaCommand.cs @@ -54,11 +54,7 @@ public override int Execute(string[] commandLineArguments) ValidateParameters(out basisFilePath, out deltaFilePath, out newFilePath); var tempNewFilePath = newFilePath + ".partial"; -#if USE_OCTODIFF_EXE - var factory = new OctoDiffCommandLineRunner(commandLineRunner); -#else var factory = new OctoDiffLibraryCallRunner(); -#endif var octoDiff = factory.OctoDiff .Action("patch") .PositionalArgument(basisFilePath) diff --git a/source/Calamari.Shared/Integration/Certificates/CryptoKeySecurityAccessRules.cs b/source/Calamari.Shared/Integration/Certificates/CryptoKeySecurityAccessRules.cs index 29ce0b6036..d8a55f1642 100644 --- a/source/Calamari.Shared/Integration/Certificates/CryptoKeySecurityAccessRules.cs +++ b/source/Calamari.Shared/Integration/Certificates/CryptoKeySecurityAccessRules.cs @@ -14,7 +14,6 @@ namespace Calamari.Integration.Certificates { - #if !NETFX [Flags] public enum CryptoKeyRights { @@ -254,7 +253,7 @@ internal static CryptoKeyRights RightsFromAccessMask(int accessMask) return (CryptoKeyRights) accessMask; } } -#endif + public static class CryptoKeySecurityAccessRules { diff --git a/source/Calamari.Shared/Integration/Packages/Download/FeedCredentialsProvider.cs b/source/Calamari.Shared/Integration/Packages/Download/FeedCredentialsProvider.cs deleted file mode 100644 index f8e5dba04e..0000000000 --- a/source/Calamari.Shared/Integration/Packages/Download/FeedCredentialsProvider.cs +++ /dev/null @@ -1,95 +0,0 @@ -#if USE_NUGET_V2_LIBS -using System; -using System.Collections.Concurrent; -using System.Net; -using NuGet; - -namespace Calamari.Integration.Packages.Download -{ - public class FeedCredentialsProvider : ICredentialProvider - { - FeedCredentialsProvider() - { - } - - public static FeedCredentialsProvider Instance = new FeedCredentialsProvider(); - static readonly ConcurrentDictionary Credentials = new ConcurrentDictionary(); - static readonly ConcurrentDictionary Retries = new ConcurrentDictionary(); - - public void SetCredentials(Uri uri, ICredentials credential) - { - Credentials[Canonicalize(uri)] = credential; - } - - public ICredentials GetCredentials(Uri uri, IWebProxy proxy, CredentialType credentialType, bool retrying) - { - var url = Canonicalize(uri); - var retry = Retries.GetOrAdd(url, _ => new RetryTracker()); - - if (!retrying) - { - retry.Reset(); - } - else - { - var retryAllowed = retry.AttemptRetry(); - if (!retryAllowed) - return null; - } - - return new DynamicCachedCredential(url); - } - - ICredentials GetCurrentCredentials(string url) - { - ICredentials credential; - if (!Credentials.TryGetValue(url, out credential)) - { - credential = CredentialCache.DefaultNetworkCredentials; - } - - return credential; - } - - string Canonicalize(Uri uri) - { - return uri.Authority.ToLowerInvariant().Trim(); - } - - public class RetryTracker - { - const int MaxAttempts = 3; - int currentCount; - - public bool AttemptRetry() - { - if (currentCount > MaxAttempts) return false; - - currentCount++; - return true; - } - - public void Reset() - { - currentCount = 0; - } - } - - class DynamicCachedCredential : CredentialCache, ICredentials - { - readonly string url; - - public DynamicCachedCredential(string url) - { - this.url = url; - } - - NetworkCredential ICredentials.GetCredential(Uri uri, string authType) - { - var credential = Instance.GetCurrentCredentials(url); - return credential.GetCredential(uri, authType); - } - } - } -} -#endif \ No newline at end of file diff --git a/source/Calamari.Shared/Integration/Packages/Download/FixedFilePathResolver.cs b/source/Calamari.Shared/Integration/Packages/Download/FixedFilePathResolver.cs deleted file mode 100644 index 7ad8fbf500..0000000000 --- a/source/Calamari.Shared/Integration/Packages/Download/FixedFilePathResolver.cs +++ /dev/null @@ -1,63 +0,0 @@ -#if USE_NUGET_V2_LIBS -using System; -using System.IO; -using NuGet; - -namespace Calamari.Integration.Packages.Download -{ - public class FixedFilePathResolver : IPackagePathResolver - { - readonly string packageName; - readonly string filePathNameToReturn; - - public FixedFilePathResolver(string packageName, string filePathNameToReturn) - { - if (packageName == null) - throw new ArgumentNullException("packageName"); - if (filePathNameToReturn == null) - throw new ArgumentNullException("filePathNameToReturn"); - - this.packageName = packageName; - this.filePathNameToReturn = filePathNameToReturn; - } - - public string GetInstallPath(IPackage package) - { - EnsureRightPackage(package.Id); - return Path.GetDirectoryName(filePathNameToReturn); - } - - public string GetPackageDirectory(IPackage package) - { - return GetPackageDirectory(package.Id, package.Version); - } - - public string GetPackageFileName(IPackage package) - { - return GetPackageFileName(package.Id, package.Version); - } - - public string GetPackageDirectory(string packageId, SemanticVersion version) - { - EnsureRightPackage(packageId); - return string.Empty; - } - - public string GetPackageFileName(string packageId, SemanticVersion version) - { - EnsureRightPackage(packageId); - return Path.GetFileName(filePathNameToReturn); - } - - void EnsureRightPackage(string packageId) - { - var samePackage = string.Equals(packageId, packageName, StringComparison.OrdinalIgnoreCase); - - if (!samePackage) - { - throw new ArgumentException(string.Format("Expected to be asked for the path for package {0}, but was instead asked for the path for package {1}", packageName, packageId)); - } - } - } -} -#endif \ No newline at end of file diff --git a/source/Calamari.Shared/Integration/Packages/Download/NuGetPackageDownloader.cs b/source/Calamari.Shared/Integration/Packages/Download/NuGetPackageDownloader.cs index 6abc0b65e1..c281efb2f0 100644 --- a/source/Calamari.Shared/Integration/Packages/Download/NuGetPackageDownloader.cs +++ b/source/Calamari.Shared/Integration/Packages/Download/NuGetPackageDownloader.cs @@ -11,11 +11,8 @@ using Calamari.Integration.Packages.NuGet; using Octopus.Versioning; using PackageName = Calamari.Common.Features.Packages.PackageName; -#if USE_NUGET_V2_LIBS -using NuGet; -#else using NuGet.Packaging; -#endif + namespace Calamari.Integration.Packages.Download { @@ -124,11 +121,8 @@ PackagePhysicalFileMetadata DownloadPackage( void CheckWhetherThePackageHasDependencies(PackagePhysicalFileMetadata pkg) { var nuGetMetadata = new LocalNuGetPackage(pkg.FullFilePath).Metadata; -#if USE_NUGET_V3_LIBS var dependencies = nuGetMetadata.DependencyGroups.SelectMany(ds => ds.Packages).ToArray(); -#else - var dependencies = nuGetMetadata.DependencySets.SelectMany(ds => ds.Dependencies).ToArray(); -#endif + if (dependencies.Any()) Log.Info( "NuGet packages with dependencies are not currently supported, and dependencies won't be installed on the Tentacle. The package '{0} {1}' appears to have the following dependencies: {2}. For more information please see {3}", diff --git a/source/Calamari.Shared/Integration/Packages/NuGet/InternalNuGetPackageDownloader.cs b/source/Calamari.Shared/Integration/Packages/NuGet/InternalNuGetPackageDownloader.cs index a3c03fb476..6618f3097a 100644 --- a/source/Calamari.Shared/Integration/Packages/NuGet/InternalNuGetPackageDownloader.cs +++ b/source/Calamari.Shared/Integration/Packages/NuGet/InternalNuGetPackageDownloader.cs @@ -98,60 +98,10 @@ private void DownloadPackageAction(string packageId, IVersion version, Uri feedU return; } -#if USE_NUGET_V2_LIBS - var timeout = GetHttpTimeout(); - if (IsHttp(feedUri.ToString())) - { - if (NuGetV3Downloader.CanHandle(feedUri, feedCredentials, timeout)) - { - NuGetV3Downloader.DownloadPackage(packageId, version, feedUri, feedCredentials, targetFilePath, timeout); - } - else - { - WarnIfHttpTimeoutHasBeenSet(); - NuGetV2Downloader.DownloadPackage(packageId, version.ToString(), feedUri, feedCredentials, targetFilePath); - } - } -#else - else - { WarnIfHttpTimeoutHasBeenSet(); NuGetV3LibDownloader.DownloadPackage(packageId, version, feedUri, feedCredentials, targetFilePath); - } -#endif - } - -#if USE_NUGET_V2_LIBS - TimeSpan GetHttpTimeout() - { - const string expectedTimespanFormat = "c"; - - // Equal to Timeout.InfiniteTimeSpan, which isn't available in net40 - var defaultTimeout = new TimeSpan(0, 0, 0, 0, -1); - - var rawTimeout = variables.Get(KnownVariables.NugetHttpTimeout); - if (string.IsNullOrWhiteSpace(rawTimeout)) - { - return defaultTimeout; - } - - if (TimeSpan.TryParseExact(rawTimeout, expectedTimespanFormat, null, out var parsedTimeout)) - { - return parsedTimeout; - } - - var exampleTimespan = new TimeSpan(0, 0, 1, 0).ToString(expectedTimespanFormat); - - var message = $"The variable {KnownVariables.NugetHttpTimeout} couldn't be parsed as a timespan. " + - $"Expected a value like '{exampleTimespan}' but received '{rawTimeout}'. " + - $"Defaulting to '{defaultTimeout.ToString(expectedTimespanFormat)}'."; - - Log.Warn(message); - return defaultTimeout; } - -#endif void WarnIfHttpTimeoutHasBeenSet() { diff --git a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV2Downloader.cs b/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV2Downloader.cs deleted file mode 100644 index e569e7b351..0000000000 --- a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV2Downloader.cs +++ /dev/null @@ -1,68 +0,0 @@ -#if USE_NUGET_V2_LIBS -using System; -using System.IO; -using System.Net; -using Calamari.Common.Plumbing.Logging; -using Calamari.Integration.Packages.Download; -using NuGet; -using SemanticVersion = NuGet.SemanticVersion; - -namespace Calamari.Integration.Packages.NuGet -{ - public class NuGetV2Downloader - { - public static void DownloadPackage(string packageId, string packageVersion, Uri feedUri, - ICredentials feedCredentials, string targetFilePath) - { - SetFeedCredentials(feedUri, feedCredentials); - - var package = FindPackage(packageId, packageVersion, feedUri, out var downloader); - DownloadPackage(package, targetFilePath, downloader); - } - - private static IPackage FindPackage(string packageId, string packageVersion, Uri feed, out PackageDownloader downloader) - { - var remoteRepository = PackageRepositoryFactory.Default.CreateRepository(feed.AbsoluteUri); - - downloader = remoteRepository is DataServicePackageRepository dspr ? dspr.PackageDownloader : null; - - var requiredVersion = new SemanticVersion(packageVersion); - var package = remoteRepository.FindPackage(packageId, requiredVersion, true, true); - - if (package == null) - throw new Exception($"Could not find package {packageId} {packageVersion} in feed: '{feed}'"); - - if (!requiredVersion.Equals(package.Version)) - { - throw new Exception($"The package version '{package.Version}' returned from the package repository doesn't match the requested package version '{requiredVersion}'."); - } - - return package; - } - - private static void DownloadPackage(IPackage package, string fullPathToDownloadTo, PackageDownloader directDownloader) - { - Log.VerboseFormat("Found package {0} v{1}", package.Id, package.Version); - Log.Verbose("Downloading to: " + fullPathToDownloadTo); - - if (package is DataServicePackage dsp && directDownloader != null) - { - Log.Verbose("A direct download is possible; bypassing the NuGet machine cache"); - using (var targetFile = new FileStream(fullPathToDownloadTo, FileMode.CreateNew)) - directDownloader.DownloadPackage(dsp.DownloadUrl, dsp, targetFile); - return; - } - - var physical = new PhysicalFileSystem(Path.GetDirectoryName(fullPathToDownloadTo)); - var local = new LocalPackageRepository(new FixedFilePathResolver(package.Id, fullPathToDownloadTo), physical); - local.AddPackage(package); - } - - static void SetFeedCredentials(Uri feedUri, ICredentials feedCredentials) - { - FeedCredentialsProvider.Instance.SetCredentials(feedUri, feedCredentials); - HttpClient.DefaultCredentialProvider = FeedCredentialsProvider.Instance; - } - } -} -#endif \ No newline at end of file diff --git a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3Downloader.cs b/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3Downloader.cs deleted file mode 100644 index 28b1e0acc9..0000000000 --- a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3Downloader.cs +++ /dev/null @@ -1,322 +0,0 @@ -// Much of this class was based on code from https://github.com/NuGet/NuGet.Client. It was ported, as the NuGet libraries are .NET 4.5 and Calamari is .NET 4.0 -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.// -#if USE_NUGET_V2_LIBS -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Web; -using Calamari.Common.Commands; -using Calamari.Common.Plumbing.Logging; -using Calamari.Deployment; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Octopus.CoreUtilities.Extensions; -using Octopus.Versioning; -using Octopus.Versioning.Semver; - -namespace Calamari.Integration.Packages.NuGet -{ - internal static class NuGetV3Downloader - { - public static bool CanHandle(Uri feedUri, ICredentials feedCredentials, TimeSpan httpTimeout) - { - if (feedUri.ToString().EndsWith(".json", StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return IsJsonEndpoint(feedUri, feedCredentials, httpTimeout); - } - - static bool IsJsonEndpoint(Uri feedUri, ICredentials feedCredentials, TimeSpan httpTimeout) - { - var request = new HttpRequestMessage(HttpMethod.Get, feedUri); - - using (var httpClient = CreateHttpClient(feedCredentials, httpTimeout)) - { - var sending = httpClient.SendAsync(request); - sending.Wait(); - - using (var response = sending.Result) - { - response.EnsureSuccessStatusCode(); - - return response.Content.Headers.ContentType.MediaType == "application/json"; - } - } - } - - class PackageIdentifier - { - public PackageIdentifier(string packageId, IVersion version) - { - Id = packageId.ToLowerInvariant(); - Version = version.ToString().ToLowerInvariant(); - SemanticVersion = version; - SemanticVersionWithoutMetadata = new SemanticVersion(version.Major, version.Minor, version.Patch, version.Revision, version.Release, null); - } - - public string Id { get; } - public string Version { get; } - public IVersion SemanticVersion { get; } - public IVersion SemanticVersionWithoutMetadata { get; } - } - - public static void DownloadPackage(string packageId, IVersion version, Uri feedUri, ICredentials feedCredentials, string targetFilePath, TimeSpan httpTimeout) - { - var packageIdentifier = new PackageIdentifier(packageId, version); - - var downloadUri = GetDownloadUri(packageIdentifier, feedUri, feedCredentials, httpTimeout); - if (downloadUri == null) - { - throw new InvalidOperationException($"Unable to find url to download package: {version} with version: {version} from feed: {feedUri}"); - } - - Log.Verbose($"Downloading package from '{downloadUri}'"); - - using (var nupkgFile = new FileStream(targetFilePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None)) - { - GetHttp(downloadUri, feedCredentials, httpTimeout, pkgStream => - { - pkgStream.CopyTo(nupkgFile); - }); - } - } - - static Uri? GetDownloadUri(PackageIdentifier packageIdentifier, Uri feedUri, ICredentials feedCredentials, TimeSpan httpTimeout) - { - var json = GetServiceIndexJson(feedUri, feedCredentials, httpTimeout); - if (json == null) - { - throw new CommandException($"'{feedUri}' is not a valid NuGet v3 feed"); - } - - var resources = GetServiceResources(json); - - var packageBaseDownloadUri = GetPackageBaseDownloadUri(resources, packageIdentifier); - if (packageBaseDownloadUri != null) return packageBaseDownloadUri; - - return GetPackageRegistrationDownloadUri(feedCredentials, httpTimeout, resources, packageIdentifier); - } - - static Uri? GetPackageRegistrationDownloadUri(ICredentials feedCredentials, TimeSpan httpTimeout, IDictionary> resources, PackageIdentifier packageIdentifier) - { - var packageRegistrationUri = GetPackageRegistrationUri(resources, packageIdentifier.Id); - var packageRegistrationResponse = GetJsonResponse(packageRegistrationUri, feedCredentials, httpTimeout); - - // Package Registration Response structure - // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#response - var registrationPages = packageRegistrationResponse["items"]; - - // Registration Page structure - // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-page-object - foreach (var registrationPage in registrationPages) - { - var registrationLeaves = registrationPage["items"]; - if (registrationLeaves == null) - { - // narrow version to specific page. - var versionedRegistrationPage = registrationPages.FirstOrDefault(x => VersionComparer.Default.Compare(new SemanticVersion(x["lower"].ToString()), packageIdentifier.SemanticVersionWithoutMetadata) <= 0 && VersionComparer.Default.Compare(new SemanticVersion(x["upper"].ToString()), packageIdentifier.SemanticVersionWithoutMetadata) >= 0); - - // If we can't find a page for the version we are looking for, return null. - if (versionedRegistrationPage == null) return null; - - var versionedRegistrationPageResponse = GetJsonResponse(new Uri(versionedRegistrationPage["@id"].ToString()), feedCredentials, httpTimeout); - registrationLeaves = versionedRegistrationPageResponse["items"]; - } - - // Leaf Structure - // https://docs.microsoft.com/en-us/nuget/api/registration-base-url-resource#registration-leaf-object-in-a-page - var leaf = registrationLeaves.FirstOrDefault(x => string.Equals(x["catalogEntry"]["version"].ToString(), packageIdentifier.Version, StringComparison.OrdinalIgnoreCase)); - // If we can't find the leaf registration for the version we are looking for, return null. - if (leaf == null) return null; - - var contentUri = leaf["packageContent"].ToString(); - - // Note: We reformat the packageContent Uri here as Artifactory (and possibly others) does not include +metadata suffixes on its packageContent Uri's - var downloadUri = new Uri($"{contentUri.Remove(contentUri.LastIndexOfAny("/".ToCharArray()) + 1)}{packageIdentifier.Version}"); - - return downloadUri; - } - - return null; - } - - static Uri? GetPackageBaseDownloadUri(IDictionary> resources, PackageIdentifier packageIdentifier) - { - var packageBaseUri = GetPackageBaseUri(resources); - - if (packageBaseUri?.AbsoluteUri.TrimEnd('/') != null) - { - return new Uri($"{packageBaseUri}/{packageIdentifier.Id}/{packageIdentifier.Version}/{packageIdentifier.Id}.{packageIdentifier.Version}.nupkg"); - } - - return null; - } - - static Uri GetPackageRegistrationUri(IDictionary> resources, string normalizedId) - { - var registrationUrl = NuGetServiceTypes.RegistrationsBaseUrl - .Where(serviceType => resources.ContainsKey(serviceType)) - .SelectMany(serviceType => resources[serviceType]) - .First() - .OriginalString.TrimEnd('/'); - - var packageRegistrationUri = new Uri($"{registrationUrl}/{normalizedId}/index.json"); - return packageRegistrationUri; - } - - static HttpClient CreateHttpClient(ICredentials credentials, TimeSpan httpTimeout) - { - var handler = new WebRequestHandler - { - Credentials = credentials, - AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate - }; - - var httpClient = new HttpClient(handler) - { - Timeout = httpTimeout - }; - - httpClient.DefaultRequestHeaders.Add("user-agent", "NuGet Client V3/3.4.3"); - - return httpClient; - } - - static void GetHttp(Uri uri, ICredentials credentials, TimeSpan httpTimeout, Action processContent) - { - var request = new HttpRequestMessage(HttpMethod.Get, uri); - - using (var httpClient = CreateHttpClient(credentials, httpTimeout)) - { - var sending = httpClient.SendAsync(request); - sending.Wait(); - using (var response = sending.Result) - { - response.EnsureSuccessStatusCode(); - var readingStream = response.Content.ReadAsStreamAsync(); - readingStream.Wait(); - processContent(readingStream.Result); - } - } - } - - static Uri? GetPackageBaseUri(IDictionary> resources) - { - // If index.json contains a flat container resource use that to directly - // construct package download urls. - if (resources.ContainsKey(NuGetServiceTypes.PackageBaseAddress)) - return resources[NuGetServiceTypes.PackageBaseAddress].FirstOrDefault(); - return null; - } - - static JObject? GetServiceIndexJson(Uri feedUri, ICredentials feedCredentials, TimeSpan httpTimeout) - { - var json = GetJsonResponse(feedUri, feedCredentials, httpTimeout); - - if (!IsValidV3Json(json)) return null; - - return json; - } - - static JObject GetJsonResponse(Uri feedUri, ICredentials feedCredentials, TimeSpan httpTimeout) - { - // Parse JSON for package base URL - JObject json = null; - GetHttp(feedUri, - feedCredentials, - httpTimeout, - stream => - { - using (var streamReader = new StreamReader(stream)) - using (var jsonReader = new JsonTextReader(streamReader)) - { - json = JObject.Load(jsonReader); - } - }); - return json; - } - - static bool IsValidV3Json(JObject json) - { - // Use SemVer instead of NuGetVersion, the service index should always be - // in strict SemVer format - JToken versionToken; - if (json.TryGetValue("version", out versionToken) && - versionToken.Type == JTokenType.String) - { - var version = VersionFactory.TryCreateSemanticVersion((string)versionToken); - if (version != null && version.Major == 3) - { - return true; - } - } - return false; - } - - static IDictionary> GetServiceResources(JObject index) - { - var result = new Dictionary>(); - - JToken resources; - if (index.TryGetValue("resources", out resources)) - { - foreach (var resource in resources) - { - JToken type = resource["@type"]; - JToken id = resource["@id"]; - - if (type == null || id == null) - { - continue; - } - - if (type.Type == JTokenType.Array) - { - foreach (var nType in type) - { - AddEndpoint(result, nType, id); - } - } - else - { - AddEndpoint(result, type, id); - } - } - } - - return result; - } - - static void AddEndpoint(IDictionary> result, JToken typeToken, JToken idToken) - { - string type = (string)typeToken; - string id = (string)idToken; - - if (type == null || id == null) - { - return; - } - - List ids; - if (!result.TryGetValue(type, out ids)) - { - ids = new List(); - result.Add(type, ids); - } - - Uri uri; - if (Uri.TryCreate(id, UriKind.Absolute, out uri)) - { - ids.Add(new Uri(id)); - } - } - } -} -#endif \ No newline at end of file diff --git a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3LibDownloader.cs b/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3LibDownloader.cs index eed44db148..a18e0fc838 100644 --- a/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3LibDownloader.cs +++ b/source/Calamari.Shared/Integration/Packages/NuGet/NuGetV3LibDownloader.cs @@ -1,6 +1,4 @@ -#if USE_NUGET_V3_LIBS - -using System; +using System; using System.Net; using System.Threading; using NuGet.Configuration; @@ -107,6 +105,4 @@ public Task LogAsync(ILogMessage message) } } -} - -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/source/Calamari.Shared/Util/GoDurationParser.cs b/source/Calamari.Shared/Util/GoDurationParser.cs index 87a212671c..487cd0cc71 100644 --- a/source/Calamari.Shared/Util/GoDurationParser.cs +++ b/source/Calamari.Shared/Util/GoDurationParser.cs @@ -47,7 +47,6 @@ static TimeSpan ParseDuration(string duration, bool hasBeenValidated) var matches = DurationRegex.Matches(duration); var result = matches - .Cast() .Select(m => { var value = m.Groups[1].Value; @@ -58,12 +57,8 @@ static TimeSpan ParseDuration(string duration, bool hasBeenValidated) { return TimeSpan.Zero; } - -#if NETFRAMEWORK - return TimeSpan.FromTicks((long)Math.Floor(result.InitialTimeSpan.Ticks * double.Parse(value))); -#else + return result.InitialTimeSpan * double.Parse(value); -#endif }) .Aggregate((accumulator, timeSpan) => accumulator + timeSpan); diff --git a/source/Calamari.Terraform.Tests/Calamari.Terraform.Tests.csproj b/source/Calamari.Terraform.Tests/Calamari.Terraform.Tests.csproj index 033202e388..2f033d36dd 100644 --- a/source/Calamari.Terraform.Tests/Calamari.Terraform.Tests.csproj +++ b/source/Calamari.Terraform.Tests/Calamari.Terraform.Tests.csproj @@ -5,8 +5,8 @@ Calamari.Terraform.Tests win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 false - 9 - net462;net8.0 + default + net8.0 CS8632 true diff --git a/source/Calamari.Terraform/Calamari.Terraform.csproj b/source/Calamari.Terraform/Calamari.Terraform.csproj index f657b522ce..e3b016bf2a 100644 --- a/source/Calamari.Terraform/Calamari.Terraform.csproj +++ b/source/Calamari.Terraform/Calamari.Terraform.csproj @@ -5,9 +5,9 @@ true false Exe - 9 + default win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - net462;net8.0 + net8.0 true diff --git a/source/Calamari.Testing/Calamari.Testing.csproj b/source/Calamari.Testing/Calamari.Testing.csproj index 00711f041a..dce75317ec 100644 --- a/source/Calamari.Testing/Calamari.Testing.csproj +++ b/source/Calamari.Testing/Calamari.Testing.csproj @@ -5,14 +5,10 @@ https://github.com/OctopusDeploy/Calamari/ Apache-2.0 default - net462;netstandard2.1 + net8.0 true Octopus.Calamari.Testing - - $(DefineConstants);NETCORE - - @@ -22,15 +18,11 @@ + - - - - - diff --git a/source/Calamari.Testing/CommandTestBuilder.cs b/source/Calamari.Testing/CommandTestBuilder.cs index 53f2fe2547..5b635bf842 100644 --- a/source/Calamari.Testing/CommandTestBuilder.cs +++ b/source/Calamari.Testing/CommandTestBuilder.cs @@ -1,8 +1,5 @@ -#if NETSTANDARD -using NuGet.Packaging; +using NuGet.Packaging; using NuGet.Versioning; -#else -#endif using System; using System.Collections.Generic; using System.IO; @@ -20,7 +17,6 @@ using Calamari.Testing.Helpers; using Calamari.Testing.LogParser; using FluentAssertions; -using NuGet; using Octopus.CoreUtilities; using KnownVariables = Calamari.Common.Plumbing.Variables.KnownVariables; using OSPlatform = System.Runtime.InteropServices.OSPlatform; @@ -39,7 +35,7 @@ public static CommandTestBuilder CreateAsync() where TCalamari : CalamariFlavourProgramAsync where TCommand : PipelineCommand { - return new CommandTestBuilder(typeof(TCommand).GetCustomAttribute().Name); + return new CommandTestBuilder(typeof(TCommand).GetCustomAttribute()!.Name); } public static CommandTestBuilder Create(string command) @@ -52,7 +48,7 @@ public static CommandTestBuilder Create() where TCalamari : CalamariFlavourProgram where TCommand : ICommand { - return new CommandTestBuilder(typeof(TCommand).GetCustomAttribute().Name); + return new CommandTestBuilder(typeof(TCommand).GetCustomAttribute()!.Name); } public static CommandTestBuilderContext WithFilesToCopy(this CommandTestBuilderContext context, string path) @@ -94,13 +90,8 @@ static string CreateNugetPackage(string packageId, string packageVersion, string { var metadata = new ManifestMetadata { -#if NETSTANDARD Authors = new [] {"octopus@e2eTests"}, Version = new NuGetVersion(packageVersion), -#else - Authors = "octopus@e2eTests", - Version = packageVersion, -#endif Id = packageId, Description = nameof(CommandTestBuilder) }; diff --git a/source/Calamari.Testing/EnvironmentVariables.cs b/source/Calamari.Testing/EnvironmentVariables.cs index 99f8f3494d..9762b851df 100644 --- a/source/Calamari.Testing/EnvironmentVariables.cs +++ b/source/Calamari.Testing/EnvironmentVariables.cs @@ -187,9 +187,9 @@ public EnvironmentVariableAttribute(string name, string? secretReference = null, SecretReference = secretReference; } - public static EnvironmentVariableAttribute? Get(object enm) + public static EnvironmentVariableAttribute? Get(object? enm) { - var mi = enm?.GetType().GetMember(enm.ToString()); + var mi = enm?.GetType().GetMember(enm.ToString()!); if (mi == null || mi.Length <= 0) { return null; diff --git a/source/Calamari.Testing/Helpers/CaptureCommandInvocationOutputSink.cs b/source/Calamari.Testing/Helpers/CaptureCommandInvocationOutputSink.cs index 6fc1031458..398cab6e69 100644 --- a/source/Calamari.Testing/Helpers/CaptureCommandInvocationOutputSink.cs +++ b/source/Calamari.Testing/Helpers/CaptureCommandInvocationOutputSink.cs @@ -92,7 +92,7 @@ void ParseServiceMessage(ServiceMessage message) var pdvRemotePath = message.GetValue(ServiceMessageNames.PackageDeltaVerification.RemotePathAttribute); DeltaError = message.GetValue(ServiceMessageNames.PackageDeltaVerification.Error); - if (pdvRemotePath != null && pdvHash != null) + if (pdvRemotePath != null && pdvHash != null && pdvSize != null) { DeltaVerification = new DeltaPackage(pdvRemotePath, pdvHash, long.Parse(pdvSize)); } diff --git a/source/Calamari.Testing/Helpers/EventualAssertionPermanentlyFailedException.cs b/source/Calamari.Testing/Helpers/EventualAssertionPermanentlyFailedException.cs index 1bb3a4457a..c66f134f2c 100644 --- a/source/Calamari.Testing/Helpers/EventualAssertionPermanentlyFailedException.cs +++ b/source/Calamari.Testing/Helpers/EventualAssertionPermanentlyFailedException.cs @@ -26,9 +26,5 @@ public EventualAssertionPermanentlyFailedException(string message) : base(messag public EventualAssertionPermanentlyFailedException(string message, Exception inner) : base(message, inner) { } - - protected EventualAssertionPermanentlyFailedException(SerializationInfo info, StreamingContext context) : base(info, context) - { - } } } diff --git a/source/Calamari.Testing/Helpers/TaskExtensionMethods.cs b/source/Calamari.Testing/Helpers/TaskExtensionMethods.cs index a7c4c365cd..6750daf55b 100644 --- a/source/Calamari.Testing/Helpers/TaskExtensionMethods.cs +++ b/source/Calamari.Testing/Helpers/TaskExtensionMethods.cs @@ -13,7 +13,7 @@ public static async Task WithCancellationToken(this Task task, CancellationToken var doerTask = task; var thrower = new TaskCompletionSource(); - using (cancellationToken.Register(tcs => ((TaskCompletionSource)tcs).SetResult(new object()), thrower)) + using (cancellationToken.Register(tcs => ((TaskCompletionSource?)tcs)?.SetResult(new object()), thrower)) { var throwerTask = thrower.Task; diff --git a/source/Calamari.Testing/Helpers/TestEnvironment.cs b/source/Calamari.Testing/Helpers/TestEnvironment.cs index a1bb3fa75d..39d537f038 100644 --- a/source/Calamari.Testing/Helpers/TestEnvironment.cs +++ b/source/Calamari.Testing/Helpers/TestEnvironment.cs @@ -6,7 +6,7 @@ namespace Calamari.Testing.Helpers public static class TestEnvironment { public static readonly string AssemblyLocalPath = typeof(TestEnvironment).Assembly.FullLocalPath(); - public static readonly string CurrentWorkingDirectory = Path.GetDirectoryName(AssemblyLocalPath); + public static readonly string CurrentWorkingDirectory = Path.GetDirectoryName(AssemblyLocalPath)!; public static readonly bool IsCI = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("TEAMCITY_VERSION")); @@ -18,7 +18,7 @@ public static string GetTestPath(params string[] paths) public static string ConstructRootedPath(params string[] paths) { - return Path.Combine(Path.GetPathRoot(CurrentWorkingDirectory), Path.Combine(paths)); + return Path.Combine(Path.GetPathRoot(CurrentWorkingDirectory)!, Path.Combine(paths)); } } } diff --git a/source/Calamari.Testing/LogParser/ScriptOutputFilter.cs b/source/Calamari.Testing/LogParser/ScriptOutputFilter.cs index 6924331b4d..092222fc91 100644 --- a/source/Calamari.Testing/LogParser/ScriptOutputFilter.cs +++ b/source/Calamari.Testing/LogParser/ScriptOutputFilter.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Reflection; using Calamari.Common.Plumbing.ServiceMessages; +using Octopus.CoreUtilities.Extensions; namespace Calamari.Testing.LogParser { @@ -47,7 +48,7 @@ public bool ContainsKey(string name) public bool TryGetValue(string name, out TestOutputVariable value) { - return items.TryGetValue(name, out value); + return items.TryGetValue(name, out value!); } public TestOutputVariable this[string name] @@ -322,7 +323,7 @@ void ServiceMessage(ServiceMessage serviceMessage) var deltaVerificationHash = serviceMessage.GetValue(ScriptServiceMessageNames.PackageDeltaVerification.HashAttribute); var deltaVerificationSize = serviceMessage.GetValue(ScriptServiceMessageNames.PackageDeltaVerification.SizeAttribute); DeltaPackageError = serviceMessage.GetValue(ScriptServiceMessageNames.PackageDeltaVerification.Error); - if (deltaVerificationRemotePath != null && deltaVerificationHash != null) + if (deltaVerificationRemotePath != null && deltaVerificationHash != null && deltaVerificationSize != null) { DeltaPackageVerifcation = new DeltaPackage(deltaVerificationRemotePath, deltaVerificationHash, long.Parse(deltaVerificationSize)); } @@ -372,13 +373,15 @@ void PopulateSupportedScriptActionNames() var actionNames = GetAllFieldValues( typeof(ScriptServiceMessageNames.ScriptOutputActions), x => Attribute.IsDefined(x, typeof(ServiceMessageNameAttribute))) - .Select(x => x.ToString()); + .Select(x => x?.ToString()) + .WhereNotNull(); + supportedScriptActionNames.AddRange(actionNames); } - static IEnumerable GetAllFieldValues(Type t, Func filter) + static IEnumerable GetAllFieldValues(Type t, Func filter) { - var values = new List(); + var values = new List(); var fields = t.GetFields(); values.AddRange(fields.Where(filter).Select(x => x.GetValue(null))); diff --git a/source/Calamari.Testing/Requirements/RequiresAdminAttribute.cs b/source/Calamari.Testing/Requirements/RequiresAdminAttribute.cs index 0e63d26e06..0e0102e9eb 100644 --- a/source/Calamari.Testing/Requirements/RequiresAdminAttribute.cs +++ b/source/Calamari.Testing/Requirements/RequiresAdminAttribute.cs @@ -9,7 +9,9 @@ public class RequiresAdminAttribute : TestAttribute, ITestAction { public void BeforeTest(ITest testDetails) { +#pragma warning disable CA1416 var isAdmin = (new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator); +#pragma warning restore CA1416 if (!isAdmin) { Assert.Ignore("Requires Admin Rights"); @@ -31,18 +33,6 @@ public void BeforeTest(ITest testDetails) { Assert.Ignore("Requires Windows"); } - -#if NETFX - var decimalVersion = Environment.OSVersion.Version.Major + Environment.OSVersion.Version.Minor * 0.1; - if(decimalVersion < 6.2) - { - Assert.Ignore("Requires Windows Server 2012 or above"); - } -#else - // .NET Core will be new enough. -#endif - - } public void AfterTest(ITest testDetails) diff --git a/source/Calamari.Testing/Requirements/RequiresDotNet45Attribute.cs b/source/Calamari.Testing/Requirements/RequiresDotNet45Attribute.cs deleted file mode 100644 index e01caa7914..0000000000 --- a/source/Calamari.Testing/Requirements/RequiresDotNet45Attribute.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Calamari.Common.Plumbing.Extensions; -using NUnit.Framework; -using NUnit.Framework.Interfaces; - -namespace Calamari.Testing.Requirements -{ - public class RequiresDotNet45Attribute : TestAttribute, ITestAction - { - public void BeforeTest(ITest testDetails) - { - if (!ScriptingEnvironment.IsNet45OrNewer()) - { - Assert.Ignore("Requires .NET 4.5"); - } - } - - public void AfterTest(ITest testDetails) - { - } - - public ActionTargets Targets { get; set; } - } -} \ No newline at end of file diff --git a/source/Calamari.Testing/Requirements/RequiresDotNetCoreAttribute.cs b/source/Calamari.Testing/Requirements/RequiresDotNetCoreAttribute.cs deleted file mode 100644 index 09e5c05c61..0000000000 --- a/source/Calamari.Testing/Requirements/RequiresDotNetCoreAttribute.cs +++ /dev/null @@ -1,27 +0,0 @@ -using NUnit.Framework; -using NUnit.Framework.Interfaces; -using NUnit.Framework.Internal; - -namespace Calamari.Testing.Requirements -{ - public class RequiresDotNetCoreAttribute: NUnitAttribute, IApplyToTest - { - static bool IsNetCore() - { - #if NETCORE - return true; - #else - return false; - #endif - } - - public void ApplyToTest(Test test) - { - if (!IsNetCore()) - { - test.RunState = RunState.Skipped; - test.Properties.Set(PropertyNames.SkipReason, "Requires dotnet core"); - } - } - } -} \ No newline at end of file diff --git a/source/Calamari.Testing/Requirements/RequiresDotNetFrameworkAttribute.cs b/source/Calamari.Testing/Requirements/RequiresDotNetFrameworkAttribute.cs deleted file mode 100644 index 9174388fe0..0000000000 --- a/source/Calamari.Testing/Requirements/RequiresDotNetFrameworkAttribute.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Calamari.Common.Plumbing.Extensions; -using NUnit.Framework; -using NUnit.Framework.Interfaces; -using NUnit.Framework.Internal; - -namespace Calamari.Testing.Requirements -{ - public class RequiresDotNetFrameworkAttribute: NUnitAttribute, IApplyToTest - { - public void ApplyToTest(Test test) - { - if (!ScriptingEnvironment.IsNetFramework()) - { - test.RunState = RunState.Skipped; - test.Properties.Set(PropertyNames.SkipReason, "Requires dotnet Framework"); - } - } - } -} \ No newline at end of file diff --git a/source/Calamari.Testing/TestHttpClientFactory.cs b/source/Calamari.Testing/TestHttpClientFactory.cs index 9a80a65f7c..1cbd3bc143 100644 --- a/source/Calamari.Testing/TestHttpClientFactory.cs +++ b/source/Calamari.Testing/TestHttpClientFactory.cs @@ -1,7 +1,6 @@ using System; using System.Net.Http; -#if NETSTANDARD || NETCORE namespace Calamari.Testing; public sealed class TestHttpClientFactory : IHttpClientFactory, IDisposable @@ -18,5 +17,3 @@ public void Dispose() } } } - -#endif \ No newline at end of file diff --git a/source/Calamari.Testing/Tools/BootstrapperModuleDeploymentTool.cs b/source/Calamari.Testing/Tools/BootstrapperModuleDeploymentTool.cs index c12c2f0f61..d92a55ef7c 100644 --- a/source/Calamari.Testing/Tools/BootstrapperModuleDeploymentTool.cs +++ b/source/Calamari.Testing/Tools/BootstrapperModuleDeploymentTool.cs @@ -30,6 +30,6 @@ public BoostrapperModuleDeploymentTool( public Maybe GetCompatiblePackage( string platform) { - return platform != "win-x64" && platform != "netfx" ? Maybe.None : new DeploymentToolPackage((IDeploymentTool) this, this.Id, this.modulePaths).AsSome(); + return platform != "win-x64" ? Maybe.None : new DeploymentToolPackage((IDeploymentTool) this, this.Id, this.modulePaths).AsSome(); } } \ No newline at end of file diff --git a/source/Calamari.Tests/Calamari.Tests.csproj b/source/Calamari.Tests/Calamari.Tests.csproj index ea1518752f..2e93d7e47e 100644 --- a/source/Calamari.Tests/Calamari.Tests.csproj +++ b/source/Calamari.Tests/Calamari.Tests.csproj @@ -10,17 +10,14 @@ win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 - net462;net8.0 - 8 + net8.0 + default true true $(DefineConstants);NETCORE;AZURE_CORE;JAVA_SUPPORT - - $(DefineConstants);NETFX;IIS_SUPPORT;USE_NUGET_V2_LIBS;USE_OCTODIFF_EXE; - all @@ -43,29 +40,10 @@ - - - - - - - - - - - - - - - - - - - @@ -273,15 +251,8 @@ - - - - - @(NuGetCommandLineRef->'%(ResolvedPath)')/tools/*.* - - @@ -292,6 +263,9 @@ + + + @@ -301,5 +275,8 @@ + + + diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.JsonFileOutput/Acme.JsonFileOutput.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.JsonFileOutput/Acme.JsonFileOutput.csproj index 77036296cf..a672254824 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.JsonFileOutput/Acme.JsonFileOutput.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.JsonFileOutput/Acme.JsonFileOutput.csproj @@ -5,7 +5,7 @@ en-US 1.0.0.0 ACME Corporation - netstandard1.0 + net8.0 Acme.JsonFileOutput Acme.JsonFileOutput https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Package/Acme.Package.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Package/Acme.Package.csproj index 6801cb609d..aa15b8bac5 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Package/Acme.Package.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Package/Acme.Package.csproj @@ -5,7 +5,7 @@ en-US 1.0.0.0 ACME Corporation - netstandard1.0 + net8.0 Acme.Package Acme.Package https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.PackageBilingual/Acme.PackageBilingual.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.PackageBilingual/Acme.PackageBilingual.csproj index bba21a1485..6da45eedff 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.PackageBilingual/Acme.PackageBilingual.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.PackageBilingual/Acme.PackageBilingual.csproj @@ -5,7 +5,7 @@ en-US 1.0.0.0 ACME Corporation - netstandard1.0 + net8.0 Acme.PackageBilingual Acme.PackageBilingual https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Service/Acme.Service.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Service/Acme.Service.csproj index aebc1c8ee4..dd5e74eadb 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Service/Acme.Service.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Service/Acme.Service.csproj @@ -4,7 +4,7 @@ A sample project containing a Windows service. en-US ACME Corporation - netstandard1.0 + net8.0 Acme.Service Acme.Service https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.StructuredConfigFiles/Acme.StructuredConfigFiles.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.StructuredConfigFiles/Acme.StructuredConfigFiles.csproj index fbb423d80f..782c942328 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.StructuredConfigFiles/Acme.StructuredConfigFiles.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.StructuredConfigFiles/Acme.StructuredConfigFiles.csproj @@ -5,7 +5,7 @@ en-US 1.0.0.0 ACME Corporation - netstandard1.0 + net8.0 Acme.StructuredConfigFiles Acme.StructuredConfigFiles https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web.Tests/Acme.Web.Tests.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web.Tests/Acme.Web.Tests.csproj index df6c53f237..ab1d375751 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web.Tests/Acme.Web.Tests.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web.Tests/Acme.Web.Tests.csproj @@ -4,7 +4,7 @@ Test project for Calamari. en-US Octopus Deploy - netstandard1.0 + net8.0 Acme.Web.Tests Acme.Web.Tests https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.Nix.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.Nix.csproj index 36fc3d1102..ac21a9a30a 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.Nix.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.Nix.csproj @@ -4,7 +4,7 @@ Test project for Calamari. en-US Octopus Deploy - netstandard1.0 + net8.0 Acme.Web Acme.Web https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.csproj index c90f4bb999..7d4370ee8b 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Acme.Web/Acme.Web.csproj @@ -4,7 +4,7 @@ Test project for Calamari. en-US Octopus Deploy - netstandard1.0 + net8.0 Acme.Web Acme.Web https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/Deployment/Packages/Octopus.Sample.AzureCloudService/Octopus.Sample.AzureCloudService.csproj b/source/Calamari.Tests/Fixtures/Deployment/Packages/Octopus.Sample.AzureCloudService/Octopus.Sample.AzureCloudService.csproj index 72d5849714..b8413caa65 100644 --- a/source/Calamari.Tests/Fixtures/Deployment/Packages/Octopus.Sample.AzureCloudService/Octopus.Sample.AzureCloudService.csproj +++ b/source/Calamari.Tests/Fixtures/Deployment/Packages/Octopus.Sample.AzureCloudService/Octopus.Sample.AzureCloudService.csproj @@ -5,7 +5,7 @@ en-US 1.0.0.0 Octopus Deploy - netstandard1.0 + net8.0 Octopus.Sample.AzureCloudService Octopus.Sample.AzureCloudService https://github.com/OctopusDeploy/Calamari/ diff --git a/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptFixture.cs b/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptFixture.cs index d4eaee3db2..c506b2e6c5 100644 --- a/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptFixture.cs +++ b/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptFixture.cs @@ -5,7 +5,6 @@ using Calamari.Common.Plumbing.Variables; using Calamari.Deployment; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using Calamari.Tests.Helpers; using FluentAssertions; using NUnit.Framework; @@ -14,7 +13,6 @@ namespace Calamari.Tests.Fixtures.DotnetScript { [TestFixture] [Category(TestCategory.ScriptingSupport.DotnetScript)] - [RequiresDotNetCore] public class DotnetScriptFixture : CalamariFixture { [Test] diff --git a/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptProxyFixture.cs b/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptProxyFixture.cs index 340b86d039..f400bc545d 100644 --- a/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptProxyFixture.cs +++ b/source/Calamari.Tests/Fixtures/DotnetScript/DotnetScriptProxyFixture.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using Calamari.Common.Plumbing.Variables; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using Calamari.Tests.Fixtures.Integration.Proxies; using NUnit.Framework; @@ -10,7 +9,6 @@ namespace Calamari.Tests.Fixtures.DotnetScript { [TestFixture] [Category(TestCategory.ScriptingSupport.DotnetScript)] - [RequiresDotNetCore] public class DotnetScriptProxyFixture : WindowsScriptProxyFixtureBase { protected override CalamariResult RunScript() diff --git a/source/Calamari.Tests/Fixtures/Integration/Proxies/ProxyEnvironmentVariablesGeneratorFixture.cs b/source/Calamari.Tests/Fixtures/Integration/Proxies/ProxyEnvironmentVariablesGeneratorFixture.cs index 4b4176ceed..55aa9c8959 100644 --- a/source/Calamari.Tests/Fixtures/Integration/Proxies/ProxyEnvironmentVariablesGeneratorFixture.cs +++ b/source/Calamari.Tests/Fixtures/Integration/Proxies/ProxyEnvironmentVariablesGeneratorFixture.cs @@ -4,7 +4,6 @@ using Calamari.Common.Plumbing; using Calamari.Common.Plumbing.Proxies; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using FluentAssertions; using NUnit.Framework; @@ -13,7 +12,7 @@ namespace Calamari.Tests.Fixtures.Integration.Proxies [TestFixture] // These tests currently only work in .NET Framework due to an issue with the .NET Core and proxy caching // See https://github.com/OctopusDeploy/Calamari/pull/1504 for more information - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public class ProxyEnvironmentVariablesGeneratorFixture { const string BadproxyUrl = "http://proxy-initializer-fixture-bad-proxy:1234"; diff --git a/source/Calamari.Tests/Fixtures/Integration/Proxies/WebProxyInitializerFixture.cs b/source/Calamari.Tests/Fixtures/Integration/Proxies/WebProxyInitializerFixture.cs index 9b2563d65b..ce31e3e832 100644 --- a/source/Calamari.Tests/Fixtures/Integration/Proxies/WebProxyInitializerFixture.cs +++ b/source/Calamari.Tests/Fixtures/Integration/Proxies/WebProxyInitializerFixture.cs @@ -3,7 +3,6 @@ using Calamari.Common.Plumbing; using Calamari.Common.Plumbing.Proxies; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using FluentAssertions; using NUnit.Framework; @@ -52,7 +51,7 @@ static void ResetSystemProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_HasSystemProxy_NoProxy() { ProxyRoutines.SetProxy(proxyUrl).Should().BeTrue(); @@ -62,7 +61,7 @@ public void Initialize_HasSystemProxy_NoProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_HasSystemProxy_UseSystemProxy() { ProxyRoutines.SetProxy(proxyUrl).Should().BeTrue(); @@ -72,7 +71,7 @@ public void Initialize_HasSystemProxy_UseSystemProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_HasSystemProxy_UseSystemProxyWithCredentials() { ProxyRoutines.SetProxy(proxyUrl).Should().BeTrue(); @@ -82,7 +81,7 @@ public void Initialize_HasSystemProxy_UseSystemProxyWithCredentials() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_HasSystemProxy_CustomProxy() { ProxyRoutines.SetProxy(BadproxyUrl).Should().BeTrue(); @@ -92,7 +91,7 @@ public void Initialize_HasSystemProxy_CustomProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_HasSystemProxy_CustomProxyWithCredentials() { ProxyRoutines.SetProxy(BadproxyUrl).Should().BeTrue(); @@ -102,7 +101,7 @@ public void Initialize_HasSystemProxy_CustomProxyWithCredentials() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_NoSystemProxy_NoProxy() { RunWith(false, "", 80, "", ""); @@ -111,7 +110,7 @@ public void Initialize_NoSystemProxy_NoProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_NoSystemProxy_UseSystemProxy() { RunWith(true, "", 80, "", ""); @@ -120,7 +119,7 @@ public void Initialize_NoSystemProxy_UseSystemProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_NoSystemProxy_UseSystemProxyWithCredentials() { RunWith(true, "", 80, ProxyUserName, ProxyPassword); @@ -129,7 +128,7 @@ public void Initialize_NoSystemProxy_UseSystemProxyWithCredentials() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_NoSystemProxy_CustomProxy() { RunWith(false, proxyHost, proxyPort, "", ""); @@ -138,7 +137,7 @@ public void Initialize_NoSystemProxy_CustomProxy() } [Test] - [RequiresDotNetFramework] + [Ignore("Currently there is an issue with .NET Core and proxy caching")] public void Initialize_NoSystemProxy_CustomProxyWithCredentials() { RunWith(false, proxyHost, proxyPort, ProxyUserName, ProxyPassword); diff --git a/source/Calamari.Tests/Fixtures/Integration/Scripting/CSharpScriptEngineFixture.cs b/source/Calamari.Tests/Fixtures/Integration/Scripting/CSharpScriptEngineFixture.cs index a310fd9f78..8c2bc1f295 100644 --- a/source/Calamari.Tests/Fixtures/Integration/Scripting/CSharpScriptEngineFixture.cs +++ b/source/Calamari.Tests/Fixtures/Integration/Scripting/CSharpScriptEngineFixture.cs @@ -5,7 +5,6 @@ using Calamari.Common.Plumbing.Logging; using Calamari.Common.Plumbing.Variables; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using NSubstitute; using NUnit.Framework; @@ -15,7 +14,7 @@ namespace Calamari.Tests.Fixtures.Integration.Scripting public class CSharpScriptEngineFixture : ScriptEngineFixtureBase { [Category(TestCategory.ScriptingSupport.DotnetScript)] - [Test, RequiresDotNetCore] + [Test] public void DotnetScript_CSharpDecryptsVariables() { using (var scriptFile = new TemporaryFile(Path.ChangeExtension(Path.GetTempFileName(), "cs"))) diff --git a/source/Calamari.Tests/Fixtures/Manifest/ExecuteManifestCommandFixture.cs b/source/Calamari.Tests/Fixtures/Manifest/ExecuteManifestCommandFixture.cs index c73fc130c8..979134dc4c 100644 --- a/source/Calamari.Tests/Fixtures/Manifest/ExecuteManifestCommandFixture.cs +++ b/source/Calamari.Tests/Fixtures/Manifest/ExecuteManifestCommandFixture.cs @@ -8,7 +8,6 @@ using Calamari.LaunchTools; using Calamari.Testing; using Calamari.Testing.Helpers; -using Calamari.Testing.Requirements; using Calamari.Tests.Helpers; using NUnit.Framework; using Octostache; @@ -16,7 +15,6 @@ namespace Calamari.Tests.Fixtures.Manifest { [TestFixture] - [RequiresDotNetCore] public class ExecuteManifestCommandFixture : CalamariFixture { [Test] diff --git a/source/Calamari/Calamari.csproj b/source/Calamari/Calamari.csproj index ad3156338e..292a770587 100644 --- a/source/Calamari/Calamari.csproj +++ b/source/Calamari/Calamari.csproj @@ -18,16 +18,12 @@ Calamari win-x64;linux-x64;osx-x64;linux-arm;linux-arm64 Calamari.exe.manifest - net462;net8.0 - 8 + net8.0 + default CS8632 true - - $(DefineConstants);IIS_SUPPORT; - anycpu - $(DefineConstants);DEBUG @@ -61,26 +57,10 @@ - - - - - - - - - - - - - - - - - - + + @@ -89,10 +69,6 @@ PreserveNewest - - - -