From: Nikolay Shaplov Date: Sun, 7 Jun 2026 09:24:56 +0000 (+0000) Subject: Script for cloning a new repository plus universal webhooks for updating existing... X-Git-Url: http://gitweb.nataraj.world/?a=commitdiff_plain;h=HEAD;p=git4ai.git Script for cloning a new repository plus universal webhooks for updating existing repositories --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6ab79d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +scripts/config._sh diff --git a/conf/nginx/git4ai b/conf/nginx/git4ai new file mode 100644 index 0000000..95f4610 --- /dev/null +++ b/conf/nginx/git4ai @@ -0,0 +1,232 @@ +map $uri $git4ai_script { + + ~^/git4ai-show/ /srv/cgi/git4ai-show.pl; + ~^/git4ai-cat-file/ /srv/cgi/git4ai-cat-file.pl; + ~^/git4ai-log/ /srv/cgi/git4ai-log.pl; + ~^/git4ai-ls-tree/ /srv/cgi/git4ai-ls-tree.pl; + ~^/git4ai/ /srv/cgi/git4ai.pl; +} + +server { + listen 80; + + location /index.cgi { + root /usr/share/gitweb/; + include fastcgi_params; + gzip off; + + fastcgi_param LANG "en_US.UTF-8"; + fastcgi_param LC_ALL "en_US.UTF-8"; + fastcgi_param PERL_UNICODE "SD"; # S=stdin/stdout UTF-8, D=@ARGV UTF-8 + + fastcgi_param SCRIPT_NAME $uri; + fastcgi_param GITWEB_CONFIG /etc/gitweb.conf; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + + # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + expires -1; + } + + location / { + root /usr/share/gitweb/; + index index.cgi; + + # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + expires -1; + } + + + location /gitweb3/index.cgi { + root /usr/share/gitweb/; + include fastcgi_params; + gzip off; + + fastcgi_param LANG "en_US.UTF-8"; + fastcgi_param LC_ALL "en_US.UTF-8"; + fastcgi_param PERL_UNICODE "D"; # S=stdin/stdout UTF-8 (убрано), D=@ARGV UTF-8 + + fastcgi_param SCRIPT_NAME $uri; + fastcgi_param SCRIPT_FILENAME /usr/share/gitweb/index.cgi; + + fastcgi_param GITWEB_CONFIG /etc/gitweb.conf; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + + # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + expires -1; + } + + location /gitweb3 { + root /usr/share/gitweb/; + # index index.cgi; + + try_files $uri /gitweb3/index.cgi$is_args$args; + + # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + expires -1; + } + + + +location ~ "^/raw/([^/]+)/([0-9a-f]{4,40})$" { + rewrite "^/raw/([^/]+)/([0-9a-f]{4,40})$" /?p=$1&a=blob_plain&h=$2 break; + proxy_pass http://127.0.0.1:80; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + + +location = /raw/ { + default_type text/plain; + return 200 "https://gitweb.nataraj.world/raw/articles.git/\n"; + add_header Cache-Control "no-store" always; +} + + + # Временная копия на то время пока не протух кеш +location /gitweb2/ { + proxy_pass http://127.0.0.1:80/; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + add_header Pragma "no-cache" always; + expires -1; +} + + +# Если без nonce'а добавляем nonce. +location ~ "^/git4ai-log/([^/]+)/([^/]+)/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/$3/$4/$request_id; + add_header Cache-Control "no-store" always; +} + +location ~ "^/git4ai-log/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/-/0; + add_header Cache-Control "no-store" always; +} + +location ~ "^/git4ai-log/([^/]+)/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/-/$3; + add_header Cache-Control "no-store" always; +} + +# repo branch id offset nonce +location ~ "^/git4ai[^/]*/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+|-)/([0-9a-f]{4,40}|-)/([0-9]+|-)(?:/([a-zA-Z0-9]+))?$" { + set $git_repo $1; + set $git_branch $2; + set $git_id $3; + set $git_offset $4; + set $git_nonce $5; + + # Должно идти после того как все $N переменные использованы. Так как map $git4ai_scrit их портит + fastcgi_param SCRIPT_FILENAME $git4ai_script; + fastcgi_param GIT_REPO $git_repo; + fastcgi_param GIT_BRANCH $git_branch; + fastcgi_param GIT_ID $git_id; + fastcgi_param GIT_OFFSET $git_offset; + fastcgi_param GIT_NONCE $git_nonce; + + fastcgi_pass unix:/var/run/fcgiwrap.socket; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +location ~ "^/gitai1/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/gitai/$1/$2/r$request_id; + add_header Cache-Control "no-store" always; +} + +location ~ "^/gitai/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/gitai/$1/$2/r$request_id; + add_header Cache-Control "no-store" always; +} + +location ~ "^/gitai/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)/[a-zA-Z0-9]+$" { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai.pl; + fastcgi_param GIT_REPO $1; + fastcgi_param GIT_BRANCH $2; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +location ~ "^/gitai-log/([^/]+)/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/gitai-log/$1/$2/$3/$request_id; + add_header Cache-Control "no-store" always; +} + +location ~ "^/gitai1-log/([^/]+)/([^/]+)/([^/]+)$" { + return 302 https://gitweb.nataraj.world/gitai-log/$1/$2/$3/$request_id; + add_header Cache-Control "no-store" always; +} + +location ~ "^/gitai-log/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)/([0-9]+)/[a-zA-Z0-9]+$" { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-log.pl; + fastcgi_param GIT_REPO $1; + fastcgi_param GIT_BRANCH $2; + fastcgi_param GIT_OFFSET $3; + fastcgi_param REQUEST_ID $request_id; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +location ~ "^/gitai-ls-tree/([a-zA-Z0-9._-]+)/([0-9a-f]{4,40})/([0-9]+)(?:/[a-zA-Z0-9]+)?$" { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-ls-tree.pl; + fastcgi_param GIT_REPO $1; + fastcgi_param GIT_COMMIT_ID $2; + fastcgi_param GIT_OFFSET $3; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +location ~ "^/gitai-show/([^/]+)/([0-9a-f]{4,40})(?:/[a-zA-Z0-9]+)?$" { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-show.pl; + fastcgi_param GIT_REPO $1; + fastcgi_param GIT_COMMIT $2; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +location ~ "^/gitai-cat-file/([^/]+)/([0-9a-f]{4,40})(?:/[a-zA-Z0-9]+)?$" { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-cat-file.pl; + fastcgi_param GIT_REPO $1; + fastcgi_param GIT_BLOB_ID $2; + include fastcgi_params; + add_header Cache-Control "no-store, no-cache, must-revalidate" always; + expires -1; +} + +#location ~ "^/gitai-raw/([^/]+)/([0-9a-f]{4,40})(?:/r[0-9]+)?$" { +# rewrite "^/gitai-raw/([^/]+)/([0-9a-f]{4,40})(?:/r[0-9]+)?$" /?p=$1&a=blob_plain&h=$2 break; +# proxy_pass http://127.0.0.1:80; +# add_header Cache-Control "no-store, no-cache, must-revalidate" always; +# expires -1; +#} + + + location ~ ^/git(/.*) { + fastcgi_pass unix:/var/run/fcgiwrap.socket; + fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + fastcgi_param GIT_PROJECT_ROOT /var/lib/git; + fastcgi_param GIT_HTTP_EXPORT_ALL ""; + fastcgi_param PATH_INFO $1; + include fastcgi_params; + } + location ~ ^/hooks/update-repo/([a-zA-Z0-9._-]+)$ { + proxy_pass http://127.0.0.1:9000/hooks/update-repo?name=$1; + } +} diff --git a/conf/webhook.conf b/conf/webhook.conf new file mode 100644 index 0000000..8ca870c --- /dev/null +++ b/conf/webhook.conf @@ -0,0 +1,22 @@ +[ + { + "id": "update-repo", + "execute-command": "/srv/scripts/update_repo.sh", + "pass-arguments-to-command": [ + { + "source": "url", + "name": "name" + } + ], + "trigger-rule": { + "match": { + "type": "regex", + "regex": "^[a-zA-Z0-9._-]+$", + "parameter": { + "source": "url", + "name": "name" + } + } + } + } +] diff --git a/nginx-conf/git4ai b/nginx-conf/git4ai deleted file mode 100644 index f18bfdf..0000000 --- a/nginx-conf/git4ai +++ /dev/null @@ -1,233 +0,0 @@ -map $uri $git4ai_script { - - ~^/git4ai-show/ /srv/cgi/git4ai-show.pl; - ~^/git4ai-cat-file/ /srv/cgi/git4ai-cat-file.pl; - ~^/git4ai-log/ /srv/cgi/git4ai-log.pl; - ~^/git4ai-ls-tree/ /srv/cgi/git4ai-ls-tree.pl; - ~^/git4ai/ /srv/cgi/git4ai.pl; -} - -server { - listen 80; - - location /index.cgi { - root /usr/share/gitweb/; - include fastcgi_params; - gzip off; - - fastcgi_param LANG "en_US.UTF-8"; - fastcgi_param LC_ALL "en_US.UTF-8"; - fastcgi_param PERL_UNICODE "SD"; # S=stdin/stdout UTF-8, D=@ARGV UTF-8 - - fastcgi_param SCRIPT_NAME $uri; - fastcgi_param GITWEB_CONFIG /etc/gitweb.conf; - fastcgi_pass unix:/var/run/fcgiwrap.socket; - - # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - add_header Pragma "no-cache" always; - expires -1; - } - - location / { - root /usr/share/gitweb/; - index index.cgi; - - # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - add_header Pragma "no-cache" always; - expires -1; - } - - - location /gitweb3/index.cgi { - root /usr/share/gitweb/; - include fastcgi_params; - gzip off; - - fastcgi_param LANG "en_US.UTF-8"; - fastcgi_param LC_ALL "en_US.UTF-8"; - fastcgi_param PERL_UNICODE "D"; # S=stdin/stdout UTF-8 (убрано), D=@ARGV UTF-8 - - fastcgi_param SCRIPT_NAME $uri; - fastcgi_param SCRIPT_FILENAME /usr/share/gitweb/index.cgi; - - fastcgi_param GITWEB_CONFIG /etc/gitweb.conf; - fastcgi_pass unix:/var/run/fcgiwrap.socket; - - # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - add_header Pragma "no-cache" always; - expires -1; - } - - location /gitweb3 { - root /usr/share/gitweb/; - # index index.cgi; - - try_files $uri /gitweb3/index.cgi$is_args$args; - - # Не кешируем. Иначе колд айай начинает видеть старые версии вместо актуальных - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - add_header Pragma "no-cache" always; - expires -1; - } - - - -location ~ "^/raw/([^/]+)/([0-9a-f]{4,40})$" { - rewrite "^/raw/([^/]+)/([0-9a-f]{4,40})$" /?p=$1&a=blob_plain&h=$2 break; - proxy_pass http://127.0.0.1:80; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - - -location = /raw/ { - default_type text/plain; - return 200 "https://gitweb.nataraj.world/raw/articles.git/\n"; - add_header Cache-Control "no-store" always; -} - - - # Временная копия на то время пока не протух кеш -location /gitweb2/ { - proxy_pass http://127.0.0.1:80/; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - add_header Pragma "no-cache" always; - expires -1; -} - - -# Если без nonce'а добавляем nonce. -location ~ "^/git4ai-log/([^/]+)/([^/]+)/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/$3/$4/$request_id; - add_header Cache-Control "no-store" always; -} - -location ~ "^/git4ai-log/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/-/0; - add_header Cache-Control "no-store" always; -} - -location ~ "^/git4ai-log/([^/]+)/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/git4ai-log/$1/$2/-/$3; - add_header Cache-Control "no-store" always; -} - -# repo branch id offset nonce -location ~ "^/git4ai[^/]*/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+|-)/([0-9a-f]{4,40}|-)/([0-9]+|-)(?:/([a-zA-Z0-9]+))?$" { - set $git_repo $1; - set $git_branch $2; - set $git_id $3; - set $git_offset $4; - set $git_nonce $5; - - # Должно идти после того как все $N переменные использованы. Так как map $git4ai_scrit их портит - fastcgi_param SCRIPT_FILENAME $git4ai_script; - fastcgi_param GIT_REPO $git_repo; - fastcgi_param GIT_BRANCH $git_branch; - fastcgi_param GIT_ID $git_id; - fastcgi_param GIT_OFFSET $git_offset; - fastcgi_param GIT_NONCE $git_nonce; - - fastcgi_pass unix:/var/run/fcgiwrap.socket; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -location ~ "^/gitai1/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/gitai/$1/$2/r$request_id; - add_header Cache-Control "no-store" always; -} - -location ~ "^/gitai/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/gitai/$1/$2/r$request_id; - add_header Cache-Control "no-store" always; -} - -location ~ "^/gitai/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)/[a-zA-Z0-9]+$" { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai.pl; - fastcgi_param GIT_REPO $1; - fastcgi_param GIT_BRANCH $2; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -location ~ "^/gitai-log/([^/]+)/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/gitai-log/$1/$2/$3/$request_id; - add_header Cache-Control "no-store" always; -} - -location ~ "^/gitai1-log/([^/]+)/([^/]+)/([^/]+)$" { - return 302 https://gitweb.nataraj.world/gitai-log/$1/$2/$3/$request_id; - add_header Cache-Control "no-store" always; -} - -location ~ "^/gitai-log/([a-zA-Z0-9._-]+)/([a-zA-Z0-9._-]+)/([0-9]+)/[a-zA-Z0-9]+$" { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-log.pl; - fastcgi_param GIT_REPO $1; - fastcgi_param GIT_BRANCH $2; - fastcgi_param GIT_OFFSET $3; - fastcgi_param REQUEST_ID $request_id; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -location ~ "^/gitai-ls-tree/([a-zA-Z0-9._-]+)/([0-9a-f]{4,40})/([0-9]+)(?:/[a-zA-Z0-9]+)?$" { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-ls-tree.pl; - fastcgi_param GIT_REPO $1; - fastcgi_param GIT_COMMIT_ID $2; - fastcgi_param GIT_OFFSET $3; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -location ~ "^/gitai-show/([^/]+)/([0-9a-f]{4,40})(?:/[a-zA-Z0-9]+)?$" { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-show.pl; - fastcgi_param GIT_REPO $1; - fastcgi_param GIT_COMMIT $2; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -location ~ "^/gitai-cat-file/([^/]+)/([0-9a-f]{4,40})(?:/[a-zA-Z0-9]+)?$" { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /srv/cgi/gitai-cat-file.pl; - fastcgi_param GIT_REPO $1; - fastcgi_param GIT_BLOB_ID $2; - include fastcgi_params; - add_header Cache-Control "no-store, no-cache, must-revalidate" always; - expires -1; -} - -#location ~ "^/gitai-raw/([^/]+)/([0-9a-f]{4,40})(?:/r[0-9]+)?$" { -# rewrite "^/gitai-raw/([^/]+)/([0-9a-f]{4,40})(?:/r[0-9]+)?$" /?p=$1&a=blob_plain&h=$2 break; -# proxy_pass http://127.0.0.1:80; -# add_header Cache-Control "no-store, no-cache, must-revalidate" always; -# expires -1; -#} - - - location ~ ^/git(/.*) { - fastcgi_pass unix:/var/run/fcgiwrap.socket; - fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; - fastcgi_param GIT_PROJECT_ROOT /var/lib/git; - fastcgi_param GIT_HTTP_EXPORT_ALL ""; - fastcgi_param PATH_INFO $1; - include fastcgi_params; - } - - location /hooks { - proxy_pass http://127.0.0.1:9000/hooks; - } -} diff --git a/scripts/clone_repo.sh b/scripts/clone_repo.sh new file mode 100755 index 0000000..469e281 --- /dev/null +++ b/scripts/clone_repo.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +set -e + +source "${BASH_SOURCE%/*}"/config._sh + +GIT_REPO=$1 + +if [ -z "$GIT_REPO" ]; then + echo "Specify repository name as a first argument" >&2 + exit 1 +fi + +if [ -d "$GIT_CLONE_PATH/$GIT_REPO" ]; then + echo "Repository $GIT_CLONE_PATH/$GIT_REPO already exists" >&2 + exit 1 +fi + +git clone --mirror "$GIT_REMOTE/$GIT_REPO" "$GIT_CLONE_PATH/$GIT_REPO" + +chown -R www-data: "$GIT_CLONE_PATH/$GIT_REPO" + diff --git a/scripts/config._sh.example b/scripts/config._sh.example new file mode 100644 index 0000000..33a1827 --- /dev/null +++ b/scripts/config._sh.example @@ -0,0 +1,9 @@ + +DEFAULT_GIT_REMOTE=https://gitlab.com/my-namespace + +DEFAULT_GIT_CLONE_PATH=/srv/repos + + + +export GIT_REMOTE=${GIT_REMOTE:-$DEFAULT_GIT_REMOTE} +export GIT_CLONE_PATH=${GIT_CLONE_PATH:-$DEFAULT_GIT_CLONE_PATH} diff --git a/scripts/update_repo.sh b/scripts/update_repo.sh new file mode 100755 index 0000000..bd03767 --- /dev/null +++ b/scripts/update_repo.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -e + +source "${BASH_SOURCE%/*}"/config._sh + +if [ -z "$GIT_REPO" ]; then + GIT_REPO=$1 +fi + +if [ -z "$GIT_REPO" ]; then + echo "Specify repository name as a first argument or in GIT_REPO env variable" >&2 + exit 1 +fi + +if [ ! -d "$GIT_CLONE_PATH/$GIT_REPO" ]; then + echo "Repository $GIT_CLONE_PATH/$GIT_REPO does not exists" >&2 + exit 1 +fi + +cd "$GIT_CLONE_PATH/$GIT_REPO" + +if [ "$(id -u)" -eq 0 ]; then + sudo -u www-data git remote update --prune +else + git remote update --prune +fi