async function downloadIssues(urlToStartAt) {
  const url = new URL(`/repos/GoogleChrome/lighthouse/issues`, GITHUB_API);
  url.searchParams.set('state', 'all');
  url.searchParams.set('since', START_FROM.toISOString());
  const urlToFetch = urlToStartAt || url.href;
  process.stdout.write(`Fetching ${urlToFetch}...\n`);
  const response = await fetch(urlToFetch, {headers: HEADERS});
  if (!response.ok) throw new Error(`Invalid API response: ${await response.text()}`);
  /** @type {Array<AugmentedGitHubIssue>} */
  const issues = await response.json();
  const linkHeader = response.headers.get('link') || '';
  const nextLink = linkHeader
    .split(',')
    .find(link => link.split(';')[1].includes('rel="next"'));
  const nextUrlMatch = (nextLink && nextLink.match(/<(https.*?)>/)) || [];
  const nextUrl = nextUrlMatch[1] || '';
  const restOfIssues = nextUrl ? await downloadIssues(nextUrl) : [];

  // Yes really do this in series to avoid hitting abuse limits of GitHub API
  for (const issue of issues) {
    await Promise.all([
      fetchAndInjectEvents(issue).catch(async err => {
        console.error('Events failed! Trying again', err);
        await wait(60 * 1000);
        return fetchAndInjectEvents(issue);
      }),
      fetchAndInjectComments(issue).catch(async err => {
        console.error('Comments failed! Trying again', err);
        await wait(60 * 1000);
        return fetchAndInjectComments(issue);
      }),
    ]);
  }

  return [...issues, ...restOfIssues];
}
@param {string} [urlToStartAt]
@return {Promise<Array<AugmentedGitHubIssue>>}