From 563a2308f1545b773d112ace0bfdbe74277373da Mon Sep 17 00:00:00 2001 From: happybell80 Date: Sat, 14 Mar 2026 13:22:34 +0900 Subject: [PATCH] Add GitHub org bootstrap runbook --- ...51123_github_org_repo_bootstrap_runbook.md | 271 ++++++++++++++++++ .../Infrastructure_Project_Structure.md | 2 + README.md | 7 +- 3 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 02_Architecture/51123_github_org_repo_bootstrap_runbook.md diff --git a/02_Architecture/51123_github_org_repo_bootstrap_runbook.md b/02_Architecture/51123_github_org_repo_bootstrap_runbook.md new file mode 100644 index 0000000..a8e88b2 --- /dev/null +++ b/02_Architecture/51123_github_org_repo_bootstrap_runbook.md @@ -0,0 +1,271 @@ +--- +tags: [infra, github, org, repository, bootstrap, runbook, 51123] +--- + +# 51123 GitHub Org Repo Bootstrap Runbook + +## 상위 원칙 +- [Infra Project Identity](../00_Philosophy/00_IDENTITY/Infra_Project_Identity.md) +- [Core Infrastructure Principles](../00_Philosophy/01_PRINCIPLES/Core_Infrastructure_Principles.md) +- [Operational Guardrails](../00_Philosophy/02_GUARDRAILS/Operational_Guardrails.md) +- 공통 작성 원칙: [0_VALUE Writing Principles](https://github.com/happybell80/0_VALUE/blob/main/02_Governance/writing-principles.md) + +## 관련 문서 +- [Infrastructure Project Structure](./Infrastructure_Project_Structure.md) +- [51123 -> 내부 NAS 동기화 점검 런북](./51123_to_internal_nas_sync_verification_runbook.md) +- [260307 infra_scripts 원격 미존재 푸시실패 및 조직레포 생성 조치](../journey/troubleshooting/260307_infra_scripts_원격_미존재_푸시실패_및_조직레포_생성_조치.md) +- [260307 수정 레포 일괄 푸시 및 infra/scripts 신규 레포 연결](../journey/worklog/260307_수정_레포_일괄_푸시_및_infra_scripts_신규_레포_연결.md) + +## 목적 + +- 51123 서버에서 GitHub org 기준 새 프로젝트 루트와 다중 저장소를 같은 절차로 만든다. +- 이 문서는 사건 기록이 아니라, 운영자가 다시 실행할 수 있는 고정 절차를 남기는 런북이다. + +## 적용 범위 + +- 실행 서버: 51123 +- 기준 경로: `/home/admin/` +- 원격 대상: GitHub organization +- 기본 저장소 묶음: + - `DOCS` + - `DATA` + - `web` + - `admin` + - `api` + +## SSOT 기준값 + +- 작업 루트: `/home/admin` +- 공통 런타임 기준 파일: + - `/home/admin/workspace-config/runtime.env` + - `/home/admin/workspace-config/secrets.env` +- Git 사용자 기준: + - `git config --global user.name` + - `git config --global user.email` +- GitHub 인증 기준: + - `~/.git-credentials`에 저장된 `github.com` 자격증명 + - `gh` CLI는 설치되어 있어야 한다. + +## 사전 확인 + +### 1. 기본 도구와 자격 확인 + +```bash +which gh +git config --global --get user.name +git config --global --get user.email +python3 - <<'PY' +from pathlib import Path +text = Path('/home/admin/.git-credentials').read_text() if Path('/home/admin/.git-credentials').exists() else '' +print('github.com credential found' if 'github.com' in text else 'github.com credential missing') +PY +``` + +확인 기준: +- `gh` 경로가 보여야 한다. +- Git 전역 사용자명이 설정되어 있어야 한다. +- `github.com credential found`가 나와야 한다. + +### 2. org와 기존 레포 상태 확인 + +```bash +python3 - <<'PY' +from pathlib import Path +from urllib.parse import urlparse +import os, subprocess + +org = 'xvaluelab' +token = None +for line in Path('/home/admin/.git-credentials').read_text().splitlines(): + if 'github.com' in line: + token = urlparse(line.strip()).password + break +env = os.environ.copy() +env['GH_TOKEN'] = token +subprocess.run(['gh', 'api', f'/orgs/{org}/repos?per_page=100'], env=env, check=True) +print('org access ok') +PY +``` + +확인 기준: +- `org access ok`가 보여야 한다. +- 실패하면 토큰 스코프나 org 접근 권한을 먼저 해결한다. + +## 생성 절차 + +### 1. 프로젝트 루트 생성 + +```bash +export ORG_NAME=xvaluelab +export PROJECT_ROOT=/home/admin/$ORG_NAME + +mkdir -p "$PROJECT_ROOT" +mkdir -p "$PROJECT_ROOT/DATA" +mkdir -p "$PROJECT_ROOT/apps/web" +mkdir -p "$PROJECT_ROOT/apps/admin" +mkdir -p "$PROJECT_ROOT/apps/api" +``` + +설명: +- 프로젝트 루트는 `/home/admin/`로 고정한다. +- `DOCS`, `DATA`, `apps/*` 경계를 처음부터 분리한다. + +### 2. `DOCS` 처리 + +```bash +git clone https://github.com/$ORG_NAME/DOCS.git "$PROJECT_ROOT/DOCS" +``` + +설명: +- 사용자가 이미 `DOCS` 원격을 만든 경우 먼저 clone한다. +- 빈 저장소면 초기 구조를 채운 뒤 커밋/푸시한다. + +### 3. 로컬 초기 파일 정리 + +최소 기준: +- `DOCS`: 원칙, 구조, 제품, journey 인덱스 +- `DATA`: `README`, `.gitignore` +- `apps/web`: `README`, `.gitignore` +- `apps/admin`: `README`, `.gitignore` +- `apps/api`: `README`, `.gitignore` + +설명: +- 공통 비밀은 프로젝트 `.env.local`에 중복 저장하지 않는다. +- 공통 값은 `workspace-config`를 SSOT로 유지하고, 프로젝트 로컬에는 오버라이드만 둔다. + +### 4. 원격 저장소 생성 + +```bash +python3 - <<'PY' +from pathlib import Path +from urllib.parse import urlparse +import os, subprocess + +org = 'xvaluelab' +repos = ['DATA', 'web', 'admin', 'api'] +token = None +for line in Path('/home/admin/.git-credentials').read_text().splitlines(): + if 'github.com' in line: + token = urlparse(line.strip()).password + break +env = os.environ.copy() +env['GH_TOKEN'] = token + +for name in repos: + subprocess.run([ + 'gh', 'api', '-X', 'POST', f'/orgs/{org}/repos', + '-f', f'name={name}', + '-f', 'private=true' + ], env=env, check=False) +PY +``` + +설명: +- 이미 있는 레포는 `422 already exists`가 나올 수 있으므로 존재 여부 확인 후 넘어간다. +- private 기본값을 사용하고, 공개 여부는 별도 판단 후 바꾼다. + +### 5. 각 저장소 초기화와 최초 푸시 + +```bash +for d in \ + /home/admin/xvaluelab/DATA \ + /home/admin/xvaluelab/apps/web \ + /home/admin/xvaluelab/apps/admin \ + /home/admin/xvaluelab/apps/api +do + git -C "$d" init -b main +done +``` + +원격 연결 기준: +- `DATA` -> `https://github.com//DATA.git` +- `apps/web` -> `https://github.com//web.git` +- `apps/admin` -> `https://github.com//admin.git` +- `apps/api` -> `https://github.com//api.git` + +최초 커밋/푸시 기준: + +```bash +git -C /home/admin/xvaluelab/DATA add . +git -C /home/admin/xvaluelab/DATA commit -m "Initialize repository structure" +git -C /home/admin/xvaluelab/DATA push -u origin main +``` + +설명: +- 각 저장소 루트에서 같은 패턴으로 `add -> commit -> push`를 반복한다. +- `DOCS`도 같은 방식이지만, clone한 저장소에서 수행한다. + +## 검증 절차 + +### 1. 로컬 추적 상태 확인 + +```bash +for d in \ + /home/admin/xvaluelab/DOCS \ + /home/admin/xvaluelab/DATA \ + /home/admin/xvaluelab/apps/web \ + /home/admin/xvaluelab/apps/admin \ + /home/admin/xvaluelab/apps/api +do + echo "[$d]" + git -C "$d" status -sb + git -C "$d" remote -v +done +``` + +확인 기준: +- 각 저장소가 `main...origin/main` 추적 상태여야 한다. +- `origin`이 GitHub org 레포를 가리켜야 한다. + +### 2. 원격 생성 결과 확인 + +```bash +python3 - <<'PY' +from pathlib import Path +from urllib.parse import urlparse +import os, subprocess + +org = 'xvaluelab' +token = None +for line in Path('/home/admin/.git-credentials').read_text().splitlines(): + if 'github.com' in line: + token = urlparse(line.strip()).password + break +env = os.environ.copy() +env['GH_TOKEN'] = token +subprocess.run(['gh', 'api', f'/orgs/{org}/repos?per_page=100'], env=env, check=True) +PY +``` + +확인 기준: +- `DOCS`, `DATA`, `web`, `admin`, `api`가 모두 보여야 한다. + +## 성공 판정 규칙 + +### A. 구조 생성 성공 +- `/home/admin/` 아래에 `DOCS`, `DATA`, `apps/web`, `apps/admin`, `apps/api`가 존재한다. + +### B. GitHub 생성 성공 +- 대상 org에 필요한 레포가 모두 생성된다. + +### C. 최초 푸시 성공 +- 각 저장소 루트가 `main...origin/main` 추적 상태다. +- 원격 기본 브랜치에 초기 커밋이 보인다. + +## 점검 결과를 어디에 남길지 + +- 반복 절차 자체는 이 런북을 SSOT로 유지한다. +- 특정 날짜의 실제 실행 기록은 아래 중 하나에 남긴다. + - 실패/차단/권한 이슈가 있으면 `journey/troubleshooting/` + - 문제 없이 끝났으면 `journey/worklog/` + +## 이 런북이 다루지 않는 것 + +- 프로젝트별 문서 내용 설계 +- 앱 코드 구현 +- GitHub 팀 권한 설계 +- 실제 secret 발급과 노출 정책 + +## 한 줄 결론 + +- 이 런북은 `51123 서버에서 GitHub org 기준 새 프로젝트 루트와 다중 저장소를 같은 절차로 반복 생성하고 최초 푸시하는 표준 절차`다. diff --git a/02_Architecture/Infrastructure_Project_Structure.md b/02_Architecture/Infrastructure_Project_Structure.md index 32c9222..595d7bc 100644 --- a/02_Architecture/Infrastructure_Project_Structure.md +++ b/02_Architecture/Infrastructure_Project_Structure.md @@ -81,3 +81,5 @@ - [51123 -> 내부 NAS 동기화 점검 런북](./51123_to_internal_nas_sync_verification_runbook.md) - 51123에서 내부 NAS에 SSH 접속해 Company X sync 상태와 Go 테스트 결과를 반복 점검하는 절차 +- [51123 GitHub org repo bootstrap 런북](./51123_github_org_repo_bootstrap_runbook.md) + - 51123에서 GitHub org 기준 프로젝트 루트와 다중 저장소를 생성하고 최초 푸시하는 절차 diff --git a/README.md b/README.md index 247513e..8d00160 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ - [01_Terminology/](./01_Terminology/) - [02_Architecture/](./02_Architecture/) - [02_Architecture/51123_to_internal_nas_sync_verification_runbook.md](./02_Architecture/51123_to_internal_nas_sync_verification_runbook.md) +- [02_Architecture/51123_github_org_repo_bootstrap_runbook.md](./02_Architecture/51123_github_org_repo_bootstrap_runbook.md) - [journey/README.md](./journey/README.md) ## 먼저 보면 좋은 문서 @@ -23,6 +24,7 @@ - [00_Philosophy/00_IDENTITY/Infra_Project_Identity.md](./00_Philosophy/00_IDENTITY/Infra_Project_Identity.md) - [02_Architecture/Infrastructure_Project_Structure.md](./02_Architecture/Infrastructure_Project_Structure.md) - [02_Architecture/51123_to_internal_nas_sync_verification_runbook.md](./02_Architecture/51123_to_internal_nas_sync_verification_runbook.md) +- [02_Architecture/51123_github_org_repo_bootstrap_runbook.md](./02_Architecture/51123_github_org_repo_bootstrap_runbook.md) ## 빠른 읽기 순서 @@ -34,5 +36,6 @@ 6. [00_Philosophy/02_GUARDRAILS/Operational_Guardrails.md](./00_Philosophy/02_GUARDRAILS/Operational_Guardrails.md) 7. [02_Architecture/Infrastructure_Project_Structure.md](./02_Architecture/Infrastructure_Project_Structure.md) 8. [02_Architecture/51123_to_internal_nas_sync_verification_runbook.md](./02_Architecture/51123_to_internal_nas_sync_verification_runbook.md) -9. [journey/research/260307_value_기준_인프라철학문서_구조초안.md](./journey/research/260307_value_기준_인프라철학문서_구조초안.md) -10. [journey/README.md](./journey/README.md) +9. [02_Architecture/51123_github_org_repo_bootstrap_runbook.md](./02_Architecture/51123_github_org_repo_bootstrap_runbook.md) +10. [journey/research/260307_value_기준_인프라철학문서_구조초안.md](./journey/research/260307_value_기준_인프라철학문서_구조초안.md) +11. [journey/README.md](./journey/README.md)