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(sdk/elixir): rework on Elixir codegen #6559
Conversation
8a815f7
to
c385d3d
Compare
Found the |
6f57364
to
9dbc689
Compare
with {:ok, items} <- execute(selection, container.client) do | ||
{:ok, | ||
for %{"id" => id} <- items do | ||
%Dagger.EnvVariable{ | ||
selection: | ||
query() | ||
|> select("loadEnvVariableFromID") | ||
|> arg("id", id), | ||
client: container.client | ||
} | ||
end} | ||
end |
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.
Any function that return a list of object are breaking changes since version 0.9.7 but didn't notice user about this breaking changes. Do we need to add a changelog about this?
24c9541
to
b1ecff5
Compare
7776fbc
to
a895daa
Compare
d52edcf
to
850b751
Compare
This PR is stale because it has been open 14 days with no activity. Remove stale label or comment or this will be closed in 7 days. |
519f3a6
to
c200e2e
Compare
WithServiceBinding("dagger-engine", devEngine). | ||
WithEnvVariable("_EXPERIMENTAL_DAGGER_RUNNER_HOST", endpoint). | ||
WithMountedFile(cliBinPath, cliBinary). | ||
WithEnvVariable("_EXPERIMENTAL_DAGGER_CLI_BIN", cliBinPath). | ||
WithExec([]string{"mix", "dagger.gen"}) | ||
WithExec([]string{"mix", "run", "scripts/fetch_introspection.exs"}). |
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 need to extract introspection fetching out of the codegen to make reusable with the module (See https://github.com/wingyplus/daggerverse/blob/main/elixir-sdk/main.go#L90-L100).
It would be nice if mage tasks (or incoming ci module) could inject an introspection JSON file and let the codegen use that file.
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 would be nice if mage tasks (or incoming ci module) could inject an introspection JSON file and let the codegen use that file.
That's done in modules, more specifically via the SDK runtime module. The server provides the introspection JSON and so, codegen needs to be able to read from that.
An external way to get it is to:
dagger -m github.com/helderco/daggerverse/codegen@v0.1.2 call introspect as-json -o introspection.json
In our CI module that can be a dependency so you get it with:
introspectionJson := dag.Codegen().Introspect().AsJson() // a dagger.File
The idea with this module is to eventually use it as a common ground for SDKs to codegen, without reinventing the wheel:
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.
That's done in modules, more specifically via the SDK runtime module. The server provides the introspection JSON and so, codegen needs to be able to read from that.
Yeah, I see it from the module runtime. So I thought it would be nice to have this included in generate task on non-support module SDK (rust, java, elixir, etc.).
An external way to get it is to:
dagger -m github.com/helderco/daggerverse/codegen@v0.1.2 call introspect as-json -o introspection.json
Ahh, so we can calling the function using cliBinPath
to download introspection and then using it to generate code. Nice! Do we have a plan to include it in new CI module (#6843)?
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.
No plan to put it in the CI module as of yet, but you can do it for Elixir 🙂
The PR size is quite big now. So I decided to stop on this and continue on a new PR for incoming improvements. |
c200e2e
to
156714c
Compare
@wingyplus what do you want to do about this PR? Should it be reviewed/merged, or do you want to split it into smaller ones? Either works for us. |
156714c
to
7abcbd8
Compare
Review and merge is the way I prefer. For the mage task changes, I'll update on #6843 to make it up-to-date if this PR merge before that PR. 🙇 |
7abcbd8
to
5fadf0f
Compare
Rebased. |
5fadf0f
to
c5aa758
Compare
This is on my list for today. If we can resolve the conflicts before then, merging this will be straigthforward. Want to take a look too @gmile? |
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.
This is a HUGE PR @wingyplus 😱 My apologies for not getting to it earlier.
This looks great to me 💪 I am keen to get it moving & so that you can follow-up with the rest. I trust that you will get the merge conflicts solved & add any new tests if needed (looks good to me as is).
In case @gmile and @helderco want to check it out too, please do, otherwise I'm excited for the follow-ups 🙌
FWIW, we - especially @jedevc - are communicating upcoming releases via https://github.com/dagger/dagger/milestones, so you can see what release is coming up, and when.
|
||
def is_list_of?(_, _), do: false | ||
|
||
# TODO: refactor me. |
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.
👍
@@ -18,12 +18,23 @@ defmodule Dagger.Core.QueryBuilder.Selection do | |||
} | |||
end | |||
|
|||
def arg(%__MODULE__{args: args} = selection, name, value) when is_binary(name) do | |||
# TODO: Remove me. |
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.
Did you mean to remove this now, or in a follow-up PR?
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 need to tackle it on the PR while I rework on the query builder.
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.
Amazing work! 👏🏅 Looking forward to having this merged!
sdk/elixir/dagger_codegen/mix.exs
Outdated
[ | ||
app: :dagger_codegen, | ||
version: "0.1.0", | ||
elixir: "~> 1.15", |
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 internal/mage/sdk/elixir.go
an earlier version is mentioned, 1.14.5. Should these be in sync?
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.
Changing it to 1.14 would align with the main package. 👍
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.
Fixed on the current commit.
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.
Ok to iterate on follow-ups, so approving now. 🚀
sdk/elixir/dagger_codegen/lib/dagger/codegen/elixir_generator/formatter.ex
Outdated
Show resolved
Hide resolved
sdk/elixir/dagger_codegen/lib/dagger/codegen/elixir_generator/formatter.ex
Show resolved
Hide resolved
def render_deprecated(%Field{deprecation_reason: ""}), do: "" | ||
def render_deprecated(%Field{deprecation_reason: nil}), do: "" | ||
|
||
def render_deprecated(%Field{deprecation_reason: reason}) do |
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.
We have a convention that deprecation reason messages can reference a field (most likely the field that should be used instead), wrapped in backticks (e.g., use `newField` instead
). The reason for this is that SDKs can extract whatever's inside the backticks from the deprecation reason and re-format it according to its own naming conventions.
Example in Python:
dagger/sdk/python/src/dagger/_codegen/generator.py
Lines 664 to 673 in 795a735
def deprecated(self, prefix='"', suffix='"') -> str: | |
def _format_name(m): | |
name = format_name(m.group().strip("`")) | |
return f"{prefix}{name}{suffix}" | |
return ( | |
DEPRECATION_RE.sub(_format_name, reason) | |
if (reason := self.graphql.deprecation_reason) | |
else "" | |
) |
dagger/docs/docs-graphql/schema.graphqls
Line 2142 in 795a735
file(id: FileID!): File! @deprecated(reason: "Use `loadFileFromID` instead.") |
dagger/sdk/python/src/dagger/client/gen.py
Line 5696 in 795a735
Use :py:meth:`load_file_from_id` instead. |
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.
Currently, I've done field conversion by transform content in backquote into snakecase. But the hard part is to link to referenced function in Elixir, we need the arity which's the number of argument of that function. So it's now become a little bit tricky that we need to traverse introspection to find the exact number. 😢
I think it would be great to follow up this issue on the next PR.
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.
Reference to issue #6939
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.
Oh, now I see that's replaced in all descriptions, not just deprecations. We've avoided referencing other fields in the description in the core API because of the wrong naming convention in other languages, but I think that's no longer the case. It's easy to creap in.
We've limited this to deprecation reasons because it's more common in field descriptions to want something in backquotes other than being a field name. Doesn't seem like there's a case like this today though, but that can change. It's smart to only match valid identifiers, but I can't rule out a name in backquotes that is a valid identifier, but meant for something else other than an API field.
Changing the casing is enough. When I said "reference", I wasn't referring to anything special in code, even though Python does generate a prefix that allows it to be hyperlinked correctly in the reference docs. But the convention here is just to rename, having IDE autocomplete in mind.
c5aa758
to
8e0e5ad
Compare
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
8e0e5ad
to
ddb74a4
Compare
Follow-up conversation in dagger#6559 (comment). The function in backquote should convert to snake case only deprecation message. Fixes dagger#6939 Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Follow-up conversation in dagger#6559 (comment). The function in backquote should convert to snake case only deprecation message. Fixes dagger#6939 Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
This is a big change but let me explain to catch up easier.
Codegen moved out from the SDK
Previously, the dagger codegen was embedded in the SDK, this caused a problem in that it could not be run when the codegen generated a bad code. This change introduces a new Elixir module called
dagger_codegen
which's responsible for generating code and uses theescript
to build a binary instead of the mix task.The way to fetch introspection is now split out of the codegen. This way can reduce the compilation annoying issue, described in #5901, but the issue still happens when using
hack/make sdk:elixir:generate
.sdk:elixir
tasks improvementThe
hack/make sdk:elixir:*
task is now upgraded to use Elixir 1.16 with Erlang/OTP 26. Thesdk:elixir:generate
will not produce a bad code when its failure.Nicer code-generation
Previously, the codegen used Elixir quote to produce code but it's not suitable for our use case, the codegen is a bit hard to read and needs to deal with complex AST structure. The new codegen uses a new approach by using EEx as a template and moving some complex code-generation to the renderer module.
The typespec and documentation also improved.
Here is comparison
0.9.7
From this PR
Fix issues in the codegen
sdk:elixir:generate
as mentioned above.sdk:elixir:generate
.Cleanup
Nestru
out of the codegen since we change how to query list object likeenvVariables
.lib/dagger/codegen
.Improvement on the next PR