Getting Started with Incoming Webhooks

This guide will walk through everything needed in order to build a FlexDeploy Project with a GitHub webhook.

Getting a GitHub message into FlexDeploy

The very first step before we can consider building a project is to simply get a Github message into FlexDeploy so we know what we are dealing with. For this to occur there are 4 things we need

  1. A FlexDeploy Webhook Provider for GitHub
  2. A FlexDeploy Webhook Function - this is what will ultimately build our Project
  3. A public endpoint for GitHub to send the message to.
  4. A GitHub Repository with Webhooks enabled.

Creating the GitHub Provider

Navigate to Administration → Integrations → Incoming Webhooks

Click the Manage Providers button and then the Create Provider button to create a new Provider.

To start with I am simply going to return true here to allow any message through (we will update this later on but right now we just want the message to get through).  Click Save.

Creating a BuildProject Function

Now that we have our Provider, navigate Back to the Webhook Functions screen. You should now see your GitHub Provider set up top. Click Create Function to create a Function for the GitHub Provider.

Similar to the Provider Script, we will circle back here and flesh this out, but for now we just simply log that we ran the function and finish. Notice the Full Resource Path that is displayed. This is the resource path we will ultimately give to GitHub to call our Function.  Make the updates as I have done here and click Save.

Creating a public endpoint (Optional)

GitHub is a publicly available service and if your FlexDeploy installation is local and not accessible from internet, then we need an endpoint that GitHub can use to send us information. We are going to use what is known as a reverse proxy, in this case Ngrok.

After downloading ngrok for your correct OS, simply run the following command:

ngrok
ngrok http fd_server_host:fd_server_port

If you are running this command on the FlexDeploy server you can omit the server and just specify the port. In this case that is exactly what we are doing:

Copy your new public endpoint (http or https works for GitHub). Lastly we need to append the Full Resource Path from our Function.  Our full url looks like the following:

http://0907b88f.ngrok.io/flexdeploy/webhooks/v1/git/push

Security Warning

The approach here is only meant for testing. We have just opened up a public url to our machine on port 8000. Anyone in the world can now hit that port. For real production setup see here.

Adding a Webhook to GitHub

Now that we have our endpoint we just need to setup a webhook in GitHub with this endpoint.

Trying it out

With the GitHub webhook enabled all we need to do is push a change to the repository. After pushing a change, navigate to Webhook Messages to ensure we received the event.

Building the Project

Updating our BuildProject Function

Now that we have communication between GitHub and FlexDeploy we can enhance our scripts to make sure it does what we expect. Edit your BuildProject Function by clicking on the name.

Update the Function script to the following:

//Execute FLEXDEPLOY functions on an incoming webhook message
def functionName = "BuildProject";
LOG.info("Running function: ${functionName}");

//build project according to projectId query param
def projectId = QUERY_PARAMS.projectId;
def branch = PAYLOAD.ref - 'refs/heads/';

if(projectId) {
  //convert the projectId to a Long
  def lprojectId = new Long(projectId);

  //we can optionally pass change logs to improve performance
  def logs = GITHUB.getChangeLogs(PAYLOAD);
  
  def streamId = FLEXDEPLOY.findStreamId(lprojectId,branch);
  
  //build our project
  FLEXDEPLOY.buildProject(streamId,lprojectId,logs);
}
else {
  LOG.warning("No project id passed to function!");
}

We are using a relatively simple script where we will just build the project that is passed in the query parameter. For more complex examples checkout other samples.

Creating our FlexDeploy Project

If you have an existing FlexDeploy Project you would like to use here you can certainly do that. I am going to use my Natours FlexDeploy Project. 

First we need to Enable Webhooks for the Project.

Testing it out

To verify our new setup lets do another push to our repository.

Resubmitting

You also have the option to resubmit messages from the Webhook Messages UI. Since we added the query parameter, resubmitting the original message would not work in this case.

Drill into the execution and check out the change logs to see the changes from your push.

Finishing the GitHub Provider

Updating the Match Script

We left our GitHub Provider script simply returning true. Its time to finish the script so it correctly matches GitHub messages. Navigate back to your GitHub Provider and update the script to the following:

GitHub Provider
// perform checks and functions to ensure an incoming message is valid and matches this provider
LOG.fine("Evaluating GitHub for incoming message");
def match = false;
 
// validating based on GitHub secret
if (HTTP_HEADERS['user-agent'] && HTTP_HEADERS['user-agent'].toLowerCase().contains('github-hookshot'))
{
    //generate hmac string, be sure to replace with your github secret
    def HMAC_RESULT = HMAC.generateHmacSHA1(FLX_PRISTINE_PAYLOAD, 'abc123');
    def RECEIVED_HMAC = HTTP_HEADERS['x-hub-signature'];
     
    match = RECEIVED_HMAC && RECEIVED_HMAC.contains(HMAC_RESULT);
}
 
LOG.fine("GitHub provider is a match: ${match}");
return match;

Setting the GitHub Secret

We are going to make use of GitHub's Secret which makes use of Hmac encryptions. As you can see from the script above I used secret 'abc123', but you can use whatever you wish. 

Properties

Providers also can also have secured properties associated with them. Normally this would be used instead of putting the secret in plain text in our script as seen here.


Final Validation

Lastly lets push one more time and validate everything is still working.

Be sure to turn off your ngrok tunnel when you are done! 

The following macros are not currently supported in the footer:
  • style