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
Elixir Module support #6967
base: main
Are you sure you want to change the base?
Elixir Module support #6967
Conversation
`Dagger.ModuleRuntime` is a runtime for `Dagger` module for Elixir. | ||
""" | ||
|
||
def __on_definition__(env, :def, name, args, _guards, _body) 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.
To reviewer, the __on_definition__
invoke when Elixir start compile the source. When it found a function declaration, it'll pass the information to this function.
This looks amazing! WDYT @helderco @gmile? What else is on your list @wingyplus before this is ready for the final review & merge? |
Yes, I've been watching this PR for a while, this is really promising, thanks for ping @gerhard! The kind of blocker I have with my article for Elixir SDK is entering a shell of the module to do interactive debugging inside, e.g. #4463 🤔 Is there anywhere I can read more about entering an interactive shell for a module? If not, is it because it's not possible yet in principle, or this kind of interactivity is not planned in the world of modules/functions? To put it differently, let's say my dagger module runs |
@gerhard I have add a checklist on the PR description. The checklist has some items that need to be done and some of it could follow-up later. The follow-up tasks may also convert to the issue after this PR ready to review. BTW, the Elixir module is now working, if anyone have time to review, I'm really appreciate. :) |
Note for me:
|
cc @gmile If you want to try. :) |
64c1018
to
9d3eed1
Compare
|
||
for _, name := range []string{"My-Module", "MyModule"} { | ||
modGen := daggerCliBase(t, c). | ||
With(daggerExec("init", "-vv", "--name="+name, "--sdk=elixir")) |
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.
When I remove -vv
I got
=== NAME TestModuleElixirInit/camel-cases_Dagger_module_name
module_elixir_test.go:39:
Error Trace: /home/wingyplus/src/github.com/dagger/dagger/core/integration/module_elixir_test.go:39
Error: []string{".gitattributes", ".gitignore", "pyproject.toml", "requirements.lock", "sdk", "src"} does not contain "my_module"
Test: TestModuleElixirInit/camel-cases_Dagger_module_name
=== NAME TestModuleElixirInit/with_source
module_elixir_test.go:65:
Error Trace: /home/wingyplus/src/github.com/dagger/dagger/core/integration/module_elixir_test.go:65
Error: []string{".gitattributes", ".gitignore", "pyproject.toml", "requirements.lock", "sdk", "src"} does not contain "bare"
Test: TestModuleElixirInit/with_source
=== NAME TestModuleElixirInit/from_scratch
Maybe because of I accidentally copy the python sdk at commit e3f97af. But the issue still occurred even correct the path. After try adding a flag, it works, change the directory name also works! 😢
4336dcb
to
0f3abf1
Compare
For what it's worth, I tested this branch few times now, all is working as expected, no complains from here. The biggest thing I was waiting is |
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.
Sorry for taking such a long time, I'm not at all familiar with Elixir. Took most notes on the runtime module. Since it's an experimental SDK, we can do more incremental improvements so my comments aren't merge blockers (except for one).
There's several tests in core/integration/module_test.go
that put several SDKs under the same test, you just have to add the equivalent elixir code as a test case. For example:
dagger/core/integration/module_test.go
Line 547 in 379e812
func TestModuleGit(t *testing.T) { |
dagger/core/integration/module_test.go
Line 1389 in 379e812
func TestModuleDescription(t *testing.T) { |
dagger/core/integration/module_test.go
Line 1733 in 379e812
func TestModuleOptionalDefaults(t *testing.T) { |
See how many you can add. It's an easy way to check for consistency and add test coverage.
Thanks for reviewing @helderco. That was a huge comments! I'll take a look during this weekend. :) |
d533461
to
a644d96
Compare
@helderco Unfortunately, I can do only one integration tests because most of it required to have struct supported, which's not covered by this PR. And found test |
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
This accident get change by dagger@e4cd936 but it get revert after rebased. This commit bring that changes back. Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
* Run `dagger develop` against dagger version 0.11.2. * Eliminate passing `dag` variable to function. * Add digest to Elixir image. Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
* Moved all constant call always on top of mounting module source that's change often. * Refactor to `dagger` sdk workdir. Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Move codegen out of the container and generate code on separate container. Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
… digit Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
Signed-off-by: Thanabodee Charoenpiriyakij <wingyminus@gmail.com>
@helderco That's my mistake 🙏 . Fixed by clone it in If you have any suggestion, feel free to comment. |
Done. Also added to the README.md but it's need a little polish after merge. |
PRs have their own URL: |
Let's try:
🎉
Technical design
CAUTION: This is the long road to make it done. The design can be change depends on the discussion and feedback.
Let's take a look at module that SDK generate for you.
Any module that want to be a Dagger module needs to call
use Dagger.Mod
and need to declare the name of the module using:name
option.Each function has a module attribute called
function
. The value of that attribute is a keyword (for non-Elixir developer, think like a ordered key/value in another language) that contain the information of the function, currently has only argument and the return type. The module runtime will use this information to generate module declaration usingModule
API and do encode/decode value between Dagger and Elixir world.The reason I declare this is because in Elixir, we have no other ways to obtain type from function argument because it is a dynamic programming language. But luckily that we can use data-structure to describe the function structure. :)
After declare the module, it's time to register a module. Take a look at
application.ex
insidedagger/potato/lib/potato
In Elixir, they has a concept called
Supervisor
which's a process (the lightweight process like a goroutine) that maintain processes defined inchildren
to keep alive. We put it underApplication
and tell the Erlang/OTP to start this application when function start invoking.In children, we have 2 process, the first one is module registry that store Dagger module information to uses at runtime, and the second one is the Dagger module implementation, it's
Potato
in the example above.Tasks that need to done in this PR
Tasks that can follow up after this PR
@field
in TypeScript). I still doubt how to do this at the moment. :(Dagger.ModuleRuntime
.