Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Support pagination while querying for issues in flaky reporter #12832

Merged
merged 2 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions playwright/flaky-reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ const REPO = "element-hq/element-web";
const LABEL = "Z-Flaky-Test";
const ISSUE_TITLE_PREFIX = "Flaky playwright test: ";

type PaginationLinks = {
prev?: string;
next?: string;
last?: string;
first?: string;
};

class FlakyReporter implements Reporter {
private flakes = new Set<string>();

Expand All @@ -35,6 +42,54 @@ class FlakyReporter implements Reporter {
}
}

/**
* Parse link header to retrieve pagination links
* @see https://docs.github.com/en/rest/using-the-rest-api/using-pagination-in-the-rest-api?apiVersion=2022-11-28#using-link-headers
* @param link link header from response or undefined
* @returns an empty object if link is undefined otherwise returns a map from type to link
*/
private parseLinkHeader(link: string): PaginationLinks {
/**
* link looks like:
* <https://api.github.com/repositories/1300192/issues?page=2>; rel="prev", <https://api.github.com/repositories/1300192/issues?page=4>;
*/
const map: PaginationLinks = {};
if (!link) return map;
const matches = link.matchAll(/(<(?<link>.+?)>; rel="(?<type>.+?)")/g);
for (const match of matches) {
const { link, type } = match.groups;
map[type] = link;
}
return map;
}

/**
* Fetch all flaky test issues that were updated since Jan-1-2024
* @returns A promise that resolves to a list of issues
*/
async getAllIssues(): Promise<any[]> {
const issues = [];
const { GITHUB_TOKEN, GITHUB_API_URL } = process.env;
// See https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#list-repository-issues
let url = `${GITHUB_API_URL}/repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=100&sort=updated&since=2024-01-01`;
const headers = {
Authorization: `Bearer ${GITHUB_TOKEN}`,
Accept: "application / vnd.github + json",
};
while (url) {
MidhunSureshR marked this conversation as resolved.
Show resolved Hide resolved
// Fetch issues and add to list
const issuesResponse = await fetch(url, { headers });
const fetchedIssues = await issuesResponse.json();
issues.push(...fetchedIssues);

// Get the next link for fetching more results
const linkHeader = issuesResponse.headers.get("Link");
const parsed = this.parseLinkHeader(linkHeader);
url = parsed.next;
}
return issues;
}

public async onExit(): Promise<void> {
if (this.flakes.size === 0) {
console.log("No flakes found");
Expand All @@ -49,18 +104,12 @@ class FlakyReporter implements Reporter {
const { GITHUB_TOKEN, GITHUB_API_URL, GITHUB_SERVER_URL, GITHUB_REPOSITORY, GITHUB_RUN_ID } = process.env;
if (!GITHUB_TOKEN) return;

const body = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`;

const headers = { Authorization: `Bearer ${GITHUB_TOKEN}` };
// Fetch all existing issues with the flaky-test label.
const issuesRequest = await fetch(
`${GITHUB_API_URL}/repos/${REPO}/issues?labels=${LABEL}&state=all&per_page=100&sort=created`,
{ headers },
);
const issues = await issuesRequest.json();
const issues = await this.getAllIssues();
for (const flake of this.flakes) {
const title = ISSUE_TITLE_PREFIX + "`" + flake + "`";
const existingIssue = issues.find((issue) => issue.title === title);
const headers = { Authorization: `Bearer ${GITHUB_TOKEN}` };
const body = `${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}`;
Comment on lines +111 to +112
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did this move into the for loop? tiny de-optimisation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't think much of it, just moved the variables closer to where they're used. I'm sure the compiler will move stuff out for us anyway 🤞


if (existingIssue) {
console.log(`Found issue ${existingIssue.number} for ${flake}, adding comment...`);
Expand Down
2 changes: 1 addition & 1 deletion playwright/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "es2016",
"target": "es2018",
MidhunSureshR marked this conversation as resolved.
Show resolved Hide resolved
"jsx": "react",
"lib": ["ESNext", "es2021", "dom", "dom.iterable"],
"resolveJsonModule": true,
Expand Down
Loading