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

feat: support for golang #476

Merged
merged 9 commits into from
May 20, 2021
Merged

Conversation

ansgarm
Copy link
Contributor

@ansgarm ansgarm commented May 14, 2021

This PR extends the work done in #342 by @campionfellin

JSII now supports specifying a packageName for Golang (which resolves the issues Campion mentioned in his PR). I added packageName as a required parameter for this library (although it isn't required when using JSII directly).

I also looked into passing the generated moduleKey from compile() back to srcmak() but ditched that completely as the generated Go package would be named with the generated hash. And I don't think anyone would actually want to use it that way.
So I decided to keep it simple and make the packageName required instead.

Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

I am still a bit confused here. The use case for jsii-srcmak is to generate source code that goes into a user project. This means, for example, that the name of the Go module (i.e. github.com/foo/bar must be derived somehow from the user project.

How do you envision the developer experience here? How will the code that calls in to srcmak will know the base Go module, etc?

@@ -264,6 +264,238 @@ namespace MyPackage
}
`;

exports[`golang output 1`] = `
Object {
"package/LICENSE": "Apache License
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this consistent with other languages? Do we really need the LICENSE file here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As nothing Go specific was added, this should be consistent with other languages.
I did a bit of digging and it seems like this was introduced via aws/jsii#2604 and this line causes the Apache License to be included.
I think we can set it to UNLICENSED to get rid of the generated license file. However, it is already included in other snapshots already.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's odd to me that we include the license file in there. Can we remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Setting it to UNLICENSED worked like a charm ✅

Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

Please update README as well

@ansgarm
Copy link
Contributor Author

ansgarm commented May 17, 2021

Thank you for having a look at this PR, @eladb!

Short Notice: I have very limited experience with Go, so please fact check and correct my assumptions 😄

My initial focus came from the use case we have with the CDK for Terraform: Generating Go modules for Terraform providers which could also be "standalone" Go modules and are not specific to the project they are generated for. So I did a bit more digging on the use case of writing project specific code in TypeScript and using it in a Go project.

From what I researched, there are two possible ways to include the generated Go code:

  1. Put just the generated Go code in a subdirectory of the project
  2. Put the generated Go code in a subdirectory of the project with a go.mod file

Currently this PR does # 2 (by copying all files which were generated by jsii-pakmak including go.mod) which comes with some drawbacks and advantages. However, I think you're right in that you might rather expect # 1 for this library (as it is not jsii-pakmak).

Sidenote: I also built a small example to showcase how these two approaches differ when including the generated code.

Without go.mod (# 1)

  • Pro: Norequire and replace directives needed in base go.mod
  • Pro: Less files overall
  • Note: Must be named after the parent module to work (and correctly include the path to e.g. /generated)

With go.mod (# 2) (currently used in this PR)

  • Pro: Could be published as a child module (e.g. what you might do with an API client)
  • Pro/Con: Can have any name (Could e.g. use "vanity" import paths or (although discouraged) use a global namespace (e.g. myapp/generated) which in Go is only used for standard libraries, but would work if using replace)
  • Pro/Con: Can be swapped out with another version via root go.mod
  • Con: Needs replace directive to refer to generated local version (if not committed in VCS)

Regarding the developer experience

For # 1 we could try to automatically determine the name of the base Go module by e.g. searching for a go.mod file in the target directory (or upwards from there). As far as I know, this would break for Go projects that don't use Go modules.
So it might be simpler to document this for the golang.moduleName option / CLI flag.

Another thing we need to account for, is that for # 1 the moduleName needs to contain the relative directory from the base go.mod to the target directory, that was passed to jsii-srcmak aswell (to be able to build the correct import for the jsii package). This is not required for # 2, as the replace directive points to that directory on a more global level already.

Edit Tue 21/05/18:
I just noticed, that with option # 1 the dependency to jsii runtime has to be defined in the root projects go.mod while for # 2 that depedency is defined in the nested go.mod file and is resolved via Go. So for # 2 users don't have to add the depedency to jsii-runtime-go in the correct version themselves.

Our use case

For the CDK for Terraform we want to use a module name that points to a repository which will (at some point in the future) host the prebuilt providers for Go. This would allow a CDKTF user to switch over to a published provider by just removing the replace directive without needing to adjust all imports aswell. With # 1 we would have to either switch to jsii-pakmak (quite some work) or to generate a go.mod ourselves (probably breaks often). So if we would persue # 1 here, it would be great to be able to retain that file somehow.

Happy to hear your thoughts on this and I hope, I didn't miss anything fundamental as this is my second time touching Go 😁

@eladb
Copy link
Contributor

eladb commented May 17, 2021

@ansgarm thanks for the details. I'll get back to you tomorrow. It's a public holiday here today.

@eladb
Copy link
Contributor

eladb commented May 20, 2021

@ansgarm I ran some tests, and I think we should go with the "without go.mod" model. Here is a sketch of how I think this could look. The root is the "parent project" and the srcmak generated stuff is under mypackage.

Sadly, we still need to know the moduleName because of the need to import jsii (which contains the embedded tarball) from the generated code. I suspect we could actually inject that into the main generated file and then we don't need to know the name of the module.

@RomainMuller @MrArnoldPalmer I am wondering if we can get rid of this jsii subdirectory altogether and just include the embedding into the main file. Not needing to know the module name is a huge benefit for something like srcmak.

At any rate, I am okay with requiring the module name for now until this is changed.

@ansgarm
Copy link
Contributor Author

ansgarm commented May 20, 2021

@eladb Oh yeah, it would be really nice to get rid of that jsii sub directory to make things easier 👍

I can understand the reasoning to go with just the source code. I'll update this PR accordingly.

@eladb
Copy link
Contributor

eladb commented May 20, 2021

@RomainMuller @MrArnoldPalmer created this: aws/jsii#2847 - I think there should be something we can do about this.

@ansgarm ansgarm requested a review from eladb May 20, 2021 10:22
src/options.ts Outdated

export interface GoLangOutputOptions {
/**
* Base root directory.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not accurate in case users want output to go to a nested directory

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added some more information here aswell ✅

@@ -264,6 +264,238 @@ namespace MyPackage
}
`;

exports[`golang output 1`] = `
Object {
"package/LICENSE": "Apache License
Copy link
Contributor

Choose a reason for hiding this comment

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

It's odd to me that we include the license file in there. Can we remove?

@ansgarm ansgarm requested a review from eladb May 20, 2021 12:55
Copy link
Contributor

@eladb eladb left a comment

Choose a reason for hiding this comment

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

Great job 🚢

@mergify mergify bot merged commit f547ab2 into cdklabs:main May 20, 2021
@ansgarm ansgarm deleted the campionfellin/golang branch May 20, 2021 15:27
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