text: #!/usr/bin/env python3
  # Copyright 2019 Google LLC
  #
  # Licensed under the the Apache License v2.0 with LLVM Exceptions (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     https://llvm.org/LICENSE.txt
  #
  # 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.
  
  # -----------------------------------------------------------------------------
  # This script will collect all breakages of the main branch builds from
  # buildkite and format the results nicely.
  # Arguments:
  #     llvm-path :  folder where the LLVM checkout is kept
  #     token     :  Access token for buildkite 
  # -----------------------------------------------------------------------------
  
  import requests
  import git
  import argparse
  import json 
  import os
  import datetime
  
  class Build:
  
    def __init__(self, json_dict):
      self._json_dict = json_dict
  
    @property
    def number(self) -> int:
      return self._json_dict['number']
  
    @property
    def web_url(self) -> str:
      return self._json_dict['web_url']
  
    @property
    def state(self) -> str:
      return self._json_dict['state']
  
    @property
    def has_passed(self) -> bool:
      return self.state == 'passed'
  
    @property
    def commit(self) -> str:
      return self._json_dict['commit']
  
    @property
    def created_at(self) -> datetime.datetime:
      #example: 2019-11-07T14:13:07.942Z
      return datetime.datetime.fromisoformat(self._json_dict['created_at'].rstrip('Z'))
  
  
  class BuildKiteMasterStats:
  
    def __init__(self, llvm_repo: str, token_path: str):
      self._llvm_repo = llvm_repo
      with open(token_path, 'r') as token_file:
        self._token = token_file.read().strip()
  
    def get_stats(self, organisation: str, pipeline: str):
      url = "https://api.buildkite.com/v2/organizations/{}/pipelines/{}/builds".format(organisation, pipeline)
      return self._get_url(url)
      
  
    def _get_url(self, url: str):
      """Get paginated results from server."""
      page = 1
      results = []
      while True:
        page_url = url + f"?api_key={self._token}&page={page}&per_page=100"
        new_results = requests.get(page_url).json()
        results.extend(new_results)
        print(len(new_results))
        if len(new_results) < 100:
          break
        page += 1 
      return results
  
    def save_results(self, output_path:str, data):
      with open(output_path, 'w') as output_file:
        json.dump(data, output_file)
  
    def get_builds(self, json_path: str):
      with open(json_path) as json_file:
        builds = json.load(json_file)
      build_dict = {}
      for b in builds:
        build = Build(b)
        build_dict[build.number] = build
      return build_dict
  
  if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Process some integers.')
    parser.add_argument('llvm_path')
    parser.add_argument('token')
    args = parser.parse_args()
    CACHE_FILE = 'tmp/bklogs.json'
    bk = BuildKiteMasterStats(args.llvm_path, args.token)
    
    if not os.path.exists(CACHE_FILE):
      results = bk.get_stats('llvm-project','llvm-main-build')
      bk.save_results(CACHE_FILE, results)
    
    builds = bk.get_builds(CACHE_FILE)
    last_fail = None
    fail_count = 0
    start_time = None
    for build_number in sorted(builds.keys()):
      if build_number < 50:
        # skip the first builds as they might not be mature enough
        continue
      build = builds[build_number]
      if build.has_passed:
        if last_fail is not None:
          print(f'* ends with [build {build.number}]({build.web_url})')
          print(f'* ends with commit {build.commit}')
          print(f'* ends on {build.created_at}')
          duration = build.created_at - start_time
          print(f'* duration: {duration} [h:m:s]')
          print('* cause: # TODO')
          print()
          last_fail = None
      else:
        if last_fail is None:
          print(f'# Outage {fail_count}')
          print()
          print(f'* starts with [build {build.number}]({build.web_url})')
          print(f'* starts with commit {build.commit}')
          print(f'* starts on {build.created_at}')
          fail_count += 1
          start_time = build.created_at
        else:
          pass
        last_fail = build.number
        
    