130 lines
4.5 KiB
Python
130 lines
4.5 KiB
Python
import requests
|
|
import os
|
|
|
|
# --- 설정 ---
|
|
# GitHub 개인용 액세스 토큰(PAT)이 필요합니다. 'repo' 권한이 필요합니다.
|
|
# 보안을 위해 환경 변수로 설정하는 것을 권장합니다.
|
|
# Linux/macOS: export GITHUB_TOKEN='your_token_here'
|
|
# Windows: set GITHUB_TOKEN='your_token_here'
|
|
GITHUB_TOKEN = os.getenv('GITHUB_TOKEN')
|
|
REPO_OWNER = 'baron-consultant' # 리포지토리 소유자 (예: 'octocat')
|
|
REPO_NAME = 'llm-gateway-plan' # 리포지토리 이름 (예: 'Hello-World')
|
|
# --- ---
|
|
|
|
GRAPHQL_URL = 'https://api.github.com/graphql'
|
|
HEADERS = {
|
|
'Authorization': f'bearer {GITHUB_TOKEN}',
|
|
'Content-Type': 'application/json',
|
|
}
|
|
|
|
def run_graphql_query(query, variables):
|
|
"""GraphQL 쿼리를 실행하고 결과를 반환하는 헬퍼 함수"""
|
|
response = requests.post(
|
|
GRAPHQL_URL,
|
|
headers=HEADERS,
|
|
json={'query': query, 'variables': variables}
|
|
)
|
|
response.raise_for_status()
|
|
json_response = response.json()
|
|
if 'errors' in json_response:
|
|
raise Exception(f"GraphQL query failed: {json_response['errors']}")
|
|
return json_response['data']
|
|
|
|
def get_all_issue_ids():
|
|
"""리포지토리의 모든 이슈 ID (GraphQL Node ID)를 가져옵니다."""
|
|
issue_details = []
|
|
has_next_page = True
|
|
cursor = None
|
|
|
|
get_issues_query = """
|
|
query($owner: String!, $name: String!, $cursor: String) {
|
|
repository(owner: $owner, name: $name) {
|
|
issues(first: 100, after: $cursor, states: [OPEN, CLOSED]) {
|
|
nodes {
|
|
id
|
|
number
|
|
title
|
|
}
|
|
pageInfo {
|
|
endCursor
|
|
hasNextPage
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
print(f"{REPO_OWNER}/{REPO_NAME} 리포지토리에서 모든 이슈를 가져오는 중...")
|
|
while has_next_page:
|
|
variables = {"owner": REPO_OWNER, "name": REPO_NAME, "cursor": cursor}
|
|
data = run_graphql_query(get_issues_query, variables)
|
|
|
|
issues_data = data['repository']['issues']
|
|
for issue in issues_data['nodes']:
|
|
issue_details.append({
|
|
"id": issue['id'],
|
|
"number": issue['number'],
|
|
"title": issue['title']
|
|
})
|
|
|
|
has_next_page = issues_data['pageInfo']['hasNextPage']
|
|
cursor = issues_data['pageInfo']['endCursor']
|
|
print(f" 지금까지 찾은 이슈: {len(issue_details)}개")
|
|
|
|
return issue_details
|
|
|
|
def delete_issue(issue_id, issue_number, issue_title):
|
|
"""GraphQL `deleteIssue` 뮤테이션을 사용하여 이슈를 삭제합니다."""
|
|
delete_mutation = """
|
|
mutation($issueId: ID!) {
|
|
deleteIssue(input: {issueId: $issueId}) {
|
|
clientMutationId
|
|
}
|
|
}
|
|
"""
|
|
variables = {"issueId": issue_id}
|
|
try:
|
|
run_graphql_query(delete_mutation, variables)
|
|
print(f"성공적으로 이슈 #{issue_number}를 삭제했습니다: '{issue_title}'")
|
|
except Exception as e:
|
|
print(f"이슈 #{issue_number} 삭제 실패: {e}")
|
|
|
|
|
|
def main():
|
|
"""메인 실행 함수"""
|
|
if not GITHUB_TOKEN:
|
|
print("오류: GITHUB_TOKEN 환경 변수가 설정되지 않았습니다.")
|
|
print("'repo' 권한을 가진 GitHub 개인용 액세스 토큰을 설정해주세요.")
|
|
return
|
|
|
|
if REPO_OWNER == 'your_repo_owner' or REPO_NAME == 'your_repo_name':
|
|
print("오류: 스크립트 상단의 REPO_OWNER와 REPO_NAME을 당신의 리포지토리 정보로 수정해주세요.")
|
|
return
|
|
|
|
try:
|
|
issues_to_delete = get_all_issue_ids()
|
|
|
|
if not issues_to_delete:
|
|
print(f"{REPO_OWNER}/{REPO_NAME} 리포지토리에서 이슈를 찾지 못했습니다.")
|
|
return
|
|
|
|
print(f"\n총 {len(issues_to_delete)}개의 이슈를 {REPO_OWNER}/{REPO_NAME}에서 찾았습니다.")
|
|
|
|
# 되돌릴 수 없는 작업이므로 사용자 확인을 받습니다.
|
|
confirm = input("이 모든 이슈를 영구적으로 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다. (yes/no): ").lower()
|
|
|
|
if confirm != 'yes':
|
|
print("삭제 작업이 취소되었습니다.")
|
|
return
|
|
|
|
print("\n삭제를 시작합니다...")
|
|
for issue in issues_to_delete:
|
|
delete_issue(issue['id'], issue['number'], issue['title'])
|
|
|
|
print("\n모든 이슈 처리가 완료되었습니다.")
|
|
|
|
except Exception as e:
|
|
print(f"\n오류가 발생했습니다: {e}")
|
|
|
|
if __name__ == '__main__':
|
|
main() |