Skip to content

Commit

Permalink
[DYN-3343] Automatically add loaded packages as crash detail (#11500)
Browse files Browse the repository at this point in the history
* Removal of unused code

* Revert "Removal of unused code"

This reverts commit c78dfe9.

* Added Obsolete Tag

* Message change

* Tests1

* Tests changes

* WorkspaceModel Tests

* Fix merge issue

* GitHub Action For Issue Content

* Refactor

* Update checkIssueInfo.yaml

* Add github action

* Template/Issue parser and comparator improvements

* Update infromation analyzer

* Delete checkIssueInfo.yaml

* Fake Crash on canvas click

* Include loaded packages in crash report

* revert fake crush

* Reference fix

* Changes

* Removed unused reference

* Update CrashUtilities.cs

* remove redundant line on issue description

* format change

* Update CrashPrompt.xaml.cs

* refactor and fixes

* spelling

* added packages versions

* Tests

Co-authored-by: tanga <[email protected]>
  • Loading branch information
Astul-Betizagasti and QilongTang authored Feb 23, 2021
1 parent 5104b52 commit 4cac452
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 12 deletions.
16 changes: 12 additions & 4 deletions src/DynamoCoreWpf/UI/Prompts/CrashPrompt.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
using System.Diagnostics;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Xml;
using Dynamo.Core;
using Dynamo.PackageManager;
using Dynamo.ViewModels;

namespace Dynamo.Nodes.Prompts
Expand All @@ -18,17 +22,18 @@ public partial class CrashPrompt : Window
private string details; // Store here for clipboard copy
private string folderPath;
private string productName;
private string markdownPackages;

public CrashPrompt(string details, DynamoViewModel dynamoViewModel)
{
InitializeComponent();
this.CrashDetailsContent.Text = details;

productName = dynamoViewModel.BrandingResourceProvider.ProductName;
Title = string.Format(Wpf.Properties.Resources.CrashPromptDialogTitle,productName);
Title = string.Format(Wpf.Properties.Resources.CrashPromptDialogTitle, productName);
txtOverridingText.Text = string.Format(Wpf.Properties.Resources.CrashPromptDialogCrashMessage, productName);
}

public CrashPrompt(DynamoViewModel dynamoViewModel)
{
InitializeComponent();
Expand All @@ -42,6 +47,9 @@ public CrashPrompt(CrashPromptArgs args, DynamoViewModel dynamoViewModel)
{
InitializeComponent();

var packageLoader = dynamoViewModel.Model.GetPackageManagerExtension()?.PackageLoader;
markdownPackages = Wpf.Utilities.CrashUtilities.PackagesToMakrdown(packageLoader);

productName = dynamoViewModel.BrandingResourceProvider.ProductName;
Title = string.Format(Wpf.Properties.Resources.CrashPromptDialogTitle, productName);
txtOverridingText.Text = string.Format(Wpf.Properties.Resources.CrashPromptDialogCrashMessage, productName);
Expand Down Expand Up @@ -92,7 +100,7 @@ private void Continue_Click(object sender, RoutedEventArgs e)

private void PostOnGithub_Click(object sender, RoutedEventArgs e)
{
DynamoViewModel.ReportABug(this.CrashDetailsContent.Text);
DynamoViewModel.ReportABug(markdownPackages);
}

private void Details_Click(object sender, RoutedEventArgs e)
Expand Down
46 changes: 41 additions & 5 deletions src/DynamoCoreWpf/Utilities/CrashUtilities.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using Dynamo.Configuration;
using Dynamo.PackageManager;
using Dynamo.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Dynamo.Wpf.Utilities
{
Expand All @@ -26,28 +29,61 @@ internal static string GithubNewIssueUrlFromCrashContent(object crashContent)
return baseUri.ToString();
}

/// <summary>
/// Converts packages information into markdown format for use in Github issue body
/// </summary>
/// <param name="packageLoader">Package loader</param>
/// <returns>A markdown format string to use in issue body.</returns>
internal static string PackagesToMakrdown(PackageLoader packageLoader)
{
if (packageLoader != null)
{
//List of the names of all the loaded packages with their corresponding version
var packagesNames = packageLoader.LocalPackages.Select(o => o.Name + " " + o.VersionName).ToList();
//Package's issue section in markdown format
string markdownText;
if (packagesNames.Any())
{
markdownText = "### Loaded Packages" + Environment.NewLine;
foreach (var name in packagesNames)
{
markdownText += "- " + name + Environment.NewLine;
}
}
else
{
markdownText = "No loaded packages were found.";
}
return markdownText;
}
else
{
return "(Fill in here)";
}
}

/// <summary>
/// Formats crash details and adds metadata for use in Github issue body
/// </summary>
/// <param name="details">Crash details, such as a stack trace.</param>
/// <returns>A formatted, but not escaped, string to use as issue body.</returns>
private static string GitHubCrashReportBody(object details)
{
var stackTrace = details?.ToString() ?? string.Empty;
var markdownPackages = details?.ToString() ?? string.Empty;

// This functionality was not available prior to version 2.1.0, so it should be the fallback value
var dynamoVersion = AssemblyHelper.GetDynamoVersion().ToString() ?? "2.1.0+";

return BuildMarkdownContent(dynamoVersion, stackTrace);
return BuildMarkdownContent(dynamoVersion, markdownPackages);
}

/// <summary>
/// Builds a Markdown string that will be posted to our new GitHub issue
/// </summary>
/// <param name="dynamoVersion">Dynamo version that should be recorded in the issue report</param>
/// <param name="stackTrace">The crash stack trace to be included in the issue report</param>
/// <param name="markdownPackages">Section of the issue with the loaded packages in markdown format</param>
/// <returns></returns>
internal static string BuildMarkdownContent(string dynamoVersion, string stackTrace)
internal static string BuildMarkdownContent(string dynamoVersion, string markdownPackages)
{
return
"# Issue Description" + Environment.NewLine +
Expand All @@ -70,7 +106,7 @@ internal static string BuildMarkdownContent(string dynamoVersion, string stackTr
"(Fill in here)" + Environment.NewLine + Environment.NewLine +

"## What packages or external references (if any) were used?" + Environment.NewLine +
"(Fill in here)" + Environment.NewLine + Environment.NewLine + Environment.NewLine +
markdownPackages + Environment.NewLine + Environment.NewLine +

"## Stack Trace" + Environment.NewLine +
"```" + Environment.NewLine +
Expand Down
78 changes: 75 additions & 3 deletions test/DynamoCoreWpfTests/CrashReportingTests.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using Dynamo.PackageManager;
using Dynamo.Utilities;
using Dynamo.ViewModels;
using DynamoCoreWpfTests;
using NUnit.Framework;

namespace Dynamo.Tests
{
[TestFixture]
public class CrashReportingTests
public class CrashReportingTests : DynamoModelTestBase
{
// This is the stack trace produced by the known crash produced when
// opening the Core.Math sample, selecting all nodes and doing NodeToCode.
Expand Down Expand Up @@ -42,6 +44,11 @@ at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at DynamoSandbox.DynamoCoreSetup.RunApplication(Application app)";

// This are example packages names used to simulate loaded packages information
private string Packages = @"
- Package Example A
- Package Example B";

[Test]
[Ignore("Test ignored because the web browser is not closed after the test execution")]
public void CanReportBugWithNoContent()
Expand All @@ -66,7 +73,7 @@ public void CanReportBugWithContent()
var dynamoVersion = "2.1.0";

// Create a crash report to submit
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, StackTrace);
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, Packages);
Assert.IsNotNullOrEmpty(crashReport);

// Report a bug with a stack trace
Expand All @@ -80,7 +87,7 @@ public void StackTraceIncludedInReport()
var dynamoVersion = AssemblyHelper.GetDynamoVersion().ToString();

// Create a crash report to submit
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, StackTrace);
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, Packages);
Assert.IsNotNullOrEmpty(crashReport);

// Mock url for request
Expand All @@ -95,10 +102,75 @@ public void StackTraceIncludedInReport()

// Verify request contains the dynamoVersion
Assert.True(decoded.Contains(dynamoVersion));
// Verify request contains the packages information
Assert.True(decoded.Contains(Packages));

// TODO - Can be re-added when stack traces are uploaded automatically (currently manual)
// Verify request contains the stack trace
// Assert.True(decoded.Contains(StackTrace));
}

[Test]
public void NullPackageLoader()
{
// Mock Dynamo version
var dynamoVersion = AssemblyHelper.GetDynamoVersion().ToString();

//Get packages data from null package loader
var packagesData = Wpf.Utilities.CrashUtilities.PackagesToMakrdown(null);

// Create a crash report to submit
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, packagesData);
Assert.IsNotNullOrEmpty(crashReport);

// Mock url for request
string url = Wpf.Utilities.CrashUtilities.GithubNewIssueUrlFromCrashContent(crashReport);
Assert.IsNotNullOrEmpty(url);

// Get body content from request
var query = "body=";
var startIndex = url.IndexOf(query) + query.Length;
var body = url.Substring(startIndex);
var decoded = Uri.UnescapeDataString(body);

var expectedString = "## What packages or external references (if any) were used?" + Environment.NewLine + "(Fill in here)";

// Verify request contains the packages information
Assert.True(decoded.Contains(expectedString));
}

[Test]
public void NoLoadedPackages()
{
// Mock Dynamo version
var dynamoVersion = AssemblyHelper.GetDynamoVersion().ToString();

//Gets package loader
var packageLoader = CurrentDynamoModel.GetPackageManagerExtension()?.PackageLoader;
Assert.IsNotNull(packageLoader);
Assert.IsEmpty(packageLoader.LocalPackages);

//Get packages data from null package loader
var packagesData = Wpf.Utilities.CrashUtilities.PackagesToMakrdown(packageLoader);

// Create a crash report to submit
var crashReport = Wpf.Utilities.CrashUtilities.BuildMarkdownContent(dynamoVersion, packagesData);
Assert.IsNotNullOrEmpty(crashReport);

// Mock url for request
string url = Wpf.Utilities.CrashUtilities.GithubNewIssueUrlFromCrashContent(crashReport);
Assert.IsNotNullOrEmpty(url);

// Get body content from request
var query = "body=";
var startIndex = url.IndexOf(query) + query.Length;
var body = url.Substring(startIndex);
var decoded = Uri.UnescapeDataString(body);

var expectedString = "No loaded packages were found.";

// Verify request contains the packages information
Assert.True(decoded.Contains(expectedString));
}
}
}

0 comments on commit 4cac452

Please sign in to comment.