Skip to content

Commit b1720d4

Browse files
authored
feat: add duplicate keys rule (#179)
* feat: add duplicate keys rule * test names * update README.md * fix main * test * chore: comitting generated dist * fix * chore: comitting generated dist --------- Co-authored-by: danadajian <danadajian@users.noreply.github.com>
1 parent ebc901b commit b1720d4

File tree

13 files changed

+217
-25
lines changed

13 files changed

+217
-25
lines changed

.github/workflows/test.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,5 @@ jobs:
5858
rules: |
5959
ranges
6060
tags
61+
resolutions
62+
keys

README.md

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
A Github Action for validating package.json conventions.
66

7-
## Usage
7+
## Rules
88

99
Use the `rules` input to specify one or more rules you would like to check for your `package.json`.
1010

@@ -16,7 +16,7 @@ The following usage would allow `"my-package": "1.2.3"` but prevent `"my-package
1616
```yaml
1717
steps:
1818
- name: Checkout
19-
uses: actions/checkout@v2
19+
uses: actions/checkout@v3
2020

2121
- uses: ExpediaGroup/package-json-validator@v1
2222
with:
@@ -27,7 +27,7 @@ You can also specify `allowed-ranges`. The following would allow `"my-package":
2727
```yaml
2828
steps:
2929
- name: Checkout
30-
uses: actions/checkout@v2
30+
uses: actions/checkout@v3
3131
3232
- uses: ExpediaGroup/package-json-validator@v1
3333
with:
@@ -43,7 +43,7 @@ The following usage would allow `"my-package": "1.2.3"` but prevent `"my-package
4343
```yaml
4444
steps:
4545
- name: Checkout
46-
uses: actions/checkout@v2
46+
uses: actions/checkout@v3
4747
4848
- uses: ExpediaGroup/package-json-validator@v1
4949
with:
@@ -55,19 +55,57 @@ The following usage would allow `"my-package": "1.2.3-canary.456.0"` but prevent
5555
```yaml
5656
steps:
5757
- name: Checkout
58-
uses: actions/checkout@v2
58+
uses: actions/checkout@v3
5959
6060
- uses: ExpediaGroup/package-json-validator@v1
6161
with:
6262
rules: tags
6363
allowed-tags: canary
6464
```
6565

66+
### Resolutions
67+
The "resolutions" rule validates that your package.json does not contain the `resolutions` option.
68+
69+
```yaml
70+
steps:
71+
- name: Checkout
72+
uses: actions/checkout@v3
73+
74+
- uses: ExpediaGroup/package-json-validator@v1
75+
with:
76+
rules: resolutions
77+
```
78+
79+
### Keys
80+
The "keys" rule validates that your package.json does not contain duplicate dependency keys.
81+
82+
```yaml
83+
steps:
84+
- name: Checkout
85+
uses: actions/checkout@v3
86+
87+
- uses: ExpediaGroup/package-json-validator@v1
88+
with:
89+
rules: keys
90+
```
91+
92+
Example invalid package.json this will prevent:
93+
```json
94+
{
95+
"dependencies": {
96+
"some-dependency": "1.0.0",
97+
"some-dependency": "2.0.0"
98+
}
99+
}
100+
```
101+
102+
## Other Inputs
103+
66104
Specify `dependency-types` to denote which type of package.json dependencies you wish to validate. Valid options include `dependencies`, `devDependencies`, `peerDependencies`, and `optionalDependencies`. Defaults to `dependencies`.
67105
```yaml
68106
steps:
69107
- name: Checkout
70-
uses: actions/checkout@v2
108+
uses: actions/checkout@v3
71109
72110
- uses: ExpediaGroup/package-json-validator@v1
73111
with:
@@ -79,7 +117,7 @@ Specify `ignore-packages` to skip validation entirely for certain packages. Opti
79117
```yaml
80118
steps:
81119
- name: Checkout
82-
uses: actions/checkout@v2
120+
uses: actions/checkout@v3
83121
84122
- uses: ExpediaGroup/package-json-validator@v1
85123
with:
@@ -92,7 +130,7 @@ You may also enforce multiple rules (and pass additional inputs) like this:
92130
```yaml
93131
steps:
94132
- name: Checkout
95-
uses: actions/checkout@v2
133+
uses: actions/checkout@v3
96134
97135
- uses: ExpediaGroup/package-json-validator@v1
98136
with:

dist/index.js

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

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,39 +17,46 @@ import { readFileSync } from 'fs';
1717
import { validateVersionRanges } from './rules/ranges';
1818
import { validateVersionTags } from './rules/tags';
1919
import { validateResolutions } from './rules/resolutions';
20+
import { validateKeys } from './rules/keys';
2021

2122
type GithubError = {
2223
status: number;
2324
message: string;
2425
};
2526

27+
const pathToPackageJson = './package.json';
28+
2629
export const RULES_MAP: {
2730
[key: string]: {
2831
method: Function;
29-
extraInputName?: string;
32+
extraInput?: string;
3033
};
3134
} = {
3235
ranges: {
3336
method: validateVersionRanges,
34-
extraInputName: 'allowed-ranges'
37+
extraInput: 'allowed-ranges'
3538
},
3639
tags: {
3740
method: validateVersionTags,
38-
extraInputName: 'allowed-tags'
41+
extraInput: 'allowed-tags'
3942
},
4043
resolutions: {
4144
method: validateResolutions
45+
},
46+
keys: {
47+
method: validateKeys,
48+
extraInput: pathToPackageJson
4249
}
4350
};
4451

4552
export const run = () => {
4653
try {
47-
const packageJson: PackageJson = JSON.parse(readFileSync('./package.json').toString());
54+
const packageJson: PackageJson = JSON.parse(readFileSync(pathToPackageJson).toString());
4855

4956
const rules = core.getMultilineInput('rules', { required: true });
5057
rules.forEach(rule => {
51-
const { method, extraInputName } = RULES_MAP[rule];
52-
method(packageJson, extraInputName);
58+
const { method, extraInput } = RULES_MAP[rule];
59+
method(packageJson, extraInput);
5360
});
5461
} catch (error) {
5562
core.setFailed((error as GithubError).message);

src/rules/keys.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
Copyright 2021 Expedia, Inc.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
https://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
import * as core from '@actions/core';
15+
import { readFileSync } from 'fs';
16+
import { PackageJson } from 'type-fest';
17+
import { getDependencies } from '../utils/get-dependencies';
18+
19+
export const validateKeys = (packageJson: PackageJson, packageJsonPath: string) => {
20+
const dependencies = getDependencies(packageJson);
21+
Object.keys(dependencies).forEach(dependency => {
22+
const stringifiedPackageJson = readFileSync(packageJsonPath).toString();
23+
const regexMatches = stringifiedPackageJson.match(new RegExp(dependency, 'g'));
24+
if (regexMatches && regexMatches.length > 1) {
25+
core.setFailed(`Duplicate keys found in package.json: ${regexMatches}`);
26+
}
27+
});
28+
};

src/rules/resolutions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { PackageJson } from 'type-fest';
1717
export const validateResolutions = (packageJson: PackageJson) => {
1818
if (packageJson.resolutions) {
1919
core.setFailed(
20-
'Resolutions may not be set. Please investigate the root cause your dependency issues!'
20+
'Resolutions may not be set. Please investigate the root cause of your dependency issues!'
2121
);
2222
}
2323
};

test/fixtures/deduped-package.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"dependencies": {
3+
"some-dependency": "1.0.0",
4+
"some-other-dependency": "2.0.0"
5+
},
6+
"devDependencies": {
7+
"some-dev-dependency": "2.0.0"
8+
}
9+
}

test/fixtures/duped-package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"dependencies": {
3+
"some-dependency": "1.0.0",
4+
"some-dependency": "2.0.0"
5+
}
6+
}

test/fixtures/duped-package2.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"dependencies": {
3+
"some-dependency": "1.0.0",
4+
"some-other-dependency": "2.0.0"
5+
},
6+
"devDependencies": {
7+
"some-dependency": "2.0.0"
8+
}
9+
}

0 commit comments

Comments
 (0)