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()