From 7d84699844ee14c814aa1fa22aa8026c43ef9450 Mon Sep 17 00:00:00 2001 From: minchodang Date: Sun, 2 Nov 2025 09:13:17 +0900 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20sync-upstream=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=A0=90=20logic=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/sync-upstream.yml | 314 ++++++++-------------------- 1 file changed, 93 insertions(+), 221 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 0a7d5fee1..977f73a0d 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -18,7 +18,7 @@ jobs: with: repository: ${{ github.repository }} token: ${{ secrets.GITHUB_TOKEN }} - fetch-depth: 0 # 모든 히스토리 가져오기 + fetch-depth: 0 - name: Configure Git run: | @@ -28,276 +28,148 @@ 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" - # *********************** - # 충돌 자동 해결을 위해 -X theirs 추가 - # *********************** - - name: Merge Upstream/master into master + - name: Find Existing master-sync PR + id: find-master-pr run: | - # 업스트림 변경을 우선으로(충돌 발생 시 upstream/master 변경사항 사용) + RESPONSE=$(curl -s \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/${{ github.repository }}/pulls?state=open) + REF=$(echo "$RESPONSE" | jq -r '.[] | select(.head.ref | startswith("sync-upstream-")) | .head.ref' | head -n1) + if [[ -n "$REF" && "$REF" != "null" ]]; then + echo "existing_pr=true" >> $GITHUB_ENV + echo "existing_ref=$REF" >> $GITHUB_ENV + else + echo "existing_pr=false" >> $GITHUB_ENV + fi + echo "Existing master-sync PR branch: $REF" + + - name: Prepare master-sync Branch + if: env.has_changes == 'true' + run: | + set -euo pipefail + BASE_BRANCH=master + if [[ "${{ env.existing_pr }}" == "true" ]]; then + BRANCH="${{ env.existing_ref }}" + git checkout -B "$BRANCH" "origin/$BRANCH" || git checkout -b "$BRANCH" origin/$BASE_BRANCH + else + BRANCH="sync-upstream-$(date +%Y%m%d%H%M%S)" + git checkout -B "$BRANCH" origin/$BASE_BRANCH + fi + 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 -A + git commit -m "Sync with upstream (remove .github & .vscode, keep .gitignore)" || echo "No changes" - # 변경 사항 스테이징 - git add . + git push -u origin "$BRANCH" --force-with-lease + echo "branch_name=$BRANCH" >> $GITHUB_ENV - # 로그 출력: 현재 스테이지에 있는 파일 - 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 + - name: Create or Update PR to master + if: env.has_changes == 'true' run: | - # .github 디렉토리 제외한 변경 사항 확인 - git diff upstream/master master -- . ':(exclude).github' > changes.diff - if [ -s changes.diff ]; then - echo "changes=true" >> $GITHUB_ENV + if [[ "${{ env.existing_pr }}" == "true" ]]; then + echo "✅ Existing PR found — branch updated." 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 \ + curl -X POST \ -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 - else - echo "existing_pr=false" >> $GITHUB_ENV + 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": "'"${{ env.branch_name }}"'", + "base": "master" + }' 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' - 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" - 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 + # ===== master-ko 업데이트 ===== - # 기존 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 - - - 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 - 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 + rm -f pnpm-lock.yaml + pnpm install --frozen-lockfile=false || true + git add -A + git commit -m "Update master-ko (deep-merge package.json, keep local files)" || echo "No changes" - - 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 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 \ No newline at end of file From 61e7fb9c1e304533dad7d2b4db1916c663ba7978 Mon Sep 17 00:00:00 2001 From: minchodang Date: Thu, 6 Nov 2025 19:07:02 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20origin=20master=EC=97=90=20upstream?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=EC=A0=90=20=EC=A7=81=EC=A0=91=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/sync-upstream.yml | 67 +++++++++-------------------- 1 file changed, 20 insertions(+), 47 deletions(-) diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml index 977f73a0d..4fdc0390e 100644 --- a/.github/workflows/sync-upstream.yml +++ b/.github/workflows/sync-upstream.yml @@ -40,36 +40,14 @@ jobs: 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 - - name: Find Existing master-sync PR - id: find-master-pr - 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?state=open) - REF=$(echo "$RESPONSE" | jq -r '.[] | select(.head.ref | startswith("sync-upstream-")) | .head.ref' | head -n1) - if [[ -n "$REF" && "$REF" != "null" ]]; then - echo "existing_pr=true" >> $GITHUB_ENV - echo "existing_ref=$REF" >> $GITHUB_ENV - else - echo "existing_pr=false" >> $GITHUB_ENV - fi - echo "Existing master-sync PR branch: $REF" - - - name: Prepare master-sync Branch + - name: Update master branch if: env.has_changes == 'true' run: | set -euo pipefail - BASE_BRANCH=master - if [[ "${{ env.existing_pr }}" == "true" ]]; then - BRANCH="${{ env.existing_ref }}" - git checkout -B "$BRANCH" "origin/$BRANCH" || git checkout -b "$BRANCH" origin/$BASE_BRANCH - else - BRANCH="sync-upstream-$(date +%Y%m%d%H%M%S)" - git checkout -B "$BRANCH" origin/$BASE_BRANCH - fi - + git checkout -B master origin/master git merge upstream/master -X theirs --no-edit for DIR in .github .vscode; do @@ -79,29 +57,18 @@ jobs: git checkout --ours .gitignore || true git add -A - git commit -m "Sync with upstream (remove .github & .vscode, keep .gitignore)" || echo "No changes" - - git push -u origin "$BRANCH" --force-with-lease - echo "branch_name=$BRANCH" >> $GITHUB_ENV - - - name: Create or Update PR to master - if: env.has_changes == 'true' - run: | - if [[ "${{ env.existing_pr }}" == "true" ]]; then - echo "✅ Existing PR found — branch updated." + if git diff --cached --quiet; then + echo "master_changed=false" >> $GITHUB_ENV else - 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": "Sync with upstream (removing .github directory)", - "body": "This PR syncs the repository with upstream changes and removes the entire .github directory.", - "head": "'"${{ env.branch_name }}"'", - "base": "master" - }' + git commit -m "Sync with upstream (remove .github & .vscode, keep .gitignore)" + echo "master_changed=true" >> $GITHUB_ENV fi + - name: Push master branch + if: env.master_changed == 'true' + run: | + git push origin master + # ===== master-ko 업데이트 ===== - name: Check Existing master-ko PR @@ -150,9 +117,15 @@ jobs: rm -f pnpm-lock.yaml pnpm install --frozen-lockfile=false || true git add -A - git commit -m "Update master-ko (deep-merge package.json, keep local files)" || echo "No changes" + 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 - name: Push and Create/Update PR for master-ko + if: env.master_ko_changed == 'true' run: | if [[ "${{ env.existing_ko_pr }}" == "true" ]]; then BRANCH="${{ env.existing_ko_ref }}"