#!/usr/bin/python # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import argparse import logging import requests import json import threading class FailedPR: def __init__(self, host, url, status, target_url, created_at, updated_at): self.host = host self.url = url self.status = status self.target_url = target_url self.created_at = created_at self.updated_at = updated_at def to_json(self): return json.dumps(self.__dict__) def get_args(): parser = argparse.ArgumentParser( description='Bootstrap repositories.') parser.add_argument( '--gh-orgs', nargs='+', default=['opentelekomcloud-docs'], help='One or more GitHub organizations to be queried for failed Pull ' 'Requests.\n' 'Default: [opentelekomcloud-docs]' ) parser.add_argument( '--gitea-orgs', nargs='+', default=['docs'], help='One or more Gitea organizations to be queried for failed Pull ' 'Requests.\n' 'Default: [docs]' ) parser.add_argument( '--gh-token', help='API Token for GitHub.' ) parser.add_argument( '--gitea-token', help='API Token for Gitea' ) parser.add_argument( '--debug', action='store_true', help='Set debug mode on.' ) parser.add_argument( '--gitea-url', default='https://gitea.eco.tsi-dev.otc-service.com/api/v1/', help='Base URL for API request.\n' 'Default: https://gitea.eco.tsi-dev.otc-service.com/api/v1/' ) parser.add_argument( '--hoster', default=['gitea', 'github'], nargs='+', help='Git hoster to be queried for failed Pull Requests.\n' 'Default: [github, gitea].' ) return(parser.parse_args()) def get_gitea_repos(url, headers, gitea_org): repositories = [] i = 1 while True: try: req_url = (url + 'orgs/' + gitea_org + '/repos?limit=50&page=' + str(i)) res = requests.request('GET', url=req_url, headers=headers) i+=1 if res.json(): for repo in res.json(): repositories.append(repo) continue else: break except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res.status_code) + " | " + str(res.reason)) break return(repositories) def get_gitea_prs(url, headers, gitea_org, repo): pullrequests = [] try: req_url = (url + 'repos/' + gitea_org + '/' + repo + '/pulls?state=open') res = requests.request('GET', url=req_url, headers=headers) if res.json(): for pr in res.json(): pullrequests.append(pr) except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res.status_code) + " | " + str(res.reason)) exit() return(pullrequests) def get_failed_gitea_commits(pull, url, gitea_org, repo, headers): failed_commits = [] try: req_url = (url + 'repos/' + gitea_org + '/' + repo['name'] + '/commits/' + pull['head']['ref'] + '/statuses?limit=1') res_sta = requests.request('GET', url=req_url, headers=headers) if res_sta.json(): if res_sta.json()[0]['status'] == 'failure': o = FailedPR( host='gitea', url=pull['url'], status=res_sta.json()[0]['status'], target_url=res_sta.json()[0]['target_url'], created_at=pull['created_at'], updated_at=res_sta.json()[0]['updated_at'] ) failed_commits.append(o) except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res_sta.status_code) + " | " + str(res_sta.reason)) print(json.dumps(res_sta.json())) exit() return(failed_commits) def get_github_repos(url, headers, gh_org): repositories = [] i = 1 while True: try: req_url = url + 'orgs/' + gh_org + '/repos?page=' + str(i) res = requests.request('GET', url=req_url, headers=headers) if res.json(): for repo in res.json(): repositories.append(repo) i+=1 continue else: break except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res.status_code) + " | " + str(res.reason)) break return(repositories) def get_github_prs(url, headers, gh_org, repo): pullrequests = [] i = 1 while True: try: req_url = (url + 'repos/' + gh_org + '/' + repo + '/pulls?state=open&page=' + str(i)) res = requests.request('GET', url=req_url, headers=headers) if res.json(): for pr in res.json(): pullrequests.append(pr) i+=1 continue else: break except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res.status_code) + " | " + str(res.reason)) break return(pullrequests) def get_failed_gh_commits(pull, url, gh_org, repo, headers): failed_commits = [] try: req_url = (url + 'repos/' + gh_org + '/' + repo['name'] + '/commits/' + pull['head']['sha'] + '/check-runs') res_sta = requests.request('GET', url=req_url, headers=headers) if res_sta.json(): if len(res_sta.json()['check_runs']) != 0: if res_sta.json()['check_runs'][0]['conclusion'] == 'failure': o = FailedPR( host='gitea', url=pull['html_url'], status=res_sta.json()['check_runs'][0]['conclusion'], target_url=(res_sta.json()['check_runs'] [0]['details_url']), created_at=pull['created_at'], updated_at=(res_sta.json()['check_runs'] [0]['completed_at']) ) failed_commits.append(o) else: o = FailedPR( host='gitea', url=pull['html_url'], status='', target_url='', created_at=pull['created_at'], updated_at=res_sta.json()['check_runs'][0]['completed_at'] ) failed_commits.append(o) except Exception as e: print("An error has occured: " + str(e)) print("The request status is: " + str(res_sta.status_code) + " | " + str(res_sta.reason)) print(json.dumps(res_sta.json())) exit() return(failed_commits) def main(): args = get_args() failed_commits = [] if args.debug: logging.basicConfig(level=logging.DEBUG) for h in args.hoster: if h == 'gitea': headers = {} headers['accept'] = 'application/json' if not args.gitea_token: raise Exception('Please, provide Gitea Token as argument.') if not args.gitea_url: raise Exception('Please, provide Gitea URL as argument.') headers['Authorization'] = 'token ' + args.gitea_token for org in args.gitea_orgs: repos = get_gitea_repos( url=args.gitea_url, headers=headers, gitea_org=org ) for repo in repos: pulls = get_gitea_prs( url=args.gitea_url, headers=headers, gitea_org=org, repo=repo['name'] ) if pulls: for pull in pulls: commits = get_failed_gitea_commits( pull=pull, url=args.gitea_url, gitea_org=org, repo=repo, headers=headers ) failed_commits.extend(commits) elif h == 'github': url = 'https://api.github.com/' headers = {} headers['accept'] = 'application/json' if not args.gh_token: raise Exception('Please, provide GitHub Token as argument.') headers['Authorization'] = 'Bearer ' + args.gh_token for org in args.gh_orgs: repos = get_github_repos( url=url, headers=headers, gh_org=org ) for repo in repos: pulls = get_github_prs( url=url, headers=headers, gh_org=org, repo=repo['name'] ) if pulls: for pull in pulls: commits = get_failed_gh_commits( pull=pull, url=url, gh_org=org, repo=repo, headers=headers ) failed_commits.extend(commits) for o in failed_commits: print(o.to_json()) if __name__ == '__main__': main()