From 84e4971aeea2137c86a50b5289c6d6d6dc536a4e Mon Sep 17 00:00:00 2001 From: Hasit Mistry Date: Mon, 14 Jul 2025 14:33:07 -0700 Subject: [PATCH 1/2] Add GitLab webhook script for automated webhook setup --- docs/self-hosted/gitlab.md | 27 +++++ static/code/gitlab-webhook.sh | 188 ++++++++++++++++++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 static/code/gitlab-webhook.sh diff --git a/docs/self-hosted/gitlab.md b/docs/self-hosted/gitlab.md index 94175bda..a74d92bb 100644 --- a/docs/self-hosted/gitlab.md +++ b/docs/self-hosted/gitlab.md @@ -44,6 +44,33 @@ Consult official CodeRabbitAI documentation for a detailed [guide](https://docs. - Issues events - Merge request events +We have a convenient [script](/static/code/gitlab-webhook.sh) to help you add webhooks to all projects in a GitLab instance. You can run it with the following command: + +```bash +# Make sure the script is executable: +chmod +x gitlab-webhook.sh + +# PAT example (header auto-detected) +export GITLAB_TOKEN="glpat-xxxxx" +./gitlab-add-webhook.sh \ + -h "gitlab.example.com" -u "http:///gitlab_webhooks" \ + -s "mySecret" -p 42 + +# PAT example (explicit header) +./gitlab-add-webhook.sh \ + -h "gitlab.example.com" -u "http:///gitlab_webhooks" \ + -s "mySecret" -g "mygroup/mysubgroup/myproject" \ + -t "glpat-xxxxx" \ + -A "PRIVATE-TOKEN" + +# OAuth token with explicit header +./gitlab-add-webhook.sh \ + -h "gitlab.example.com" -u "http:///gitlab_webhooks" \ + -s "mySecret" -g "company/backend" \ + -t "eyJhbGciOi..." \ + -A "Authorization: Bearer" +``` + ## Prepare a `.env` file Create a `.env` file with the following content: diff --git a/static/code/gitlab-webhook.sh b/static/code/gitlab-webhook.sh new file mode 100644 index 00000000..b217079e --- /dev/null +++ b/static/code/gitlab-webhook.sh @@ -0,0 +1,188 @@ +#!/usr/bin/env bash + +## gitlab-webhook.sh +# Add a webhook to one project, or every project in a subgroup tree. + +## Example usage: +# Make sure the script is executable: +# chmod +x gitlab-webhook.sh + +# PAT example (header auto-detected) +# export GITLAB_TOKEN="glpat-xxxxx" +# ./gitlab-add-webhook.sh \ +# -h "gitlab.example.com" -u "https://ci.example.com/gitlab-hook" \ +# -s "mySecret" -p 42 + +# PAT example (explicit header) +# ./gitlab-add-webhook.sh \ +# -h "gitlab.example.com" -u "https://ci.example.com/gitlab-hook" \ +# -s "mySecret" -g "mygroup/mysubgroup/myproject" \ +# -t "glpat-qj5s..." \ +# -A "PRIVATE-TOKEN" + +# OAuth token with explicit header +# ./gitlab-add-webhook.sh \ +# -h "gitlab.example.com" -u "https://ci.example.com/gitlab-hook" \ +# -s "mySecret" -g "company/backend" \ +# -t "eyJhbGciOi..." \ +# -A "Authorization: Bearer" + + +set -euo pipefail + +usage() { + cat < -u -s \\ + [-t ] [-A ] [-p | -g ] + +Required: + -h GitLab host (e.g. gitlab.example.com) + -u Webhook endpoint URL to receive POSTs + -s Webhook secret token (used for signature verification) + +Authentication (one of): + -t Access token (PAT, project, group or OAuth). If omitted, \$GITLAB_TOKEN is used + -A Auth header to use. Default detects: + PAT → "PRIVATE-TOKEN" + anything else → "Authorization: Bearer" + +Scope (choose one): + -p Project ID or full path (e.g. 42 or group/app) + -g Group ID or full path, recurse through all subgroups & projects +EOF + exit 1 +} + +HOST="" HOOK_URL="" HOOK_SECRET="" +TOKEN="${GITLAB_TOKEN:-}" AUTH_HEADER="" +PROJECT="" GROUP="" + +while getopts "h:u:s:t:A:p:g:" opt; do + case "$opt" in + h) HOST=$OPTARG ;; + u) HOOK_URL=$OPTARG ;; + s) HOOK_SECRET=$OPTARG ;; + t) TOKEN=$OPTARG ;; + A) AUTH_HEADER=$OPTARG ;; + p) PROJECT=$OPTARG ;; + g) GROUP=$OPTARG ;; + *) usage ;; + esac +done + +# Mandatory checks +[[ -z $HOST || -z $HOOK_URL || -z $HOOK_SECRET ]] && usage +[[ -n $PROJECT && -n $GROUP ]] && usage +[[ -z $PROJECT && -z $GROUP ]] && usage + +# Token handling +if [[ -z $TOKEN ]]; then + echo "❌ No access token provided. Use -t or set \$GITLAB_TOKEN" >&2 + exit 1 +fi + +# Choose header if not forced +if [[ -z $AUTH_HEADER ]]; then + if [[ $TOKEN == glpat-* || $TOKEN == "PAT-"* ]]; then + AUTH_HEADER="PRIVATE-TOKEN" + else + AUTH_HEADER="Authorization: Bearer" + fi +fi + +API="https://${HOST}/api/v4" +CURL_BASE=(curl -sSf --header "${AUTH_HEADER}: ${TOKEN}") + +# Track processed projects to avoid duplicates +declare -A PROCESSED_PROJECTS +# Track projects where webhooks were successfully added +WEBHOOK_PROJECTS=() + +############################################################################## +# Helpers +############################################################################## +url_encode() { + local string="$1" + # URL encode the string using printf and sed + printf '%s' "$string" | sed 's/\//%2F/g; s/ /%20/g; s/@/%40/g; s/:/%3A/g; s/#/%23/g; s/?/%3F/g; s/&/%26/g; s/=/%3D/g; s/+/%2B/g' +} + +create_hook() { + local pid=$1 + + # Skip if already processed + if [[ -n "${PROCESSED_PROJECTS[$pid]:-}" ]]; then + return 0 + fi + + # Mark as processed + PROCESSED_PROJECTS[$pid]=1 + + local encoded_pid + # URL encode if pid is not purely numeric + if [[ $pid =~ ^[0-9]+$ ]]; then + encoded_pid=$pid + else + encoded_pid=$(url_encode "$pid") + fi + + "${CURL_BASE[@]}" --request POST \ + --data-urlencode "url=${HOOK_URL}" \ + --data "token=${HOOK_SECRET}" \ + --data "push_events=true" \ + --data "note_events=true" \ + --data "issues_events=true" \ + --data "merge_requests_events=true" \ + --data "enable_ssl_verification=true" \ + "${API}/projects/${encoded_pid}/hooks" \ + >/dev/null + + # Track successful webhook creation + WEBHOOK_PROJECTS+=("$pid") +} + +traverse_group() { + local gid=$1 + local encoded_gid + # URL encode if gid is not purely numeric + if [[ $gid =~ ^[0-9]+$ ]]; then + encoded_gid=$gid + else + encoded_gid=$(url_encode "$gid") + fi + # projects (includes nested sub-groups) + while IFS= read -r pid; do + [[ -n "$pid" ]] && create_hook "$pid" + done < <( + "${CURL_BASE[@]}" \ + "${API}/groups/${encoded_gid}/projects?include_subgroups=true&per_page=100" | + jq -r '.[].id' + ) + # recurse explicit subgroups (older GitLab) + while IFS= read -r sg; do + [[ -n "$sg" ]] && traverse_group "$sg" + done < <( + "${CURL_BASE[@]}" "${API}/groups/${encoded_gid}/subgroups?per_page=100" | + jq -r '.[].id' + ) +} + +############################################################################## +# Main +############################################################################## +if [[ -n $PROJECT ]]; then + create_hook "$PROJECT" +else + traverse_group "$GROUP" +fi + +# Print final summary +if [[ ${#WEBHOOK_PROJECTS[@]} -eq 0 ]]; then + echo "❌ No webhooks were installed." +else + echo "✅ Webhooks installed successfully on ${#WEBHOOK_PROJECTS[@]} project(s):" + for pid in "${WEBHOOK_PROJECTS[@]}"; do + echo " - Project ID: $pid" + done +fi From eebcd5ad19faf7f28f17128c4062f91f964f1d81 Mon Sep 17 00:00:00 2001 From: Hasit Mistry Date: Mon, 14 Jul 2025 15:07:08 -0700 Subject: [PATCH 2/2] Fix link to GitLab webhook script in documentation --- docs/self-hosted/gitlab.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/self-hosted/gitlab.md b/docs/self-hosted/gitlab.md index a74d92bb..2488cfa0 100644 --- a/docs/self-hosted/gitlab.md +++ b/docs/self-hosted/gitlab.md @@ -44,7 +44,7 @@ Consult official CodeRabbitAI documentation for a detailed [guide](https://docs. - Issues events - Merge request events -We have a convenient [script](/static/code/gitlab-webhook.sh) to help you add webhooks to all projects in a GitLab instance. You can run it with the following command: +We have a convenient [script](/code/gitlab-webhook.sh) to help you add webhooks to all projects in a GitLab instance. You can run it with the following command: ```bash # Make sure the script is executable: pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy