text: "use strict";
  // Copyright 2017 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
  //
  //     https://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.
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.GitHubRepository = void 0;
  // Abstractions over GitHub REST API v3 and related features. For GitHub API,
  // see https://developer.github.com/v3/.
  const gaxios_1 = require("gaxios");
  const path_1 = require("path");
  const url_1 = require("url");
  function isSingleResponseData(respData) {
      return !Array.isArray(respData);
  }
  function ensureSingleResponseData(respData) {
      if (!isSingleResponseData(respData)) {
          throw new Error('Expected a single response, got multiple.');
      }
      return respData;
  }
  class GitHubRepository {
      constructor(owner, repo) {
          this.pathPrefix = path_1.posix.join('/repos', owner, repo);
      }
      getAxiosConfig(authToken) {
          return authToken ? { headers: { Authorization: `token ${authToken}` } } : {};
      }
      async apiGet(path, params) {
          const url = new url_1.URL('https://api.github.com');
          url.pathname = path_1.posix.join(this.pathPrefix, path);
          if (params) {
              Object.keys(params).forEach(key => {
                  url.searchParams.set(key, params[key]);
              });
          }
          const resp = await gaxios_1.request({
              method: 'GET',
              url: url.href,
              ...this.getAxiosConfig(),
          });
          return resp.data;
      }
      async apiPost(path, body) {
          const url = new url_1.URL('https://api.github.com');
          url.pathname = path_1.posix.join(this.pathPrefix, path);
          const resp = await gaxios_1.request({
              method: 'POST',
              url: url.href,
              data: body,
              ...this.getAxiosConfig(),
          });
          return resp.data;
      }
      async getPRCommits(prId, attemptCount = 1) {
          let answer = await this.apiGet(path_1.posix.join('pulls', prId.toString()));
          answer = ensureSingleResponseData(answer);
          if (answer.mergeable === null) {
              if (attemptCount > GitHubRepository.MAX_PR_COMMIT_RETRIES) {
                  throw new Error(`Tried ${attemptCount} times but the mergeable field is not set. Giving up`);
              }
              console.log('The `mergeable` field is not set yet. Will retry later.');
              return new Promise(resolve => {
                  setTimeout(async () => {
                      resolve(await this.getPRCommits(prId, attemptCount + 1));
                  }, 1000);
              });
          }
          else if (!answer.mergeable) {
              throw new Error('PR is not mergeable');
          }
          const mergeCommitSha = answer.merge_commit_sha;
          if (!mergeCommitSha) {
              throw new Error('Merge commit SHA is not found');
          }
          const headCommitSha = answer.head && answer.head.sha;
          if (!headCommitSha) {
              throw new Error('HEAD commit SHA is not found');
          }
          return { mergeCommitSha, headCommitSha };
      }
      async createPRReview(prId, commitSha, body) {
          await this.apiPost(path_1.posix.join('pulls', prId.toString(), 'reviews'), {
              commit_id: commitSha,
              body,
              event: 'COMMENT',
          });
      }
      async setCommitStatus(commitSha, status, description, context) {
          await this.apiPost(path_1.posix.join('statuses', commitSha), {
              state: status,
              description,
              context,
          });
      }
      async getFileContent(commitSha, path) {
          let answer;
          try {
              answer = await this.apiGet(path_1.posix.join('contents', path), {
                  ref: commitSha,
              });
          }
          catch (_a) {
              return null;
          }
          answer = ensureSingleResponseData(answer);
          if (answer.content === undefined) {
              throw new Error(`Content of ${path} not found`);
          }
          const content = Buffer.from(answer.content, 'base64').toString();
          return content;
      }
      async getSinglePackageJson(dir, commitSha) {
          const content = await this.getFileContent(commitSha, path_1.posix.join(dir, 'package.json'));
          if (!content) {
              return null;
          }
          const filePath = path_1.posix.join('/', dir, 'package.json');
          return { filePath, content };
      }
      async getPackageJsonFiles(commitSha) {
          const packageJsons = [];
          // Find the top-level package.json first.
          const pj = await this.getSinglePackageJson('', commitSha);
          if (pj !== null) {
              packageJsons.push(pj);
          }
          // Find `packages/<name>/package.json` files in case this is a monorepo.
          let answer;
          try {
              answer = await this.apiGet('contents/packages', { ref: commitSha });
          }
          catch (_a) {
              // Not a monorepo. Return just the top-level package.json.
              return packageJsons;
          }
          if (!isSingleResponseData(answer)) {
              // Response is an array, which means there's the `packages` directory and
              // this is a monorepo. Find package.json from each directory under
              // `packages`.
              for (const entry of answer) {
                  if (entry.type === 'dir' && entry.name) {
                      const pj = await this.getSinglePackageJson(path_1.posix.join('packages', entry.name), commitSha);
                      if (pj !== null) {
                          packageJsons.push(pj);
                      }
                  }
              }
          }
          return packageJsons;
      }
  }
  exports.GitHubRepository = GitHubRepository;
  // How many times to retry PR commit retrieval until giving up.
  GitHubRepository.MAX_PR_COMMIT_RETRIES = 10;
  //# sourceMappingURL=github.js.map