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
- A FlexDeploy Webhook Provider for GitHub
- A FlexDeploy Webhook Function - this is what will ultimately build our Project
- A public endpoint for GitHub to send the message to.
- 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
GitHub is a publicly available service and our FlexDeploy installation is local and only known to us, so 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 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
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:
// 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;
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.
Lastly lets push one more time and validate everything is still working.
Be sure to turn off your ngrok tunnel when you are done!