diff --git a/.dependabot/config.yml b/.dependabot/config.yml new file mode 100644 index 000000000000..14fd8e77128f --- /dev/null +++ b/.dependabot/config.yml @@ -0,0 +1,7 @@ +version: 1 +update_configs: + - package_manager: "dotnet:nuget" + directory: "/honeypot" + update_schedule: "daily" + default_labels: + - "vendors" diff --git a/honeypot/Datadog.Dependabot.Honeypot.csproj b/honeypot/Datadog.Dependabot.Honeypot.csproj new file mode 100644 index 000000000000..285e1f949282 --- /dev/null +++ b/honeypot/Datadog.Dependabot.Honeypot.csproj @@ -0,0 +1,26 @@ + + + + netcoreapp3.1 + Datadog.Dependabot.Honeypot + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/UpdateVendors/Datadog.Dependabot.Honeypot.template b/tools/UpdateVendors/Datadog.Dependabot.Honeypot.template new file mode 100644 index 000000000000..0cfe325a7c37 --- /dev/null +++ b/tools/UpdateVendors/Datadog.Dependabot.Honeypot.template @@ -0,0 +1,11 @@ + + + + netcoreapp3.1 + Datadog.Dependabot.Honeypot + + + ##PACKAGE_REFS## + + + diff --git a/tools/UpdateVendors/Program.cs b/tools/UpdateVendors/Program.cs index 4c88bbfc22ec..1f417253cef4 100644 --- a/tools/UpdateVendors/Program.cs +++ b/tools/UpdateVendors/Program.cs @@ -4,19 +4,12 @@ using System.IO.Compression; using System.Linq; using System.Net; -using System.Text; -using System.Text.RegularExpressions; +using Datadog.Trace.TestHelpers; namespace UpdateVendors { public class Program { - private const string AutoGeneratedMessage = @"//------------------------------------------------------------------------------ -// -// This file was automatically generated by the UpdateVendors tool. -//------------------------------------------------------------------------------ -"; - private static readonly string DownloadDirectory = Path.Combine(Environment.CurrentDirectory, "downloads"); private static string _vendorProjectDirectory; @@ -26,83 +19,51 @@ public static void Main() var solutionDirectory = GetSolutionDirectory(); _vendorProjectDirectory = Path.Combine(solutionDirectory, "src", "Datadog.Trace", "Vendors"); - UpdateVendor( - libraryName: "Serilog", - downloadUrl: "https://github.com/serilog/serilog/archive/v2.8.0.zip", - pathToSrc: new[] { "serilog-2.8.0", "src", "Serilog" }, - transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); - - UpdateVendor( - libraryName: "Serilog.Sinks.File", - downloadUrl: "https://github.com/serilog/serilog-sinks-file/archive/v4.0.0.zip", - pathToSrc: new[] { "serilog-sinks-file-4.0.0", "src", "Serilog.Sinks.File" }, - transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); - - UpdateVendor( - libraryName: "StatsdClient", - downloadUrl: "https://github.com/DataDog/dogstatsd-csharp-client/archive/6.0.0.zip", - pathToSrc: new[] { "dogstatsd-csharp-client-6.0.0", "src", "StatsdClient" }, - transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "StatsdClient")); - - UpdateVendor( - libraryName: "MessagePack", - downloadUrl: "https://github.com/neuecc/MessagePack-CSharp/archive/v1.9.3.zip", - pathToSrc: new[] { "MessagePack-CSharp-1.9.3", "src", "MessagePack" }, - transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "MessagePack")); - - UpdateVendor( - libraryName: "Newtonsoft.Json", - downloadUrl: "https://github.com/JamesNK/Newtonsoft.Json/archive/12.0.1.zip", - pathToSrc: new[] { "Newtonsoft.Json-12.0.1", "src", "Newtonsoft.Json" }, - transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Newtonsoft.Json")); + var fakeRefs = string.Empty; + + foreach (var dependency in VendoredDependency.All) + { + fakeRefs += $@"{Environment.NewLine} "; + fakeRefs += $@"{Environment.NewLine} {Environment.NewLine}"; + UpdateVendor(dependency); + } + + var honeypotProjTemplate = GetHoneyPotProjTemplate(); + honeypotProjTemplate = honeypotProjTemplate.Replace("##PACKAGE_REFS##", fakeRefs); + var projLocation = Path.Combine(EnvironmentHelper.GetSolutionDirectory(), "honeypot", "Datadog.Dependabot.Honeypot.csproj"); + File.WriteAllText(projLocation, honeypotProjTemplate); } - private static void RewriteCsFileWithStandardTransform(string filePath, string originalNamespace, Func extraTransform = null) + private static string GetHoneyPotProjTemplate() { - if (string.Equals(Path.GetExtension(filePath), ".cs", StringComparison.OrdinalIgnoreCase)) + var templateName = "Datadog.Dependabot.Honeypot.template"; + var directory = Directory.GetCurrentDirectory(); + string template = null; + var levelLimit = 4; + + while (template == null && --levelLimit >= 0) { - RewriteFileWithTransform( - filePath, - content => + foreach (var filePath in Directory.EnumerateFiles(directory)) + { + if (filePath.Contains(templateName)) { - // Disable analyzer - var builder = new StringBuilder(AutoGeneratedMessage, content.Length * 2); - - builder.Append(content); - - // Special Newtonsoft.Json processing - if (originalNamespace.Equals("Newtonsoft.Json")) - { - builder.Replace($"using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs", "using ErrorEventArgs = Datadog.Trace.Vendors.Newtonsoft.Json.Serialization.ErrorEventArgs"); - - if (content.Contains("using Newtonsoft.Json.Serialization;")) - { - builder.Replace($"Func<", $"System.Func<"); - builder.Replace($"Action<", $"System.Action<"); - } - } - - // Prevent namespace conflicts - builder.Replace($"using {originalNamespace}", $"using Datadog.Trace.Vendors.{originalNamespace}"); - builder.Replace($"namespace {originalNamespace}", $"namespace Datadog.Trace.Vendors.{originalNamespace}"); - builder.Replace($"[CLSCompliant(false)]", $"// [CLSCompliant(false)]"); - - // Don't expose anything we don't intend to - // by replacing all "public" access modifiers with "internal" - return Regex.Replace( - builder.ToString(), - @"public(\s+((abstract|sealed|static)\s+)?(partial\s+)?(class|readonly\s+struct|struct|interface|enum|delegate))", - match => $"internal{match.Groups[1]}"); - }); + template = File.ReadAllText(filePath); + break; + } + } + + directory = Directory.GetParent(directory).FullName; } + + return template; } - private static void UpdateVendor( - string libraryName, - string downloadUrl, - string[] pathToSrc, - Action transform = null) + private static void UpdateVendor(VendoredDependency dependency) { + var libraryName = dependency.LibraryName; + var downloadUrl = dependency.DownloadUrl; + var pathToSrc = dependency.PathToSrc; + Console.WriteLine($"Starting {libraryName} upgrade."); var zipLocation = Path.Combine(DownloadDirectory, $"{libraryName}.zip"); @@ -142,30 +103,27 @@ private static void UpdateVendor( SafeDeleteDirectory(assemblyPropertiesFolder); Console.WriteLine($"Deleted {libraryName} assembly properties file."); - if (transform != null) - { - Console.WriteLine($"Running transforms on files for {libraryName}."); + Console.WriteLine($"Running transforms on files for {libraryName}."); - var files = Directory.GetFiles( - sourceLocation, - "*.*", - SearchOption.AllDirectories); + var files = Directory.GetFiles( + sourceLocation, + "*.*", + SearchOption.AllDirectories); - foreach (var file in files) + foreach (var file in files) + { + if (ShouldDropFile(file)) { - if (ShouldDropFile(file)) - { - File.Delete(file); - } - else - { - transform(file); - } + File.Delete(file); + } + else + { + dependency.Transform(file); } - - Console.WriteLine($"Finished transforms on files for {libraryName}."); } + Console.WriteLine($"Finished transforms on files for {libraryName}."); + // Move it all to the vendors directory Console.WriteLine($"Copying source of {libraryName} to vendor project."); SafeDeleteDirectory(vendorFinalPath); @@ -192,18 +150,6 @@ private static bool ShouldDropFile(string filePath) return false; } - private static void RewriteFileWithTransform(string filePath, Func transform) - { - var fileContent = File.ReadAllText(filePath); - fileContent = transform(fileContent); - // Normalize text to use CRLF line endings so we have deterministic results - fileContent = fileContent.Replace("\r\n", "\n").Replace("\n", "\r\n"); - File.WriteAllText( - filePath, - fileContent, - new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); - } - private static void InitializeCleanDirectory(string directoryPath) { SafeDeleteDirectory(directoryPath); diff --git a/tools/UpdateVendors/UpdateVendors.csproj b/tools/UpdateVendors/UpdateVendors.csproj index 59804b067ea8..59727fbf0b53 100644 --- a/tools/UpdateVendors/UpdateVendors.csproj +++ b/tools/UpdateVendors/UpdateVendors.csproj @@ -5,4 +5,8 @@ net5.0 + + + + diff --git a/tools/UpdateVendors/VendoredDependency.cs b/tools/UpdateVendors/VendoredDependency.cs new file mode 100644 index 000000000000..64f72c31909b --- /dev/null +++ b/tools/UpdateVendors/VendoredDependency.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +namespace UpdateVendors +{ + public class VendoredDependency + { + private const string AutoGeneratedMessage = @"//------------------------------------------------------------------------------ +// +// This file was automatically generated by the UpdateVendors tool. +//------------------------------------------------------------------------------ +"; + + static VendoredDependency() + { + Add( + libraryName: "Serilog", + version: "2.8.0", + downloadUrl: "https://github.com/serilog/serilog/archive/v2.8.0.zip", + pathToSrc: new[] { "serilog-2.8.0", "src", "Serilog" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); + + Add( + libraryName: "Serilog.Sinks.File", + version: "4.0.0", + downloadUrl: "https://github.com/serilog/serilog-sinks-file/archive/v4.0.0.zip", + pathToSrc: new[] { "serilog-sinks-file-4.0.0", "src", "Serilog.Sinks.File" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Serilog")); + + Add( + libraryName: "StatsdClient", + version: "6.0.0", + downloadUrl: "https://github.com/DataDog/dogstatsd-csharp-client/archive/6.0.0.zip", + pathToSrc: new[] { "dogstatsd-csharp-client-6.0.0", "src", "StatsdClient" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "StatsdClient")); + + Add( + libraryName: "MessagePack", + version: "1.9.3", + downloadUrl: "https://github.com/neuecc/MessagePack-CSharp/archive/v1.9.3.zip", + pathToSrc: new[] { "MessagePack-CSharp-1.9.3", "src", "MessagePack" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "MessagePack")); + + Add( + libraryName: "Newtonsoft.Json", + version: "12.0.1", + downloadUrl: "https://github.com/JamesNK/Newtonsoft.Json/archive/12.0.1.zip", + pathToSrc: new[] { "Newtonsoft.Json-12.0.1", "src", "Newtonsoft.Json" }, + transform: filePath => RewriteCsFileWithStandardTransform(filePath, originalNamespace: "Newtonsoft.Json")); + } + + public static List All { get; set; } = new List(); + + public string LibraryName { get; set; } + + public string Version { get; set; } + + public string DownloadUrl { get; set; } + + public string[] PathToSrc { get; set; } + + public Action Transform { get; set; } + + private static void Add( + string libraryName, + string version, + string downloadUrl, + string[] pathToSrc, + Action transform) + { + All.Add(new VendoredDependency() + { + LibraryName = libraryName, + Version = version, + DownloadUrl = downloadUrl, + PathToSrc = pathToSrc, + Transform = transform, + }); + } + + private static void RewriteCsFileWithStandardTransform(string filePath, string originalNamespace, Func extraTransform = null) + { + if (string.Equals(Path.GetExtension(filePath), ".cs", StringComparison.OrdinalIgnoreCase)) + { + RewriteFileWithTransform( + filePath, + content => + { + // Disable analyzer + var builder = new StringBuilder(AutoGeneratedMessage, content.Length * 2); + + builder.Append(content); + + // Special Newtonsoft.Json processing + if (originalNamespace.Equals("Newtonsoft.Json")) + { + builder.Replace($"using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs", "using ErrorEventArgs = Datadog.Trace.Vendors.Newtonsoft.Json.Serialization.ErrorEventArgs"); + + if (content.Contains("using Newtonsoft.Json.Serialization;")) + { + builder.Replace($"Func<", $"System.Func<"); + builder.Replace($"Action<", $"System.Action<"); + } + } + + // Prevent namespace conflicts + builder.Replace($"using {originalNamespace}", $"using Datadog.Trace.Vendors.{originalNamespace}"); + builder.Replace($"namespace {originalNamespace}", $"namespace Datadog.Trace.Vendors.{originalNamespace}"); + builder.Replace($"[CLSCompliant(false)]", $"// [CLSCompliant(false)]"); + + // Don't expose anything we don't intend to + // by replacing all "public" access modifiers with "internal" + return Regex.Replace( + builder.ToString(), + @"public(\s+((abstract|sealed|static)\s+)?(partial\s+)?(class|readonly\s+struct|struct|interface|enum|delegate))", + match => $"internal{match.Groups[1]}"); + }); + } + } + + private static void RewriteFileWithTransform(string filePath, Func transform) + { + var fileContent = File.ReadAllText(filePath); + fileContent = transform(fileContent); + // Normalize text to use CRLF line endings so we have deterministic results + fileContent = fileContent.Replace("\r\n", "\n").Replace("\n", "\r\n"); + File.WriteAllText( + filePath, + fileContent, + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + } + } +}