Skip to content

Commit

Permalink
chore: report flaky tests to jira (#32593)
Browse files Browse the repository at this point in the history
  • Loading branch information
ggazzo committed Jun 22, 2024
1 parent 2597791 commit 1827e95
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/workflows/ci-test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ on:
required: false
CODECOV_TOKEN:
required: false
REPORTER_JIRA_ROCKETCHAT_API_KEY:
required: false

env:
MONGO_URL: mongodb://localhost:27017/rocketchat?replicaSet=rs0&directConnection=true
Expand Down Expand Up @@ -250,10 +252,15 @@ jobs:
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_REPORT: ${{ github.event.pull_request.draft != 'true' && 'true' || '' }}
REPORTER_ROCKETCHAT_RUN: ${{ github.run_number }}
REPORTER_ROCKETCHAT_BRANCH: ${{ github.ref }}
REPORTER_ROCKETCHAT_DRAFT: ${{ github.event.pull_request.draft }}
REPORTER_ROCKETCHAT_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
REPORTER_ROCKETCHAT_AUTHOR: ${{ github.event.pull_request.user.login }}
REPORTER_ROCKETCHAT_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
REPORTER_ROCKETCHAT_PR: ${{ github.event.pull_request.number }}
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}
QASE_REPORT: ${{ github.ref == 'refs/heads/develop' && 'true' || '' }}
CI: true
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ jobs:
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}

test-api-ee:
name: 🔨 Test API (EE)
Expand Down Expand Up @@ -400,6 +401,7 @@ jobs:
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}

test-ui-ee-no-watcher:
name: 🔨 Test UI (EE)
Expand Down Expand Up @@ -430,6 +432,7 @@ jobs:
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}

tests-done:
name: ✅ Tests Done
Expand Down
15 changes: 15 additions & 0 deletions apps/meteor/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ export default {
branch: process.env.REPORTER_ROCKETCHAT_BRANCH,
run: Number(process.env.REPORTER_ROCKETCHAT_RUN),
draft: process.env.REPORTER_ROCKETCHAT_DRAFT === 'true',
headSha: process.env.REPORTER_ROCKETCHAT_HEAD_SHA,
},
],
process.env.REPORTER_ROCKETCHAT_REPORT === 'true' && [
'./reporters/jira.ts',
{
url: `https://rocketchat.atlassian.net`,
apiKey: process.env.REPORTER_JIRA_ROCKETCHAT_API_KEY ?? process.env.JIRA_TOKEN,
branch: process.env.REPORTER_ROCKETCHAT_BRANCH,
run: Number(process.env.REPORTER_ROCKETCHAT_RUN),
headSha: process.env.REPORTER_ROCKETCHAT_HEAD_SHA,
author: process.env.REPORTER_ROCKETCHAT_AUTHOR,
run_url: process.env.REPORTER_ROCKETCHAT_RUN_URL,
pr: Number(process.env.REPORTER_ROCKETCHAT_PR),
draft: process.env.REPORTER_ROCKETCHAT_DRAFT === 'true',
},
],
[
Expand Down
186 changes: 186 additions & 0 deletions apps/meteor/reporters/jira.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import type { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
import fetch from 'node-fetch';

class JIRAReporter implements Reporter {
private url: string;

private apiKey: string;

private branch: string;

private draft: boolean;

private run: number;

private headSha: string;

private author: string;

private run_url: string;

private pr: number;

constructor(options: {
url: string;
apiKey: string;
branch: string;
draft: boolean;
run: number;
headSha: string;
author: string;
run_url: string;
pr: number;
}) {
this.url = options.url;
this.apiKey = options.apiKey;
this.branch = options.branch;
this.draft = options.draft;
this.run = options.run;
this.headSha = options.headSha;
this.author = options.author;
this.run_url = options.run_url;
this.pr = options.pr;
}

async onTestEnd(test: TestCase, result: TestResult) {
if (process.env.REPORTER_ROCKETCHAT_REPORT !== 'true') {
return;
}

if (this.draft === true) {
return;
}

if (result.status === 'passed' || result.status === 'skipped') {
return;
}

const payload = {
name: test.title,
status: result.status,
duration: result.duration,
branch: this.branch,
draft: this.draft,
run: this.run,
headSha: this.headSha,
};

console.log(`Sending test result to JIRA: ${JSON.stringify(payload)}`);

// first search and check if there is an existing issue

const search = await fetch(
`${this.url}/rest/api/2/search?${new URLSearchParams({
jql: `project = FLAKY AND summary ~ '${payload.name}'`,
})}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${this.apiKey}`,
},
},
);

if (!search.ok) {
throw new Error(
`JIRA: Failed to search for existing issue: ${search.statusText}.` +
`${this.url}/rest/api/2/search${new URLSearchParams({
jql: `project = FLAKY AND summary ~ '${payload.name}'`,
})}`,
);
}

const { issues } = await search.json();

const existing = issues.find(
(issue: {
fields: {
summary: string;
};
}) => issue.fields.summary === payload.name,
);

if (existing) {
const { location } = test;

await fetch(`${this.url}/rest/api/2/issue/${existing.key}/comment`, {
method: 'POST',
body: JSON.stringify({
body: `Test run ${payload.run} failed
author: ${this.author}
PR: ${this.pr}
https://github.com/RocketChat/Rocket.Chat/blob/${payload.headSha}/${location.file.replace(
'/home/runner/work/Rocket.Chat/Rocket.Chat',
'',
)}#L${location.line}:${location.column}
${this.run_url}
`,
}),
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${this.apiKey}`,
},
});
return;
}

const data: {
fields: {
summary: string;
description: string;
issuetype: {
name: string;
};
project: {
key: string;
};
};
} = {
fields: {
summary: payload.name,
description: '',
issuetype: {
name: 'Tech Debt',
},
project: {
key: 'FLAKY',
},
},
};

const responseIssue = await fetch(`${this.url}/rest/api/2/issue`, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${this.apiKey}`,
},
});

const issue = (await responseIssue.json()).key;

const { location } = test;

await fetch(`${this.url}/rest/api/2/issue/${issue}/comment`, {
method: 'POST',
body: JSON.stringify({
body: `Test run ${payload.run} failed
author: ${this.author}
PR: ${this.pr}
https://github.com/RocketChat/Rocket.Chat/blob/${payload.headSha}/${location.file.replace(
'/home/runner/work/Rocket.Chat/Rocket.Chat',
'',
)}#L${location.line}:${location.column},
${this.run_url}
`,
}),
headers: {
'Content-Type': 'application/json',
'Authorization': `Basic ${this.apiKey}`,
},
});
}
}

export default JIRAReporter;

0 comments on commit 1827e95

Please sign in to comment.