-
Notifications
You must be signed in to change notification settings - Fork 559
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
Groundwork for exposing core API in CLI #6293
Conversation
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.
One alternative I tried but backed out of was to do this all entirely client-side w/ introspection queries.
Potentially, this would also allow us to use this new API in our module codegen instead of relying on introspection?
If so, that feels like it could clear up quite a lot of code, and since we have control over the TypeDef
s, we can embed more contextual information. One use I quite like the idea of an SDK being able to put different types into sub-packages if it likes, depending on the origin module (or at least listing the source in the relevant doc-comments)
cmd/dagger/functions.go
Outdated
// Whether to load core API types along side the user module types. | ||
// TODO: this should become the default behavior once the CLI simplification | ||
// work is done, can be removed at that time. | ||
IncludeCore bool |
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.
Potential discussion point: would we ever want to allow including dependency types (and not just core)?
Maybe this is not as useful for end-users, but for devs, I can see this being super useful - I have all my dependencies listed in dagger.json
, I want to play around with those on the CLI, as I write my code.
Or, do interfaces make this kind of irrelevant, since we won't allow accepting/returning foreign concrete types directly?
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 could see that being potentially useful and provided it's only direct dependencies then it would be totally logically consistent since you'd essentially be operating on the same schema that the module itself has (modules have access to both their own APIs and the APIs of their direct deps).
Honestly the only real impediment is that the CLI currently only lets you load one user module at a time (#5866) and has some assumptions around that. E.g. because there's only one user module loaded you don't have to specify the "main module object" as a top-level command and can instead just start calling functions on it right away (or provide top-level flags for the constructor).
- We can resolve that by just requiring that if multiple user modules are loaded then you have to specify a top-level object/constructor.
But that's all getting out of scope of this PR obviously 😄
Possibly but there's some nuance to it (this was another consideration that caused me to waffle around in how to approach all this). The potential weirdness there is that You could deal with this fairly easily by just requiring that SDKs predeclare the various That sounds not great, but then if you consider that today the way it works is that the SDKs need predeclared types for all the graphql introspection types and unpack the introspection json into those, it's not quite as bad, feels more like a wash.
Overall, after wracking my brain about all that I just decided to go with what's in this PR since it's pretty straightforward, integrated w/ the existing CLI easiest and doesn't rule out our options in the future if we want to change approach (e.g. if we wanted to switch the CLI to just use graphql introspection instead, you can mostly just move the code that's currently in the server to the CLI and then just need to deal with adding directives for distinguishing the source module name) |
I think |
b937dd3
to
382fedf
Compare
The reason I went with that is the naive implementation actually breaks existing use of However, I took another look and realized it's actually fairly straightforward to both lift that requirement and retain the previous behavior (for the time being, pending more follow up improvements as part of this whole effort).
So as a result of that, I could remove |
382fedf
to
b24fb27
Compare
ping @helderco to 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.
sync
shows in --help
but doesn't work:
Error: response from query: input:1: Field "sync" of type "ContainerID!" must not have a sub selection.
That's because the default stdout
is being applied:
query{pythonSdkDev{test{default{sync{stdout}}}}}
@helderco good catch, problem was that we were converting |
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.
LGTM 🚀
Two things I'd like to see changed is to not output anything with sync
and maybe allow id
as well.
The reason for wanting no output in sync
is to allow for a workflow of using with_focus
for the output. Using stdout
or sync
is noisy but a silent sync
would enable that.
As for allowing id
, it could be used for composability in the CLI (e.g., Directory
input accepting a DirectoryID
value, from another command).
This enables callers to directly introspect a full loaded schema on the level of TypeDefs rather than the introspection json. This includes the core API, which is what the bulk of the new code here is supporting. This is intended to be used by the CLI to support exposing the core API the same way the way user module objects+functions currently are. Signed-off-by: Erik Sipsma <erik@dagger.io>
We want this to eventually become the default behavior of a unified dagger CLI command for invoking module functions, but in the mean time this experimental flag allows us to iterate on the UX and features needed without breaking or impacting existing functionality. Signed-off-by: Erik Sipsma <erik@dagger.io>
We can actually do this in the short term without breaking the current UX. The modification needed was to change the OnSelectObjectLeaf callback to run once the last command is being executed (i.e. we're about to construct and submit the actual API query). This allows the existing behavior to be retained (for now) while also supporting continued chaining off of core object types like Container/Directory/File too. As part of this I also split the existing `dagger call` integ tests to their own file, backfilled some coverage around the current behavior when Container/Directory/File is the final return type and also added new coverage for the new core chaining abilities. Signed-off-by: Erik Sipsma <erik@dagger.io>
Wanted to have this to ensure the CLI changes don't break the up command. The test currently only uses `--native` because I hit a pre-existing bug with `--port` (linked to the GH issue opened for it in the test case code). Signed-off-by: Erik Sipsma <erik@dagger.io>
Signed-off-by: Erik Sipsma <erik@dagger.io>
Yes agreed, at least if we end up keeping
Yeah something like this is at least in the cards once #6297 lands, though there'd be stuff to figure out still (only want to enable re-use of "pure" IDs, etc.) |
Signed-off-by: Erik Sipsma <erik@dagger.io>
This lays out of some of the low-level plumbing needed to support #6229 :
TypeDef
s.core
type defs it now has access to thanks to the abovedagger call
,--experimental-include-core
(-x
for short), that if set enables the behavior of includingcore
APIsImplementation notes
Getting
TypeDef
s forcore
I spent a while waffling around how best to approach exposing the
core
API asTypeDef
s (or whether to at all), with these considerations in mind:core
to be fully modeled as a loadable module, so any reasonable baby steps we can take towards that are nice all else being equalcore
as aModule
, so we don't want to necessarily go all out on pretending that it is yetModule
representation ofcore
, but with almost all of the fields returning an error if called. This felt best to avoid for the time being; too much API weirdness and new sources of backwards-incompatible changes if we decide to approach this differently.Given the above, I landed on this approach:
currentTypeDefs
is added underQuery
and returns a list ofTypeDef
s for everything loaded into the current schema.core
TypeDefs without (yet) actually modelingcore
as a module from clients' perspectives.sourceModuleName
is added toObjectTypeDef
that is set with the name of the user module if theObjectTypeDef
is associated with one (empty otherwise).core
as full-blown Module (the field is just""
if it's not associated with a user module).Alternative - introspection query
One alternative I tried but backed out of was to do this all entirely client-side w/ introspection queries.
So the CLI just relies purely on introspection queries and constructs it's
modTypeDef
/modObject
/etc. representations from that.This almost works nicely but there's a wrench when trying to determine whether an object is from core or not, which we may want for the rest of this effort.
The only non-hacky way I could think of doing that without corner cases was via directives, which while plausible starts getting much more involved and changes how we generate the actual core schemas we present to clients.
That being said, this is still a viable option that I'm open to (either now or in the future once we made more progress here), let me know if you have any thoughts.
dagger call -x
EDIT: I found a simple path to have core included by default in the existing commands, so there's no
-x
flag needed anymore: #6293 (comment)Previous content
I wanted us to be able to try this all out right away without making complex changes to
dagger run
immediately or breaking the DX ofdagger call
immediately.Adding the flag to
dagger call --experimental-include-core
(akadagger call -x
) was the fastest route to get this usable and testable I saw, but there's plenty of other options:dagger modrun
command or similar that's just likedagger call
but with core types always included.dagger run
that trigger this new behavior.dagger run
should behave like before and when it should have the new "module-aware" behavior; including corner cases like when no-m
flag is provided but you are in a directory containing adagger.json
I'm not strongly opposed to either of those options if others feel strongly one way or another.
Example
This module:
when invoked with
dagger call
now allows commands like this:and