Skip to content

Commit 91c1d9f

Browse files
authored
Merge pull request #2 from SocketDev/bret/v1
2 parents 82061a5 + 7f2b741 commit 91c1d9f

File tree

7 files changed

+117
-13
lines changed

7 files changed

+117
-13
lines changed

index.js

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ const { default: Ajv } = require('ajv')
66
const { ErrorWithCause } = require('pony-cause')
77
const { parse: yamlParse } = require('yaml')
88

9+
const { socketYmlSchemaV1 } = require('./lib/v1')
10+
911
/**
1012
* @typedef SocketYmlGitHub
11-
* @property {boolean} [beta] beta opt in field
1213
* @property {boolean} [enabled] enable/disable the Socket.dev GitHub app entirely
1314
* @property {boolean} [projectReportsEnabled] enable/disable Github app project report checks
1415
* @property {boolean} [pullRequestAlertsEnabled] enable/disable GitHub app pull request alert checks
@@ -31,22 +32,21 @@ const socketYmlSchema = {
3132
projectIgnorePaths: {
3233
type: 'array',
3334
items: { type: 'string' },
34-
nullable: true,
35+
nullable: true
3536
},
3637
issueRules: {
3738
type: 'object',
3839
nullable: true,
3940
required: [],
40-
additionalProperties: { type: 'boolean' },
41+
additionalProperties: { type: 'boolean' }
4142
},
4243
githubApp: {
4344
type: 'object',
4445
nullable: true,
4546
properties: {
46-
beta: { type: 'boolean', nullable: true },
47-
enabled: { type: 'boolean', nullable: true },
48-
projectReportsEnabled: { type: 'boolean', nullable: true },
49-
pullRequestAlertsEnabled: { type: 'boolean', nullable: true },
47+
enabled: { type: 'boolean', nullable: true, default: true },
48+
projectReportsEnabled: { type: 'boolean', nullable: true, default: true },
49+
pullRequestAlertsEnabled: { type: 'boolean', nullable: true, default: true },
5050
},
5151
required: [],
5252
additionalProperties: false,
@@ -56,15 +56,27 @@ const socketYmlSchema = {
5656
additionalProperties: false,
5757
}
5858

59-
const ajv = new Ajv({
59+
const ajvOptions = /** @type {const} */ ({
6060
allErrors: true,
6161
coerceTypes: 'array',
6262
logger: false,
63+
useDefaults: true
64+
})
65+
66+
const ajv = new Ajv({
67+
...ajvOptions,
6368
removeAdditional: 'failing',
6469
})
6570

6671
const validate = ajv.compile(socketYmlSchema)
6772

73+
// We want to be strict and fail rather than removeAdditional when we parse a possible v1 config – only fallback to it when it actually matches well
74+
const ajvV1 = new Ajv({
75+
...ajvOptions
76+
})
77+
78+
const validateV1 = ajvV1.compile(socketYmlSchemaV1)
79+
6880
/**
6981
* @param {string} filePath
7082
* @returns {Promise<SocketYml|undefined>}
@@ -101,6 +113,13 @@ async function parseSocketConfig (fileContent) {
101113
throw new ErrorWithCause('Error when parsing socket.yml config', { cause: err })
102114
}
103115

116+
if (parsedContent && typeof parsedContent === 'object' && !('version' in parsedContent)) {
117+
const parsedV1 = await parseV1SocketConfig(parsedContent)
118+
if (parsedV1) {
119+
return parsedV1
120+
}
121+
}
122+
104123
if (!validate(parsedContent)) {
105124
throw new SocketValidationError(
106125
'Invalid config definition',
@@ -146,6 +165,29 @@ class SocketValidationError extends Error {
146165
}
147166
}
148167

168+
/**
169+
* @param {object} parsedV1Content
170+
* @returns {Promise<SocketYml | undefined>}
171+
*/
172+
async function parseV1SocketConfig (parsedV1Content) {
173+
if (!validateV1(parsedV1Content)) {
174+
return
175+
}
176+
177+
/** @type {SocketYml} */
178+
const v2 = {
179+
version: 2,
180+
projectIgnorePaths: parsedV1Content?.ignore ?? [],
181+
issueRules: parsedV1Content?.issues ?? {},
182+
githubApp: {
183+
enabled: parsedV1Content?.enabled,
184+
pullRequestAlertsEnabled: parsedV1Content?.pullRequestAlertsEnabled,
185+
projectReportsEnabled: parsedV1Content?.projectReportsEnabled
186+
}
187+
}
188+
return v2
189+
}
190+
149191
module.exports = {
150192
parseSocketConfig,
151193
readSocketConfig,

lib/v1.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
3+
/**
4+
* @typedef SocketYmlV1
5+
* @property {string[]} [ignore]
6+
* @property {{ [issueName: string]: boolean }} [issues]
7+
* @property {boolean} [beta] unused v1 option
8+
* @property {boolean} [enabled] enable/disable the Socket.dev GitHub app entirely
9+
* @property {boolean} [projectReportsEnabled] enable/disable Github app project report checks
10+
* @property {boolean} [pullRequestAlertsEnabled] enable/disable GitHub app pull request alert checks
11+
*/
12+
13+
/** @type {import('ajv').JSONSchemaType<SocketYmlV1>} */
14+
const socketYmlSchemaV1 = {
15+
$schema: 'http://json-schema.org/draft-07/schema#',
16+
type: 'object',
17+
properties: {
18+
ignore: {
19+
type: 'array',
20+
items: { type: 'string' },
21+
nullable: true,
22+
},
23+
issues: {
24+
type: 'object',
25+
nullable: true,
26+
required: [],
27+
additionalProperties: { type: 'boolean' },
28+
},
29+
beta: { type: 'boolean', nullable: true, default: true },
30+
enabled: { type: 'boolean', nullable: true, default: true },
31+
projectReportsEnabled: { type: 'boolean', nullable: true, default: true },
32+
pullRequestAlertsEnabled: { type: 'boolean', nullable: true, default: true },
33+
},
34+
minProperties: 1,
35+
additionalProperties: false,
36+
}
37+
38+
module.exports = {
39+
socketYmlSchemaV1
40+
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"index.js",
2222
"index.d.ts",
2323
"index.d.ts.map",
24-
"schema.json"
24+
"schema.json",
25+
"lib/*"
2526
],
2627
"scripts": {
2728
"build:0": "run-s clean",

test/parse.spec.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@ const {
1414
chai.use(chaiAsPromised)
1515
chai.should()
1616

17-
describe('readSocketConfig()', () => {
17+
describe('parseSocketConfig()', () => {
1818
it('should read and parse socket.yml', async () => {
1919
const fileContent = await readFile(path.resolve(__dirname, 'sample.yml'), 'utf8')
2020

2121
await parseSocketConfig(fileContent).should.eventually.become({
2222
'githubApp': {
23-
'beta': false,
2423
'enabled': true,
2524
'projectReportsEnabled': true,
2625
'pullRequestAlertsEnabled': true,
@@ -36,6 +35,24 @@ describe('readSocketConfig()', () => {
3635
})
3736
})
3837

38+
it('should read and parse socket.yml v1', async () => {
39+
const fileContent = await readFile(path.resolve(__dirname, 'sample-v1.yml'), 'utf8')
40+
41+
await parseSocketConfig(fileContent).should.eventually.become({
42+
'githubApp': {
43+
'enabled': true,
44+
'projectReportsEnabled': false,
45+
'pullRequestAlertsEnabled': true,
46+
},
47+
'issueRules': {},
48+
'projectIgnorePaths': [
49+
'foo',
50+
'bar',
51+
],
52+
'version': 2,
53+
})
54+
})
55+
3956
it('should throw on invalid document structure', async () => {
4057
await parseSocketConfig(`
4158
projectIgnorePaths: true

test/read.spec.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ describe('readSocketConfig()', () => {
1616
it('should read and parse socket.yml', async () => {
1717
await readSocketConfig(path.resolve(__dirname, 'sample.yml')).should.eventually.become({
1818
'githubApp': {
19-
'beta': false,
2019
'enabled': true,
2120
'projectReportsEnabled': true,
2221
'pullRequestAlertsEnabled': true,

test/sample-v1.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
ignore:
2+
- foo
3+
- bar
4+
projectReportsEnabled: false
5+
beta: true

test/sample.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ version: 2
22

33
projectIgnorePaths:
44
- workspaces/test*
5-
- '!workspaces/test-framework'
5+
- "!workspaces/test-framework"
66

77
issueRules:
88
unresolvedRequire: false

0 commit comments

Comments
 (0)