Ask Cloud Architech
        Logo Ask Cloud Architech
GitHub YouTube Medium Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

How to Write a Netlify Post-Deploy Function in Golang

Serverless Made Simple
Serverless Made Simple

If you are hosting your website on, the Netlify Functions feature has the potential to add a ton of functionality to your JAMStack site for no additional cost. Netlify functions are simply serverless functions that can be triggered either by submitting data to a certain URL on your site or by triggered events in your site’s build process.

Recently I needed a way to execute some additional functionality after a successful deployment of my Hugo site hosted on Netlify. To accomplish this, I used the post-deploy Netlify function and it worked great!

My Use Case

I’ve been working on a tool that will automatically take any new post I write on my website and post it to as a draft. I’ve written a few articles about this tool and you can read them here and here. The last step I needed to complete was the automation that would post my new article when I published it. Previously I had been running the tool manually, and while this worked fine, I am incredibly lazy and just wanted it to work without even thinking about it.

Creating the Netlify Function

Netlify’s documentation on Netlify Functions is OK, but not great. It took some jumping around and some additional digging to figure out everything I needed to do, but eventually, I figured it all out. Here are the steps I completed as well as some helpful “missing documentation” I encountered along the way.

Create the File - Naming is important!

File location netlify/functions/deploy-succeeded
File location netlify/functions/deploy-succeeded

According to the Netlify Functions documentation, if I want a function to fire after a successful deployment, I need to put the function in the path netlify/functions/deploy-success. Since I’m writing this in Go, I should put my main.go file as well as any other necessary dependencies in this directory. This is a naming convention created by Netlify to make it so you don’t have to register functions with the build system.

After I created my empty main.go file, I also initialized the directory as a Go module. This is not in the docs, but it is the way most Go apps are written, so it seemed like the right thing to do.

go mod init

Writing the execution steps

This is the contents of my main.go file. I will explain each line below.

  • Lines 1-11 - Set the package as main and add any necessary imports. If you are using VScode with the Go tools installed, it will add many of these imports automatically, but you will need most of these (minus the mediumautopost package which is my custom code for my functionality)
  • Lines 13-19 - For my specific functionality, I needed this function to only run for production deployments (and not test environments). To accomplish this, I needed to get the payload.context property from the body of the request which kicks off this function. These two Structs represent the data structure of the request body which will get me that one value. NOTE: see the next section for more on this. This part is not documented anywhere and I had to just figure it out.
  • Line 21 - The handler function is from the Netlify functions go example. It is the function that is called by AWS lambda when this function executes.
  • Lines 23-24 - Unmarshal the request body to the Request body type that I mentioned above. Again, see below for more on this.
  • Lines 26-30 - This is the actual functionality of my mediumautopost tool. If this is a production build, run the medium auto-post tool, otherwise print a message indicating that the step was skipped.
  • Lines 32-36 - Send back a 200 response indicating success.
  • Lines 39-41 - This is the main function as defined in the example on the Netlify site listed above.

Debugging the Payload

Like I mentioned above, it took me forever to figure out how to get all the details of the deployment. I knew the details had to be available, but the docs really don’t mention much about it. It ends up that the request argument passed to the handler function contains a ton of details about the build. Unfortunately, since Go is a strongly typed language, you can’t really just access the JSON data without Unmarshaling it to your own type. In order to unmarshal, you need to know the structure (it’s a catch 22). So… the Gist below contains all the details of the request body so you don’t have to do it yourself. You can thank me later :)

Setting your Environment Variables

One last setup step before firing this thing up! If your function requires access to any environment variables, you need to set them in the Netlify settings page on the Netlify admin website. Just log into the Netlify admin site, click on your site, then go to /settings/deploys#environment.

Checking for Proper Execution

Alright, now you can go ahead and commit your changes to Github. After pushing the changes up to your main branch, head back to the Netlify admin site and check your deployment logs, you should see something like the info below indicating that a new function was created and deployed.

12:11:25 AM: ────────────────────────────────────────────────────────────────
12:11:25 AM:   2. Functions bundling
12:11:25 AM: ────────────────────────────────────────────────────────────────
12:11:25 AM: ​
12:11:25 AM: Packaging Functions from netlify/functions directory:
12:11:25 AM:  - deploy-succeeded/main.go
12:11:25 AM: ​
12:11:32 AM: ​
12:11:32 AM: (Functions bundling completed in 7.5s)
12:11:32 AM: ​
12:11:32 AM: ────────────────────────────────────────────────────────────────
12:11:32 AM:   3. Deploy site
12:11:32 AM: ────────────────────────────────────────────────────────────────
12:11:32 AM: ​
12:11:32 AM: Starting to deploy site from 'asksitestatic/public'
12:11:33 AM: Creating deploy tree
12:11:33 AM: Creating deploy upload records
12:11:33 AM: 0 new files to upload
12:11:33 AM: 1 new functions to upload
12:11:39 AM: Site deploy was successfully initiated
12:11:39 AM: ​

If all went well you should also be able to go to the Functions menu at the top and see that your function has successfully run.

Happy Coding!