docs: 공통컴포넌트 - 로그인인증 > 아이디/비밀번호 찾기 문서 3건 신규 이식 #304
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Merge PR with main branch | |
| # 포크에서 PR이 오거나 업데이트될 때 | |
| on: | |
| pull_request_target: | |
| # 다음의 경우에만 실행 | |
| types: | |
| - opened # PR이 open 될 때 | |
| - synchronize # PR에 commit 추가시 | |
| # PR의 base(refs/heads/…)가 다음 브랜치에 해당할 때만 실행 | |
| branches: | |
| - main | |
| # 특정 디렉토리 내에서, 그리고 Markdown 파일과 이미지 파일에 대한 변경사항만 트리거 | |
| paths: | |
| - '!.github/**' | |
| - '**.md' | |
| - '**.png' | |
| - '**.jpg' | |
| - '**.jpeg' | |
| - '**.gif' | |
| - '**.tiff' | |
| - '**.raw' | |
| - '**.psd' | |
| - '**.pdf' | |
| - '**.eps' | |
| - '**.ai' | |
| - '**.svg' | |
| # 동시성 문제 대응 | |
| concurrency: | |
| # Base의 main 브랜치에 대한 PR인 경우에만 하나의 큐를 공유하는 그룹으로 묶음 | |
| # - PR 이벤트 에서는 github.event.pull_request.base.ref 가 “main” 이 되므로 그룹 이름이 main | |
| # - 다른 이벤트(push, schedule-workflow 등)에서는 github.ref_name 이 “main” 이 되어 그룹 이름이 main | |
| group: ${{ github.event.pull_request.base.ref || github.ref_name }} | |
| # 진행 중인 run은 취소하지 않고 새로 들어온 run만 대기(pending)시킨다. | |
| # A PR의 run이 끝나는 시점에 B PR의 run이 자동으로 시작된다. | |
| cancel-in-progress: false # 기본값 false | |
| # GitHub_Token에 write 권한 부여 | |
| permissions: | |
| contents: write | |
| pull-requests: write # 자동 머지 차단 시 PR에 사유 코멘트를 남기기 위함 | |
| jobs: | |
| merge: | |
| runs-on: ubuntu-latest | |
| steps: | |
| # Step 1. Base Repository의 main 브랜치를 체크아웃 | |
| - name: Checkout the main branch | |
| uses: actions/checkout@v3 | |
| with: | |
| ref: main # 체크아웃 대상 브랜ㅊ; : main | |
| fetch-depth: 0 # 깊이 0 → 전체 커밋 히스토리 가져오기 | |
| persist-credentials: true # 토큰 유지 : 레포지토리를 체크아웃할 때 사용한 인증 토큰을 로컬 Git 설정(.git/config)에 그대로 남겨두므로써, | |
| # 이후 스텝에서도 별도 인증 없이 fetch, push 등의 git 명령 실행 가능 | |
| # Step 2. PR 번호에 해당하는 merge-commit(refs/pull/.../merge)을 가져와서 로컬 브랜치(name = pr_merge)로 받아 놓기 | |
| # - refs/pull/<N>/merge 은 GitHub가 PR head 와 base 를 미리 합친(merge) 가상의 커밋 | |
| # - 참고) GitHub는 PR이 열려 있는 동안 내부적으로 PR의 head 브랜치와 base 브랜치를 미리 합친 상태의 커밋을 refs/pull/<number>/merge 라는 이름으로 계속 관리 | |
| # - refs/pull/<number>/merge는 Step1이 선행돼야 함 | |
| - name: Fetch PR merge commit | |
| run: | | |
| git fetch origin pull/${{ github.event.pull_request.number }}/merge:pr_merge | |
| # Step 3. 변경된 .md 파일의 frontmatter 변경 여부 검사 | |
| # - 기존 .md frontmatter 수정/추가/삭제 시 자동 머지 차단 | |
| # - 신규 추가/삭제된 .md 파일은 검사 대상에서 제외(자동 머지 허용) | |
| # - frontmatter = 파일 첫 줄 '---' ~ 두 번째 '---' 사이의 영역을 확인 | |
| # - base(main)와 PR 머지 결과(pr_merge) 양쪽에 모두 존재하는 .md(=기존 파일 수정)만 비교 | |
| # - frontmatter가 변경된 파일이 하나라도 있으면 PR에 코멘트를 남기고 자동 머지를 중단(exit 1) | |
| # - PR 코드를 실행하지 않고 git show/diff만 사용하므로 pull_request_target 보안 모델 유지 | |
| # - 로직 | |
| # 변경된 .md 목록 구함 (HEAD vs pr_merge) | |
| # └─ 각 파일마다: | |
| # ├─ base에 없다 : 신규 → 건너뜀(허용) | |
| # ├─ head에 없다 : 삭제 → 건너뜀(허용) | |
| # └─ 양쪽 다 있다 : 수정 → frontmatter 추출·비교 → 다르면 blocked 목록에 추가 | |
| # blocked 비어있음? → 정상 종료 → Step4 push(머지 진행) | |
| # blocked 있음? → 에러주석 + PR코멘트 + exit 1 → Step4 안 돔(머지 차단) | |
| - name: Block auto-merge on frontmatter changes | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| # set -o pipefail : 파이프 중 실패한 명령의 종료 코드를 파이프의 종료 코드로 설정(기본값은 파이프 마지막 명령의 종료 코드) | |
| # -u : 정의 안 된 변수를 참조하면 에러로 중단(오타로 인한 빈 값 버그 방지) | |
| set -uo pipefail | |
| # frontmatter만 뽑아내기 | |
| # - git show "$1:$2" : 특정 커밋 시점의 파일 내용을 출력 | |
| # - $1 : ref → 커밋 참조(HEAD, pr_merge 등) | |
| # - $2 : path → 파일 경로 | |
| # - 2>/dev/null : 파일이 없을 때 나오는 에러 메시지를 버림(빈 출력만 남김) | |
| # - awk '...' : awk 스크립트를 사용하여 파일 내용을 필터링 | |
| extract_fm() { | |
| git show "$1:$2" 2>/dev/null | awk ' | |
| { sub(/\r$/, "") } # 모든 줄에서 끝의 \r(윈도우 CRLF) 제거 → CRLF/LF 차이를 frontmatter 변경으로 오탐하지 않게 함 | |
| NR==1 && $0 != "---" { exit } # 첫 줄이 "---"가 아니면(frontmatter 없음) 종료(빈 출력) | |
| NR==1 { next } # 첫 줄("---")은 건너뜀 | |
| $0 == "---" { exit } # 닫는 "---"를 만나면 종료 | |
| { print } # 그 사이의 나머지 줄(frontmatter)을 출력 | |
| ' | |
| } | |
| # 변경된 .md 순회 — while 루프 | |
| # - blocked : 차단 대상 파일 경로를 쌓아둘 누적 변수 | |
| # - IFS= read -r f : 파일명을 원문 그대로 안전하게 처리한 후 변수 f에 담음 | |
| # - HEAD = 현재 main(base), pr_merge = PR이 main에 머지된 결과 | |
| blocked="" | |
| while IFS= read -r f; do | |
| [ -z "$f" ] && continue | |
| # 기존 파일 수정만 차단 → base/head 양쪽에 모두 존재할 때만 비교 | |
| git cat-file -e "HEAD:$f" 2>/dev/null || continue # base에 없음(신규 추가) → 허용 | |
| git cat-file -e "pr_merge:$f" 2>/dev/null || continue # head에 없음(삭제) → 허용 | |
| base_fm="$(extract_fm HEAD "$f")" | |
| head_fm="$(extract_fm pr_merge "$f")" | |
| if [ "$base_fm" != "$head_fm" ]; then | |
| blocked="${blocked}- ${f}"$'\n' | |
| fi | |
| done < <(git diff --name-only HEAD pr_merge -- '*.md') | |
| # 차단 처리 — 에러·코멘트·종료 | |
| if [ -n "$blocked" ]; then | |
| echo "::error::frontmatter 변경이 감지되어 자동 머지를 중단합니다." | |
| printf '%s\n' "$blocked" | |
| body="$(printf '**자동 머지가 중단되었습니다.**\n\n다음 Markdown 파일의 frontmatter(상단 `---` ~ `---` 영역)가 변경되었습니다. frontmatter 변경은 메인테이너의 수동 검토가 필요합니다.\n\n%s\n본문만 수정했거나 frontmatter 변경이 의도된 것이라면 메인테이너에게 검토를 요청해 주세요.' "$blocked")" | |
| gh pr comment "$PR_NUMBER" --body "$body" || echo "::warning::PR 코멘트 등록 실패 (pull-requests 권한 확인 필요)" | |
| exit 1 | |
| fi | |
| echo "frontmatter 변경 없음 — 자동 머지를 진행합니다." | |
| # Step 4. merge-commit을 받아 놓은 pr_merge 브랜치를 main 브랜치로 푸시 (=자동 머지) | |
| - name: Push merge commit to main | |
| run: | | |
| git push origin pr_merge:main |