企业项目管理、ORK、研发管理与敏捷开发工具平台

网站首页 > 精选文章 正文

利用 GitLab CI 同步组织内的各项目的代码

wudianyun 2025-03-06 20:12:30 精选文章 17 ℃

利用 GitLab CI 定时计划,每天将本组织名下的所有仓库,从指定的源站更新最新代码。

  1. 将创建一个组织
  2. 在组织名下,创建一个仓库
  3. 设置仓库 CI 的环境变量 USER_TOKEN:设置 -> CI/CD -> 变量 -> 添加变量

  1. 设置定时计划:构建 -> 流水线计划 -> 新建计划 -> 创建流水线计划

  1. 设置定时计划:构建 -> 流水线计划 -> 新建计划 -> 创建流水线计划

该仓库下文件列表为:

.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 
#
#

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

Tags:

最近发表
标签列表