# [scratchpad] Netlify playground approaches issue: https://github.com/vmware-tanzu/carvel/issues/75 </br> miro: https://miro.com/app/board/uXjVOOLQCZk=/ </br> Netlify-lambda: https://kentcdodds.com/blog/super-simple-start-to-netlify-functions --- ## The incomplete work in progress: - Most recent branch uses vendir to dynamically include and build carvel-ytt lambda and copy the 2 binaries to the default `netlify/functions` folder. Doesn't work, netlify does not recognize the binaries and deploy them. https://github.com/vmware-tanzu/carvel/pull/428 - The work for combining the ytt lambda into a single binary is on this branch (unclear if it is working, but it compiles): https://github.com/vmware-tanzu/carvel-ytt/tree/website-no-ytt-binary ## Important details: - **Golang functions don't get deployed locally**. You must use Netlify deploy previews that are created in a PR to recognize and deploy golang functions that are compatable with netlify. The netlify-cli (`netlify dev` command) will not recognize golang functions ever (using netlify-cli 10.1.0). - **The command to build locally is `netlify build --context development`**. This will run the `[build]` step in the `netlify.toml` file. Note: the PR deploy preview actually runs the `[context.deploy-preview]` step. - **A working example of a golang function getting deployed to netlify is at..** [This commit](https://github.com/vmware-tanzu/carvel/commit/d357dd8a080abb3328a2560fd27fc638c159d395) shows that with a simple function. Note: you will have to recreate a PR with this commit to see the deploy preview since the history in netlify doesn't stick around. Visit it at `<deployurl>/.netlify/functions/playground`. - **Golang precompiled binaries don't work**. It doesn't appear that placing golang function binaries directly in the `neltify/functions` folder works. It appears that golang functions must be built by netlify. - This is based on the data that a deploy preview [PR](https://github.com/vmware-tanzu/carvel/commit/d357dd8a080abb3328a2560fd27fc638c159d395) where netlify built the binaries worked, but another [PR](https://github.com/vmware-tanzu/carvel/pull/428/commits/0dfa3bb3c90bb48c664e4086ee355263392f3017) that commited the same binary directly did not recognize any functions. - **Zip file golang functions don't work**. Placing the function binaies in a zip file and in the netlify/functions folder misrecognizes them as a Node function. It does see the function, and deploys it, however when you visit it it yeilds an error. - **Netlify docs can't be trusted**. Much of the documentation for go lambda functions for netlify is slightly incorrect or just wrong. - **Once a solution is working think about this**. There are some copied SCSS files in both the Carvel-ytt repo and the Carvel repo for styling the playground. It would be cool if the solution could get rid of the duplication (not required). ## Recommended next things to try: - **Modify the current function to use a `Handler` and a APIGatewayProxyResponse** This is based purely on a hunch that the netlify docs say that a function [MUST](https://docs.netlify.com/functions/build-with-go/#synchronous-function-format) contain a handler function, but [ours](https://github.com/vmware-tanzu/carvel-ytt/blob/develop/cmd/ytt-lambda-website/main.go#L20) does not exactly. That could be a reason the function is not recognized. May also require work to combine our current 2 binary build into a single binary. - **Don't use Netlify**. We have a working AWS lambda function code that doesn't work on Netlify. Can we get an AWS or Google account and just use that? - **Rewrite the ytt playground function in WASM or javascript**. Netlify should be able to recognize a javascript function easier. It is not clear if even as a javascript function if the current 2 binary approach will work. ## Netlify Support Log (not helpful) **Starts from the bottom up, oldest email at bottom.** | My emails with netlify | what i tried in code | | -------- | ------| |Netlify: For the compiled binaries to be picked up, they need to be cross-compiled to Linux when the compilation happens on a non-Linux machine. So they need the GOOS environment variable in their build command: https://github.com/eduardoboucas/go-netlify-functions/commit/1f4a4c7c6b6930642c48688bc152f99ec5294a5a |N/A| |Netlify: Q: Does the function need to go inside another directory in the netlify/functions? </br> A: No, it does not need to be in a subdirectory. However, it can be. Both methods work. You can also mix both methods with prebuilt binaries in the base directory and also nested one directory deep. Both the base directory functions and subdirectory functions will be deployed. </br> Q: The github repo example that Eduardo Bouças set up for me: https://github.com/eduardoboucas/go-netlify-functions does not actually work when I pull it down locally, and try to build and run locally with netlify dev. What I see is the function built with a custom go build command (go-func-2) does not get deployed, and the link on the site is a 404. This concerns me because the custom go build command is what I want to use, right now I have `go build -o netlify/functions/template ./carvel-ytt/cmd/ytt-lambda-website/... ` in my netlify.toml file. </br> A: I'm also not able to get Go functions to work with CLI manual deploys. I'm sure it works for node functions but I cannot find successful workflow for Go functions. I think this might be an undocumented limitation of the CLI manual deploys and I'll ask our developers to confirm. If CLI manual deploys do not support Go functions, then I'll create a feature request to support them and also a docs page update to make that limitation clear until support is added. </br> Q: Is there a timeout for netlify functions? How long can a process run on a netlify lambda function before the execution stops? </br> A: There is a default timeout of 10 seconds. This can be extended to a recommended maximum of 26 seconds. Our support team can extend this timeout for individual sites or we can make the change account wide so all sites have the new timeout. |N/A| |GC: My desire is now to run a custom go build command on a directory and output the build into my netlify/functions directory.Questions: </br> - Does the function need to go inside another directory in the netlify/functions? </br> - The github repo example that Eduardo Bouças set up: https://github.com/eduardoboucas/go-netlify-functions does not actually work when I pull it down locally, and try to build and run locally with netlify dev. - What I see is the function built with a custom go build command (go-func-2) does not get deployed, and the link on the site is a 404. - This concerns me because the custom go build command is what I want to use, right now I have `go build -o netlify/functions/template ./carvel-ytt/cmd/ytt-lambda-website/... ` in my netlify.toml file. </br>- Is there a timeout for netlify functions? How long can a process run on a netlify lambda function before the execution stops?|N/A| |Netlify: Here's the major piece of advice you need to set a version at Netlify: https://docs.netlify.com/configure-builds/environment-variables/#netlify-configuration-variables (TL;DR set $GO_VERSION to something like 1.17.7) | changed netlify toml to include GO_VERSION config variable | | GC: Okay, we are using go 1.17 so the go build commands may need to be different. Plus, some dependencies that we are using in the project may rely on go 1.17. I am going to check with my team about that. I am going to try and learn more about how we could combine the function and the executable into one build, so everything is deployed as a single function. | changed entry point for the ytt lambda server so that it doesn't exec out to a ytt binary | | Netlify: While I think you may be able to exec another file within a function, I am not 100% sure about that and it would be a bit of poking in the dark if it failed as to where the file in question was versus deploying each as separate functions. But I also don't know how they interact (e.g. the server is only called by the client, so having them separate isn't useful?) I also did want to mention that the go version we are using is a bit old - just checking that your build isn't know to need a newer version than: `go version go1.14.4 linux/amd64` | N/A | | GC: thanks for getting me an example I could look at. I tried to replicate it as closely as I could with my new set up. The new set up is as follows: </br> There is now a git submodule under the directory carvel/site/carvel-ytt that includes all of the source code for the function we want to build. - The directories in this submodule that we need to go build are: `carvel-ytt/cmd/ytt`, and `carvel-ytt/cmd/ytt-lambda-website`. I have attempted to build these folders by shelling out to a script in netlify.toml’s build command – but I think the set-up is wrong and I could use some help. I think I only need one function, this is because: the output of go building `carvel-ytt/cmd/ytt` is just a compiled binary and the output of go building `carvel-ytt/cmd/ytt-lambda-website` is the server using go-aws-lambda package, and the function we want to deploy and hit using its endpoint. HOWEVER `ytt-lambda-website` shells out to the `ytt` binary, so you could call the `ytt` binary a dependency of `ytt-lambda-website`. Ultimately, I wasn’t able to get the deploy to work locally or through the online preview, I will include relevant links below: https://app.netlify.com/sites/carvel/deploys/62201530fdccad0007a4340f | N/A | | Netlify: Well, an answer came very quickly from someone I thought would be asleep or at least not working. He set up a sample open repo you can look at: https://github.com/eduardoboucas/go-netlify-functions ...and here is what that repo builds like, showing how we log both functions types he demonstrates (one we build, one pre-built and copied into place). https://app.netlify.com/sites/upbeat-austin-1b98a4/deploys/62197e2b323eb400618ddad3 to be quite honest I don't really see much different than what you do, but it's also been a long day for me, so maybe you'll see something I don't. | I tried to clone, build, and deploy the example they provided, but only one of the two examples worked and the approach we want to use was not working. | | Netlify: Hmm, I do read that the same as you do - should work - so I will work with our docs team to update it once you and I find a good way to do this :) I've also put in the ask to our serverless team to point me to...any...working example so I'd say hold off on doing that work I requested/you agreed to, til monday, in case they have a quick example that I can share with you and we can save you some work! | N/A | | GC: The reason we thought that we could deploy prebuilt go binaries is because of this docs page: https://docs.netlify.com/functions/build-with-go/#precompiled-binaries </br> We build these binaries separately so that our website does not have a dependency on the large project. However, I will commit our source files and their dependencies in order to build with netlify and we can see what happens | N/A | | Netlify: To answer your question, you might be able to do what you suggest, but I think that would be really suboptimal and possibly impractical. I can't tell how to deploy pre-compiled functions, but I finally got a directory structure that should let us build them for you. This is how I laid things out: 1. my functions directory is called functions, 2. in that directory I have a main/main.go and ytt/ytt.go, 3. that leads to us trying to *build* the functions as you can see here in my test site's deploy logs: https://app.netlify.com/sites/cyclocrass/deploys/6216e40737cff70007dd767f#L155-L168 </br> Can you commit the source instead of the precompiled packages? I couldn't see any indication that we accept pre-built go functions since we document it explicitly for javascript (and it targets only pre-built sites - not git backed sites as you can see here: https://docs.netlify.com/functions/build-with-javascript/#manage-dependencies), but don't see anything like that for go in our docs. </br> If that isn't possible, let me know and I'll work with our functions dev team to understand if there is a different workaround besides not using our build system to deploy the functions (we could definitely coach you through deploying those functions to a second site and proxying to it, and you could do that without building the site, and keep building your main site as you already do). | N/A | | GC: As you suggested, I performed a rename of the executable binary files to have a `.go` suffix. These files were zipped together into `template.zip` and deployed. “Deploy Preview #375”: https://app.netlify.com/sites/carvel/deploys/62166e6b7a5edf00084708c3 Function: https://app.netlify.com/sites/carvel/functions/template?scope=deploypreview:375. In terms of deploying in javascript vs. go, do you think it would be possible to just deploy a javascript function that simply calls our executable with the parameters that it was called with? In this case, my two executables, `main` and `ytt`, would be dependencies of our javascript function, and would need to be available to the javascript function when running. | N/A | Netlify: We seem to have deployed this as a (single) javascript function. I think this is because our docs say that "go functions must be named something.go": https://docs.netlify.com/functions/build-with-go/. Could you try renaming each file to our suggested convention, and see if things work better then? You are one of maybe a dozen customers using Go functions on our service (versus hundreds of thousands using javascript), so there is no expert on our Support team around using them - thus, this took a bit more research and time than it should have | I tried renaming the built binaries to end in .go, this did not work. | GC: To build and zip these binaries the script we run contains: (*shows build script from ytt*) Where we are building two binaries, one that is the server (main), and one that is a build of a CLI (ytt). The server should essentially call the CLI with the parameters passed to the lambda function’s endpoint. | N/A | | Netlify: The error message is a Node.js function error. This seems to imply (at least to me) that the Go function is being deployed as a Node function - not as a Go function. However, I cannot think of any reason why that might happen | N/A | Extra notes on past discussions: - It may be possible to use javascript: web assembly binary - john has a branch somewhere - DL: for the task ytt/main, we can combine with website main, and run one operation for local website command, and run the other for lambda function, we can set an environment variable to distinguoish this. - GC: in the netlify.toml file, we need to be concious of which context is being deployed to and what settings we have set depending on the context. Generally if you are using `netlify build`, you'll want to include `--context development`, This is not needed for the `netlify dev` command (I believe) ## Brainstorm of possible approaches 1. Import carvel-ytt repo into carvel repo via git submodule and build the playground from source - Pros: - can point to a tag or commit of ytt - scss files and playground source code do not need to be duplicated in carvel-ytt and carvel repos - 1/3 of the work already done - easy to call function - Cons: - The binary will be built independently of a release - must make sure go version is correct - adds complexity to website build script (and a dependancy on carvel-ytt repo) - is a vector for vulerabilities in the website playground binary since no trivy scanning or checksum validation happens in the website build script 2. publish lambda function when ytt is released and then use the release to deploy the playground function - pros: - binary and function source files are already built and can be used - functions are versioned, so there is an easy fallback/option to change with version the playground templates with. - easy to call lambda function - Cons: - requires that a playground is a ytt release - scss files will still need to be duplicated in carvel-ytt and carvel repos - GH action on published release -> not all contained within Carvel repo - notes: - we will need to auth with the netlify api - there is gh actions https://github.com/marketplace/actions/netlify-deploy 3. Separate the lambda code from carvel-ytt. Move the aws lambda code to carvel repo, and then have lambda use a ytt binary from a github release. - Pros: - lambda code would only need to live in carvel repo, not carvel-ytt - Cons: - Loads examples and has dependency on ytt source currently Notes: - scss files used in ytt website command and in website playgriound - Can we separate the function code from ytt repo? no - the lambda function calls out to ytt - two artifacts: the adapter and the ytt binary - we can ignore the scss/js inconsistencies for MVP - we need wrapper code to invoke ytt whenever the website calls that wrapper code (wrapper code: the lambda wrapper) - this go function could live in carvel... well maybe not AS-IS because the ytt-lambda-website/main.go file calls a command in pkg - aws adapts well if you hand it the mux - JP: personal experience with submodules is not great - if we can seperate the handler func - receive parmas - call ytt - return results - consider the lambda function another way of packaging up ytt - full blown ytt with a binary - if the lambda could live by itself and just shell out to ytt, we could just pick one. Can we - right now - we may (want) be able to _only_ deploy the netlify function when you want to - "When you deploy JavaScript functions using the netlify deploy command, Netlify CLI parses each function file to note its dependencies. For each function, the CLI then pulls the required dependencies from the associated node_modules folder and zips them with the function file for deployment"