Skip to content

Commit 3655ac7

Browse files
authored
add Jest, switch to semver for compare, fix downgrade issue (#39)
* add Jest, fix downgrade issue * fix main workflow, add test workflow * switch to `semver`, improve sorting, add more complex test
1 parent 1d53f4d commit 3655ac7

File tree

18 files changed

+24417
-186
lines changed

18 files changed

+24417
-186
lines changed

.eslintrc.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
"es2021": true,
55
"node": true
66
},
7-
"plugins": ["prettier"],
7+
"plugins": ["jest", "prettier"],
88
"extends": [
99
"eslint:recommended",
10+
"plugin:jest/recommended",
1011
"plugin:prettier/recommended"
1112
],
1213
"parserOptions": {
@@ -20,5 +21,6 @@
2021
"prefer-const": "error",
2122
"quotes": ["error", "single"],
2223
"semi": ["error", "always"]
23-
}
24+
},
25+
"ignorePatterns": ["dist", "node_modules"]
2426
}

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ jobs:
1313
uses: ./
1414
with:
1515
token: ${{ secrets.GITHUB_TOKEN }}
16-
- name: Yarn Lock Changes Detached Package
16+
- name: '[Test] Yarn Lock Changes Detached Package'
1717
uses: ./
1818
with:
19-
path: tests/detached/yarn.lock
19+
path: tests/ci/yarn.lock
2020
token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/tests.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Run Tests
2+
on: [pull_request]
3+
4+
jobs:
5+
check:
6+
runs-on: ubuntu-latest
7+
steps:
8+
- uses: actions/checkout@v2
9+
- uses: actions/setup-node@v2
10+
with:
11+
node-version: '14'
12+
- run: yarn
13+
- run: yarn test

babel.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
presets: [['@babel/preset-env', { targets: { node: 'current' } }]]
3+
};

dist/index.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jest.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
transformIgnorePatterns: ['<rootDir>/node_modules/*']
3+
};

package.json

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,28 @@
77
"license": "MIT",
88
"scripts": {
99
"compile": "ncc build ./src/action.js -m",
10-
"lint": "eslint ./src",
11-
"optimize": "svgo -f ./assets"
10+
"lint": "eslint .",
11+
"optimize": "svgo -f ./assets",
12+
"test": "jest"
1213
},
1314
"dependencies": {
14-
"@actions/core": "^1.4.0",
15+
"@actions/core": "^1.5.0",
1516
"@actions/github": "^5.0.0",
1617
"@yarnpkg/lockfile": "^1.1.0",
17-
"compare-versions": "^3.6.0",
1818
"js-base64": "^3.6.1",
19-
"markdown-table": "^3.0.1"
19+
"markdown-table": "^3.0.1",
20+
"semver": "^7.3.5"
2021
},
2122
"devDependencies": {
23+
"@babel/core": "^7.15.0",
24+
"@babel/preset-env": "^7.15.0",
25+
"babel-jest": "^27.0.6",
2226
"eslint": "^7.32.0",
2327
"eslint-config-prettier": "^8.3.0",
24-
"eslint-plugin-prettier": "^3.4.0",
28+
"eslint-plugin-jest": "^24.4.0",
29+
"eslint-plugin-prettier": "^3.4.1",
30+
"jest": "^27.0.6",
2531
"prettier": "^2.3.2",
26-
"svgo": "^2.3.1"
32+
"svgo": "^2.4.0"
2733
}
2834
}

src/action.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const fs = require('fs');
55
const { Base64 } = require('js-base64');
66
const path = require('path');
77

8-
const { STATUS, countStatuses, createTable, createSummary, diffLocks } = require('./utils');
8+
const { STATUS, countStatuses, diffLocks } = require('./utils');
9+
const { createTable, createSummary } = require('./comment');
910

1011
const getCommentId = async (octokit, oktokitParams, issueNumber, commentHeader) => {
1112
const currentComments = await octokit.rest.issues.listComments({

src/comment.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const { markdownTable } = require('markdown-table');
2+
3+
const { STATUS, countStatuses } = require('./utils');
4+
5+
const ASSETS_URL = {
6+
ADDED: 'https://git.io/J38HP',
7+
DOWNGRADED: 'https://git.io/J38ds',
8+
REMOVED: 'https://git.io/J38dt',
9+
UPDATED: 'https://git.io/J38dY'
10+
};
11+
12+
const getStatusLabel = status =>
13+
`[<sub><img alt="${status}" src="${ASSETS_URL[status]}" height="16" /></sub>](#)`;
14+
15+
export const createTable = (lockChanges, plainStatuses = false) =>
16+
markdownTable(
17+
[
18+
['Name', 'Status', 'Previous', 'Current'],
19+
...Object.entries(lockChanges)
20+
.map(([key, { status, previous, current }]) => [
21+
'`' + key + '`',
22+
plainStatuses ? status : getStatusLabel(status),
23+
previous,
24+
current
25+
])
26+
.sort((a, b) => a[0].localeCompare(b[0]))
27+
],
28+
{ align: ['l', 'c', 'c', 'c'], alignDelimiters: false }
29+
);
30+
31+
const createSummaryRow = (lockChanges, status) => {
32+
const statusCount = countStatuses(lockChanges, status);
33+
return statusCount ? [getStatusLabel(status), statusCount] : undefined;
34+
};
35+
36+
export const createSummary = lockChanges =>
37+
markdownTable(
38+
[
39+
['Status', 'Count'],
40+
createSummaryRow(lockChanges, STATUS.ADDED),
41+
createSummaryRow(lockChanges, STATUS.UPDATED),
42+
createSummaryRow(lockChanges, STATUS.DOWNGRADED),
43+
createSummaryRow(lockChanges, STATUS.REMOVED)
44+
].filter(Boolean),
45+
{ align: ['l', 'c'], alignDelimiters: false }
46+
);

src/utils.js

Lines changed: 22 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
1-
const compareVersions = require('compare-versions');
2-
const { markdownTable } = require('markdown-table');
3-
4-
const ASSETS_URL = {
5-
ADDED: 'https://git.io/J38HP',
6-
DOWNGRADED: 'https://git.io/J38ds',
7-
REMOVED: 'https://git.io/J38dt',
8-
UPDATED: 'https://git.io/J38dY'
9-
};
1+
const semverCompare = require('semver/functions/compare');
2+
const semverCoerce = require('semver/functions/coerce');
3+
const semverValid = require('semver/functions/valid');
104

115
export const STATUS = {
126
ADDED: 'ADDED',
@@ -15,52 +9,31 @@ export const STATUS = {
159
UPDATED: 'UPDATED'
1610
};
1711

18-
const getStatusLabel = status =>
19-
`[<sub><img alt="${status}" src="${ASSETS_URL[status]}" height="16" /></sub>](#)`;
20-
21-
export const createTable = (lockChanges, plainStatuses = false) =>
22-
markdownTable(
23-
[
24-
['Name', 'Status', 'Previous', 'Current'],
25-
...Object.entries(lockChanges)
26-
.map(([key, { status, previous, current }]) => [
27-
'`' + key + '`',
28-
plainStatuses ? status : getStatusLabel(status),
29-
previous,
30-
current
31-
])
32-
.sort((a, b) => a[0].localeCompare(b[0]))
33-
],
34-
{ align: ['l', 'c', 'c', 'c'], alignDelimiters: false }
35-
);
36-
3712
export const countStatuses = (lockChanges, statusToCount) =>
3813
Object.values(lockChanges).filter(({ status }) => status === statusToCount).length;
3914

40-
const createSummaryRow = (lockChanges, status) => {
41-
const statusCount = countStatuses(lockChanges, status);
42-
return statusCount ? [getStatusLabel(status), statusCount] : undefined;
43-
};
15+
const formatForNameCompare = key => key.substr(0, key.lastIndexOf('@'));
4416

45-
export const createSummary = lockChanges =>
46-
markdownTable(
47-
[
48-
['Status', 'Count'],
49-
createSummaryRow(lockChanges, STATUS.ADDED),
50-
createSummaryRow(lockChanges, STATUS.UPDATED),
51-
createSummaryRow(lockChanges, STATUS.DOWNGRADED),
52-
createSummaryRow(lockChanges, STATUS.REMOVED)
53-
].filter(Boolean),
54-
{ align: ['l', 'c'], alignDelimiters: false }
55-
);
17+
const formatForVersionCompare = key => {
18+
const version = key.substr(key.lastIndexOf('@') + 1);
19+
return semverValid(semverCoerce(version)) || '0.0.0';
20+
};
5621

5722
const formatLockEntry = obj =>
5823
Object.fromEntries(
59-
Object.keys(obj.object).map(key => {
60-
const nameParts = key.split('@');
61-
const name = nameParts[0] === '' ? '@' + nameParts[1] : nameParts[0];
62-
return [name, { name, version: obj.object[key].version }];
63-
})
24+
Object.keys(obj.object)
25+
.sort((a, b) => {
26+
const nameCompare = formatForNameCompare(a).localeCompare(formatForNameCompare(b));
27+
if (nameCompare === 0) {
28+
return semverCompare(formatForVersionCompare(a), formatForVersionCompare(b));
29+
}
30+
return nameCompare;
31+
})
32+
.map(key => {
33+
const nameParts = key.split('@');
34+
const name = nameParts[0] === '' ? '@' + nameParts[1] : nameParts[0];
35+
return [name, { name, version: obj.object[key].version }];
36+
})
6437
);
6538

6639
export const diffLocks = (previous, current) => {
@@ -88,7 +61,7 @@ export const diffLocks = (previous, current) => {
8861
delete changes[key];
8962
} else {
9063
changes[key].current = currentPackages[key].version;
91-
if (compareVersions(changes[key].previous, changes[key].current) === 1) {
64+
if (semverCompare(changes[key].previous, changes[key].current) === 1) {
9265
changes[key].status = STATUS.DOWNGRADED;
9366
} else {
9467
changes[key].status = STATUS.UPDATED;

0 commit comments

Comments
 (0)