Example #1
0
        public override bool Execute()
        {
            var used = UsageData.Parse(XElement.Parse(File.ReadAllText(DataFile)));

            string baselineText = string.IsNullOrEmpty(BaselineDataFile)
                ? "<UsageData />"
                : File.ReadAllText(BaselineDataFile);

            var baseline = UsageData.Parse(XElement.Parse(baselineText));

            UsageValidationData data = GetUsageValidationData(baseline, used);

            Directory.CreateDirectory(Path.GetDirectoryName(OutputBaselineFile));
            File.WriteAllText(OutputBaselineFile, data.ActualUsageData.ToXml().ToString());

            Directory.CreateDirectory(Path.GetDirectoryName(OutputReportFile));
            File.WriteAllText(OutputReportFile, data.Report.ToString());

            return(!Log.HasLoggedErrors);
        }
Example #2
0
        public override bool Execute()
        {
            string baselineRelativeFileName = PrebuiltBaselineFile.Replace(RootDirectory, "");
            string gitLogCommand            = $"log --first-parent --pretty=format:%H,%f,%ci -- {PrebuiltBaselineFile}";

            DateTime startTime = DateTime.Now;

            Log.LogMessage(MessageImportance.High, "Generating summary usage burndown data...");

            ParallelQuery <string> data = ExecuteGitCommand(RootDirectory, gitLogCommand).AsParallel().Select(commitLine =>
            {
                var splitLine = commitLine.Split(',');
                var commit    = new Commit()
                {
                    Sha        = splitLine[0],
                    Title      = splitLine[1],
                    CommitDate = DateTime.Parse(splitLine[2])
                };
                string fileContents        = GetFileContents(baselineRelativeFileName, commit.Sha);
                Usage[] usages             = UsageData.Parse(XElement.Parse(fileContents)).Usages.NullAsEmpty().ToArray();
                commit.PackageVersionCount = usages.Count();
                commit.PackageCount        = usages.GroupBy(i => i.PackageIdentity.Id).Select(grp => grp.First()).Count();
                return(commit);
            })
                                          .Select(c => c.ToString());

            Directory.CreateDirectory(Path.GetDirectoryName(OutputFilePath));

            File.WriteAllLines(OutputFilePath, data);

            Log.LogMessage(
                MessageImportance.High,
                $"Generating summary usage burndown data at {OutputFilePath} done. Took {DateTime.Now - startTime}");

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            var used     = UsageData.Parse(XElement.Parse(File.ReadAllText(DataFile)));
            var baseline = UsageData.Parse(XElement.Parse(File.ReadAllText(BaselineDataFile)));

            Comparison <PackageIdentity> diff = Compare(
                used.Usages.Select(u => u.GetIdentityWithoutRid()).Distinct(),
                baseline.Usages.Select(u => u.GetIdentityWithoutRid()).Distinct());

            var report = new XElement("BaselineComparison");

            bool tellUserToUpdateBaseline = false;

            if (diff.Added.Any())
            {
                tellUserToUpdateBaseline = true;
                Log.LogError(
                    $"{diff.Added.Length} new packages used not in baseline! See report " +
                    $"at {OutputReportFile} for more information. Package IDs are:\n" +
                    string.Join("\n", diff.Added.Select(u => u.ToString())));

                // In the report, list full usage info, not only identity.
                report.Add(
                    new XElement(
                        "New",
                        used.Usages
                        .Where(u => diff.Added.Contains(u.GetIdentityWithoutRid()))
                        .Select(u => u.ToXml())));
            }
            if (diff.Removed.Any())
            {
                tellUserToUpdateBaseline = true;
                Log.LogMessage(
                    MessageImportance.High,
                    $"{diff.Removed.Length} packages in baseline weren't used!");

                report.Add(new XElement("Removed", diff.Removed.Select(id => id.ToXElement())));
            }
            if (diff.Unchanged.Any())
            {
                Log.LogMessage(
                    MessageImportance.High,
                    $"{diff.Unchanged.Length} packages used as expected in the baseline.");
            }

            // Simplify the used data to what is necessary for a baseline, to reduce file size.
            foreach (var usage in used.Usages)
            {
                usage.AssetsFile = null;
            }
            used.Usages = used.Usages.Distinct().ToArray();

            Directory.CreateDirectory(Path.GetDirectoryName(OutputBaselineFile));
            File.WriteAllText(OutputBaselineFile, used.ToXml().ToString());

            Directory.CreateDirectory(Path.GetDirectoryName(OutputReportFile));
            File.WriteAllText(OutputReportFile, report.ToString());

            if (tellUserToUpdateBaseline)
            {
                Log.LogWarning(
                    "Prebuilt usages are different from the baseline. If detected changes are " +
                    "acceptable, update baseline with:\n" +
                    $"cp '{OutputBaselineFile}' '{BaselineDataFile}'");
            }

            return(!Log.HasLoggedErrors);
        }
        public override bool Execute()
        {
            UsageData data = UsageData.Parse(XElement.Parse(File.ReadAllText(DataFile)));

            IEnumerable <RepoOutput> sourceBuildRepoOutputs = GetSourceBuildRepoOutputs();

            // Map package id to the build name that created them in a ProdCon build.
            var prodConPackageOrigin = new Dictionary <string, string>(
                StringComparer.OrdinalIgnoreCase);

            foreach (ITaskItem item in ProdConPackageInfos.NullAsEmpty())
            {
                AddProdConPackage(
                    prodConPackageOrigin,
                    item.GetMetadata("PackageId"),
                    item.GetMetadata("OriginBuildName"));
            }

            if (File.Exists(ProdConBuildManifestFile))
            {
                var xml = XElement.Parse(File.ReadAllText(ProdConBuildManifestFile));
                foreach (var x in xml.Descendants("Package"))
                {
                    AddProdConPackage(
                        prodConPackageOrigin,
                        x.Attribute("Id")?.Value,
                        x.Attribute("OriginBuildName")?.Value);
                }
            }

            var poisonNupkgFilenames = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            if (File.Exists(PoisonedReportFile))
            {
                foreach (string line in File.ReadAllLines(PoisonedReportFile))
                {
                    string[] segments = line.Split('\\');
                    if (segments.Length > 2 &&
                        segments[0].Trim() == "intermediate" &&
                        segments[1].EndsWith(".nupkg"))
                    {
                        poisonNupkgFilenames.Add(Path.GetFileNameWithoutExtension(segments[1]));
                    }
                }
            }

            var report = new XElement("AnnotatedUsages");

            foreach (Usage usage in data.Usages.NullAsEmpty())
            {
                string id      = usage.PackageIdentity.Id;
                string version = usage.PackageIdentity.Version.OriginalVersion;

                string pvpIdent = WriteBuildOutputProps.GetPropertyName(id);

                var sourceBuildCreator = new StringBuilder();
                foreach (RepoOutput output in sourceBuildRepoOutputs)
                {
                    foreach (PackageVersionPropsElement p in output.Built)
                    {
                        if (p.Name.Equals(pvpIdent, StringComparison.OrdinalIgnoreCase))
                        {
                            if (sourceBuildCreator.Length != 0)
                            {
                                sourceBuildCreator.Append(" ");
                            }
                            sourceBuildCreator.Append(output.Repo);
                            sourceBuildCreator.Append(" ");
                            sourceBuildCreator.Append(p.Name);
                            sourceBuildCreator.Append("/");
                            sourceBuildCreator.Append(p.Version);
                        }
                    }
                }

                prodConPackageOrigin.TryGetValue(id, out string prodConCreator);

                var annotated = new AnnotatedUsage
                {
                    Usage = usage,

                    Project = data.ProjectDirectories
                              ?.FirstOrDefault(p => usage.AssetsFile?.StartsWith(p) ?? false),

                    SourceBuildPackageIdCreator = sourceBuildCreator.Length == 0
                        ? null
                        : sourceBuildCreator.ToString(),

                    ProdConPackageIdCreator = prodConCreator,

                    EndsUpInOutput = poisonNupkgFilenames.Contains($"{id}.{version}")
                };

                report.Add(annotated.ToXml());
            }

            Directory.CreateDirectory(OutputDirectory);

            File.WriteAllText(
                Path.Combine(OutputDirectory, "annotated-usage.xml"),
                report.ToString());

            return(!Log.HasLoggedErrors);
        }
Example #5
0
        public override bool Execute()
        {
            var used = UsageData.Parse(XElement.Parse(File.ReadAllText(DataFile)));

            string baselineText = string.IsNullOrEmpty(BaselineDataFile)
                ? "<UsageData />"
                : File.ReadAllText(BaselineDataFile);

            var baseline = UsageData.Parse(XElement.Parse(baselineText));

            Comparison <PackageIdentity> diff = Compare(
                used.Usages.Select(u => u.GetIdentityWithoutRid()).Distinct(),
                baseline.Usages.Select(u => u.GetIdentityWithoutRid()).Distinct());

            var report = new XElement("BaselineComparison");

            bool tellUserToUpdateBaseline = false;

            if (diff.Added.Any())
            {
                tellUserToUpdateBaseline = true;
                Log.LogError(
                    $"{diff.Added.Length} new packages used not in baseline! See report " +
                    $"at {OutputReportFile} for more information. Package IDs are:\n" +
                    string.Join("\n", diff.Added.Select(u => u.ToString())));

                // In the report, list full usage info, not only identity.
                report.Add(
                    new XElement(
                        "New",
                        used.Usages
                        .Where(u => diff.Added.Contains(u.GetIdentityWithoutRid()))
                        .Select(u => u.ToXml())));
            }
            if (diff.Removed.Any())
            {
                tellUserToUpdateBaseline = true;
                Log.LogMessage(
                    MessageImportance.High,
                    $"{diff.Removed.Length} packages in baseline weren't used!");

                report.Add(new XElement("Removed", diff.Removed.Select(id => id.ToXElement())));
            }
            if (diff.Unchanged.Any())
            {
                Log.LogMessage(
                    MessageImportance.High,
                    $"{diff.Unchanged.Length} packages used as expected in the baseline.");
            }

            if (!AllowTestProjectUsage)
            {
                Usage[] testProjectUsages = used.Usages
                                            .Where(WriteUsageReports.IsTestUsageByHeuristic)
                                            .ToArray();

                if (testProjectUsages.Any())
                {
                    string[] projects = testProjectUsages
                                        .Select(u => u.AssetsFile)
                                        .Distinct()
                                        .ToArray();

                    Log.LogError(
                        $"{testProjectUsages.Length} forbidden test usages found in " +
                        $"{projects.Length} projects:\n" +
                        string.Join("\n", projects));
                }
            }

            // Simplify the used data to what is necessary for a baseline, to reduce file size.
            foreach (var usage in used.Usages)
            {
                usage.AssetsFile = null;
            }
            used.Usages = used.Usages.Distinct().ToArray();

            Directory.CreateDirectory(Path.GetDirectoryName(OutputBaselineFile));
            File.WriteAllText(OutputBaselineFile, used.ToXml().ToString());

            Directory.CreateDirectory(Path.GetDirectoryName(OutputReportFile));
            File.WriteAllText(OutputReportFile, report.ToString());

            if (tellUserToUpdateBaseline)
            {
                string baselineNotFoundWarning = "";
                if (string.IsNullOrEmpty(BaselineDataFile))
                {
                    baselineNotFoundWarning =
                        $"not expected, because no baseline file exists at '{BaselineDataUpdateHintFile}'";
                }
                else
                {
                    baselineNotFoundWarning =
                        $"different from the baseline found at '{BaselineDataFile}'";
                }

                Log.LogWarning(
                    $"Prebuilt usages are {baselineNotFoundWarning}. If it's acceptable to " +
                    "update the baseline, copy the contents of the automatically generated " +
                    $"baseline '{OutputBaselineFile}'.");
            }

            return(!Log.HasLoggedErrors);
        }