diff --git a/source/Nuke.Common/CI/AppVeyor/AppVeyorAttribute.cs b/source/Nuke.Common/CI/AppVeyor/AppVeyorAttribute.cs index 98f0938e..be76cb97 100644 --- a/source/Nuke.Common/CI/AppVeyor/AppVeyorAttribute.cs +++ b/source/Nuke.Common/CI/AppVeyor/AppVeyorAttribute.cs @@ -28,6 +28,13 @@ public AppVeyorAttribute(AppVeyorImage image, params AppVeyorImage[] images) _images = new[] { image }.Concat(images).ToArray(); } + private string ConfigurationFile => NukeBuild.RootDirectory / "appveyor.yml"; + + protected override HostType HostType => HostType.AppVeyor; + protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; + protected override IEnumerable RelevantTargetNames => InvokedTargets; + protected override IEnumerable IrrelevantTargetNames => new string[0]; + public AppVeyorService[] Services { get; set; } = new AppVeyorService[0]; public string[] InvokedTargets { get; set; } = new string[0]; public string[] BranchesOnly { get; set; } = new string[0]; @@ -41,26 +48,14 @@ public AppVeyorAttribute(AppVeyorImage image, params AppVeyorImage[] images) public string[] Init { get; set; } = new string[0]; public string[] Cache { get; set; } = new string[0]; - protected virtual string ConfigurationFile => NukeBuild.RootDirectory / "appveyor.yml"; - - protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; - - protected override HostType HostType => HostType.AppVeyor; - - protected override void Generate( - NukeBuild build, - IReadOnlyCollection executableTargets) + protected override CustomFileWriter CreateWriter() { - var relevantTargets = InvokedTargets - .SelectMany(x => ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { x })) - .Distinct().ToList(); - var configuration = GetConfiguration(build, relevantTargets); - - using var writer = new CustomFileWriter(ConfigurationFile, indentationFactor: 2); - configuration.Write(writer); + return new CustomFileWriter(ConfigurationFile, indentationFactor: 2, "#"); } - protected virtual AppVeyorConfiguration GetConfiguration(NukeBuild build, List relevantTargets) + protected override ConfigurationEntity GetConfiguration( + NukeBuild build, + IReadOnlyCollection relevantTargets) { return new AppVeyorConfiguration { @@ -81,7 +76,7 @@ protected virtual AppVeyorConfiguration GetConfiguration(NukeBuild build, List GetArtifacts(List relevantTargets) + private IEnumerable GetArtifacts(IReadOnlyCollection relevantTargets) { return relevantTargets .Select(x => ArtifactExtensions.ArtifactProducts[x.Definition]) diff --git a/source/Nuke.Common/CI/AzurePipelines/AzurePipelinesAttribute.cs b/source/Nuke.Common/CI/AzurePipelines/AzurePipelinesAttribute.cs index 391f09b1..1df95848 100644 --- a/source/Nuke.Common/CI/AzurePipelines/AzurePipelinesAttribute.cs +++ b/source/Nuke.Common/CI/AzurePipelines/AzurePipelinesAttribute.cs @@ -25,6 +25,13 @@ public AzurePipelinesAttribute(AzurePipelinesImage image, params AzurePipelinesI _images = new[] { image }.Concat(images).ToArray(); } + private string ConfigurationFile => NukeBuild.RootDirectory / "azure-pipelines.yml"; + + protected override HostType HostType => HostType.AzurePipelines; + protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; + protected override IEnumerable RelevantTargetNames => InvokedTargets; + protected override IEnumerable IrrelevantTargetNames => NonEntryTargets.Concat(ExcludedTargets); + public string[] InvokedTargets { get; set; } = new string[0]; public string[] NonEntryTargets { get; set; } = new string[0]; public string[] ExcludedTargets { get; set; } = new string[0]; @@ -43,26 +50,12 @@ public AzurePipelinesAttribute(AzurePipelinesImage image, params AzurePipelinesI public string[] PullRequestsPathsInclude { get; set; } = new string[0]; public string[] PullRequestsPathsExclude { get; set; } = new string[0]; - protected virtual string ConfigurationFile => NukeBuild.RootDirectory / "azure-pipelines.yml"; - - protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; - - protected override HostType HostType => HostType.AzurePipelines; - - protected override void Generate(NukeBuild build, IReadOnlyCollection executableTargets) + protected override CustomFileWriter CreateWriter() { - var relevantTargets = InvokedTargets - .SelectMany(x => ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { x })) - .Distinct() - .Where(x => !ExcludedTargets.Contains(x.Name) && !NonEntryTargets.Contains(x.Name)).ToList(); - - var configuration = GetConfiguration(relevantTargets); - - using var writer = new CustomFileWriter(ConfigurationFile, indentationFactor: 2); - configuration.Write(writer); + return new CustomFileWriter(ConfigurationFile, indentationFactor: 2, commentPrefix: "#"); } - protected virtual AzurePipelinesConfiguration GetConfiguration(IReadOnlyCollection relevantTargets) + protected override ConfigurationEntity GetConfiguration(NukeBuild build, IReadOnlyCollection relevantTargets) { return new AzurePipelinesConfiguration { diff --git a/source/Nuke.Common/CI/ConfigurationAttributeBase.cs b/source/Nuke.Common/CI/ConfigurationAttributeBase.cs index aed002c3..b163b69b 100644 --- a/source/Nuke.Common/CI/ConfigurationAttributeBase.cs +++ b/source/Nuke.Common/CI/ConfigurationAttributeBase.cs @@ -29,7 +29,10 @@ public abstract class ConfigurationAttributeBase : Attribute, IOnBeforeLogo, IOn public bool ShutdownDotNetBuildServer { get; set; } = true; + protected abstract HostType HostType { get; } protected abstract IEnumerable GeneratedFiles { get; } + protected abstract IEnumerable RelevantTargetNames { get; } + protected abstract IEnumerable IrrelevantTargetNames { get; } protected virtual string PowerShellScript => NukeBuild.RootDirectory.GlobFiles("build.ps1", "*/build.ps1") @@ -47,10 +50,43 @@ public void OnBeforeLogo(NukeBuild build, IReadOnlyCollection NukeBuild.Host != HostType) return; - Generate(build, executableTargets); + ControlFlow.Assert(NukeBuild.RootDirectory != null, "NukeBuild.RootDirectory != null"); + + var relevantTargets = RelevantTargetNames + .SelectMany(x => ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { x })) + .Distinct() + .Where(x => !IrrelevantTargetNames.Contains(x.Name)).ToList(); + + using (var writer = CreateWriter()) + { + WriteAutoGenerationComment(writer); + var configuration = GetConfiguration(build, relevantTargets); + configuration.Write(writer); + } + Environment.Exit(0); } + protected virtual void WriteAutoGenerationComment(CustomFileWriter writer) + { + writer.WriteComment("------------------------------------------------------------------------------"); + writer.WriteComment(""); + writer.WriteComment(); + writer.WriteComment(" This code was generated."); + writer.WriteComment(); + writer.WriteComment(" - To turn off auto-generation set:"); + writer.WriteComment(); + writer.WriteComment($" [{GetType().Name.TrimEnd(nameof(Attribute))} ({nameof(AutoGenerate)} = false)]"); + writer.WriteComment(); + writer.WriteComment(" - To trigger manual generation invoke:"); + writer.WriteComment(); + writer.WriteComment($" nuke --{ConfigurationParameterName} --host {HostType}"); + writer.WriteComment(); + writer.WriteComment(""); + writer.WriteComment("------------------------------------------------------------------------------"); + writer.WriteLine(); + } + public void OnAfterLogo( NukeBuild build, IReadOnlyCollection executableTargets, @@ -61,6 +97,7 @@ public void OnAfterLogo( GeneratedFiles.ForEach(EnsureExistingParentDirectory); + // TODO: necessary? Logger.LogLevel = LogLevel.Trace; var previousHashes = GeneratedFiles .Where(File.Exists) @@ -97,14 +134,8 @@ public void OnBuildFinished(NukeBuild build) OnBuildFinishedInternal(build); } - private string GetCurrentHash() - { - return GeneratedFiles.Select(GetFileHash).JoinComma(); - } - - protected abstract HostType HostType { get; } - - protected abstract void Generate(NukeBuild build, IReadOnlyCollection executableTargets); + protected abstract CustomFileWriter CreateWriter(); + protected abstract ConfigurationEntity GetConfiguration(NukeBuild build, IReadOnlyCollection relevantTargets); protected virtual void OnBuildFinishedInternal(NukeBuild build) { diff --git a/source/Nuke.Common/CI/GitHubActions/GitHubActionsAttribute.cs b/source/Nuke.Common/CI/GitHubActions/GitHubActionsAttribute.cs index ae9f112f..9888fc24 100644 --- a/source/Nuke.Common/CI/GitHubActions/GitHubActionsAttribute.cs +++ b/source/Nuke.Common/CI/GitHubActions/GitHubActionsAttribute.cs @@ -34,13 +34,12 @@ public GitHubActionsAttribute( _images = new[] { image }.Concat(images).ToArray(); } - private AbsolutePath GitHubDirectory => NukeBuild.RootDirectory / ".github"; - private AbsolutePath WorkflowsDirectory => GitHubDirectory / "workflows"; - private string ConfigurationFile => WorkflowsDirectory / $"{_name}.yml"; - - protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; + private string ConfigurationFile => NukeBuild.RootDirectory / ".github" / "workflows" / $"{_name}.yml"; protected override HostType HostType => HostType.GitHubActions; + protected override IEnumerable GeneratedFiles => new[] { ConfigurationFile }; + protected override IEnumerable RelevantTargetNames => InvokedTargets; + protected override IEnumerable IrrelevantTargetNames => new string[0]; public GitHubActionsTrigger[] On { get; set; } = new GitHubActionsTrigger[0]; public string[] OnPushBranches { get; set; } = new string[0]; @@ -58,20 +57,14 @@ public GitHubActionsAttribute( public string[] InvokedTargets { get; set; } = new string[0]; - protected override void Generate( - NukeBuild build, - IReadOnlyCollection executableTargets) + protected override CustomFileWriter CreateWriter() { - var relevantTargets = InvokedTargets - .SelectMany(x => ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { x })) - .Distinct().ToList(); - var configuration = GetConfiguration(build, relevantTargets); - - using var writer = new CustomFileWriter(ConfigurationFile, indentationFactor: 2); - configuration.Write(writer); + return new CustomFileWriter(ConfigurationFile, indentationFactor: 2, commentPrefix: "#"); } - protected virtual GitHubActionsConfiguration GetConfiguration(NukeBuild targets, IReadOnlyCollection relevantTargets) + protected override ConfigurationEntity GetConfiguration( + NukeBuild build, + IReadOnlyCollection relevantTargets) { var configuration = new GitHubActionsConfiguration { diff --git a/source/Nuke.Common/CI/TeamCity/Configuration/TeamCityConfiguration.cs b/source/Nuke.Common/CI/TeamCity/Configuration/TeamCityConfiguration.cs index 042beaf3..537ff3e6 100644 --- a/source/Nuke.Common/CI/TeamCity/Configuration/TeamCityConfiguration.cs +++ b/source/Nuke.Common/CI/TeamCity/Configuration/TeamCityConfiguration.cs @@ -14,19 +14,17 @@ public class TeamCityConfiguration : ConfigurationEntity public virtual string[] Header => new[] { - "// THIS FILE IS AUTO-GENERATED", - "// ITS CONTENT IS OVERWRITTEN WITH EXCEPTION OF MARKED USER BLOCKS", - "", "import jetbrains.buildServer.configs.kotlin.v2018_1.*", "import jetbrains.buildServer.configs.kotlin.v2018_1.buildFeatures.*", "import jetbrains.buildServer.configs.kotlin.v2018_1.buildSteps.*", "import jetbrains.buildServer.configs.kotlin.v2018_1.triggers.*", "import jetbrains.buildServer.configs.kotlin.v2018_1.vcs.*", "", - "version = \"2019.1\"", + $"version = {Version.DoubleQuote()}", "" }; + public string Version { get; set; } public TeamCityProject Project { get; set; } public override void Write(CustomFileWriter writer) diff --git a/source/Nuke.Common/CI/TeamCity/TeamCityAttribute.cs b/source/Nuke.Common/CI/TeamCity/TeamCityAttribute.cs index 77ef2a4e..5154ed6f 100644 --- a/source/Nuke.Common/CI/TeamCity/TeamCityAttribute.cs +++ b/source/Nuke.Common/CI/TeamCity/TeamCityAttribute.cs @@ -32,8 +32,17 @@ public TeamCityAttribute(TeamCityAgentPlatform platform) private string SettingsFile => TeamcityDirectory / "settings.kts"; private string PomFile => TeamcityDirectory / "pom.xml"; + protected override HostType HostType => HostType.TeamCity; protected override IEnumerable GeneratedFiles => new[] { PomFile, SettingsFile }; + protected override IEnumerable RelevantTargetNames => + VcsTriggeredTargets.Concat(NightlyTriggeredTargets).Concat(ManuallyTriggeredTargets); + + protected override IEnumerable IrrelevantTargetNames => + NonEntryTargets.Concat(ExcludedTargets); + + public string Version { get; set; } = "2018.2"; + public TeamCityAgentPlatform Platform { get; } public string Description { get; set; } public string DefaultBranch { get; set; } = "develop"; @@ -62,29 +71,22 @@ protected override void OnBuildFinishedInternal(NukeBuild build) // TeamCity.Instance.PublishArtifacts($"+:{stateFile} => .teamcity/states"); } - protected override HostType HostType => HostType.TeamCity; - - protected override void Generate(NukeBuild build, IReadOnlyCollection executableTargets) + protected override CustomFileWriter CreateWriter() { - var relevantTargets = VcsTriggeredTargets.Concat(ManuallyTriggeredTargets) - .SelectMany(x => ExecutionPlanner.GetExecutionPlan(executableTargets, new[] { x })) - .Distinct() - .Where(x => !ExcludedTargets.Contains(x.Name) && !NonEntryTargets.Contains(x.Name)).ToList(); - var configuration = GetConfiguration(build, relevantTargets); - - ControlFlow.Assert(NukeBuild.RootDirectory != null, "NukeBuild.RootDirectory != null"); + return new CustomFileWriter(SettingsFile, indentationFactor: 4, commentPrefix: "//"); + } + protected override ConfigurationEntity GetConfiguration(NukeBuild build, IReadOnlyCollection relevantTargets) + { TextTasks.WriteAllLines( PomFile, ResourceUtility.GetResourceAllLines("pom.xml")); - using var writer = new CustomFileWriter(SettingsFile, indentationFactor: 4); - configuration.Write(writer); - } - - protected virtual TeamCityConfiguration GetConfiguration(NukeBuild build, IReadOnlyCollection relevantTargets) - { - return new TeamCityConfiguration { Project = GetProject(build, relevantTargets) }; + return new TeamCityConfiguration + { + Version = Version, + Project = GetProject(build, relevantTargets) + }; } protected virtual TeamCityProject GetProject(NukeBuild build, IReadOnlyCollection relevantTargets) diff --git a/source/Nuke.Common/Utilities/CustomFileWriter.cs b/source/Nuke.Common/Utilities/CustomFileWriter.cs index c092f5f1..ace041fa 100644 --- a/source/Nuke.Common/Utilities/CustomFileWriter.cs +++ b/source/Nuke.Common/Utilities/CustomFileWriter.cs @@ -14,14 +14,16 @@ public class CustomFileWriter : IDisposable private readonly FileStream _fileStream; private readonly StreamWriter _streamWriter; private readonly int _indentationFactor; + private readonly string _commentPrefix; private int _indentation; - public CustomFileWriter(string filename, int indentationFactor, FileMode fileMode = FileMode.Create) + public CustomFileWriter(string filename, int indentationFactor, string commentPrefix, FileMode fileMode = FileMode.Create) { _fileStream = File.Open(filename, fileMode); _streamWriter = new StreamWriter(_fileStream); _indentationFactor = indentationFactor; + _commentPrefix = commentPrefix; } public void Dispose() @@ -38,6 +40,11 @@ public void WriteLine(string text = null) : string.Empty); } + public void WriteComment(string text = null) + { + WriteLine($"{_commentPrefix} {text}".TrimEnd()); + } + public IDisposable Indent() { return DelegateDisposable.CreateBracket(