-
Notifications
You must be signed in to change notification settings - Fork 9
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
Maintainability Items: linting and typing #69
Conversation
default: { | ||
assertExhaustiveSwitch(kind); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case someone reviewing isn't a TypeScript person: this trick will detect any unhandled (or, coincidentally, un-terminated) branches of the enum switch and turn them into compiler errors (familiar to Rust folks, probably other languages too), since never
is a bottom type.
new AsyncResultWrapper( | ||
Result.wrapAsync(async () => | ||
zulipInit({ | ||
apiKey, | ||
username, | ||
realm, | ||
}) | ||
) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frankly this interaction between ts-async-results
and the parent library, ts-results
, looks pretty gross. There may be a simpler way to do this, but after reading upstream issues in both repos and a lengthy conversation with the type checker, this is the best I came up with so far.
Result.all( | ||
getMandatoryInputFromJob("content"), | ||
getDestinationDetails(), | ||
await getZulipClient() | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may make sense to instead use AsyncResult.all
, though the ergonomics are a little weirder there. It would probably replace the manual call to new AsyncResultWrapper
at the top level, though may create two new calls to it on L144+L145. I'll do some investigation on this Monday.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that using [AsyncResult.all](https://github.com/movesthatmatter/ts-async-results#combining-results)
didn't bear any fruit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all of the work converting this! I'm excited to have this be more up to the standards of zulip/zulip.
I'm pretty non-qualified for the TS parts of this, but I left a couple comments on things that jumped out at me.
"@typescript-eslint/no-floating-promises": "off", | ||
"unicorn/prefer-top-level-await": "off" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense to apply eslint --fix
in this commit? Usually we do that when configuring a linter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After eslint --fix
we'll still have 16 non-auto-fixable (and frankly non-trivial even with human intervention) linter errors. I'd wager probably not worth rolling back to try to fix that since the code being fixed gets fully replaced in the next commits anyway, but that's not a hill I'd die on or anything.
(woods) github-actions-zulip » (0cfc8ee...) » git checkout 0cfc8eec86b7719aed832f13bd3528c92615d5ef; npm ci; npx eslint --fix ./src/send-message.js
HEAD is now at 0cfc8ee deps: Install and configure ESLint based on XO defaults.
added 278 packages, and audited 279 packages in 3s
# snip...
/home/j/src/zulip/github-actions-zulip/src/send-message.js
29:13 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment
29:31 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call
29:50 error Unsafe return of an `any` typed value @typescript-eslint/no-unsafe-return
29:50 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call
31:9 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment
31:14 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call
49:11 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment
49:26 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call
57:11 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment
57:28 error Unsafe call of an `any` typed value @typescript-eslint/no-unsafe-call
60:50 error Invalid type "any" of template literal expression @typescript-eslint/restrict-template-expressions
62:13 error Unsafe assignment of an `any` value @typescript-eslint/no-unsafe-assignment
63:14 error Invalid type "any" of template literal expression @typescript-eslint/restrict-template-expressions
63:32 error Invalid type "any" of template literal expression @typescript-eslint/restrict-template-expressions
67:5 error Implicit any in catch clause @typescript-eslint/no-implicit-any-catch
75:5 error Implicit any in catch clause @typescript-eslint/no-implicit-any-catch
✖ 16 problems (16 errors, 0 warnings)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to go back to the add-linting commit anyway to address a commit cleanliness comment from Alex so I met in the middle here if that's cool with you: ran lint:fix
over the original JS in the commit that adds eslint-config-xo and company, but does not resolve the outstanding 18 (up from 16 because I'd missed eslint-config-xo
not being inherently pulled in by eslint-config-xo-typescript
, oops) non-auto-fixable errors. It does, however, resolve about 50 auto-fixable errors at that point in the commit history.
That's all now implemented in ecdacd5
@Mogztter it'd be great for you to review/test this as well when you get a chance. (@klardotsh for context, he's the original author). |
I've done the documentation updates I wanted to do and have a successful simple regression test in https://github.com/klardotsh/zulip-gha-playground/actions/runs/3579426796, so I'm marking this ready for review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not qualified to review the actual Typescript changes (paging @andersk if he has any ideas about cleaning up the AsyncResultWrapper
/ wrapAsync
in getZulipClient
), but the rest of this looks great to me.
Result.all( | ||
getMandatoryInputFromJob("content"), | ||
getDestinationDetails(), | ||
await getZulipClient() | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume that using [AsyncResult.all](https://github.com/movesthatmatter/ts-async-results#combining-results)
didn't bear any fruit?
Not having heard any objections, and since this is a clear improvement on the current state of affairs, I've merged this -- thanks for all of the cleanups, @klardotsh! |
As mentioned on CZO, I figured I'd take a pass at tidying up this codebase before adding more in-house uses of it in some future work. As such, this PR sets up linting (based on xojs/xo's defaults, largely similar to the style in zulip/zulipbot), and refactors the existing
send-message
action into a strict and functional flavor of TypeScript.I'd originally intended to just run the existing code through the TypeScript compiler, see what complained, touch those up, and move on, but after realizing I hated the type annotation of
string | number | (string|number)[]
for the heavily-reassignedto
variable, and also that validation/business logic was spread all around the function in difficult-to-trace ways, I went for a more comprehensive refactor.Opening as a draft to get high-level feeedback on approaches within (particularly, the use of the heavily-Rust-inspired
ts-results
andts-async-results
helper libraries to get aResult
/Maybe
monad)while I dig into testing this with my own bot users: as it stands this code passes type checking, but I have not actually run the action in a GitHub Actions environment to regression-test the functionality.update: https://github.com/klardotsh/zulip-gha-playground/actions/runs/3579426796 passes a simple regression test.The
zulip-js.d.ts
stubs are purely structural hints: I don't attempt to model the responses from the server, I simply model a subset of the Zulip client itself. As it stands the hints are incomplete enough as to potentially be confusing if integrated to zulip/zulip-js, so I've kept them separate (despite the pitfalls regarding theResponse
objects mentioned in a comment). I'm open to discussing a proper plan for mainlining those to the proper repo and what that process would look like, or to punting that discussion for later.