GitHub Magrations 전체 이슈 가져오기

혜빈·2025년 8월 24일

보충내용

목록 보기
38/38

GitHub Magrations 전체 이슈 가져오기

전체 이슈 가져오는 방법입니다 ☺️

# 0) UTF-8 고정
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
[Console]::InputEncoding  = [System.Text.UTF8Encoding]::new()
$ErrorActionPreference = "Stop"

# 1) 변수
$SRC = "원본 레포"
$DST = "대상 레포"

# 2) 소스 이슈 번호 수집 (PR은 어차피 issue list에 안 섞임)
$srcAll   = gh issue list -R $SRC --state all --limit 2000 --json number | ConvertFrom-Json
$issueIds = $srcAll | ForEach-Object { $_.number }
"source issues: $($issueIds.Count) found"

if (-not $issueIds -or $issueIds.Count -eq 0) {
  throw "No issues to migrate from $SRC"
}

# 3) 라벨 동기화
$srcLabels = (gh api "repos/$SRC/labels?per_page=100" --paginate) | ConvertFrom-Json
$dstLabels = (gh api "repos/$DST/labels?per_page=100" --paginate) | ConvertFrom-Json
$dstLabelNames = @{}; $dstLabels | % { $dstLabelNames[$_.name] = $true }
foreach ($lab in $srcLabels) {
  if (-not $dstLabelNames.ContainsKey($lab.name)) {
    gh api -X POST "repos/$DST/labels" -f name="$($lab.name)" -f color="$($lab.color)" | Out-Null
    Start-Sleep -Milliseconds 60
  }
}

# 4) 마일스톤 동기화(제목 기반)
$srcMsAll = (gh api "repos/$SRC/milestones?state=all&per_page=100" --paginate) | ConvertFrom-Json
foreach ($ms in $srcMsAll) {
  $exists = (gh api "repos/$DST/milestones?state=all&per_page=100" --paginate) | ConvertFrom-Json |
            Where-Object { $_.title -eq $ms.title } | Select-Object -First 1
  if (-not $exists) {
    gh api -X POST "repos/$DST/milestones" -f title="$($ms.title)" | Out-Null
    Start-Sleep -Milliseconds 60
  }
}
$dstMs = (gh api "repos/$DST/milestones?state=all&per_page=100" --paginate) | ConvertFrom-Json
$dstMsByTitle = @{}; $dstMs | % { $dstMsByTitle[$_.title] = $_ }

# 5) 마이그레이션 (번호별 개별 조회 → 생성/패치)
foreach ($n in $issueIds) {
  # 중복 방지: 이미 이관된 건 스킵
  $marker = "migrated from $SRC#$n"
  $dup = gh issue list -R $DST --state all --search "$marker" --json number | ConvertFrom-Json
  if ($dup -and $dup.Count -gt 0) { "skip dup -> src #$n"; continue }

  # a) 원본 단일 이슈 풀 조회 (필드 Null 안정성 ↑)
  $i = gh issue view -R $SRC $n --json `
      number,title,body,url,state,labels,assignees,milestone,comments `
      | ConvertFrom-Json

  if (-not $i) { "skip (cannot view) -> src #$n"; continue }

  $origin  = "[$marker | $($i.url)]`n`n"
  $bodyTxt = if ($null -ne $i.body) { [string]$i.body } else { "" }
  $bodyFull = @"
$origin$bodyTxt
"@

  # b) 이슈 생성 (필드 방식)
  $newNum = gh api -X POST "repos/$DST/issues" `
            -f title="$($i.title)" `
            -f body="$bodyFull" `
            --jq ".number"
  if (-not $newNum) { throw "create failed -> src #$($i.number)" }
  "created -> dst #$newNum (from src #$($i.number))"

  # c) 마일스톤
  if ($i.milestone -and $dstMsByTitle.ContainsKey($i.milestone.title)) {
    gh api -X PATCH "repos/$DST/issues/$newNum" -f milestone="$($dstMsByTitle[$i.milestone.title].number)" | Out-Null
  }

  # d) 라벨
  foreach ($lab in $i.labels) {
    gh api -X POST "repos/$DST/issues/$newNum/labels" -f "labels[]=$($lab.name)" | Out-Null
    Start-Sleep -Milliseconds 30
  }

  # e) 어싸이니
  foreach ($a in $i.assignees) {
    gh api -X POST "repos/$DST/issues/$newNum/assignees" -f "assignees[]=$($a.login)" | Out-Null
    Start-Sleep -Milliseconds 30
  }

  # f) 코멘트
  foreach ($c in $i.comments) {
    $cBody = if ($null -ne $c.body) { [string]$c.body } else { "" }
    $cFull = @"
[from @$($c.author.login) | $($c.createdAt)]

$cBody
"@
    gh api -X POST "repos/$DST/issues/$newNum/comments" -f body="$cFull" | Out-Null
    Start-Sleep -Milliseconds 30
  }

  # g) 상태
  if ($i.state -eq "CLOSED") {
    gh api -X PATCH "repos/$DST/issues/$newNum" -f state="closed" | Out-Null
  }

  "ok -> dst #$newNum"
  Start-Sleep -Milliseconds 90
}

# 6) 결과 확인
gh issue list -R $DST --state all --limit 20
profile
최강 개발자를 꿈꾸는 병아리

0개의 댓글