@lvce-editor/eslint-plugin-github-actions 15.4.0 → 16.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +184 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,15 +14,15 @@ const platforms = {
|
|
|
14
14
|
windows: 'windows'
|
|
15
15
|
};
|
|
16
16
|
const actions = {
|
|
17
|
-
'actions/cache': ['actions/cache@
|
|
18
|
-
'actions/checkout': ['actions/checkout@
|
|
17
|
+
'actions/cache': ['actions/cache@v6'],
|
|
18
|
+
'actions/checkout': ['actions/checkout@v7'],
|
|
19
19
|
'actions/create-release': ['actions/create-release@v1'],
|
|
20
|
-
'actions/deploy-pages': ['actions/deploy-pages@
|
|
21
|
-
'actions/download-artifact': ['actions/download-artifact@
|
|
20
|
+
'actions/deploy-pages': ['actions/deploy-pages@v5'],
|
|
21
|
+
'actions/download-artifact': ['actions/download-artifact@v8'],
|
|
22
22
|
'actions/setup-node': ['actions/setup-node@v6'],
|
|
23
23
|
'actions/setup-python': ['actions/setup-python@v6'],
|
|
24
|
-
'actions/upload-artifact': ['actions/upload-artifact@
|
|
25
|
-
'actions/upload-pages-artifact': ['actions/upload-pages-artifact@
|
|
24
|
+
'actions/upload-artifact': ['actions/upload-artifact@v7'],
|
|
25
|
+
'actions/upload-pages-artifact': ['actions/upload-pages-artifact@v5']
|
|
26
26
|
};
|
|
27
27
|
const npmRegistries = ['https://registry.npmjs.org', 'https://npm.pkg.github.com'];
|
|
28
28
|
const onProperties = ['push', 'pull_request'];
|
|
@@ -38,7 +38,7 @@ const permissions$1 = {
|
|
|
38
38
|
const isSupported = (actions, value) => {
|
|
39
39
|
return actions.includes(value);
|
|
40
40
|
};
|
|
41
|
-
const meta$
|
|
41
|
+
const meta$i = {
|
|
42
42
|
docs: {
|
|
43
43
|
description: 'Disallow unsupported action versions'
|
|
44
44
|
},
|
|
@@ -48,7 +48,7 @@ const meta$g = {
|
|
|
48
48
|
},
|
|
49
49
|
type: 'problem'
|
|
50
50
|
};
|
|
51
|
-
const create$
|
|
51
|
+
const create$i = context => {
|
|
52
52
|
const sourceCode = getSourceCode(context);
|
|
53
53
|
if (!sourceCode.parserServices?.isYAML) {
|
|
54
54
|
return {};
|
|
@@ -79,8 +79,8 @@ const create$g = context => {
|
|
|
79
79
|
|
|
80
80
|
const actionVersions = {
|
|
81
81
|
__proto__: null,
|
|
82
|
-
create: create$
|
|
83
|
-
meta: meta$
|
|
82
|
+
create: create$i,
|
|
83
|
+
meta: meta$i
|
|
84
84
|
};
|
|
85
85
|
|
|
86
86
|
const parseVersion = value => {
|
|
@@ -104,7 +104,7 @@ const isSupportedMacosversion = version => {
|
|
|
104
104
|
const isSupportedWindowsVersion = version => {
|
|
105
105
|
return config.windows.includes(version);
|
|
106
106
|
};
|
|
107
|
-
const meta$
|
|
107
|
+
const meta$h = {
|
|
108
108
|
docs: {
|
|
109
109
|
description: 'Disallow unsupported ci versions'
|
|
110
110
|
},
|
|
@@ -113,7 +113,7 @@ const meta$f = {
|
|
|
113
113
|
},
|
|
114
114
|
type: 'problem'
|
|
115
115
|
};
|
|
116
|
-
const create$
|
|
116
|
+
const create$h = context => {
|
|
117
117
|
const sourceCode = getSourceCode(context);
|
|
118
118
|
if (!sourceCode.parserServices?.isYAML) {
|
|
119
119
|
return {};
|
|
@@ -157,11 +157,11 @@ const create$f = context => {
|
|
|
157
157
|
|
|
158
158
|
const ciVersions = {
|
|
159
159
|
__proto__: null,
|
|
160
|
-
create: create$
|
|
161
|
-
meta: meta$
|
|
160
|
+
create: create$h,
|
|
161
|
+
meta: meta$h
|
|
162
162
|
};
|
|
163
163
|
|
|
164
|
-
const meta$
|
|
164
|
+
const meta$g = {
|
|
165
165
|
docs: {
|
|
166
166
|
description: 'Disallow unsupported fail fast values'
|
|
167
167
|
},
|
|
@@ -170,7 +170,7 @@ const meta$e = {
|
|
|
170
170
|
},
|
|
171
171
|
type: 'problem'
|
|
172
172
|
};
|
|
173
|
-
const create$
|
|
173
|
+
const create$g = context => {
|
|
174
174
|
const sourceCode = getSourceCode(context);
|
|
175
175
|
if (!sourceCode.parserServices?.isYAML) {
|
|
176
176
|
return {};
|
|
@@ -193,11 +193,108 @@ const create$e = context => {
|
|
|
193
193
|
|
|
194
194
|
const failFast = {
|
|
195
195
|
__proto__: null,
|
|
196
|
-
create: create$
|
|
197
|
-
meta: meta$
|
|
196
|
+
create: create$g,
|
|
197
|
+
meta: meta$g
|
|
198
198
|
};
|
|
199
199
|
|
|
200
|
-
const meta$
|
|
200
|
+
const meta$f = {
|
|
201
|
+
docs: {
|
|
202
|
+
description: 'Require GitHub Pages deployment best practices'
|
|
203
|
+
},
|
|
204
|
+
messages: {
|
|
205
|
+
missingGithubPagesConcurrency: 'GitHub Pages deployment requires concurrency group pages with cancel-in-progress false',
|
|
206
|
+
missingGithubPagesPermissions: 'GitHub Pages deployment requires contents read, pages write, and id-token write permissions'
|
|
207
|
+
},
|
|
208
|
+
type: 'problem'
|
|
209
|
+
};
|
|
210
|
+
const isCiWorkflow = fileName => {
|
|
211
|
+
return fileName.endsWith('/ci.yml') || fileName.endsWith('/ci.yaml') || fileName.endsWith('\\ci.yml') || fileName.endsWith('\\ci.yaml');
|
|
212
|
+
};
|
|
213
|
+
const isYamlScalarString = (node, value) => {
|
|
214
|
+
return node?.type === 'YAMLScalar' && node.value === value;
|
|
215
|
+
};
|
|
216
|
+
const isYamlScalarBoolean = (node, value) => {
|
|
217
|
+
return node?.type === 'YAMLScalar' && node.value === value;
|
|
218
|
+
};
|
|
219
|
+
const isDeployPagesAction = node => {
|
|
220
|
+
return node?.type === 'YAMLScalar' && typeof node.value === 'string' && node.value.startsWith('actions/deploy-pages@');
|
|
221
|
+
};
|
|
222
|
+
const isTopLevelPair = node => {
|
|
223
|
+
return node.parent?.parent?.type === 'YAMLDocument';
|
|
224
|
+
};
|
|
225
|
+
const getMappingValue = (mapping, key) => {
|
|
226
|
+
for (const pair of mapping.pairs) {
|
|
227
|
+
if (pair.key?.type === 'YAMLScalar' && pair.key.value === key) {
|
|
228
|
+
return pair.value;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
};
|
|
233
|
+
const hasGithubPagesPermissions = mapping => {
|
|
234
|
+
if (!mapping) {
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
237
|
+
return isYamlScalarString(getMappingValue(mapping, 'contents'), 'read') && isYamlScalarString(getMappingValue(mapping, 'pages'), 'write') && isYamlScalarString(getMappingValue(mapping, 'id-token'), 'write');
|
|
238
|
+
};
|
|
239
|
+
const hasGithubPagesConcurrency = mapping => {
|
|
240
|
+
if (!mapping) {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
return isYamlScalarString(getMappingValue(mapping, 'group'), 'pages') && isYamlScalarBoolean(getMappingValue(mapping, 'cancel-in-progress'), false);
|
|
244
|
+
};
|
|
245
|
+
const create$f = context => {
|
|
246
|
+
const sourceCode = getSourceCode(context);
|
|
247
|
+
if (!sourceCode.parserServices?.isYAML || !isCiWorkflow(context.filename)) {
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
250
|
+
let deployPagesNode;
|
|
251
|
+
let permissions;
|
|
252
|
+
let concurrency;
|
|
253
|
+
return {
|
|
254
|
+
'Program:exit'() {
|
|
255
|
+
if (!deployPagesNode) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (!hasGithubPagesPermissions(permissions)) {
|
|
259
|
+
context.report({
|
|
260
|
+
messageId: 'missingGithubPagesPermissions',
|
|
261
|
+
node: deployPagesNode
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
if (!hasGithubPagesConcurrency(concurrency)) {
|
|
265
|
+
context.report({
|
|
266
|
+
messageId: 'missingGithubPagesConcurrency',
|
|
267
|
+
node: deployPagesNode
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
YAMLPair(node) {
|
|
272
|
+
if (!node.key || node.key.type !== 'YAMLScalar' || typeof node.key.value !== 'string') {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (node.key.value === 'uses' && isDeployPagesAction(node.value)) {
|
|
276
|
+
deployPagesNode = node;
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (!isTopLevelPair(node) || node.value?.type !== 'YAMLMapping') {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (node.key.value === 'permissions') {
|
|
283
|
+
permissions = node.value;
|
|
284
|
+
} else if (node.key.value === 'concurrency') {
|
|
285
|
+
concurrency = node.value;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const githubPages = {
|
|
292
|
+
__proto__: null,
|
|
293
|
+
create: create$f,
|
|
294
|
+
meta: meta$f
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const meta$e = {
|
|
201
298
|
docs: {
|
|
202
299
|
description: 'Disallow unsupported github token values'
|
|
203
300
|
},
|
|
@@ -206,7 +303,7 @@ const meta$d = {
|
|
|
206
303
|
},
|
|
207
304
|
type: 'problem'
|
|
208
305
|
};
|
|
209
|
-
const create$
|
|
306
|
+
const create$e = context => {
|
|
210
307
|
const sourceCode = getSourceCode(context);
|
|
211
308
|
if (!sourceCode.parserServices?.isYAML) {
|
|
212
309
|
return {};
|
|
@@ -231,11 +328,11 @@ const create$d = context => {
|
|
|
231
328
|
|
|
232
329
|
const githubToken = {
|
|
233
330
|
__proto__: null,
|
|
234
|
-
create: create$
|
|
235
|
-
meta: meta$
|
|
331
|
+
create: create$e,
|
|
332
|
+
meta: meta$e
|
|
236
333
|
};
|
|
237
334
|
|
|
238
|
-
const meta$
|
|
335
|
+
const meta$d = {
|
|
239
336
|
docs: {
|
|
240
337
|
description: 'Disallow unsupported matrix values'
|
|
241
338
|
},
|
|
@@ -244,7 +341,7 @@ const meta$c = {
|
|
|
244
341
|
},
|
|
245
342
|
type: 'problem'
|
|
246
343
|
};
|
|
247
|
-
const create$
|
|
344
|
+
const create$d = context => {
|
|
248
345
|
const sourceCode = getSourceCode(context);
|
|
249
346
|
if (!sourceCode.parserServices?.isYAML) {
|
|
250
347
|
return {};
|
|
@@ -267,11 +364,11 @@ const create$c = context => {
|
|
|
267
364
|
|
|
268
365
|
const matrix = {
|
|
269
366
|
__proto__: null,
|
|
270
|
-
create: create$
|
|
271
|
-
meta: meta$
|
|
367
|
+
create: create$d,
|
|
368
|
+
meta: meta$d
|
|
272
369
|
};
|
|
273
370
|
|
|
274
|
-
const meta$
|
|
371
|
+
const meta$c = {
|
|
275
372
|
docs: {
|
|
276
373
|
description: 'Disallow unsupported max parallel values'
|
|
277
374
|
},
|
|
@@ -280,7 +377,7 @@ const meta$b = {
|
|
|
280
377
|
},
|
|
281
378
|
type: 'problem'
|
|
282
379
|
};
|
|
283
|
-
const create$
|
|
380
|
+
const create$c = context => {
|
|
284
381
|
const sourceCode = getSourceCode(context);
|
|
285
382
|
if (!sourceCode.parserServices?.isYAML) {
|
|
286
383
|
return {};
|
|
@@ -303,11 +400,11 @@ const create$b = context => {
|
|
|
303
400
|
|
|
304
401
|
const maxParallel = {
|
|
305
402
|
__proto__: null,
|
|
306
|
-
create: create$
|
|
307
|
-
meta: meta$
|
|
403
|
+
create: create$c,
|
|
404
|
+
meta: meta$c
|
|
308
405
|
};
|
|
309
406
|
|
|
310
|
-
const meta$
|
|
407
|
+
const meta$b = {
|
|
311
408
|
docs: {
|
|
312
409
|
description: 'Disallow unsupported needs values'
|
|
313
410
|
},
|
|
@@ -340,7 +437,7 @@ const getValidNeeds = node => {
|
|
|
340
437
|
}
|
|
341
438
|
return validNeeds;
|
|
342
439
|
};
|
|
343
|
-
const create$
|
|
440
|
+
const create$b = context => {
|
|
344
441
|
const sourceCode = getSourceCode(context);
|
|
345
442
|
if (!sourceCode.parserServices?.isYAML) {
|
|
346
443
|
return {};
|
|
@@ -398,6 +495,57 @@ const create$a = context => {
|
|
|
398
495
|
};
|
|
399
496
|
|
|
400
497
|
const needs = {
|
|
498
|
+
__proto__: null,
|
|
499
|
+
create: create$b,
|
|
500
|
+
meta: meta$b
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const meta$a = {
|
|
504
|
+
docs: {
|
|
505
|
+
description: 'Disallow e2e tests in release workflows'
|
|
506
|
+
},
|
|
507
|
+
messages: {
|
|
508
|
+
noE2eInRelease: 'Do not run e2e tests in release workflows'
|
|
509
|
+
},
|
|
510
|
+
type: 'problem'
|
|
511
|
+
};
|
|
512
|
+
const isReleaseWorkflow = filename => {
|
|
513
|
+
const normalized = filename.replaceAll('\\', '/');
|
|
514
|
+
return normalized.endsWith('/release.yml') || normalized.endsWith('/release.yaml') || normalized === 'release.yml' || normalized === 'release.yaml';
|
|
515
|
+
};
|
|
516
|
+
const runsE2eTests = value => {
|
|
517
|
+
const commands = value.replaceAll('\r', '\n').replaceAll('&&', ';').replaceAll('||', ';').split(/[\n;]/);
|
|
518
|
+
for (const command of commands) {
|
|
519
|
+
const tokens = command.trim().split(/\s+/);
|
|
520
|
+
const npmIndex = tokens.indexOf('npm');
|
|
521
|
+
if (npmIndex === -1) {
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
const scriptName = tokens[npmIndex + 2];
|
|
525
|
+
if (tokens[npmIndex + 1] === 'run' && (scriptName === 'e2e' || scriptName?.startsWith('e2e:'))) {
|
|
526
|
+
return true;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
return false;
|
|
530
|
+
};
|
|
531
|
+
const create$a = context => {
|
|
532
|
+
const sourceCode = getSourceCode(context);
|
|
533
|
+
if (!sourceCode.parserServices?.isYAML || !isReleaseWorkflow(context.filename)) {
|
|
534
|
+
return {};
|
|
535
|
+
}
|
|
536
|
+
return {
|
|
537
|
+
YAMLPair(node) {
|
|
538
|
+
if (node && node.type === 'YAMLPair' && node.key && typeof node.key === 'object' && 'type' in node.key && node.key.type === 'YAMLScalar' && node.key.value === 'run' && node.value && typeof node.value === 'object' && 'type' in node.value && node.value.type === 'YAMLScalar' && typeof node.value.value === 'string' && runsE2eTests(node.value.value)) {
|
|
539
|
+
context.report({
|
|
540
|
+
messageId: 'noE2eInRelease',
|
|
541
|
+
node: node.value
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
const noE2eInRelease = {
|
|
401
549
|
__proto__: null,
|
|
402
550
|
create: create$a,
|
|
403
551
|
meta: meta$a
|
|
@@ -862,10 +1010,12 @@ const plugin = {
|
|
|
862
1010
|
'action-versions': actionVersions,
|
|
863
1011
|
'ci-versions': ciVersions,
|
|
864
1012
|
'fail-fast': failFast,
|
|
1013
|
+
'github-pages': githubPages,
|
|
865
1014
|
'github-token': githubToken,
|
|
866
1015
|
matrix: matrix,
|
|
867
1016
|
'max-parallel': maxParallel,
|
|
868
1017
|
needs: needs,
|
|
1018
|
+
'no-e2e-in-release': noE2eInRelease,
|
|
869
1019
|
'node-version-file': nodeVersionFile,
|
|
870
1020
|
npm: npm,
|
|
871
1021
|
'npm-registry': npmRegistry,
|
|
@@ -890,10 +1040,12 @@ const recommended = [{
|
|
|
890
1040
|
'github-actions/action-versions': 'error',
|
|
891
1041
|
'github-actions/ci-versions': 'error',
|
|
892
1042
|
'github-actions/fail-fast': 'error',
|
|
1043
|
+
'github-actions/github-pages': 'error',
|
|
893
1044
|
'github-actions/github-token': 'error',
|
|
894
1045
|
'github-actions/matrix': 'off',
|
|
895
1046
|
'github-actions/max-parallel': 'error',
|
|
896
1047
|
'github-actions/needs': 'error',
|
|
1048
|
+
'github-actions/no-e2e-in-release': 'error',
|
|
897
1049
|
'github-actions/node-version-file': 'error',
|
|
898
1050
|
'github-actions/npm': 'error',
|
|
899
1051
|
'github-actions/npm-registry': 'error',
|