최초 커밋

This commit is contained in:
Lectom C Han
2025-12-15 17:48:21 +09:00
commit 546a1337fd
5 changed files with 221 additions and 0 deletions

120
.gitea/workflows/mirror.yml Normal file
View File

@@ -0,0 +1,120 @@
name: Git Repository Mirroring
on:
workflow_dispatch:
inputs:
branches:
description: 'Comma-separated list of branches to mirror (e.g., Develop_Net8,Develop_Net8_box). If empty, all branches from branch_list file will be mirrored.'
required: false
default: ''
schedule:
- cron: '0 2 * * *' # Runs every day at 2:00 AM
jobs:
mirror:
runs-on: ubuntu-latest
timeout-minutes: 360 # 6 hours timeout
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -p 22 172.16.42.118 >> ~/.ssh/known_hosts
- name: Mirror Branches
env:
BASE_GITEA_TOKEN: ${{ secrets.BASE_GITEA_TOKEN }}
BASE_GITEA_URL: ${{ vars.BASE_GITEA_URL }} # e.g., https://gitea.example.com
BASE_GITEA_USER: ${{ vars.BASE_GITEA_USER }} # The user who owns the token
INPUT_BRANCHES: ${{ github.event.inputs.branches }}
run: |
set -e # Exit immediately if a command exits with a non-zero status.
# Gitea API Header
AUTH_HEADER="Authorization: token ${BASE_GITEA_TOKEN}"
process_branch() {
local branch_name=$1
if [[ -z "$branch_name" ]]; then
return
fi
echo "================================================="
echo "Processing branch: ${branch_name}"
repo_name=""
if [ "${branch_name}" == "Develop_Net8" ]; then
repo_name="base"
else
repo_name=$(echo "${branch_name}" | sed 's/^Develop_Net8_//')
fi
echo "Target repository name: ${repo_name}"
# Check if repository exists on Gitea
http_status=$(curl -s -o /dev/null -w "%{http_code}" -H "${AUTH_HEADER}" "${BASE_GITEA_URL}/api/v1/repos/center_dev/${repo_name}")
if [ "${http_status}" == "404" ]; then
echo "Repository 'center_dev/${repo_name}' does not exist. Creating it..."
create_repo_response=$(curl -s -w "%{http_code}" -X POST -H "Content-Type: application/json" -H "${AUTH_HEADER}" -d "{\"name\":\"${repo_name}\",\"private\":true}" "${BASE_GITEA_URL}/api/v1/orgs/center_dev/repos")
create_status=$(echo "${create_repo_response}" | tail -c 3)
if [[ "${create_status}" -ne "201" ]]; then
echo "::error::Failed to create repository. API response:"
echo "${create_repo_response}" | head -c -3
exit 1
fi
echo "Repository created successfully."
elif [ "${http_status}" != "200" ]; then
echo "::error::Error checking repository. HTTP status: ${http_status}"
exit 1
else
echo "Repository 'center_dev/${repo_name}' already exists."
fi
# Define remote URL's hostname, stripping protocol
GITEA_HOSTNAME=$(echo "${BASE_GITEA_URL}" | sed -e 's,^\(https*://\)\\,\\",g')
GITEA_REMOTE="https://${BASE_GITEA_USER}:${BASE_GITEA_TOKEN}@${GITEA_HOSTNAME}/center_dev/${repo_name}.git"
SOURCE_REPO="ssh://engdev@172.16.42.118/dev_Net8.git"
# Create a temporary directory for cloning
CLONE_DIR=$(mktemp -d)
echo "Cloning source into ${CLONE_DIR}..."
git clone --bare "${SOURCE_REPO}" "${CLONE_DIR}"
cd "${CLONE_DIR}"
echo "Pushing '${branch_name}' to Gitea repository '${repo_name}'..."
# Push the specific branch to the main branch of the target repository
git push --force "${GITEA_REMOTE}" "refs/heads/${branch_name}:refs/heads/main"
# Cleanup
cd ..
rm -rf "${CLONE_DIR}"
echo "Successfully mirrored ${branch_name} to center_dev/${repo_name}"
echo "================================================="
echo ""
}
if [[ -n "${INPUT_BRANCHES}" ]]; then
echo "Processing manually specified branches: ${INPUT_BRANCHES}"
# Split comma-separated string into an array
IFS=',' read -r -a branches_to_process <<< "${INPUT_BRANCHES}"
for branch in "${branches_to_process[@]}"; do
# Trim whitespace
trimmed_branch=$(echo "$branch" | xargs)
process_branch "${trimmed_branch}"
done
else
echo "Processing all branches from branch_list file."
while IFS= read -r branch_name || [[ -n "$branch_name" ]]; do
process_branch "${branch_name}"
done < branch_list
fi

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
engdev*
engdev/**

77
GEMINI.md Normal file
View File

@@ -0,0 +1,77 @@
# Gitea Action을 이용한 Git 저장소 미러링 계획
## 1. 개요
이 문서는 외부 SSH 프로토콜 기반의 Git 저장소를 Gitea로 미러링하는 Gitea Action 워크플로우의 설계 및 구현 계획을 정의합니다.
소스 저장소의 특정 브랜치들을 각각 별개의 Gitea 저장소로 매핑하고, 주기적으로 (Cron) 소스 저장소의 변경 사항을 가져와 Gitea 저장소에 반영하는 것을 목표로 합니다. 데이터의 크기가 크다는 점을 감안하여 모든 작업은 순차적으로 진행되도록 설계합니다.
## 2. 주요 요구사항
- **소스 저장소**: `engdev@172.16.42.118:dev_Net8.git` (SSH 프로토콜)
- **인증**: SSH 비공개 키 (`engdev` -> Gitea Secret `SSH_PRIVATE_KEY`로 저장)
- **대상**: Gitea `center_dev` 조직 (Organization)
- **작업 트리거**: 스케줄링 (Cron) 및 수동 실행 (workflow_dispatch)
- **처리 방식**: `branch_list` 파일에 명시된 브랜치 목록을 순차적으로 처리
- **저장소 매핑 규칙**:
- `Develop_Net8` 브랜치 -> `base` 저장소
- `Develop_Net8_*` 브랜치 -> `*` 이름의 저장소 (예: `Develop_Net8_box` -> `box`)
- **제약 조건**: 대용량 데이터를 고려하여 병렬 처리를 지양하고 순차적으로 미러링을 수행합니다.
## 3. Gitea Action 설계
워크플로우는 하나의 Job으로 구성되며, 해당 Job 안에서 스크립트를 통해 브랜치 목록을 순회하며 미러링 작업을 순차적으로 수행합니다.
### 워크플로우 트리거
```yaml
on:
workflow_dispatch: # 수동 실행
schedule:
- cron: '0 2 * * *' # 매일 새벽 2시에 실행 (주기는 추후 변경 가능)
```
### 필요한 Gitea Secrets
Gitea 저장소의 `Settings > Secrets`에 다음 정보들을 추가해야 합니다.
1. **`SSH_PRIVATE_KEY`**: 소스 Git 저장소(`engdev@172.16.42.118`)에 접근하기 위한 SSH 비공개 키.
2. **`GITEA_TOKEN`**: Gitea 저장소를 생성하고 코드를 Push 하기 위한 Gitea 개인용 액세스 토큰. 이 토큰은 `center_dev` 조직에 저장소를 생성하고 코드를 쓸 수 있는 권한을 가져야 합니다.
3. **`GITEA_URL`**: Gitea 인스턴스의 전체 URL (예: `https://gitea.yourdomain.com`)
### 워크플로우 주요 단계 (Steps)
1. **워크플로우 실행 환경 준비**:
- `actions/checkout@v4`를 사용하여 현재 워크플로우가 포함된 저장소의 코드를 체크아웃합니다. (`branch_list` 파일을 읽기 위함)
2. **SSH 환경 설정**:
- Gitea Secret으로 등록된 `SSH_PRIVATE_KEY`를 runner의 특정 파일(`~/.ssh/id_rsa`)에 저장합니다.
- 저장된 키 파일의 권한을 `600`으로 설정하여 SSH 클라이언트가 사용할 수 있도록 합니다.
- `ssh-keyscan`을 사용하여 소스 Git 서버(`172.16.42.118`)의 호스트 키를 `~/.ssh/known_hosts`에 추가하여, "man-in-the-middle" 공격 경고 없이 SSH 접속이 가능하도록 설정합니다.
3. **미러링 스크립트 실행**:
- `branch_list` 파일을 한 줄씩 읽어 반복문을 실행합니다.
- **저장소 이름 결정**: 각 브랜치 이름에 따라 위 "저장소 매핑 규칙"에 맞게 Gitea에 생성될 저장소 이름을 결정합니다.
- **Gitea 저장소 확인 및 생성 (API)**:
- Gitea API를 사용하여 `center_dev` 조직 아래에 해당 이름의 저장소가 있는지 확인합니다.
- 저장소가 없다면 Gitea API를 통해 새로 생성합니다. (`GITEA_TOKEN` 사용)
- **소스 코드 클론 및 푸시**:
- `git clone --mirror`를 사용하여 소스 저장소의 모든 레퍼런스를 가져옵니다. (최초 한 번만 실행되거나, 매번 새로 실행할 수 있음. 효율성을 위해 `git fetch`를 사용하는 방향으로 최적화)
- 클론된 로컬 저장소에서 현재 처리 중인 브랜치를 Gitea의 대상 저장소로 `git push --force` 명령어를 사용하여 푸시합니다. 이때 브랜치의 내용을 Gitea 저장소의 `main` (또는 다른 기본) 브랜치로 덮어쓰게 됩니다.
- 예시: `git push --force https://<user>:${GITEA_TOKEN}@${GITEA_URL}/center_dev/${repo_name}.git refs/remotes/origin/${branch_name}:refs/heads/main`
- **임시 파일 정리**: 각 브랜치 처리 후 생성된 임시 클론 저장소를 삭제하여 디스크 공간을 관리합니다.
## 4. 구현 단계
1. Gitea 저장소에 `SSH_PRIVATE_KEY`, `GITEA_TOKEN`, `GITEA_URL` 시크릿을 추가합니다.
2. `.gitea/workflows/` 디렉터리 아래에 `mirror.yml` (또는 원하는 이름) 파일을 생성합니다.
3. 위 설계에 따라 워크플로우 YAML 파일의 내용을 작성합니다.
4. 작성된 워크플로우 파일을 Gitea 저장소에 푸시하여 활성화합니다.
5. Gitea Actions 탭에서 `workflow_dispatch`를 통해 수동으로 실행하여 정상 동작하는지 테스트합니다.
## 5. 고려사항
- **초기 실행 시간**: 첫 미러링 시에는 모든 Git 데이터를 가져와야 하므로 상당한 시간이 소요될 수 있습니다.
- **오류 처리**: 특정 브랜치 미러링에 실패하더라도 다음 브랜치 작업은 계속 진행되도록 스크립트를 구성해야 합니다.
- **Gitea API**: Gitea API를 사용하는 부분은 Gitea 버전에 따라 endpoint나 요청 방식이 다를 수 있으므로, 사용 중인 Gitea 버전에 맞는 API 문서를 참고해야 합니다.
- **보안**: `GITEA_TOKEN`은 저장소 생성 및 쓰기 권한을 가지므로 안전하게 관리되어야 합니다.

11
branch_list Normal file
View File

@@ -0,0 +1,11 @@
Develop_Net8
Develop_Net8_box
Develop_Net8_bridge
Develop_Net8_Graphics
Develop_Net8_Graphics_ModelerUI
Develop_Net8_heh
Develop_Net8_Strana
Develop_Net8_tunnel
Develop_Net8_wall
Develop_Net8_way
Develop_Net8_way_bridge

11
to-do.md Normal file
View File

@@ -0,0 +1,11 @@
# Git Mirroring Workflow 개선 작업 목록
- [ ] `mirror.yml`: 작업 시간 초과(timeout) 설정 추가
- [ ] `mirror.yml`: 수동 실행 시 특정 브랜치를 지정할 수 있는 입력(input) 기능 추가
- [ ] `mirror.yml`: Gitea 관련 시크릿 및 변수 이름을 `BASE_GITEA_` 접두사로 변경 (`secrets.BASE_GITEA_TOKEN`, `vars.BASE_GITEA_URL`, `vars.BASE_GITEA_USER`)
- [ ] `mirror.yml`: 스크립트 로직을 수정하여 수동 입력된 브랜치를 처리하거나, 입력이 없을 경우 `branch_list` 파일을 사용하도록 변경
- [ ] `to-do.md`: 모든 작업 완료 후 KST 시간 기준으로 완료 시간 기록
---
* 모든 작업이 완료되었습니다. (2025-12-15 17:42:52 KST)