Skip to content

Commit

Permalink
Diagnose print parsing error on missing report (#454)
Browse files Browse the repository at this point in the history
When the diagnose command is run and the installation report is missing
the diagnose command crashes with an error.

```
UnhandledPromiseRejectionWarning: TypeError: Cannot read property
  'download_url' of undefined
```

This is because when the report can't be read the
`getInstallationReport` function would only return an empty object,
rather than the expected object with a parsing error. (Expected in the
sense that's how our other integrations handle this type of error and
that's what the diagnose tool on the server side expects.)

With this change the report should no longer crash and the sent report
includes the error about the missing installation report.

I didn't know how to resolve a TypeScript issue with the optional `raw`
key on the parsing error object, so I created a ParsingError type to
indicate that it's a optional key. I couldn't get it to work otherwise.

Part of #448
  • Loading branch information
tombruijn authored Oct 19, 2021
1 parent 7788739 commit 98f11a0
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 46 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
bump: "patch"
---

The diagnose report will report parsing errors on reading or parsing the installation report. Previously, a missing installation report file would crash the diagnose tool.
94 changes: 53 additions & 41 deletions packages/nodejs/src/cli/diagnose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,50 +32,62 @@ export class Diagnose {
this.print_newline()

console.log(`Extension installation report`)
console.log(` Installation result`)
const installReport = data["installation"]
console.log(` Status: ${installReport["result"]["status"]}`)
const resultMessage = data["installation"]["result"]["message"]
if (resultMessage) {
console.log(` Message: ${resultMessage}`)
}
const resultError = data["installation"]["result"]["error"]
if (resultError) {
console.log(` Error: ${resultError}`)
const parsingError = installReport["parsing_error"]
if (parsingError) {
console.log(` Error found while parsing the report.`)
console.log(` Error: ${parsingError["error"]}`)
if (parsingError["raw"]) {
console.log(` Raw report:`)
console.log(parsingError["raw"])
}
} else {
console.log(` Installation result`)
console.log(` Status: ${installReport["result"]["status"]}`)
const resultMessage = data["installation"]["result"]["message"]
if (resultMessage) {
console.log(` Message: ${resultMessage}`)
}
const resultError = data["installation"]["result"]["error"]
if (resultError) {
console.log(` Error: ${resultError}`)
}

console.log(` Language details`)
console.log(
` Node.js version: ${data["installation"]["language"]["version"]}`
)
console.log(` Download details`)
console.log(
` Download URL: ${data["installation"]["download"]["download_url"]}`
)
console.log(
` Checksum: ${data["installation"]["download"]["checksum"]}`
)
console.log(` Build details`)
console.log(` Install time: ${data["installation"]["build"]["time"]}`)
console.log(
` Architecture: ${data["installation"]["build"]["architecture"]}`
)
console.log(` Target: ${data["installation"]["build"]["target"]}`)
console.log(
` Musl override: ${data["installation"]["build"]["musl_override"]}`
)
console.log(
` Linux ARM override: ${data["installation"]["build"]["linux_arm_override"]}`
)
console.log(
` Library type: ${data["installation"]["build"]["library_type"]}`
)
console.log(` Host details`)
console.log(` Root user: ${data["installation"]["host"]["root_user"]}`)
console.log(
` Dependencies: ${this.format_value(
data["installation"]["host"]["dependencies"]
)}`
)
}

console.log(` Language details`)
console.log(
` Node.js version: ${data["installation"]["language"]["version"]}`
)
console.log(` Download details`)
console.log(
` Download URL: ${data["installation"]["download"]["download_url"]}`
)
console.log(` Checksum: ${data["installation"]["download"]["checksum"]}`)
console.log(` Build details`)
console.log(` Install time: ${data["installation"]["build"]["time"]}`)
console.log(
` Architecture: ${data["installation"]["build"]["architecture"]}`
)
console.log(` Target: ${data["installation"]["build"]["target"]}`)
console.log(
` Musl override: ${data["installation"]["build"]["musl_override"]}`
)
console.log(
` Linux ARM override: ${data["installation"]["build"]["linux_arm_override"]}`
)
console.log(
` Library type: ${data["installation"]["build"]["library_type"]}`
)
console.log(` Host details`)
console.log(` Root user: ${data["installation"]["host"]["root_user"]}`)
console.log(
` Dependencies: ${this.format_value(
data["installation"]["host"]["dependencies"]
)}`
)

this.print_newline()

console.log(`Host information`)
Expand Down
24 changes: 20 additions & 4 deletions packages/nodejs/src/diagnose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ interface FileMetadata {
writable?: boolean
}

interface ParsingError {
error: string
backtrace: []
raw?: string
}

export class DiagnoseTool {
#config: Configuration
#extension: Extension
Expand Down Expand Up @@ -84,11 +90,21 @@ export class DiagnoseTool {
}

private getInstallationReport() {
let rawReport
try {
const rawReport = fs.readFileSync(reportPath(), "utf8")
return rawReport ? JSON.parse(rawReport) : {}
} catch (e) {
return {}
rawReport = fs.readFileSync(reportPath(), "utf8")
return JSON.parse(rawReport)
} catch (error) {
const report = {
parsing_error: {
error: `${error.name}: ${error.message}`,
backtrace: error.stack.split("\n")
} as ParsingError
}
if (rawReport) {
report.parsing_error.raw = rawReport
}
return report
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/integration/diagnose

0 comments on commit 98f11a0

Please sign in to comment.