Skip to content
This repository has been archived by the owner on Aug 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #126 from indeedeng/displayProjectLanguages
Browse files Browse the repository at this point in the history
Display project languages
  • Loading branch information
IngridGdesigns authored Jul 7, 2022
2 parents b7a3ca1 + ed4a598 commit 1c4a97c
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 61 deletions.
79 changes: 49 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ You'll also need a GitHub token and a config file. (Keep reading for more info o
1. Run `npm install oss-mariner`
1. Add `"type": "module"` to `package.json` to allow using "import" rather than "require".
1. Get a GitHub token. [See instructions here](https://github.com/indeedeng/Mariner#token)
1. Store your GitHub token in your system's environment by running `export MARINER_GITHUB_TOKEN={Insert your GitHub token here}`. You will either have to do this once each time you restart your system, or else configure your system to do so automatically.
1. Store your GitHub token in your system's environment by running `export MARINER_GITHUB_TOKEN={Insert your GitHub token here}`. You will either have to do this once each time you restart your system, or else configure your system to do so automatically.
1. Finally, run the application to find open issues in your dependencies, using the command `node index.js`.

### Optional: Generating HTML
Expand All @@ -64,58 +64,74 @@ You'll also need a GitHub token and a config file. (Keep reading for more info o
```html
<h3 class="dependency-name">facebook/jest</h3>
<table class="issue-list">
<tr class="issue-header-row"><th>Title</th><th>Age</th></tr>
<tr class="issue-row">
<td class="issue-title"><a href="https://github.com/facebook/jest/issues/12522">Rework asynchronous tests documentation</a></td>
<td class="issue-age">15&nbsp;days</td>
</tr>
<tr class="issue-row">
<td class="issue-title"><a href="https://github.com/facebook/jest/issues/12495">Use Admonitions on website</a></td>
<td class="issue-age">22&nbsp;days</td>
</tr>
<tr class="issue-row">
<td class="issue-title"><a href="https://github.com/facebook/jest/issues/12592">[Bug]: test `notify › does not report --notify flag` is flaky</a></td>
<td class="issue-age">17&nbsp;days</td>
</tr>
<tr class="issue-header-row">
<th>Title</th>
<th>Age</th>
</tr>
<tr class="issue-row">
<td class="issue-title">
<a href="https://github.com/facebook/jest/issues/12522"
>Rework asynchronous tests documentation</a>
</td>
<td class="issue-age">15&nbsp;days</td>
<td class="issue-languages">JavaScript,CSS,Shell,Handlebars,Prolog</td>
</tr>
<tr class="issue-row">
<td class="issue-title">
<a href="https://github.com/facebook/jest/issues/12495">Use Admonitions on website</a>
</td>
<td class="issue-age">22&nbsp;days</td>
<td class="issue-languages">JavaScript,CSS,TypeScript,Shell,Handlebars,Prolog</td>
</tr>
<tr class="issue-row">
<td class="issue-title">
<a href="https://github.com/facebook/jest/issues/12592"
>[Bug]: test `notify › does not report --notify flag` is flaky</a
>
</td>
<td class="issue-age">17&nbsp;days</td>
<td class="issue-languages">JavaScript,CSS,TypeScript,Shell,Handlebars,Prolog</td>
</tr>
</table>
```

### Optional: Generating Markup

- You can generate markup for use in Confluence/jira
- The `generateConfluenceMarkup()` creates the markup based on two parameters: `maxIssuesAge` and `issuesByDependency`
- `maxIssueAge` defaults to 30 days, anything over 30 days won't get written, You can edit this number.
- Square brackets and curly braces in issue titles will be replaced by parentheses.
- Example of confluenceMarkup output:
- You can generate markup for use in Confluence/jira
- The `generateConfluenceMarkup()` creates the markup based on two parameters: `maxIssuesAge` and `issuesByDependency`
- `maxIssueAge` defaults to 30 days, anything over 30 days won't get written, You can edit this number.
- Square brackets and curly braces in issue titles will be replaced by parentheses.
- Example of confluenceMarkup output:

```md
h2. Updated: February 22, 2021, 5:38 PM PST

h3. babel/babel
||*Title*||*Age*||
|[all the core-js imports are removed|https://github.com/babel/babel/issues/12545]|62&nbsp;days|

||_Title_||_Age_||_Languages_||
|[all the core-js imports are removed|https://github.com/babel/babel/issues/12545]|62&nbsp;days|Javascript|

h3. facebook/jest
||*Title*||*Age*||
|[Lost of context between tests when using dynamic ESM import|https://github.com/facebook/jest/issues/10944]|72&nbsp;days|
||_Title_||_Age_||_Languages_||
|[Lost of context between tests when using dynamic ESM import|https://github.com/facebook/jest/issues/10944]|72&nbsp;days|Typescript, Javascript|
```

### Optional: Generating Markdown
- You can generate markdown for use in GitHub
- The `generateGitHubMarkdown()` creates the markdown based on two parameters: `maxIssuesAge` and `issuesByDependency`
- `maxIssueAge` defaults to 30 days, anything over 30 days won't get written, You can edit this number.
- Example of GitHub markdown output:

- You can generate markdown for use in GitHub
- The `generateGitHubMarkdown()` creates the markdown based on two parameters: `maxIssuesAge` and `issuesByDependency`
- `maxIssueAge` defaults to 30 days, anything over 30 days won't get written, You can edit this number.
- Example of GitHub markdown output:

```md
## Updated: 2022-01-18T22:53:35.522Z

### babel/babel

|**Title**|**Age**|
|:----|:----|
|[[Bug]: Typescript plugin fails on named tuple positions where the name is a reserved word in JS|https://github.com/babel/babel/issues/13702]|147&nbsp;days|
|[[Bug]: Typescript plugin fails on named tuple positions where the name is a reserved word in JS|https://github.com/babel/babel/issues/13702]|147&nbsp;days|Typescript|
|[[preset-env] all the core-js imports are removed|https://github.com/babel/babel/issues/12545]|392&nbsp;days|
|[[Bug]: TypeError: Error while loading config - yield* (intermediate value) is not iterable|https://github.com/babel/babel/issues/13462]|218&nbsp;days|
| [[Bug]: TypeError: Error while loading config - yield\* (intermediate value) is not iterable|https://github.com/babel/babel/issues/13462]|218&nbsp;days|Typescript|
```

### Config.json Format
Expand Down Expand Up @@ -151,6 +167,7 @@ The output file is a JSON file in the format:
"title": "Issue Title 1",
"createdAt": "2020-10-16T01:07:36Z",
"repositoryNameWithOwner": "repository/name",
"languages": ["JavaScript", "TypeScript", "CSS"],
"url": "https://github.com/repository/name/issues/65",
"updatedAt": "2020-10-16T01:07:36Z",
"labels": [
Expand All @@ -162,6 +179,7 @@ The output file is a JSON file in the format:
"title": "Issue Title 2",
"createdAt": "2020-10-12T22:37:17Z",
"repositoryNameWithOwner": "repository/name",
"languages": ["JavaScript"],
"url": "https://github.com/repository/name/issues/58",
"updatedAt": "2020-10-12T22:37:17Z",
"labels": [
Expand All @@ -175,6 +193,7 @@ The output file is a JSON file in the format:
"title": "Issue 102",
"createdAt": "2020-10-03T13:16:58Z",
"repositoryNameWithOwner": "respository/second_name",
"languages": ["JavaScript", "Rust"],
"url": "https://github.com/respository/second_name/issues/12137",
"updatedAt": "2020-10-03T13:16:58Z",
"labels": [
Expand Down
7 changes: 4 additions & 3 deletions src/Utilities/generateConfluenceMarkup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,14 @@ export function generateConfluenceMarkup(

markupArray.push('\n');
markupArray.push(`h3. ${dependency}`);
markupArray.push('||*Title*||*Age*||');
markupArray.push('||*Title*||*Age*||*Languages*||');

relevantIssues.forEach((issue) => {
const ageInWholeDays = calculateAgeInWholeDays(issue.createdAt, now);

const cleanedTitleMarkup = removeBracesAndBrackets(issue.title);
markupArray.push(`|[${cleanedTitleMarkup}|${issue.url}]|${ageInWholeDays}&nbsp;days|`);
markupArray.push(
`|[${cleanedTitleMarkup}|${issue.url}]|${ageInWholeDays}&nbsp;days|${issue.languages}|`
);
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/Utilities/generateGitHubMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ export function generateGitHubMarkdown(

markdownArray.push('\n');
markdownArray.push(`### ${dependency}`);
markdownArray.push('|**Title**|**Age**|');
markdownArray.push('|**Title**|**Age**|**Languages**|');
markdownArray.push('|:----|:----|');

relevantIssues.forEach((issue) => {
const ageInWholeDays = calculateAgeInWholeDays(issue.createdAt, now);
const cleanTitleMarkdown = removeBracesAndBrackets(issue.title);
markdownArray.push(
`|[${cleanTitleMarkdown}|${issue.url}]|${ageInWholeDays}&nbsp;days|`
`|[${cleanTitleMarkdown}|${issue.url}]|${ageInWholeDays}&nbsp;days|${issue.languages}|`
);
});
}
Expand Down
5 changes: 4 additions & 1 deletion src/Utilities/generateHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ function generateHtmlFragmentsForDependency(
const encodedDependencyName = encode(dependencyName);
arrayOfHtmlFragments.push(`<h3 class="dependency-name">${encodedDependencyName}</h3>`);
arrayOfHtmlFragments.push('<table class="issue-list">');
arrayOfHtmlFragments.push('<tr class="issue-header-row"><th>Title</th><th>Age</th></tr>');
arrayOfHtmlFragments.push(
'<tr class="issue-header-row"><th>Title</th><th>Age</th><th>Languages</th></tr>'
);

relevantIssues.forEach((issue) => {
const ageInWholeDays = calculateAgeInWholeDays(issue.createdAt, now);
Expand All @@ -54,6 +56,7 @@ function generateHtmlFragmentsForDependency(
arrayOfHtmlFragments.push('<tr class="issue-row">');
arrayOfHtmlFragments.push(`<td class="issue-title"><a href="${url}">${title}</a></td>`);
arrayOfHtmlFragments.push(`<td class="issue-age">${ageInWholeDays}&nbsp;days</td>`);
arrayOfHtmlFragments.push(`<td class="issue-languages">${issue.languages}</td>`);
arrayOfHtmlFragments.push('</tr>');
});

Expand Down
35 changes: 24 additions & 11 deletions src/__tests__/generateConfluenceMarkup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const fakeIssues: Issue[] = [
url: 'https://github.com/bc/typescript/issues/30',
updatedAt: '',
labels: ['help wanted', 'documentation'],
languages: ['JavaScript', 'Typescript', 'Python'],
},

{
Expand All @@ -22,6 +23,7 @@ const fakeIssues: Issue[] = [
url: 'https://github.com/material-ui/issues/24',
updatedAt: '',
labels: ['good first issue', 'help wanted', 'documentation'],
languages: ['JavaScript', 'CSS', 'Shell'],
},
];

Expand All @@ -33,6 +35,7 @@ const singleIssue: Issue[] = [
url: 'https://github.com/marmelab/react-admin/issues/5620',
updatedAt: twoDaysAgo,
labels: ['good first issue', 'documentation'],
languages: ['Typescript', 'JavaScript'],
},
];

Expand All @@ -45,7 +48,7 @@ describe('generateConfluenceMarkup function', () => {
const oneDependencyNoIssue = issuesByDependency.set(dependency, noIssues);
const results = mariner.generateConfluenceMarkup(oneDependencyNoIssue);
expect(results).not.toContain(dependency);
expect(results).not.toContain('||*Title*||*Age*||');
expect(results).not.toContain('||*Title*||*Age*||*Languages*||');
expect(results).not.toContain('days');
});

Expand All @@ -56,8 +59,12 @@ describe('generateConfluenceMarkup function', () => {
const twoIssues = mockDependencyMap.set(dependency, fakeIssues);
const results = mariner.generateConfluenceMarkup(twoIssues);

expect(results).toContain(`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|`);
expect(results).toContain(`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|`);
expect(results).toContain(
`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|${fakeIssues[0].languages}|`
);
expect(results).toContain(
`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|${fakeIssues[1].languages}`
);
});
it('should include both dependencies that have issues', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
Expand All @@ -70,13 +77,19 @@ describe('generateConfluenceMarkup function', () => {
const results = mariner.generateConfluenceMarkup(mockDependencyMap);

expect(results).toContain(`h3. ${dependency1}`);
expect(results).toContain('||*Title*||*Age*||');
expect(results).toContain(`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|`);
expect(results).toContain(`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|`);
expect(results).toContain('||*Title*||*Age*||*Languages*||');
expect(results).toContain(
`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|${fakeIssues[0].languages}|`
);
expect(results).toContain(
`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|${fakeIssues[1].languages}|`
);

expect(results).toContain(`h3. ${dependency2}`);
expect(results).toContain('||*Title*||*Age*||');
expect(results).toContain(`|[${singleIssue[0].title}|${singleIssue[0].url}]|8&nbsp;days|`);
expect(results).toContain('||*Title*||*Age*||*Languages*||');
expect(results).toContain(
`|[${singleIssue[0].title}|${singleIssue[0].url}]|8&nbsp;days|${singleIssue[0].languages}`
);
});
it('should remove curly braces and square brackets from an issue title', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
Expand All @@ -87,7 +100,7 @@ describe('generateConfluenceMarkup function', () => {
const results = mariner.generateConfluenceMarkup(mockDependencyMap);
expect(results).not.toContain(singleIssue[0].title);
expect(results).toMatch(
`|[(Navigation Editor) Dropdown menus too narrow ()|${singleIssue[0].url}]|8&nbsp;days|`
`|[(Navigation Editor) Dropdown menus too narrow ()|${singleIssue[0].url}]|8&nbsp;days|${singleIssue[0].languages}`
);
});
it('should return correct markup for a dependency and an issue', () => {
Expand All @@ -100,7 +113,7 @@ describe('generateConfluenceMarkup function', () => {
mockDependencyMap.set(dependency, singleIssue);
const results = mariner.generateConfluenceMarkup(mockDependencyMap);
expect(results).toContain(`h3. ${dependency}`);
expect(results).toContain('||*Title*||*Age*||');
expect(results).toContain('||*Title*||*Age*||*Languages*||');
expect(results).toContain(`|[${singleIssue[0].title}|${singleIssue[0].url}]|`);
expect(results).toContain(`|${ageInWholeDays}&nbsp;days|`);
});
Expand All @@ -113,7 +126,7 @@ describe('generateConfluenceMarkup function', () => {
const results = mariner.generateConfluenceMarkup(mockDependencyMap);

expect(results).not.toContainEqual(`h3. ${dependency}`);
expect(results).not.toContainEqual('\n||*Title*||*Age*||');
expect(results).not.toContainEqual('\n||*Title*||*Age*||*Languages*||');
expect(results).not.toContainEqual(singleIssue[0].title);
});
});
Expand Down
37 changes: 26 additions & 11 deletions src/__tests__/generateGitHubMarkdown.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const fakeIssues: Issue[] = [
url: 'https://github.com/moment/luxon/issues/1107',
updatedAt: '',
labels: ['help wanted', 'enhancement'],
languages: ['Javascript', 'Typescript'],
},

{
Expand All @@ -22,6 +23,7 @@ const fakeIssues: Issue[] = [
url: 'https://github.com/expressjs/express/issues/4769',
updatedAt: '',
labels: ['good first issue', 'help wanted', 'question'],
languages: ['Javascript', 'Python'],
},
];

Expand All @@ -33,6 +35,7 @@ const singleIssue: Issue[] = [
url: 'https://github.com/sinonjs/sinon/issues/1898',
updatedAt: twoDaysAgo,
labels: ['good first issue', 'documentation', 'help wanted'],
languages: ['Javascript'],
},
];

Expand All @@ -45,7 +48,7 @@ describe('generateGithubMarkdown function', () => {
const oneDependencyNoIssue = issuesByDependency.set(dependency, noIssues);
const results = mariner.generateGitHubMarkdown(oneDependencyNoIssue);
expect(results).not.toContain(dependency);
expect(results).not.toContain('||*Title*||*Age*||');
expect(results).not.toContain('||*Title*||*Age*||*Languages*||');
expect(results).not.toContain('days');
});

Expand All @@ -56,8 +59,12 @@ describe('generateGithubMarkdown function', () => {
const twoIssues = mockDependencyMap.set(dependency, fakeIssues);
const results = mariner.generateGitHubMarkdown(twoIssues);

expect(results).toContain(`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|`);
expect(results).toContain(`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|`);
expect(results).toContain(
`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|${fakeIssues[0].languages}|`
);
expect(results).toContain(
`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|${fakeIssues[1].languages}|`
);
});
it('should include both dependencies that have issues', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
Expand All @@ -70,13 +77,19 @@ describe('generateGithubMarkdown function', () => {
const results = mariner.generateGitHubMarkdown(mockDependencyMap);

expect(results).toContain(`### ${dependency1}`);
expect(results).toContain('|**Title**|**Age**|');
expect(results).toContain(`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|`);
expect(results).toContain(`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|`);
expect(results).toContain('|**Title**|**Age**|**Languages**|');
expect(results).toContain(
`|[${fakeIssues[0].title}|${fakeIssues[0].url}]|8&nbsp;days|${fakeIssues[0].languages}|`
);
expect(results).toContain(
`|[${fakeIssues[1].title}|${fakeIssues[1].url}]|8&nbsp;days|${fakeIssues[1].languages}|`
);

expect(results).toContain(`### ${dependency2}`);
expect(results).toContain('|**Title**|**Age**|');
expect(results).toContain(`|[${singleIssue[0].title}|${singleIssue[0].url}]|8&nbsp;days|`);
expect(results).toContain('|**Title**|**Age**|**Languages**');
expect(results).toContain(
`|[${singleIssue[0].title}|${singleIssue[0].url}]|8&nbsp;days|${singleIssue[0].languages}|`
);
});
it('should remove curly braces and square brackets from an issue title', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
Expand All @@ -90,7 +103,7 @@ describe('generateGithubMarkdown function', () => {
`|[(Navigation Editor) Dropdown menus too narrow ()|${singleIssue[0].url}]|8&nbsp;days|`
);
});
it('should return correct markup for a dependency and an issue', () => {
it('should return correct markdown for a dependency and an issue', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
const dependency = 'OSS';
singleIssue[0].title = 'Fixed interface';
Expand All @@ -100,9 +113,10 @@ describe('generateGithubMarkdown function', () => {
mockDependencyMap.set(dependency, singleIssue);
const results = mariner.generateGitHubMarkdown(mockDependencyMap);
expect(results).toContain(`### ${dependency}`);
expect(results).toContain('|**Title**|**Age**|');
expect(results).toContain('|**Title**|**Age**|**Languages**|');
expect(results).toContain(`|[${singleIssue[0].title}|${singleIssue[0].url}]|`);
expect(results).toContain(`|${ageInWholeDays}&nbsp;days|`);
expect(results).toContain(`|${singleIssue[0].languages}|`);
});
it('should not list a dependency with no issues if its issue is too old', () => {
const mockDependencyMap: Map<string, Issue[]> = new Map();
Expand All @@ -116,7 +130,8 @@ describe('generateGithubMarkdown function', () => {
const results = mariner.generateGitHubMarkdown(mockDependencyMap);
expect(results).toContain(`## Updated: ${date}`);
expect(results).not.toContainEqual(`### ${dependency}`);
expect(results).not.toContainEqual('\n|**Title**|**Age**|');
expect(results).not.toContainEqual('\n|**Title**|**Age**|**Languages**|');
expect(results).not.toContainEqual(singleIssue[0].title);
expect(results).not.toContainEqual(singleIssue[0].languages);
});
});
Loading

0 comments on commit 1c4a97c

Please sign in to comment.