利用 GitLab CI 同步组织内的各项目的代码
利用 GitLab CI 定时计划,每天将本组织名下的所有仓库,从指定的源站更新最新代码。
将创建一个组织
在组织名下,创建一个仓库
设置仓库 CI 的环境变量 USER_TOKEN
:设置
-> CI/CD
-> 变量
-> 添加变量
设置定时计划:构建
-> 流水线计划
-> 新建计划
-> 创建流水线计划
本组织下的各项目信息内容设置为以下格式开头
::org/repo
# 或
::github@org/repo
# 或
::gitcode.com@org/repo
该仓库下文件列表为:
.gitlab-ci.yml
.sync.sh
.gitlab-ci.yml
default:
image: alpine:latest
stages:
- sync
variables :
GIT_DEPTH: 0
GIT_STRATEGY: clone
GIT_SUBMODULE_STRATEGY: recursive
TZ: Asia/Shanghai
sync-code:
stage: sync
before_script: |
apk update
apk add curl git jq bash
script: |
bash ./.sync.sh
.sync.sh
#!/usr/bin/env bash
#
# Name: .sync.sh
# Description: 从源站拉取代码,并更新本组织的项目
# Author: Jetsung Chan <jetsungchan@gmail.com>
#
#
set -euo pipefail
main() {
if [ -f "./.env" ]; then
# shellcheck source=/dev/null
source "./.env"
fi
# Git User Name
if [ -z "${USER_NAME:-}" ]; then
USER_NAME="${GITLAB_USER_LOGIN:-}"
fi
# Git User Token
USER_TOKEN="${USER_TOKEN:-}"
# Git Server Host
if [ -z "${SERVER_HOST:-}" ]; then
SERVER_HOST="${CI_SERVER_HOST:-}"
fi
# Organization Name
if [ -z "${ORG_NAME:-}" ]; then
ORG_NAME="${CI_PROJECT_NAMESPACE:-}"
fi
if [ -z "$USER_NAME" ] || [ -z "$USER_TOKEN" ] || [ -z "$SERVER_HOST" ] || [ -z "$ORG_NAME" ]; then
echo "[ERROR] USER_NAME, USER_TOKEN, SERVER_HOST, ORG_NAME must be set"
exit 0
fi
git config --global url."https://$USER_NAME:$USER_TOKEN@$SERVER_HOST".insteadOf "https://$SERVER_HOST"
DATA=$(curl -L -H "PRIVATE-TOKEN:$USER_TOKEN" "https://$SERVER_HOST/api/v4/groups/$ORG_NAME/projects?per_page=100")
# 使用 jq 解析 JSON 并遍历
echo "$DATA" | jq -c '.[]' | while read -r row; do
_path=$(echo "$row" | jq -r '.path')
_description=$(echo "$row" | jq -r '.description')
_http_url_to_repo=$(echo "$row" | jq -r '.http_url_to_repo')
echo
_desc=$(echo "$_description" | head -n 1 | awk -F ' ' '{print $1}')
if echo "$_desc" | grep -v -q '^::'; then
echo "skip: $_path"
continue
fi
# ::org/repo
# ::github@org/repo
# ::gitcode.com@org/repo
IFS='@' read -r SOURCE_HUB SOURCE_REPO <<< "${_desc//::/}"
# default github
if [ -z "$SOURCE_REPO" ]; then
SOURCE_REPO="$SOURCE_HUB"
SOURCE_HUB="github"
fi
case "$SOURCE_HUB" in
github | gitlab | gitee | gitcode )
SOURCE_CODE_URL="https://$SOURCE_HUB.com/$SOURCE_REPO.git"
;;
*)
SOURCE_CODE_URL="https://$SOURCE_HUB/$SOURCE_REPO.git"
;;
esac
# 镜像目标仓库
# TARGET_CODE_URL="https://$SERVER_HOST/$TARGET_REPO.git"
TARGET_CODE_URL="$_http_url_to_repo"
echo "SOURCE_CODE_URL: $SOURCE_CODE_URL"
echo "TARGET_CODE_URL: $TARGET_CODE_URL"
target_dir=$(mktemp -u -t clone-XXXXXX)
git clone "$SOURCE_CODE_URL" "$target_dir"
pushd "$target_dir" || {
printf "\n\033[31mnot found source code: %s\033[0m\n" "$SOURCE_CODE_URL"
exit
}
git remote add target "$TARGET_CODE_URL"
git fetch
git push target --all --force
git push target --tags --force
echo ""
popd
done
}
main "$@" || exit 1