Skip to content
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

feat(gatsby): enable richer error handling for unknown APIs #16105

Merged
merged 13 commits into from
Aug 11, 2019

Conversation

DSchau
Copy link
Contributor

@DSchau DSchau commented Jul 26, 2019

Description

This WIP PR enables nicer error handling (structured errors!) for invalid APIs.

It does a few things (all of which I'll need to test more):

  1. Uses a postinstall script to download latest-apis.json from Unpkg
  2. Uses this API lookup to provide nicer errors/warnings
  3. Improves (!?) the warning based on data from that API lookup
  4. Does not panic/fail the build on these missing/typo'd API errors

Screen Shot 2019-07-25 at 5 19 17 PM

Still to-do:

  1. More manual testing
  2. Unit and/or e2e testing
  3. Validate postinstall script, and specifically error handling

Related Issues

Implements #16055

Helps unblock #16027

Copy link
Contributor Author

@DSchau DSchau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some prelim. comments.

@@ -3,6 +3,40 @@ import path from "path"
import { Color, Box } from "ink"
import { get } from "lodash"

const colors = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll remove this -- I was testing with a structured "error" of warning.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need theme-ui theme for CLI!

Copy link
Contributor Author

@DSchau DSchau Jul 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lol! Design tokens and theme-ui for our CLI, I like it!

const { version: gatsbyVersion } = require(`gatsby/package.json`)
const reporter = require(`gatsby-cli/lib/reporter`)
const resolveModuleExports = require(`../resolve-module-exports`)

const getGatsbyUpgradeVersion = entries =>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gets the most recent/newest version of Gatsby if multiple new APIs.

message += `\n\n`
const similarities = stringSimiliarity.findBestMatch(bady.exportName, apis)
const isDefaultPlugin = bady.pluginName == `default-site-plugin`
const badExportsMigrationMap = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just removed these. Is there a reason to keep these around in Gatsby 2.x?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we don't remove those. It's definitely less likely that any user will hit that at this point in time (almost year after gatsby@2). Was this causing some headaches with refactoring?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in screenshot from PR description you had migration tips for those - was this just mockup?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope! That one (and maybe the other) get covered by the string distance algorithm!

@@ -160,6 +162,34 @@ const errorMap = {
}`,
level: `ERROR`,
},
// invalid or deprecated APIs
"11329": {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a pattern to these errors? Were the error codes chosen for a reason, or am I correct in presuming it's effectively an incrementing id that just makes things easier to Google?

Also next-level would be to generate docs pages based on these structured errors, and then provide even richer detail e.g.

To learn more about fixing this error, please visit https://gatsby.dev/11329

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no special meaning to codes. Actually if codes have less patterns the better ;) We want them to be easily google-able (for example to find related issues if linked docs are not enough). So best avoid codes like 11111, 12345 that have higher chance of returning unrelated search results.

One thing that is not really specified, but I think could make sense here, is to not increment by 1 when adding new structured error (if new error is related to different thing than last one).
As example you can check error related to loading gatsby-config - those occupy 10123-10125 range right now and there are slots after that to add more related errors in the future and still keep those grouped.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should just print a prefix maybe then? GTSB-12345 is pretty unique!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pieh circling back to this. Few questions:

One thing that is not really specified, but I think could make sense here, is to not increment by 1 when adding new structured error

What are you proposing here exactly?

those occupy 10123-10125 range right now and there are slots after that to add more related errors in the future and still keep those grouped.

I'm happy to add it there (what you may be saying?) but those are config errors? This could be a gatsby-node.js error, but it wouldn't be a config error necessarily.

// to happen once the the API queue is empty. Ideally of course
// we'd have an API (returning a promise) for that. But this
// works nicely in the meantime.
if (!apiList[api] && api !== `FAKE_API_CALL`) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was kind of a strange one -- I think I can safely remove this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe? See #11831 - FAKE_API_CALL was added as workaround for issues when page is deleted. I think you could try gatsby develop in gatsby-starter-blog and try to delete one of markdown posts and see what happens :P

*/
if (await fs.exists(OUTPUT_FILE)) {
return fs.readJSON(OUTPUT_FILE)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think trying to load from file makes more sense as fallback and to prefer fetching fresh if possible.

In case of creating new gatsby project - cached latest-apis.json will be equaivalent to what gatsby package was doing already - as it will be list of APIs that is only up-to-date with their version of gatsby. If later on we add new API and implement it in plugin. Users install plugin - he still will have cached latest-apis.json that have no data about this new API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good call! Will fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed!

const fs = require(`fs-extra`)
const axios = require(`axios`)

const API_FILE = `https://unpkg.com/gatsby/apis.json`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd put this behind a gatsby.dev url (gatsby.dev/apis.json) for future proofing and if we ever move this to something else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah -- not sure. The main drawback is that sometimes .dev domains are blocked due to some localhosts hackery, which would mean the file never downloads.

I think keeping it like this is a little safer. I don't think it's likely we'll need to re-name this file, either?

I get what you're doing here, just not sure I'm fully on board!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm likely overthinking this. The file isn't mission critical anyway and is a progressive enhancement so you're probably right in keeping things simple!

Looking great otherwise 🙌

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was (and still may be!) a good idea! Just want to try and think of all the trade offs, good and bad!

@DSchau DSchau marked this pull request as ready for review July 31, 2019 05:11
@DSchau DSchau requested review from a team as code owners July 31, 2019 05:11
@DSchau DSchau changed the title [WIP] feat(gatsby): enable richer error handling for unknown APIs feat(gatsby): enable richer error handling for unknown APIs Jul 31, 2019
Copy link
Contributor

@sidharthachatterjee sidharthachatterjee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time to ship this! Thank you so much @DSchau 👍

@sidharthachatterjee sidharthachatterjee merged commit 0adab13 into gatsbyjs:master Aug 11, 2019
@sidharthachatterjee
Copy link
Contributor

Published in gatsby@2.13.58

@DSchau DSchau deleted the gatsby/apis-list branch August 12, 2019 20:31
@thchia
Copy link
Contributor

thchia commented Sep 9, 2019

I haven’t grokked what’s going on here, but is it possible to opt out of downloading the latest apis?

My motivation is that this is running behind a firewall at my work network, and I have to wait for it to timeout which is a bit annoying. If there is a way to fast fail and go straight to reading the default apis.json file, that would do. Happy to contribute.

@DSchau
Copy link
Contributor Author

DSchau commented Sep 9, 2019

@thchia the idea is that introducing this functionality enables us to keep errors/warnings on invalid APIs (e.g. typos or APIs we don't support) but not break on newer APIs that we release in newer versions of Gatsby, e.g. #16027 which introduces an API to validate/coerce the shape of plugin/theme options.

Could you share more info as to the work firewall? It seems like unpkg is an extremely safe candidate to not be blocked. Blocking that would block a significant chunk of the web.

What we could do is add a timeout (e.g. 2500 ms or something, but this is a "guess" that may then break slower connections unnecessarily) and fail if the timeout is exceeded -- but I'd like to hear more about your use case before we do that.

@thchia
Copy link
Contributor

thchia commented Sep 9, 2019

@DSchau thanks for the response.

I work at a financial institution, which has a security policy that is

  1. Mysterious and;
  2. Hard to change T_T

I’ve run into issues like this before (postinstall scripts that download from github also don’t work), and unfortunately for me the solution has never been to relook at the security policy. Packages like node-sass offer configurable URLs for downloading the necessary binaries, I’m not sure if you would consider this in the same bucket of issues?

I don’t think adding a timeout sounds like the right solution for the same reason you mentioned - it ends up being non-deterministic.

Anyway I’m aware that in any “normal” environment this wouldn’t be an issue and the problem is through no fault of this awesome tool 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants