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

Package update #216

Closed
wants to merge 2 commits into from
Closed

Package update #216

wants to merge 2 commits into from

Conversation

gavin-stackrox
Copy link
Contributor

Brings packages up to date using old skool ncu -u.

Testing performed: login, logout, built a GKE cluster with non-standard params, changed lifespan, grabbed artifacts, deleted.

Copy link
Contributor

@vjwilson vjwilson left a comment

Choose a reason for hiding this comment

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

I don't know enough about TS, and esp. TSv4 to say whether all this is the best way. It does worry me that we have to add so many eslint exceptions--but I know some eslint maintainers are "true believers" (in the Eric Hoffer sense).

Perhaps Ivan can shed more light on it.

Other than that, I'm good with this.

Comment on lines +60 to 61
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
setRequestState({ called: true, loading: false, error, data: undefined });
Copy link
Contributor

Choose a reason for hiding this comment

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

Assume this is needed because of the TypeScript upgrade, but it's not obvious to me why.
The apollo-client React implementation, on which we based this, but for our REST calls, allows undefined.
https://www.apollographql.com/docs/react/api/react/hooks/#result-1

Or is it b/c of 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.

This was due to:
Unsafe assignment of an any value @typescript-eslint/no-unsafe-assignment
I think the 'any' was from error but I really could not figure it out.

Copy link
Contributor

Choose a reason for hiding this comment

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

Going to review the whole PR, but here looks like TS failed to do the type inference properly, so instead of disabling rules we should just help it by replacing current catch statement with

      .catch((error: AxiosError<T>) => {

explicitly specifying the type.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, it's not that it fails to infer, it's just Promise type defined, surprisingly, w/o the explicit type for the error. Anyway, we just can be explicit about the type of error we expect to catch.

@@ -38,17 +38,20 @@ class ErrorBoundary extends Component<PropsWithLocation, State> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
componentDidCatch(error: any): void {
const { location } = this.props;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Copy link
Contributor

Choose a reason for hiding this comment

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

Now I'm really worried. Either we need to update our signatures, or this is one of those cases where the eslint folks are so intent on "doing the right thing", they're just dissuading people from using TS.

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 think TS is saying just don't use any anywhere time or place. And we have a few uses that would probably need some type acrobatics to refactor.

Copy link
Contributor

@ikornienko ikornienko left a comment

Choose a reason for hiding this comment

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

I agree with Van, too many ESLint exceptions. While they're opinionated, I always follow the rule

  • Those people are smarted than me;
  • It's unlikely the code we write is such a super-special snowflake that its above all those rules.

And indeed many of those ignores are unnecessary, as we can just be more specific with types, also making code more strictly typed (yay, more types!).

@@ -37,6 +37,7 @@ export default function useApiOperation<T>(requester: ApiCaller<T>): [() => void
})
.catch((error) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here, just specify the error type with catch((error: AxiosError<T>) => {

@@ -38,17 +38,20 @@ class ErrorBoundary extends Component<PropsWithLocation, State> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
componentDidCatch(error: any): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

Gavin, can you please

  • change definition of type State = to have prop error: Error | null and kill //eslint-disable there;
  • change this error: any to error: Error;
  • then remove both //eslint-disable above this line and the one you added in this method.

It's my mistake that I've put any here when it should be either unknown or just more specific Error.

this.setState({ error, errorLocation: location });
}

render(): ReactElement {
const { message, children } = this.props;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Copy link
Contributor

Choose a reason for hiding this comment

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

That can be removed once you change State type to have prop error typed as Error and not any.

const { error } = this.state;

if (error) {
return (
<div className="flex h-full items-center justify-center text-base-600">
<XSquare size="48" />
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */}
Copy link
Contributor

Choose a reason for hiding this comment

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

And this can be just removed as well.

@@ -1,6 +1,6 @@
import React, { forwardRef } from 'react';

const StackRoxLogo = forwardRef<SVGSVGElement, {}>((_, ref) => (
const StackRoxLogo = forwardRef<SVGSVGElement, unknown>((_, ref) => (
Copy link
Contributor

Choose a reason for hiding this comment

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

unknown isn't correct. Quite the opposite, we know that the component doesn't take any props, so there are two options as I see it:

  • use never instead of unknown (we never expect props to be passed)
  • just remove it, i.e. make it forwardRef<SVGSVGElement>, second type parameter will become the default value as defined in function forwardRef<T, P = {}> (i.e. {} again :) ).

});
const initialValues: FormikValues = {
ID: flavorId,
Description: '',
Parameters: createInitialParameterValues(flavorParameters),
};

// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
const [error, setError] = useState<any>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, if I understand the code correctly, here we should be doing useState<AxiosError<V1ResourceByID>>();, then you can remove all // eslint-disable above.

@@ -249,7 +249,9 @@ export default function ClusterForm({
<Form className="md:w-1/3">
{error && (
<div className="p-2 mb-2 bg-alert-200">
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */}
Copy link
Contributor

Choose a reason for hiding this comment

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

You can remove this line once you updated useState above.

{`[Server Error] ${error.message || 'Cluster creation request failed'}`}
{/* eslint-disable-next-line @typescript-eslint/no-unsafe-member-access */}
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm... ok, that's tricky, V1ResourceByID that I suggested above doesn't have error, but none of the data types in api.ts do... Was I delusional when I wrote this line, as no way the backend can return error with the response data? Or it can it's just swagger / proto definitions are off?

Assuming the backend can return error this way, there are two options:

  • Fix swagger definitions and regenerate client, using the right type in useState<> above (instead of V1ResourceByID). Yet haven't dug deep enough to understand if it's actually a limit of client generator.. but somewhere there should be a type that defines that backend can return error in response data, shouldn't it?
  • Hack-y way... change useState above to something like
  // actually backend can return `error` with as a prop on `data`, hack to indicate it, as there are limiting factors to define it properly with proto / swagger 
  const [error, setError] = useState<AxiosError<V1ResourceByID & { error: string }>>();

Copy link
Contributor

Choose a reason for hiding this comment

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

... Was I delusional when I wrote this line, as no way the backend can return error with the response data? Or it can it's just swagger / proto definitions are off?

Assuming the backend can return error this way, there are two options:

  • Fix swagger definitions and regenerate client, using the right type in useState<> above (instead of V1ResourceByID). Yet haven't dug deep enough to understand if it's actually a limit of client generator.. but somewhere there should be a type that defines that backend can return error in response data, shouldn't it?

Not sure if this is relevant, but I found this article about annotating errors for Go and Swagger,
https://www.ribice.ba/swagger-golang/

@@ -1,4 +1,6 @@
/* eslint @typescript-eslint/no-var-requires: 0, @typescript-eslint/explicit-function-return-type: 0 */
/* eslint @typescript-eslint/no-unsafe-member-access: 0 */
Copy link
Contributor

Choose a reason for hiding this comment

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

[Non-action] Hm, some downsides, apparently, of applying @typescript-eslint to .js files... At least we have very few JS files here.

@@ -8,12 +8,14 @@
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"strictNullChecks": false, // allow delete in gen-srcs (delete localVarUrlObj.search)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm really against this change... It's like we have TS, but we're turning it into JS for the sake of some generated code, ultimately rejecting a benefit of compiler telling us problems before we see in runtime "property blah doesn't exist on type null" errors.

Yet.. I don't know how to disable type checking of sub-directory (i.e. src/generated)... Maybe I'm missing something.

I do have a solution though... switch openapi-generator to 5.0.0-beta2. I.e. in generate-client.sh instead of going to 4.3.1 do

OPENAPI_GENERATOR_CLI_IMAGE_TAG="v5.0.0-beta2"

There they fixed this particular issue with OpenAPITools/openapi-generator#6960. Arguments in favor of using beta2:

  • it looks like this beta2 is the last one before the final 5.0.0 release
  • we can always compare the diff of generate code and see if something suspicious is there (I haven't found anything, it's mostly the same except for this URL stuff change)
  • infra is an internal tool
  • not that we're shying away from beta versions even in our main product

All of it tells me that we shouldn't do strictNullChecks: false and instead just upgrade the generator.

Copy link
Contributor

Choose a reason for hiding this comment

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

...
Yet.. I don't know how to disable type checking of sub-directory (i.e. src/generated)... Maybe I'm missing something.
...

We could try adding a subdirectory of a directory being checked to the exclude list in tsconfig.json

Example: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#examples

Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK, it doesn't work this way, see here https://www.typescriptlang.org/tsconfig#exclude Because the files from the generated dir are included through import statement, they're part of the code and therefore will be type checked, adding them to exclude in the tsconfig will do essentially nothing.

@gavin-stackrox
Copy link
Contributor Author

In hindsight, trying to bump up all these packages in a single PR was probably a bad idea. I will close this and try a more incremental and careful upgrade if n' when these upgrades are needed.

@vjwilson
Copy link
Contributor

In hindsight, trying to bump up all these packages in a single PR was probably a bad idea. I will close this and try a more incremental and careful upgrade if n' when these upgrades are needed.

That was also what I decided about doing it for the main app, too. It's partly what drove adopting dependabot--to make regular, incremental progress.

@ikornienko
Copy link
Contributor

In hindsight, trying to bump up all these packages in a single PR was probably a bad idea. I will close this and try a more incremental and careful upgrade if n' when these upgrades are needed.

I don't know... I felt you were so close :) Just couple of code changes and... Yet you're the boss :)

@gavin-stackrox
Copy link
Contributor Author

gavin-stackrox commented Oct 26, 2020 via email

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.

3 participants