#!/bin/bash # ============================================================== # GUARDiA Gitea 설치 + 자동 초기화 공통 함수 # ============================================================== # 기능: # - Gitea 바이너리 설치 및 systemd 등록 # - 관리자 계정 자동 생성 # - GUARDiA 조직 + 레파지토리 생성 # - 개발자 계정 + 개인 브랜치 자동 생성 # - main 브랜치 보호 (PR 필수) # # 브랜치 전략: # main - 보호 브랜치, PR + 리뷰 1명 필수 # develop - 통합 브랜치 # feature/이름/기능명 - 개인 개발 브랜치 # ============================================================== GITEA_VER="${GITEA_VER:-1.21.11}" GITEA_HOME="/opt/gitea" GITEA_DATA="/var/lib/gitea" GITEA_PORT="${GITEA_PORT:-3000}" GITEA_ADMIN="${GITEA_ADMIN:-gitadmin}" GITEA_ADMIN_PW="${GITEA_ADMIN_PW:-Gitea@guardia!}" GITEA_ADMIN_EMAIL="${GITEA_ADMIN_EMAIL:-admin@guardia.local}" GITEA_ORG="${GITEA_ORG:-guardia}" GITEA_REPO="${GITEA_REPO:-GUARDiA}" GITEA_BASE="http://localhost:${GITEA_PORT}" GITEA_MIRROR="${GITEA_MIRROR:-https://dl.gitea.com/gitea/${GITEA_VER}}" install_gitea() { echo "" echo "=== Gitea 설치 (포트 ${GITEA_PORT}) ===" # 1. 시스템 계정 생성 id git &>/dev/null || useradd -r -s /bin/bash -d "$GITEA_DATA" git # 2. 디렉토리 생성 mkdir -p "$GITEA_HOME" "$GITEA_DATA"/{custom,data,log,repositories} chown -R git:git "$GITEA_DATA" # 3. 바이너리 설치 ARCH="$(uname -m)" case "$ARCH" in x86_64) GITEA_ARCH="amd64" ;; aarch64) GITEA_ARCH="arm64" ;; *) GITEA_ARCH="amd64" ;; esac GITEA_BIN="gitea-${GITEA_VER}-linux-${GITEA_ARCH}" if [[ ! -f "/usr/local/bin/gitea" ]]; then info "Gitea $GITEA_VER 다운로드..." wget -q "${GITEA_MIRROR}/${GITEA_BIN}" -O /tmp/gitea \ || fail "Gitea 다운로드 실패 — GITEA_MIRROR 환경변수 설정" install -m 755 /tmp/gitea /usr/local/bin/gitea ok "Gitea 바이너리 설치: /usr/local/bin/gitea" else info "Gitea 이미 설치됨" fi # 4. Gitea 설정 파일 mkdir -p "$GITEA_DATA/custom/conf" cat > "$GITEA_DATA/custom/conf/app.ini" << APPINI [DEFAULT] RUN_USER = git RUN_MODE = prod [server] HTTP_ADDR = 0.0.0.0 HTTP_PORT = ${GITEA_PORT} ROOT_URL = http://localhost:${GITEA_PORT}/ DISABLE_SSH = false SSH_PORT = 22022 [database] DB_TYPE = sqlite3 PATH = ${GITEA_DATA}/data/gitea.db [repository] ROOT = ${GITEA_DATA}/repositories [log] ROOT_PATH = ${GITEA_DATA}/log MODE = file LEVEL = info [security] INSTALL_LOCK = true SECRET_KEY = $(openssl rand -hex 32 2>/dev/null || date | md5sum | head -c 32) INTERNAL_TOKEN = $(openssl rand -hex 32 2>/dev/null || date +%s | md5sum | head -c 32) [service] DISABLE_REGISTRATION = false REQUIRE_SIGNIN_VIEW = false DEFAULT_KEEP_EMAIL_PRIVATE = true [git] DEFAULT_BRANCH = main APPINI chown -R git:git "$GITEA_DATA" # 5. systemd 서비스 cat > /etc/systemd/system/gitea.service << GITSVC [Unit] Description=Gitea (Git service) After=network.target [Service] Type=simple User=git Group=git WorkingDirectory=${GITEA_DATA} Environment="USER=git" "HOME=${GITEA_DATA}" "GITEA_WORK_DIR=${GITEA_DATA}" ExecStart=/usr/local/bin/gitea web --config ${GITEA_DATA}/custom/conf/app.ini Restart=always RestartSec=3 [Install] WantedBy=multi-user.target GITSVC systemctl daemon-reload systemctl enable gitea systemctl start gitea # Gitea 기동 대기 info "Gitea 기동 대기 중..." local attempt=0 until curl -sf "http://localhost:${GITEA_PORT}/api/v1/version" -o /dev/null 2>/dev/null; do sleep 3 ((attempt++)) [[ $attempt -ge 20 ]] && { warn "Gitea 기동 타임아웃"; break; } done ok "Gitea 서비스 시작 완료 (http://localhost:${GITEA_PORT})" } init_gitea_repos() { echo "" echo "=== Gitea 초기화 (조직·저장소·브랜치) ===" local api="${GITEA_BASE}/api/v1" local auth_header="Authorization: Basic $(echo -n "${GITEA_ADMIN}:${GITEA_ADMIN_PW}" | base64)" # 1. 관리자 계정 생성 _wait_gitea gitea admin user create \ --username "$GITEA_ADMIN" \ --password "$GITEA_ADMIN_PW" \ --email "$GITEA_ADMIN_EMAIL" \ --admin \ --config "$GITEA_DATA/custom/conf/app.ini" \ 2>/dev/null || info "관리자 계정 이미 존재" ok "관리자 계정: $GITEA_ADMIN" # 2. 조직 생성 curl -sf -X POST "$api/orgs" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d "{\"username\":\"${GITEA_ORG}\",\"visibility\":\"private\",\"description\":\"GUARDiA ITSM\"}" \ -o /dev/null 2>/dev/null \ || info "조직 이미 존재: $GITEA_ORG" ok "조직 생성: $GITEA_ORG" # 3. GUARDiA 메인 저장소 생성 curl -sf -X POST "$api/orgs/${GITEA_ORG}/repos" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d "{\"name\":\"${GITEA_REPO}\",\"description\":\"GUARDiA ITSM 플랫폼\",\"private\":true,\"default_branch\":\"main\",\"auto_init\":true}" \ -o /dev/null 2>/dev/null \ || info "저장소 이미 존재: ${GITEA_ORG}/${GITEA_REPO}" ok "저장소 생성: ${GITEA_ORG}/${GITEA_REPO}" # 초기화 후 저장소가 생성될 때까지 대기 sleep 3 # 4. develop 브랜치 생성 curl -sf -X POST "$api/repos/${GITEA_ORG}/${GITEA_REPO}/branches" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d '{"new_branch_name":"develop","old_branch_name":"main"}' \ -o /dev/null 2>/dev/null \ || info "develop 브랜치 이미 존재" ok "develop 브랜치 생성" # 5. main 브랜치 보호 규칙 설정 (PR 필수) curl -sf -X POST "$api/repos/${GITEA_ORG}/${GITEA_REPO}/branch_protections" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d '{ "branch_name": "main", "enable_push": false, "enable_push_whitelist": true, "push_whitelist_usernames": ["'"${GITEA_ADMIN}"'"], "require_signed_commits": false, "enable_status_check": false, "required_approvals": 1, "enable_approvals_whitelist": false, "merge_whitelist_usernames": ["'"${GITEA_ADMIN}"'"] }' \ -o /dev/null 2>/dev/null \ || info "main 브랜치 보호 이미 설정됨" ok "main 브랜치 보호 설정 (PR + 리뷰 1명 필수)" # 6. 현재 Git 소스를 Gitea에 push if [[ -d "${GUARDIA_ROOT:-/opt/guardia}/.git" ]]; then info "기존 소스를 Gitea에 push..." local gitea_url="http://${GITEA_ADMIN}:${GITEA_ADMIN_PW}@localhost:${GITEA_PORT}/${GITEA_ORG}/${GITEA_REPO}.git" git -C "${GUARDIA_ROOT:-/opt/guardia}" remote remove gitea 2>/dev/null || true git -C "${GUARDIA_ROOT:-/opt/guardia}" remote add gitea "$gitea_url" git -C "${GUARDIA_ROOT:-/opt/guardia}" push gitea main 2>/dev/null \ && ok "소스 push 완료 → Gitea main 브랜치" \ || warn "소스 push 실패 — 나중에 수동으로 push" git -C "${GUARDIA_ROOT:-/opt/guardia}" push gitea develop 2>/dev/null || true fi ok "Gitea 초기화 완료" echo "" info "Gitea URL: http://localhost:${GITEA_PORT}" info "관리자 계정: ${GITEA_ADMIN} / ${GITEA_ADMIN_PW}" info "저장소: ${GITEA_BASE}/${GITEA_ORG}/${GITEA_REPO}" info "" info "=== 브랜치 전략 ===" info " main : 보호 브랜치 (PR + 리뷰 1명 필수)" info " develop : 통합 브랜치 (feature 브랜치 merge 대상)" info " feature/이름/기능명 : 개인 개발 브랜치" info "" info " 새 개발자 브랜치 생성:" info " git checkout develop" info " git checkout -b feature/홍길동/신기능" info " git push -u gitea feature/홍길동/신기능" } create_dev_user() { local username="$1" local password="${2:-Dev@guardia!}" local email="${3:-${username}@guardia.local}" local api="${GITEA_BASE}/api/v1" local auth_header="Authorization: Basic $(echo -n "${GITEA_ADMIN}:${GITEA_ADMIN_PW}" | base64)" # 사용자 생성 curl -sf -X POST "$api/admin/users" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d "{\"username\":\"${username}\",\"password\":\"${password}\",\"email\":\"${email}\",\"login_name\":\"${username}\",\"source_id\":0,\"send_notify\":false,\"must_change_password\":false}" \ -o /dev/null 2>/dev/null \ || { info "사용자 이미 존재: $username"; return; } # 조직에 팀 멤버 추가 local team_id team_id=$(curl -sf "$api/orgs/${GITEA_ORG}/teams" \ -H "$auth_header" 2>/dev/null \ | python3 -c "import sys,json; teams=json.load(sys.stdin); t=[t for t in teams if t.get('name')=='Developers']; print(t[0]['id'] if t else '')" 2>/dev/null) if [[ -z "$team_id" ]]; then # Developers 팀 생성 team_id=$(curl -sf -X POST "$api/orgs/${GITEA_ORG}/teams" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d "{\"name\":\"Developers\",\"permission\":\"write\",\"units\":[\"repo.code\",\"repo.issues\",\"repo.pulls\"]}" \ 2>/dev/null \ | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null) fi if [[ -n "$team_id" ]]; then # 팀에 사용자 추가 curl -sf -X PUT "$api/teams/${team_id}/members/${username}" \ -H "$auth_header" -o /dev/null 2>/dev/null # 팀에 저장소 추가 curl -sf -X PUT "$api/teams/${team_id}/repos/${GITEA_ORG}/${GITEA_REPO}" \ -H "$auth_header" -o /dev/null 2>/dev/null fi # 개인 브랜치 생성 (feature/이름/init) curl -sf -X POST "$api/repos/${GITEA_ORG}/${GITEA_REPO}/branches" \ -H "$auth_header" \ -H "Content-Type: application/json" \ -d "{\"new_branch_name\":\"feature/${username}/init\",\"old_branch_name\":\"develop\"}" \ -o /dev/null 2>/dev/null ok "개발자 계정 + 브랜치 생성: $username (feature/${username}/init)" } _wait_gitea() { local attempt=0 until curl -sf "http://localhost:${GITEA_PORT}/api/v1/version" -o /dev/null 2>/dev/null; do sleep 2 ((attempt++)) [[ $attempt -ge 30 ]] && { fail "Gitea 서비스 응답 없음"; return; } done }