text: # Copyright 2021 Google LLC
  #
  # 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.
  """Module for dealing with the GitHub API. This is different from
  github_actions_toolkit which only deals with the actions API. We need to use
  both."""
  import logging
  import os
  import sys
  
  import requests
  
  import filestore
  
  # pylint: disable=wrong-import-position,import-error
  
  sys.path.append(
      os.path.join(__file__, os.path.pardir, os.path.pardir, os.path.pardir,
                   os.path.pardir))
  import retry
  
  _MAX_ITEMS_PER_PAGE = 100
  
  _GET_ATTEMPTS = 3
  _GET_BACKOFF = 1
  
  
  def get_http_auth_headers(config):
    """Returns HTTP headers for authentication to the API."""
    authorization = f'token {config.github_token}'
    return {
        'Authorization': authorization,
        'Accept': 'application/vnd.github.v3+json'
    }
  
  
  def _get_artifacts_list_api_url(repo_owner, repo_name):
    """Returns the artifacts_api_url for |repo_name| owned by |repo_owner|."""
    return (f'https://api.github.com/repos/{repo_owner}/'
            f'{repo_name}/actions/artifacts')
  
  
  @retry.wrap(_GET_ATTEMPTS, _GET_BACKOFF)
  def _do_get_request(*args, **kwargs):
    """Wrapped version of requests.get that does retries."""
    return requests.get(*args, **kwargs)
  
  
  def _get_items(url, headers):
    """Generator that gets and yields items from a GitHub API endpoint (specified
    by |URL|) sending |headers| with the get request."""
    # Github API response pages are 1-indexed.
    page_counter = 1
  
    # Set to infinity so we run loop at least once.
    total_num_items = float('inf')
  
    item_num = 0
    while item_num < total_num_items:
      params = {'per_page': _MAX_ITEMS_PER_PAGE, 'page': str(page_counter)}
      response = _do_get_request(url, params=params, headers=headers)
      response_json = response.json()
      if not response.status_code == 200:
        # Check that request was successful.
        logging.error('Request to %s failed. Code: %d. Response: %s',
                      response.request.url, response.status_code, response_json)
        raise filestore.FilestoreError('Github API request failed.')
  
      if total_num_items == float('inf'):
        # Set proper total_num_items
        total_num_items = response_json['total_count']
  
      # Get the key for the items we are after.
      keys = [key for key in response_json.keys() if key != 'total_count']
      assert len(keys) == 1, keys
      items_key = keys[0]
  
      for item in response_json[items_key]:
        yield item
        item_num += 1
  
      page_counter += 1
  
  
  def find_artifact(artifact_name, artifacts):
    """Find the artifact with the name |artifact_name| in |artifacts|."""
    for artifact in artifacts:
      # TODO(metzman): Handle multiple by making sure we download the latest.
      if artifact['name'] == artifact_name and not artifact['expired']:
        return artifact
    return None
  
  
  def list_artifacts(owner, repo, headers):
    """Returns a generator of all the artifacts for |owner/repo|."""
    url = _get_artifacts_list_api_url(owner, repo)
    logging.debug('Getting artifacts from: %s', url)
    return _get_items(url, headers)
  