Config Refresh With Git Webhook

Configure github hooked with an application for publishing it events, used for configuration reload and other purposes)

There are 2 ways to capture the github events (Options)
  • Using Redis pub/sub as described in this sample
  • Directly adding a controller into the application with Actions using WebHook attributes [Attribute: GitHubWebHook] and other specific WebHook attributes.

    The target url to the controller should be /api/webhooks/incoming/github

Step 1: Configuring GitHub WebHook (Reference)
  • Navigate to repository –> settings –> webhook
  • provide the url to which the event to be posted, make sure the url is in the format http://<hostname>/api/webhooks/incoming/github
  • Select an appropriate ContentType
  • Create a random SecretKey and paste it into the box, note this will be passed on as a header to the POST for security purposes. The same SecretKey should be provided into the configuration of the application which is using the WebHook, in this case publisher application
  • Select appropriate events for which you need the events to be published, as an alternate you can handle the same in the WebHook Action Methods as well
Step 2: Application to be hooked up with Github
  • Add a controller named GitHubController
  • Add an Action method as below

    public IActionResult GitHubHandler(string id, string @event, JObject data)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }
        if(@event == "push")
        {
            //Add anything you want to perform during a PUSH event like IConfigurationRoot.Reload(), if you want to reload the configurations (as mentioned on Option #1)
            //In this example, we publish to a redis channel using IPublisher (option #2)
        }
        return Ok();
    }
    
  • Add method attribute [GitHubWebHook] to the above Action method

  • Add SecretKey to the configuration file as below

    "WebHooks": {
        "GitHub": {
            "SecretKey": {
                "default": "<Secret Key you added in webhook configuration of github repository>"
            }
        }
    }
    
  • Add reference to webhook nuget package as below

    <PackageReference Include="Microsoft.AspNetCore.WebHooks.Receivers.GitHub" Version="1.0.0-preview2-final" />
    
  • In Startup.cs, inject GithubWebHooks as below

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1).AddGitHubWebHooks();
    }
    
Projects in this example
  • Redis Messaging Library (redis_messaging.csproj)
    • Simple library eases out using redis pub/sub events
  • Consumer Application (subscriber.csproj)
    • This application subscribes to a Redis channel from where it listens for messages published in that channel
  • Producer Application (publisher.csproj)
    • This application is hooked with github (WebHook) which upon receiving a POST from github publishes a message to a redis channel
To run this sample
  • Clone the code from github to you local directory using below command

    git clone https://github.com/pivotalservices/redis_pub_sub_with_git_webhook.git
    
  • Follow step #1 to configure your git repo

  • Modify the appsettings.json file to reflect your new SecretKey

  • Open terminal from the root and run dotnet build command to compile the application

  • Make sure redis is running in your local machine, if not install and start Redis, before running this application, for more info on installation of Redis please refer to their site.

  • Since we are running the application in local, github cannot connect to the local application. This can be easily be achieved by using ngrok, which can act as a reverse proxy for your local applicaiton to the internet. For more information on ngrok, please refer to their getting started guide.

  • After installation of ngrok setup the proxy by running the below command

    ./ngrok http 5001
    

    as the sample publisher application runs on port 5001.

  • Navigate to publisher folder and run dotnet run command to start publisher app, which waits for github POST events and then publishes to redis on a channel specified in the configuration

  • Navigate to subscriber folder and run dotnet run command to start publisher app, which listens to redis events on the channel specified in the configuration

  • Make sure the redis channel name is same on the publisher and subscriber appsettings.json

  • Now you are all set to do a test commit and push to the git reposiory. You should see the messages flowing through your publisher and the to subscriber

  • Subscriber App –> MessageProcessor –> OnMessageReceived can be used for configuration reload or any other purposes as below

    private void OnMessageReceived(Message message)
    {
      config.Reload(); //config is IConfigurationRoot
    }
    

Configure gitlab hooked with an application for publishing it events

  • There is no prebuilt webhook api available for gitlab
  • So we can create our own controller with POST action and route as described in the sample publisher app code (GitLabController)
  • In this example your path should be /api/webhooks/incoming/gitlab, made it similar to github for convenience
  • For setting up Webhook integration in gitlab, please refer to their documentation. There are minor differences in navigation compared to github.
  • There is also change in the structure of the posted body, so created a concrete model for a clear picture
  • In Startup.cs, no need of any special injection for webhooks, so below should suffice

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }
    
  • Otherwise, please follow the above steps to configure and execute the sample

  • In addition, you can add middlewares/filters to add more security/signature validation kind of stuff.

Hope you have fun!