Example: Handling a GitLab Webhook

This example shows how to handle a webhook from GitLab. Unlike GitHub's signature-based approach, GitLab's webhooks typically use a static secret token for verification.

The Script: gitlab.sh

This script is designed to:

  1. Validate the Secret Token: It checks if the X-Gitlab-Token header sent by GitLab matches a pre-configured secret token.
  2. Parse the Payload: It uses jq to parse the JSON payload and react to a specific event. In this case, it creates a notification for a push event.
#!/bin/sh

# Functions
die() { echo "error: $1" 1>&2 ; exit 1; }
confDie() { echo "error: $1 Check the server configuration!" 1>&2 ; exit 2; }
debug() {
  [ "$debug" = "true" ] && echo "debug: $1"
}

# Validate global configuration
[ -z "$GITLAB_TOKEN" ] && confDie "GITLAB_TOKEN not set."

# Validate Gitlab hook token
[ "$x_gitlab_token" != "$GITLAB_TOKEN" ] && die "bad hook token"

# Validate parameters
payload=$1
payload="$(echo "$payload"|tr -d '\n')"
[ -z "$payload" ] && die "missing request payload"
payload_type=$(echo $payload | jq type -r)
[ $? != 0 ] && die "bad body format: expecting JSON"
[ ! $payload_type = "object" ] && die "bad body format: expecting JSON object but having $payload_type"

debug "received payload: $payload"

# Extract values
object_kind=$(echo $payload | jq .object_kind -r)
[ $? != 0 -o "$object_kind" = "null" ] && die "unable to extract 'object_kind' from JSON payload"

# Do something with the payload:
# Here create a simple notification when a push has occurred
if [ "$object_kind" = "push" ]
then
  username=$(echo $payload | jq .user_name -r)
  git_ssh_url=$(echo $payload | jq .project.git_ssh_url -r)
  total_commits_count=$(echo $payload | jq .total_commits_count -r)
  echo "notify: $username push $total_commits_count commit(s) on $git_ssh_url"
fi

Setup Instructions

  1. Place the Script: Save the script above as scripts/gitlab.sh and make it executable (chmod +x scripts/gitlab.sh).

  2. Set the Secret Token: The script needs a secret token for validation. This should be passed to webhookd as an environment variable.

    File: .env

    GITLAB_WEBHOOK_TOKEN=a_very_long_and_random_secret_string

  3. Configure Docker Compose: Use the distrib image to ensure jq is available.

    File: docker-compose.yml

    version: "3.6"
    
    services:
      webhookd:
        image: ncarlier/webhookd:latest-distrib
        container_name: webhookd
        restart: always
        ports:
          - "8080:8080"
        env_file:
          - .env
        environment:
          # Pass the token from the .env file to the container environment
          - GITLAB_TOKEN=${GITLAB_WEBHOOK_TOKEN}
          - WHD_NOTIFICATION_URI=... # Your notification channel URI
        volumes:
          - ./scripts:/scripts

  4. Configure GitLab Webhook:

    • In your GitLab project, go to Settings > Webhooks.
    • URL: Set this to your public webhookd URL, e.g., http://your-server.com:8080/gitlab.
    • Secret token: Enter the same secret string you defined in your .env file.
    • Trigger: Select the events you want to listen for, for example, Push events.
    • Click Add webhook.

Now, when you push to your GitLab repository, a webhook will be sent to webhookd, triggering the script and sending a notification with the push details.