This commit is contained in:
Rokin 2022-02-14 12:52:52 +01:00
commit 5838118829
3 changed files with 377 additions and 0 deletions

1
CHANGELOG.md Normal file
View File

@ -0,0 +1 @@
* 02-14-2022 - Init

64
README.md Normal file
View File

@ -0,0 +1,64 @@
# g2g
Tested on Alpine-Linux with Gitea server.
Simple Gitea hook / service who mirroring all your Gitea repo to Github (with git push --mirror).
Tested only on Alpine-Linux with Gitea server.
The script requires bash, jq, curl, grep and git.
This should be easily adapted to other distributions without too many modifications, it should certainly be necessary to modify the location where the cronjob is installed (/etc/periodic/15min) for Debian/Arch/... based system.
BE VERY CAREFUL !!, if a Github repo already exists with the same name as a Gitea repo but with different content, the whole Github repository will be overwritten !.
How the hook is triggered :
- Every 15min, a cronjob install the hook in the repos of the configured <user>.
- Every 15min, a cronjob launches the synchronization of the whole <user> repo (git push --mirror).
- When a Gitea depo receives a push, the hook (.hooks/post-receive.d/github_mirror) is triggered and start the synchronization on Github.
What does the script do :
- Clone your Gitea repositories on Github.
- Automatically create a new repository on Github if it does not exist.
- Synchronize the description.
- Synchronize the stat (private/public) of the repository.
What the script doesn't do :
- Does not manage several different accounts.
- Do not delete any Github repo (if you delete a Gitea repo, you will have to do it manually on Github).
- Does not synchronize anything from Github to Gitea.
(The creation of Github repositories and the retrieval of information from Gitea repositories is done through the official API with curl).
#### Install
```
apk add bash jq curl grep
chown root:root /usr/bin/g2g
chmod 755 /usr/bin/g2g
g2g service install
```
#### Uninstall
```
g2g hook uninstall
g2g service uninstall
rm -f /usr/bin/g2g
```
#### Usage
```
Manual push (single repo):
g2g mirror <repo_name>
Manual push (all repo):
/etc/periodic/15min/github_mirror_sync
```

312
g2g.sh Executable file
View File

@ -0,0 +1,312 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# ___ __ _ ___ __ _
# | _ \/__\| |/ / | \| |
# | v / \/ | <| | | ' |
# |_|_\\__/|_|\_\_|_|\__|
#
# @name : g2g
# @version : 1.0.0
# @date : 12/02/2022
# @description : Gitea to Github : Simple Gitea hook / service who mirroring all your Gitea repo to Github (with git push --mirror).
# @author : Rokin
# @contact : git@rokin.in
# @website : https://git.rokin.in
#
# @install : (Tested on Alpine-Linux with Gitea server)
# > apk add bash jq curl
# > dst='/usr/bin/g2g' ; > $dst && chmod 755 $dst && vi $dst
# > g2g service install
#
# @uninstall :
# > g2g hook uninstall && g2g service uninstall && rm -f /usr/bin/g2g
#
##
#============================================
# Config : #
#============================================
# Enable console messages ? : "true/false".
DEBUG="true"
# Gitea local root path repository.
GITEA_SERVER_ROOT='/var/lib/gitea/git'
GITEA_SERVER_USER='gitea'
GITEA_SERVER_GROUP='www-data'
# Gitea user credential
GITEA_USERNAME=''
GITEA_TOKEN=''
GITEA_BASEURL="https://YOURGITEA.XYZ/api/v1/repos"
# Github user credential
GITHUB_USERNAME=''
GITHUB_TOKEN=''
GITHUB_BASEURL="https://api.github.com/repos/${GITHUB_USERNAME}"
#============================================
# Base fuctions : #
#============================================
e='echo -en'; E='echo -e'
msg() { [ "$DEBUG" == "true" ] && $E " > $1"; }
bye() { $E '***************************' && $E '' && exit 0 ; }
strip() { $e "${1//\"/}";}
gitea_get() {
raw=$($e "$gitea_raw" | jq ".data[0].${1}") # data[] for all entry.
$e "$(strip "$raw")"
}
github_get() {
raw=$($e "$github_raw" | jq ".${1}")
$e "$(strip "$raw")"
}
github_create() {
# https://docs.github.com/en/rest/reference/repos#create-a-repository-for-the-authenticated-user
curl -s -S -X POST -H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GITHUB_TOKEN}" "https://api.github.com/user/repos" \
-d "{
\"name\": \"${gitea_name}\",
\"description\": \"${gitea_description} > Mirror of ${gitea_html_url}\",
\"homepage\": \"${gitea_html_url}\",
\"private\": ${gitea_private},
\"has_issues\": true,
\"has_projects\": false,
\"has_wiki\": false,
\"auto_init\": false
}" > /dev/null
}
github_update() {
# https://docs.github.com/en/rest/reference/repos#update-a-repository
curl -s -S -X PATCH -H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GITHUB_TOKEN}" "${GITHUB_BASEURL}/${gitea_name}" \
-d "{
\"name\": \"${gitea_name}\",
\"description\": \"${gitea_description} > Mirror of ${gitea_html_url}\",
\"homepage\": \"${gitea_html_url}\",
\"private\": ${gitea_private}
}" > /dev/null
}
github_push() {
_root="${GITEA_SERVER_ROOT}/${GITEA_USERNAME,,}/${gitea_name}.git"
if [[ ! "${PWD}" == "${_root}" ]]; then
cd "${_root}" || exit 0
fi
git push --mirror "https://${GITHUB_USERNAME}:${GITHUB_TOKEN}@github.com/${GITHUB_USERNAME}/${gitea_name}.git"
}
#============================================
# Hook : #
#============================================
hook() {
# Install hooks
if [[ "${1}" == "install" ]]; then
dir_list=$(ls -d ${GITEA_SERVER_ROOT}/${GITEA_USERNAME,,}/*/)
for repo in $dir_list; do
if [[ ! "$repo" = *.wiki.git* ]]; then # we dont want the wiki dir.
ddir="${repo}hooks/post-receive.d"
if [[ -d "${ddir}" ]]; then
_file="${ddir}/github_mirror"
hook_raw "${_file}"
chown ${GITEA_SERVER_USER}:${GITEA_SERVER_GROUP} "${_file}"
chmod 755 "${_file}"
fi
fi
done
return 0
fi
# Uninstall hooks
if [[ "${1}" == "uninstall" ]]; then
dir_list=$(ls -d ${GITEA_SERVER_ROOT}/${GITEA_USERNAME,,}/*/)
for repo in $dir_list; do
ddir="${repo}hooks/post-receive.d"
if [[ -d "${ddir}" ]]; then
rm -f "${ddir}/github_mirror"
fi
done
fi
return 0
}
hook_raw() {
sc="${1}"
cat > "${sc}" <<-'EOF'
#!/usr/bin/env bash
command -v g2g >/dev/null 2>&1 || { exit 0; }
name=$(basename "$PWD")
name=${name%.git}
#echo "*** Script executed from: ${PWD}" >&2
#echo "*** Script location: $(dirname $0)" >&2
if [[ -n "$name" ]]; then
g2g mirror "${name,,}" 2>&1
fi
EOF
}
#============================================
# Service : #
#============================================
service() {
# Install service
if [[ "${1}" == "install" ]]; then
service_raw_inst "/etc/periodic/15min/github_mirror_deploy"
service_raw_mirror "/etc/periodic/15min/github_mirror_sync"
return 0
fi
# Uninstall service
if [[ "${1}" == "uninstall" ]]; then
rm -f "/etc/periodic/15min/github_mirror_deploy"
rm -f "/etc/periodic/15min/github_mirror_sync"
return 0
fi
}
# Deploy hook on repo.
service_raw_inst() {
sc="$1"
cat > "${sc}" << 'EOF'
#!/usr/bin/env bash
command -v g2g >/dev/null 2>&1 || { exit 0; }
g2g hook install 2>&1
EOF
chown root:root "${sc}"
chmod 755 "${sc}"
}
# Sync repo each 15min.
service_raw_mirror() {
sc="$1"
cat > "${sc}" << 'EOF'
#!/usr/bin/env bash
command -v g2g >/dev/null 2>&1 || { exit 0; }
key='GITEA_USERNAME='
v=$(grep "${key}" "$(command -v g2g)" | head -n1)
v=${v//$key/''} && v=${v//\"/} && usr=${v//\'/}
key='GITEA_SERVER_ROOT='
v=$(grep "${key}" "$(command -v g2g)" | head -n1)
v=${v//$key/''} && v=${v//\"/} && gpath=${v//\'/}
gpath=$(ls -d ${gpath}/${usr,,}/*/)
for repo in $gpath; do
if [[ ! "$repo" = *.wiki.git* ]]; then
repo="${repo%.git\/}"
g2g mirror "${repo##*/}" 2>&1
fi
done
EOF
chown root:root "${sc}"
chmod 755 "${sc}"
}
#============================================
# Mirror : #
#============================================
mirror() {
$E ''
$E '***************************'
$E '* Gitea 2 Github Hook *'
$E '***************************'
name="${1,,}"
# Get Gitea values for the repo <name> (API).
gitea_raw=$(curl --silent "${GITEA_BASEURL}/search?q=${name}&private=true&token=${GITEA_TOKEN}" -H 'accept: application/json')
gitea_name=$(gitea_get "name")
gitea_name="${gitea_name,,}"
msg "name : ${gitea_name}"
# IF gitea_name not empty AND gitea_name == name.
if [[ -n "$gitea_name" && "$gitea_name" == "$name" ]]; then
gitea_description=$(gitea_get "description")
gitea_html_url=$(gitea_get "html_url")
gitea_private=$(gitea_get "private")
gitea_mirror=$(gitea_get "mirror")
gitea_fork=$(gitea_get "fork")
# We do not want copy Gitea mirror(s) or fork(s) to Github.
if [[ "$gitea_mirror" == "true" || "$gitea_fork" == "true" ]]; then
msg "INFO : Abord clonning (source is a mirror or a fork)"
bye
fi
# debug
msg "description : ${gitea_description}"
msg "url : ${gitea_html_url}"
msg "private : ${gitea_private}"
msg "mirror : ${gitea_mirror}"
msg "fork : ${gitea_fork}"
#
# GITHUB
# (https://docs.github.com/en/rest/reference/repos#get-a-repository--code-samples)
#
# Get Github values for the repo <name> (API).
github_raw=$(curl --silent -H "Authorization: token ${GITHUB_TOKEN}" "${GITHUB_BASEURL}/${gitea_name}")
gh_status=$(github_get "message")
if [[ "$gh_status" == "Bad credentials" ]]; then
msg " ERROR ! : Github : Bad credentials."
bye
fi
if [[ "$gh_status" == "Not Found" ]]; then
msg "Github repo not found: Initialized Creation"
github_create
github_push
bye
fi
if [[ "$gh_status" == "null" ]]; then #TODO update desc/private
msg "Github repo found: Pushing Updates"
github_update
github_push
fi
bye
fi
msg "WARNING ! : Gitea repo not found ! (bad name ?)"
bye
}
#============================================
# Init : #
#============================================
_help() {
$E && $E 'g2g Help :'
msg 'g2g mirror <repo name> : Called by Gitea hooks for mirrorig repo.'
msg 'g2g hook <install/uninstall> : Install/Uninstall githook on every repo founds at <conf:PATH>'
msg 'g2g service <install/uninstall> : Install cron service.'
$E
}
case ${1} in
'mirror') mirror "${2}" ;;
'hook') hook "${2}" ;;
'service') service "${2}" ;;
'help') _help ;;
*) _help ;;
esac
exit 0