Skip to content

Fix GenerateBugReport command to pre-fill template #4454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 15 additions & 95 deletions src/features/GenerateBugReport.ts
Original file line number Diff line number Diff line change
@@ -1,123 +1,43 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import os = require("os");
import vscode = require("vscode");
import child_process = require("child_process");
import { SessionManager } from "../session";

const queryStringPrefix = "?";

const project = "https://github.com/PowerShell/vscode-powershell";
const issuesUrl = `${project}/issues/new`;

const extensions =
vscode.extensions.all.filter((element) => element.packageJSON.isBuiltin === false)
.sort((leftSide, rightSide): number => {
if (leftSide.packageJSON.name.toLowerCase() < rightSide.packageJSON.name.toLowerCase()) {
return -1;
}
if (leftSide.packageJSON.name.toLowerCase() > rightSide.packageJSON.name.toLowerCase()) {
return 1;
}
return 0;
});
const issuesUrl = "https://github.com/PowerShell/vscode-powershell/issues/new?";

export class GenerateBugReportFeature implements vscode.Disposable {

private command: vscode.Disposable;

constructor(private sessionManager: SessionManager) {
this.command = vscode.commands.registerCommand("PowerShell.GenerateBugReport", async () => {

const body = `Issue Description
=====

I am experiencing a problem with...

Attached Logs
=====

Follow the instructions in the [README](https://github.com/PowerShell/vscode-powershell/blob/main/docs/troubleshooting.md) about
capturing and sending logs.

Environment Information
=====

Visual Studio Code
-----

| Name | Version |
| --- | --- |
| Operating System | ${os.type()} ${os.arch()} ${os.release()} |
| VSCode | ${vscode.version}|
| PowerShell Extension Version | ${sessionManager.HostVersion} |

PowerShell Information
-----

${this.getRuntimeInfo()}

Visual Studio Code Extensions
-----

<details><summary>Visual Studio Code Extensions(Click to Expand)</summary>

${this.generateExtensionTable(extensions)}
</details>

`;

const encodedBody = encodeURIComponent(body);
const fullUrl = `${issuesUrl}${queryStringPrefix}body=${encodedBody}`;
await vscode.commands.executeCommand("vscode.open", vscode.Uri.parse(fullUrl));
const params = [
"labels=Issue-Bug",
"template=bug-report.yml",
"powershell-version=" + this.getRuntimeInfo(),
"vscode-version=" + vscode.version + "\n" + process.arch,
"extension-version=" + sessionManager.Publisher + "." + sessionManager.HostName + "@" + sessionManager.HostVersion,
];
const url = vscode.Uri.parse(issuesUrl + encodeURIComponent(params.join("&")));
await vscode.env.openExternal(url);
});
}

public dispose() {
this.command.dispose();
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
private generateExtensionTable(installedExtensions: vscode.Extension<any>[]): string {
if (!installedExtensions.length) {
return "none";
}

const tableHeader = "|Extension|Author|Version|\n|---|---|---|";
const table = installedExtensions.map((e) => {
if (e.packageJSON.isBuiltin === false) {
return `|${e.packageJSON.name}|${e.packageJSON.publisher}|${e.packageJSON.version}|`;
}
return undefined;
}).join("\n");

const extensionTable = `
${tableHeader}\n${table};
`;
// 2000 chars is browsers de-facto limit for URLs, 400 chars are allowed for other string parts of the issue URL
// http://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers
// if (encodeURIComponent(extensionTable).length > 1600) {
// return 'the listing length exceeds browsers\' URL characters limit';
// }

return extensionTable;
}

private getRuntimeInfo(): string | undefined {
private getRuntimeInfo(): string {
if (this.sessionManager.PowerShellExeDetails === undefined) {
return;
return "Session's PowerShell details are unknown!";
}

const powerShellExePath = this.sessionManager.PowerShellExeDetails.exePath;
const powerShellArgs = [
"-NoProfile",
"-Command",
"$PSVersionString = \"|Name|Value|\n\"; $PSVersionString += \"|---|---|\n\"; $PSVersionTable.keys | " +
"ForEach-Object { $PSVersionString += \"|$_|$($PSVersionTable.Item($_))|\n\" }; $PSVersionString",
];

const powerShellArgs = [ "-NoProfile", "-Command", "$PSVersionTable | Out-String" ];
const child = child_process.spawnSync(powerShellExePath, powerShellArgs);
return child.stdout.toString().replace(";", ",");
// Replace semicolons as they'll cause the URI component to truncate
return child.stdout.toString().trim().replace(";", ",");
}
}
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,10 @@ export async function activate(context: vscode.ExtensionContext): Promise<IPower
settings,
logger,
documentSelector,
PackageJSON.name,
PackageJSON.displayName,
PackageJSON.version,
PackageJSON.publisher,
telemetryReporter);

// Register commands that do not require Language client
Expand Down
12 changes: 9 additions & 3 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ export const PowerShellVersionRequestType =

export class SessionManager implements Middleware {
public HostName: string;
public DisplayName: string;
public HostVersion: string;
public Publisher: string;
public PowerShellExeDetails: IPowerShellExeDetails | undefined;
private ShowSessionMenuCommandName = "PowerShell.ShowSessionMenu";
private sessionStatus: SessionStatus = SessionStatus.NeverStarted;
Expand All @@ -100,7 +102,9 @@ export class SessionManager implements Middleware {
private logger: ILogger,
private documentSelector: DocumentSelector,
hostName: string,
displayName: string,
hostVersion: string,
publisher: string,
private telemetryReporter: TelemetryReporter) {

// Create the language status item
Expand All @@ -110,14 +114,16 @@ export class SessionManager implements Middleware {
this.sessionsFolder = vscode.Uri.joinPath(extensionContext.globalStorageUri.with({ scheme: "file"}), "sessions");
this.platformDetails = getPlatformDetails();
this.HostName = hostName;
this.DisplayName = displayName;
this.HostVersion = hostVersion;
this.Publisher = publisher;

const osBitness = this.platformDetails.isOS64Bit ? "64-bit" : "32-bit";
const procBitness = this.platformDetails.isProcess64Bit ? "64-bit" : "32-bit";

this.logger.write(
`Visual Studio Code v${vscode.version} ${procBitness}`,
`${this.HostName} Extension v${this.HostVersion}`,
`${this.DisplayName} Extension v${this.HostVersion}`,
`Operating System: ${OperatingSystem[this.platformDetails.operatingSystem]} ${osBitness}`);

// Fix the host version so that PowerShell can consume it.
Expand Down Expand Up @@ -563,9 +569,9 @@ export class SessionManager implements Middleware {
// Unfortunately this means that for some installs of PowerShell
// (such as through the `dotnet` package manager), we can't include
// a multi-line startup banner as the quotes break the command.
editorServicesArgs += `-StartupBanner '${this.HostName} Extension v${this.HostVersion}' `;
editorServicesArgs += `-StartupBanner '${this.DisplayName} Extension v${this.HostVersion}' `;
} else {
const startupBanner = `${this.HostName} Extension v${this.HostVersion}
const startupBanner = `${this.DisplayName} Extension v${this.HostVersion}
Copyright (c) Microsoft Corporation.

https://aka.ms/vscode-powershell
Expand Down