Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
291 changes: 68 additions & 223 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
with:
repository: ${{ github.repository }}
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0 # 모든 히스토리 가져오기
fetch-depth: 0

- name: Configure Git
run: |
Expand All @@ -28,276 +28,121 @@ jobs:
- name: Add Upstream Remote
run: |
git remote add upstream https://github.com/react-hook-form/documentation
git fetch upstream
git fetch upstream --prune --tags --depth=1000000
git fetch origin --prune

- name: Checkout and Set Up Master Branch
- name: Detect Upstream Changes
id: detect
run: |
git checkout -B master origin/master
if git diff --quiet origin/master..upstream/master -- . ':(exclude).github'; then
echo "has_changes=false" >> $GITHUB_ENV
else
echo "has_changes=true" >> $GITHUB_ENV
fi
echo "Detected changes between origin/master and upstream/master"
echo "master_changed=false" >> $GITHUB_ENV
echo "master_ko_changed=false" >> $GITHUB_ENV

# ***********************
# 충돌 자동 해결을 위해 -X theirs 추가
# ***********************
- name: Merge Upstream/master into master
- name: Update master branch
if: env.has_changes == 'true'
run: |
# 업스트림 변경을 우선으로(충돌 발생 시 upstream/master 변경사항 사용)
set -euo pipefail
git checkout -B master origin/master
git merge upstream/master -X theirs --no-edit

# .github 및 .vscode 디렉토리 삭제
for DIR in .github .vscode; do
git rm -r --cached "$DIR" || true
rm -rf "$DIR"
done

# .gitignore 유지
git checkout --ours .gitignore || true

# 변경 사항 스테이징
git add .

# 로그 출력: 현재 스테이지에 있는 파일
echo "Staged files:"
git diff --cached --name-only

# 변경 사항이 있을 경우에만 커밋
git commit -m "Sync with upstream (remove .github & .vscode, keep .gitignore)" || echo "No changes to commit"
shell: bash

- name: Check for Changes
id: changes
run: |
# .github 디렉토리 제외한 변경 사항 확인
git diff upstream/master master -- . ':(exclude).github' > changes.diff
if [ -s changes.diff ]; then
echo "changes=true" >> $GITHUB_ENV
else
echo "changes=false" >> $GITHUB_ENV
fi
echo "Changes detected (excluding .github):"
cat changes.diff
shell: bash

- name: Check Existing PRs for Master Sync
id: existing-prs
run: |
RESPONSE=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls)
EXISTING_PR=$(echo "$RESPONSE" | jq -r '.[] | select(.head.ref | startswith("sync-upstream-")) | .head.ref' | tr '\n' ' ')
if [[ -n "$EXISTING_PR" ]]; then
echo "existing_pr=true" >> $GITHUB_ENV
echo "existing_pr_ref=$EXISTING_PR" >> $GITHUB_ENV
git add -A
if git diff --cached --quiet; then
echo "master_changed=false" >> $GITHUB_ENV
else
echo "existing_pr=false" >> $GITHUB_ENV
git commit -m "Sync with upstream (remove .github & .vscode, keep .gitignore)"
echo "master_changed=true" >> $GITHUB_ENV
fi
echo "Existing PRs for master sync: $EXISTING_PR"
shell: bash

- name: Compare Changes with Existing PRs for Master Sync
id: compare-changes
if: env.existing_pr == 'true' && env.changes == 'true'
- name: Push master branch
if: env.master_changed == 'true'
run: |
ALL_EXISTING_INCLUDED=true
for pr_ref in ${{ env.existing_pr_ref }}
do
echo "Fetching branch: $pr_ref"
git fetch origin "$pr_ref:$pr_ref-branch"
git push origin master

echo "Comparing with upstream/master excluding .github"
if ! git diff --quiet upstream/master "$pr_ref-branch" -- . ':(exclude).github'; then
ALL_EXISTING_INCLUDED=false
break
fi
done

if [ "$ALL_EXISTING_INCLUDED" = true ]; then
echo "diff=false" >> $GITHUB_ENV
else
echo "diff=true" >> $GITHUB_ENV

# 기존 PR 닫기
for pr_ref in ${{ env.existing_pr_ref }}
do
PR_NUMBER=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
| jq -r '.[] | select(.head.ref=="'$pr_ref'") | .number')
echo "Closing PR #$PR_NUMBER"
curl -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER \
-d '{"state":"closed"}'
done
fi
shell: bash
# ===== master-ko 업데이트 =====

- name: Create Pull Request for Master Sync
if: env.diff == 'true' || env.existing_pr == 'false'
- name: Check Existing master-ko PR
id: find-ko-pr
run: |
# 새로운 브랜치 생성
BRANCH_NAME=sync-upstream-$(date +%Y%m%d%H%M%S)
git checkout -b $BRANCH_NAME

# 브랜치 푸시
git push origin $BRANCH_NAME

# PR 생성
curl -X POST \
RESPONSE=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d '{
"title": "Sync with upstream (removing .github directory)",
"body": "This PR syncs the repository with upstream changes and removes the entire .github directory.",
"head": "'"${BRANCH_NAME}"'",
"base": "master"
}'
shell: bash

# ===== master-ko 업데이트 파트 =====

- name: Check Existing PRs for master-ko Update
id: existing-prs-ko
run: |
RESPONSE=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls")
EXISTING_KO_PR=$(echo "$RESPONSE" | jq -r '.[] | select(.head.ref | startswith("update-master-ko-")) | .head.ref' | tr '\n' ' ')
if [[ -n "$EXISTING_KO_PR" ]]; then
echo "existing_pr_ko=true" >> $GITHUB_ENV
echo "existing_pr_ko_ref=$EXISTING_KO_PR" >> $GITHUB_ENV
"https://api.github.com/repos/${{ github.repository }}/pulls?state=open")
REF=$(echo "$RESPONSE" | jq -r '.[] | select(.head.ref | startswith("update-master-ko-")) | .head.ref' | head -n1)
if [[ -n "$REF" && "$REF" != "null" ]]; then
echo "existing_ko_pr=true" >> $GITHUB_ENV
echo "existing_ko_ref=$REF" >> $GITHUB_ENV
else
echo "existing_pr_ko=false" >> $GITHUB_ENV
echo "existing_ko_pr=false" >> $GITHUB_ENV
fi
echo "Existing PRs for master-ko update: $EXISTING_KO_PR"
shell: bash
echo "Existing master-ko PR branch: $REF"

- name: Prepare master-ko Update
run: |
set -euo pipefail
# 최신 master 브랜치 체크아웃
git checkout master
# 원격의 master-ko 브랜치가 있으면 가져오고, 없으면 새로 생성
git fetch origin master-ko || true
git checkout -B master-ko origin/master-ko || git checkout -B master-ko

# 1) master-ko 패키지 백업
cp package.json /tmp/pkg_old.json || true

# 2) upstream/master → master-ko (src, .github 제외) 복사
git checkout upstream/master -- . ":(exclude)src" ":(exclude).github"

# 3) package.json 깊이 병합
node <<'NODE'
const fs = require('fs');
const oldPkg = fs.existsSync('/tmp/pkg_old.json') ? JSON.parse(fs.readFileSync('/tmp/pkg_old.json','utf8')) : {};
const newPkg = JSON.parse(fs.readFileSync('package.json','utf8'));

// 의존성 스마트 병합: upstream과 master-ko 둘 다에 있으면 upstream 버전, master-ko에만 있으면 유지
['dependencies','devDependencies','peerDependencies'].forEach(k=>{
const upstreamDeps = newPkg[k] || {};
const localDeps = oldPkg[k] || {};
const merged = {...upstreamDeps}; // upstream을 기본으로 시작

// master-ko에만 있는 패키지들 추가
for(const pkg in localDeps) {
if(!(pkg in upstreamDeps)) {
merged[pkg] = localDeps[pkg];
}
}
newPkg[k] = merged;
const upstreamDeps=newPkg[k]||{}, localDeps=oldPkg[k]||{}, merged={...upstreamDeps};
for(const pkg in localDeps){ if(!(pkg in upstreamDeps)) merged[pkg]=localDeps[pkg]; }
newPkg[k]=merged;
});

// scripts는 기존 방식으로 병합 (중복되지 않는 것만 추가)
const merge = (a,b)=>{for(const k in b){if(b[k]&&typeof b[k]==='object'&&!Array.isArray(b[k]))a[k]=merge(a[k]||{},b[k]);else if(!(k in a))a[k]=b[k];}return a;}
if(oldPkg.scripts) {
newPkg.scripts = merge(newPkg.scripts||{}, oldPkg.scripts);
}

const merge=(a,b)=>{for(const k in b){if(b[k]&&typeof b[k]==='object'&&!Array.isArray(b[k]))a[k]=merge(a[k]||{},b[k]);else if(!(k in a))a[k]=b[k];}return a;}
if(oldPkg.scripts){newPkg.scripts=merge(newPkg.scripts||{},oldPkg.scripts);}
fs.writeFileSync('package.json',JSON.stringify(newPkg,null,2)+'\n');
NODE

# 4) 로컬 전용 파일 복원 (존재할 때만)
for f in .yarnrc.yml README.md; do
git ls-files --error-unmatch "$f" >/dev/null 2>&1 && git checkout master-ko -- "$f" || true
done

# 5) pnpm lockfile 클린 재생성
if command -v pnpm &> /dev/null; then
# 기존 lockfile 제거하고 클린 설치
rm -f pnpm-lock.yaml
pnpm install --frozen-lockfile=false
git add pnpm-lock.yaml
rm -f pnpm-lock.yaml
pnpm install --frozen-lockfile=false || true
git add -A
if git diff --cached --quiet; then
echo "master_ko_changed=false" >> $GITHUB_ENV
else
git commit -m "Update master-ko (deep-merge package.json, keep local files)"
echo "master_ko_changed=true" >> $GITHUB_ENV
fi

git add .
git commit -m "Update master-ko (deep-merge package.json, keep local files including README.md)" || echo "No changes to commit"
shell: bash

- name: Compare Changes with Existing master-ko PRs
id: compare-changes-ko
if: env.existing_pr_ko == 'true'
- name: Push and Create/Update PR for master-ko
if: env.master_ko_changed == 'true'
run: |
ALL_INCLUDED=true
EXISTING_BRANCH=""
for pr_ref in ${{ env.existing_pr_ko_ref }}
do
echo "Fetching branch: $pr_ref"
git fetch origin "$pr_ref:$pr_ref-branch"
echo "Comparing updated master-ko with existing PR branch (excluding src)"
if ! git diff --quiet master-ko "$pr_ref-branch" -- . ':(exclude)src'; then
ALL_INCLUDED=false
EXISTING_BRANCH=$pr_ref
break
fi
done

if [ "$ALL_INCLUDED" = true ]; then
echo "ko_diff=false" >> $GITHUB_ENV
if [[ "${{ env.existing_ko_pr }}" == "true" ]]; then
BRANCH="${{ env.existing_ko_ref }}"
echo "Updating existing master-ko PR branch: $BRANCH"
git push origin master-ko:"$BRANCH" --force
else
echo "ko_diff=true" >> $GITHUB_ENV
if [ -n "$EXISTING_BRANCH" ]; then
PR_NUMBER=$(curl -s \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls" \
| jq -r '.[] | select(.head.ref=="'$EXISTING_BRANCH'") | .number')
echo "Closing master-ko PR #$PR_NUMBER"
curl -X PATCH \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls/$PR_NUMBER \
-d '{"state":"closed"}'
fi
BRANCH="update-master-ko-$(date +%Y%m%d%H%M%S)"
git checkout -b "$BRANCH"
git push origin "$BRANCH"
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d '{
"title": "Update master-ko (excluding src)",
"body": "This PR updates the master-ko branch with upstream changes except for the src directory.",
"head": "'"$BRANCH"'",
"base": "master-ko"
}'
fi
shell: bash

- name: Update Existing master-ko PR Branch
if: env.existing_pr_ko == 'true' && env.ko_diff == 'false'
run: |
# 기존 PR 브랜치(첫번째 값)를 사용하여 업데이트
EXISTING_BRANCH=$(echo "${{ env.existing_pr_ko_ref }}" | awk '{print $1}')
echo "Pushing updated changes to existing master-ko branch: $EXISTING_BRANCH"
git push origin master-ko:"$EXISTING_BRANCH" --force
shell: bash

- name: Create New PR for master-ko Update
if: env.ko_diff == 'true' || env.existing_pr_ko == 'false'
run: |
BRANCH_NAME=update-master-ko-$(date +%Y%m%d%H%M%S)
git checkout -b $BRANCH_NAME
git push origin $BRANCH_NAME
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d '{
"title": "Update master-ko (excluding src)",
"body": "This PR updates the master-ko branch with upstream changes except for the src directory.",
"head": "'"${BRANCH_NAME}"'",
"base": "master-ko"
}'
shell: bash