@netlify/build 29.31.4 → 29.32.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/lib/log/messages/plugins.d.ts +10 -8
- package/lib/log/messages/plugins.js +5 -6
- package/lib/plugins/compatibility.d.ts +23 -31
- package/lib/plugins/compatibility.js +52 -93
- package/lib/plugins/compatibility.test.d.ts +1 -0
- package/lib/plugins/compatibility.test.js +148 -0
- package/lib/plugins/expected_version.d.ts +3 -2
- package/lib/plugins/expected_version.js +23 -8
- package/lib/plugins/list.d.ts +32 -9
- package/lib/plugins/list.js +25 -21
- package/lib/plugins/node_version.d.ts +2 -1
- package/lib/plugins/node_version.js +27 -15
- package/lib/plugins/plugin_conditions.d.ts +24 -0
- package/lib/plugins/plugin_conditions.js +61 -0
- package/lib/plugins/resolve.js +2 -0
- package/package.json +10 -4
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import type { PluginList } from '../../plugins/list.js';
|
|
2
|
+
import { BufferedLogs } from '../logger.js';
|
|
3
|
+
export declare const logPluginsFetchError: (logs: BufferedLogs | undefined, message: string) => void;
|
|
4
|
+
export declare const logPluginsList: ({ pluginsList, debug, logs, }: {
|
|
5
|
+
pluginsList: PluginList;
|
|
6
|
+
logs: BufferedLogs | undefined;
|
|
7
|
+
debug?: boolean | undefined;
|
|
8
|
+
}) => void;
|
|
9
|
+
export declare const logFailPluginWarning: (methodName: any, event: any) => void;
|
|
10
|
+
export declare const logDeploySuccess: (logs?: BufferedLogs) => void;
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
import { log, logArray,
|
|
1
|
+
import { log, logArray, logSubHeader, logWarning } from '../logger.js';
|
|
2
2
|
export const logPluginsFetchError = function (logs, message) {
|
|
3
3
|
logWarning(logs, `
|
|
4
4
|
Warning: could not fetch latest plugins list. Plugins versions might not be the latest.
|
|
5
5
|
${message}`);
|
|
6
6
|
};
|
|
7
|
-
export const logPluginsList = function ({ pluginsList, debug, logs }) {
|
|
7
|
+
export const logPluginsList = function ({ pluginsList, debug, logs, }) {
|
|
8
8
|
if (!debug) {
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
|
-
const pluginsListArray = Object.entries(pluginsList)
|
|
11
|
+
const pluginsListArray = Object.entries(pluginsList)
|
|
12
|
+
.map(([packageName, versions]) => `${packageName}@${versions[0].version}`)
|
|
13
|
+
.sort();
|
|
12
14
|
logSubHeader(logs, 'Available plugins');
|
|
13
15
|
logArray(logs, pluginsListArray);
|
|
14
16
|
};
|
|
15
|
-
const getPluginsListItem = function ([packageName, versions]) {
|
|
16
|
-
return `${packageName}@${versions[0].version}`;
|
|
17
|
-
};
|
|
18
17
|
export const logFailPluginWarning = function (methodName, event) {
|
|
19
18
|
logWarning(undefined, `Plugin error: since "${event}" happens after deploy, the build has already succeeded and cannot fail anymore. This plugin should either:
|
|
20
19
|
- use utils.build.failPlugin() instead of utils.build.${methodName}() to clarify that the plugin failed, but not the build.
|
|
@@ -1,33 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { PackageJson } from 'read-pkg-up';
|
|
2
|
+
import { PluginVersion } from './list.js';
|
|
3
|
+
/**
|
|
4
|
+
* Retrieve the `expectedVersion` of a plugin:
|
|
5
|
+
* - This is the version which should be run
|
|
6
|
+
* - This takes version pinning into account
|
|
7
|
+
* - If this does not match the currently cached version, it is installed first
|
|
8
|
+
* This is also used to retrieve the `compatibleVersion` of a plugin
|
|
9
|
+
* - This is the most recent version compatible with this site
|
|
10
|
+
* - This is the same logic except it does not use version pinning
|
|
11
|
+
* - This is only used to print a warning message when the `compatibleVersion`
|
|
12
|
+
* is older than the currently used version.
|
|
13
|
+
*/
|
|
14
|
+
export declare const getExpectedVersion: ({ versions, nodeVersion, packageJson, packagePath, buildDir, pinnedVersion, }: {
|
|
15
|
+
versions: PluginVersion[];
|
|
16
|
+
/** The package.json of the repository */
|
|
17
|
+
packageJson: PackageJson;
|
|
18
|
+
packagePath?: string | undefined;
|
|
19
|
+
buildDir: string;
|
|
20
|
+
nodeVersion: string;
|
|
21
|
+
pinnedVersion?: string | undefined;
|
|
22
|
+
}) => Promise<{
|
|
23
|
+
version: string;
|
|
9
24
|
compatWarning: string;
|
|
10
25
|
}>;
|
|
11
|
-
export namespace CONDITIONS {
|
|
12
|
-
namespace nodeVersion {
|
|
13
|
-
export { nodeVersionTest as test };
|
|
14
|
-
export { nodeVersionWarning as warning };
|
|
15
|
-
}
|
|
16
|
-
namespace siteDependencies {
|
|
17
|
-
export { siteDependenciesTest as test };
|
|
18
|
-
export { siteDependenciesWarning as warning };
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
declare function nodeVersionTest(allowedNodeVersion: any, { nodeVersion }: {
|
|
22
|
-
nodeVersion: any;
|
|
23
|
-
}): boolean;
|
|
24
|
-
declare function nodeVersionWarning(allowedNodeVersion: any): string;
|
|
25
|
-
declare function siteDependenciesTest(allowedSiteDependencies: any, { packageJson: { devDependencies, dependencies }, buildDir }: {
|
|
26
|
-
packageJson: {
|
|
27
|
-
devDependencies: any;
|
|
28
|
-
dependencies: any;
|
|
29
|
-
};
|
|
30
|
-
buildDir: any;
|
|
31
|
-
}): Promise<any>;
|
|
32
|
-
declare function siteDependenciesWarning(allowedSiteDependencies: any): string;
|
|
33
|
-
export {};
|
|
@@ -1,104 +1,63 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _pEvery from 'p-every';
|
|
2
2
|
import pLocate from 'p-locate';
|
|
3
3
|
import semver from 'semver';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
4
|
+
import { CONDITIONS } from './plugin_conditions.js';
|
|
5
|
+
// the types of that package seem to be not correct and demand a `pEvery.default()` usage which is wrong
|
|
6
|
+
const pEvery = _pEvery;
|
|
7
|
+
/**
|
|
8
|
+
* Retrieve the `expectedVersion` of a plugin:
|
|
9
|
+
* - This is the version which should be run
|
|
10
|
+
* - This takes version pinning into account
|
|
11
|
+
* - If this does not match the currently cached version, it is installed first
|
|
12
|
+
* This is also used to retrieve the `compatibleVersion` of a plugin
|
|
13
|
+
* - This is the most recent version compatible with this site
|
|
14
|
+
* - This is the same logic except it does not use version pinning
|
|
15
|
+
* - This is only used to print a warning message when the `compatibleVersion`
|
|
16
|
+
* is older than the currently used version.
|
|
17
|
+
*/
|
|
18
|
+
export const getExpectedVersion = async function ({ versions, nodeVersion, packageJson, packagePath, buildDir, pinnedVersion, }) {
|
|
19
|
+
const { version, conditions = [] } = await getCompatibleEntry({
|
|
17
20
|
versions,
|
|
18
21
|
nodeVersion,
|
|
19
22
|
packageJson,
|
|
23
|
+
packagePath,
|
|
20
24
|
buildDir,
|
|
21
25
|
pinnedVersion,
|
|
22
26
|
});
|
|
23
|
-
|
|
27
|
+
// Retrieve warning message shown when using an older version with `compatibility`
|
|
28
|
+
const compatWarning = conditions.map(({ type, condition }) => CONDITIONS[type].warning(condition)).join(', ');
|
|
24
29
|
return { version, compatWarning };
|
|
25
30
|
};
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const getCompatWarning = function (conditions = []) {
|
|
59
|
-
return conditions.map(getConditionWarning).join(', ');
|
|
60
|
-
};
|
|
61
|
-
const getConditionWarning = function ({ type, condition }) {
|
|
62
|
-
return CONDITIONS[type].warning(condition);
|
|
63
|
-
};
|
|
64
|
-
// Plugins can use `compatibility.{version}.nodeVersion: 'allowedNodeVersion'`
|
|
65
|
-
// to deliver different plugin versions based on the Node.js version
|
|
66
|
-
const nodeVersionTest = function (allowedNodeVersion, { nodeVersion }) {
|
|
67
|
-
return semver.satisfies(nodeVersion, allowedNodeVersion);
|
|
68
|
-
};
|
|
69
|
-
const nodeVersionWarning = function (allowedNodeVersion) {
|
|
70
|
-
return `Node.js ${allowedNodeVersion}`;
|
|
71
|
-
};
|
|
72
|
-
const siteDependenciesTest = async function (allowedSiteDependencies, { packageJson: { devDependencies, dependencies }, buildDir }) {
|
|
73
|
-
const siteDependencies = { ...devDependencies, ...dependencies };
|
|
74
|
-
return await pEvery(Object.entries(allowedSiteDependencies), ([dependencyName, allowedVersion]) => siteDependencyTest({ dependencyName, allowedVersion, siteDependencies, buildDir }));
|
|
75
|
-
};
|
|
76
|
-
const siteDependencyTest = async function ({ dependencyName, allowedVersion, siteDependencies, buildDir }) {
|
|
77
|
-
const siteDependency = siteDependencies[dependencyName];
|
|
78
|
-
if (typeof siteDependency !== 'string') {
|
|
79
|
-
return false;
|
|
80
|
-
}
|
|
81
|
-
// if this is a valid version we can apply the rule directly
|
|
82
|
-
if (semver.clean(siteDependency) !== null) {
|
|
83
|
-
return semver.satisfies(siteDependency, allowedVersion);
|
|
84
|
-
}
|
|
85
|
-
try {
|
|
86
|
-
// if this is a range we need to get the exact version
|
|
87
|
-
const packageJsonPath = await resolvePath(`${dependencyName}/package.json`, buildDir);
|
|
88
|
-
const { version } = await importJsonFile(packageJsonPath);
|
|
89
|
-
return semver.satisfies(version, allowedVersion);
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
return false;
|
|
93
|
-
}
|
|
94
|
-
};
|
|
95
|
-
const siteDependenciesWarning = function (allowedSiteDependencies) {
|
|
96
|
-
return Object.entries(allowedSiteDependencies).map(siteDependencyWarning).join(',');
|
|
97
|
-
};
|
|
98
|
-
const siteDependencyWarning = function ([dependencyName, allowedVersion]) {
|
|
99
|
-
return `${dependencyName}@${allowedVersion}`;
|
|
100
|
-
};
|
|
101
|
-
export const CONDITIONS = {
|
|
102
|
-
nodeVersion: { test: nodeVersionTest, warning: nodeVersionWarning },
|
|
103
|
-
siteDependencies: { test: siteDependenciesTest, warning: siteDependenciesWarning },
|
|
31
|
+
/**
|
|
32
|
+
* This function finds the right `compatibility` entry to use with the plugin.
|
|
33
|
+
* - `compatibility` entries are meant for backward compatibility
|
|
34
|
+
* Plugins should define each major version in `compatibility`.
|
|
35
|
+
* - The entries are sorted from most to least recent version.
|
|
36
|
+
* - After their first successful run, plugins are pinned by their major
|
|
37
|
+
* version which is passed as `pinnedVersion` to the next builds.
|
|
38
|
+
* When the plugin does not have a `pinnedVersion`, we use the most recent
|
|
39
|
+
* `compatibility` entry with a successful condition.
|
|
40
|
+
* When the plugin has a `pinnedVersion`, we do not use the `compatibility`
|
|
41
|
+
* conditions. Instead, we just use the most recent entry with a `version`
|
|
42
|
+
* matching `pinnedVersion`.
|
|
43
|
+
* When no `compatibility` entry matches, we use:
|
|
44
|
+
* - If there is a `pinnedVersion`, use it unless `latestVersion` matches it
|
|
45
|
+
* - Otherwise, use `latestVersion`
|
|
46
|
+
*/
|
|
47
|
+
const getCompatibleEntry = async function ({ versions, nodeVersion, packageJson, packagePath, buildDir, pinnedVersion, }) {
|
|
48
|
+
const compatibleEntry = await pLocate(versions, async ({ version, overridePinnedVersion, conditions }) => {
|
|
49
|
+
// Detect if the overridePinnedVersion intersects with the pinned version in this case we don't care about filtering
|
|
50
|
+
const overridesPin = Boolean(pinnedVersion && overridePinnedVersion && semver.intersects(overridePinnedVersion, pinnedVersion));
|
|
51
|
+
// ignore versions that don't satisfy the pinned version here if a pinned version is set
|
|
52
|
+
if (!overridesPin && pinnedVersion && !semver.satisfies(version, pinnedVersion, { includePrerelease: true })) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// no conditions means nothing to filter
|
|
56
|
+
if (conditions.length === 0 && pinnedVersion === undefined) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return await pEvery(conditions, async ({ type, condition }) => CONDITIONS[type].test(condition, { nodeVersion, packageJson, packagePath, buildDir }));
|
|
60
|
+
});
|
|
61
|
+
return (compatibleEntry ||
|
|
62
|
+
(pinnedVersion ? { version: pinnedVersion, conditions: [] } : { version: versions[0].version, conditions: [] }));
|
|
104
63
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { expect, test } from 'vitest';
|
|
2
|
+
import { getExpectedVersion } from './compatibility.js';
|
|
3
|
+
test('`getExpectedVersion` should ignore the new major version if the version is pinned', async () => {
|
|
4
|
+
const versions = [
|
|
5
|
+
{ version: '5.0.0', conditions: [] },
|
|
6
|
+
{ version: '4.41.2', conditions: [] },
|
|
7
|
+
];
|
|
8
|
+
const { version } = await getExpectedVersion({
|
|
9
|
+
versions,
|
|
10
|
+
nodeVersion: '18.19.0',
|
|
11
|
+
packageJson: {},
|
|
12
|
+
buildDir: '/some/path',
|
|
13
|
+
pinnedVersion: '4',
|
|
14
|
+
});
|
|
15
|
+
expect(version).toBe('4.41.2');
|
|
16
|
+
});
|
|
17
|
+
test('`getExpectedVersion` matches prerelease versions', async () => {
|
|
18
|
+
const versions = [
|
|
19
|
+
{ version: '5.0.0', conditions: [] },
|
|
20
|
+
{ version: '4.42.0-alpha.1', conditions: [] },
|
|
21
|
+
{ version: '4.41.2', conditions: [] },
|
|
22
|
+
];
|
|
23
|
+
const { version: version1 } = await getExpectedVersion({
|
|
24
|
+
versions,
|
|
25
|
+
nodeVersion: '18.19.0',
|
|
26
|
+
packageJson: {},
|
|
27
|
+
buildDir: '/some/path',
|
|
28
|
+
});
|
|
29
|
+
const { version: version2 } = await getExpectedVersion({
|
|
30
|
+
versions,
|
|
31
|
+
nodeVersion: '18.19.0',
|
|
32
|
+
packageJson: {},
|
|
33
|
+
buildDir: '/some/path',
|
|
34
|
+
pinnedVersion: '4',
|
|
35
|
+
});
|
|
36
|
+
expect(version1).toBe('5.0.0');
|
|
37
|
+
expect(version2).toBe('4.42.0-alpha.1');
|
|
38
|
+
});
|
|
39
|
+
test('`getExpectedVersion`should retrieve a new major version if the overridePinnedVersion is specified', async () => {
|
|
40
|
+
const versions = [
|
|
41
|
+
{ version: '5.0.0', conditions: [], overridePinnedVersion: '>=4.0.0' },
|
|
42
|
+
{ version: '4.41.2', conditions: [] },
|
|
43
|
+
];
|
|
44
|
+
const { version } = await getExpectedVersion({
|
|
45
|
+
versions,
|
|
46
|
+
nodeVersion: '18.19.0',
|
|
47
|
+
packageJson: {},
|
|
48
|
+
buildDir: '/some/path',
|
|
49
|
+
pinnedVersion: '4',
|
|
50
|
+
});
|
|
51
|
+
expect(version).toBe('5.0.0');
|
|
52
|
+
});
|
|
53
|
+
test('`getExpectedVersion`should retrieve the plugin based on the condition of a nodeVersion', async () => {
|
|
54
|
+
const versions = [
|
|
55
|
+
{
|
|
56
|
+
version: '4.42.0',
|
|
57
|
+
conditions: [{ type: 'nodeVersion', condition: '>=18.0.0' }],
|
|
58
|
+
},
|
|
59
|
+
{ version: '4.41.2', conditions: [] },
|
|
60
|
+
];
|
|
61
|
+
const { version } = await getExpectedVersion({
|
|
62
|
+
versions,
|
|
63
|
+
nodeVersion: '17.19.0',
|
|
64
|
+
packageJson: {},
|
|
65
|
+
buildDir: '/some/path',
|
|
66
|
+
pinnedVersion: '4',
|
|
67
|
+
});
|
|
68
|
+
expect(version).toBe('4.41.2');
|
|
69
|
+
});
|
|
70
|
+
test('`getExpectedVersion` should retrieve the plugin based on conditions and feature flag due to pinned version', async () => {
|
|
71
|
+
const versions = [
|
|
72
|
+
{
|
|
73
|
+
version: '5.0.0-beta.1',
|
|
74
|
+
conditions: [
|
|
75
|
+
{ type: 'nodeVersion', condition: '>= 18.0.0' },
|
|
76
|
+
{ type: 'siteDependencies', condition: { next: '>=13.5.0' } },
|
|
77
|
+
],
|
|
78
|
+
overridePinnedVersion: '>=4.0.0',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
version: '4.42.0',
|
|
82
|
+
conditions: [{ type: 'siteDependencies', condition: { next: '>=10.0.9' } }],
|
|
83
|
+
},
|
|
84
|
+
{ version: '4.41.2', conditions: [] },
|
|
85
|
+
{
|
|
86
|
+
version: '3.9.2',
|
|
87
|
+
conditions: [{ type: 'siteDependencies', condition: { next: '<10.0.9' } }],
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
const { version: version1 } = await getExpectedVersion({
|
|
91
|
+
versions,
|
|
92
|
+
nodeVersion: '17.19.0',
|
|
93
|
+
packageJson: { dependencies: { next: '10.0.8' } },
|
|
94
|
+
buildDir: '/some/path',
|
|
95
|
+
pinnedVersion: '3',
|
|
96
|
+
});
|
|
97
|
+
expect(version1).toBe('3.9.2');
|
|
98
|
+
const { version: version2 } = await getExpectedVersion({
|
|
99
|
+
versions,
|
|
100
|
+
nodeVersion: '17.19.0',
|
|
101
|
+
packageJson: { dependencies: { next: '11.0.0' } },
|
|
102
|
+
buildDir: '/some/path',
|
|
103
|
+
pinnedVersion: '4',
|
|
104
|
+
});
|
|
105
|
+
expect(version2).toBe('4.42.0');
|
|
106
|
+
const { version: version3 } = await getExpectedVersion({
|
|
107
|
+
versions,
|
|
108
|
+
nodeVersion: '18.19.0',
|
|
109
|
+
packageJson: { dependencies: { next: '13.5.0' } },
|
|
110
|
+
buildDir: '/some/path',
|
|
111
|
+
pinnedVersion: '4',
|
|
112
|
+
});
|
|
113
|
+
expect(version3).toBe('5.0.0-beta.1');
|
|
114
|
+
});
|
|
115
|
+
test('`getExpectedVersion` should retrieve the plugin based on conditions and feature flag due to pinned version', async () => {
|
|
116
|
+
const versions = [
|
|
117
|
+
{
|
|
118
|
+
version: '5.0.0-beta.1',
|
|
119
|
+
conditions: [
|
|
120
|
+
{ type: 'nodeVersion', condition: '>= 18.0.0' },
|
|
121
|
+
{ type: 'siteDependencies', condition: { next: '>=13.5.0' } },
|
|
122
|
+
],
|
|
123
|
+
overridePinnedVersion: '>=4.0.0',
|
|
124
|
+
},
|
|
125
|
+
{ version: '4.41.2', conditions: [] },
|
|
126
|
+
{
|
|
127
|
+
version: '3.9.2',
|
|
128
|
+
conditions: [{ type: 'siteDependencies', condition: { next: '<10.0.9' } }],
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
const { version: version1 } = await getExpectedVersion({
|
|
132
|
+
versions,
|
|
133
|
+
nodeVersion: '20.0.0',
|
|
134
|
+
packageJson: { dependencies: { next: '14.0.0' } },
|
|
135
|
+
buildDir: '/some/path',
|
|
136
|
+
pinnedVersion: '4',
|
|
137
|
+
});
|
|
138
|
+
expect(version1).toBe('5.0.0-beta.1');
|
|
139
|
+
// out of range
|
|
140
|
+
const { version: version2 } = await getExpectedVersion({
|
|
141
|
+
versions,
|
|
142
|
+
nodeVersion: '20.0.0',
|
|
143
|
+
packageJson: { dependencies: { next: '13.0.0' } },
|
|
144
|
+
buildDir: '/some/path',
|
|
145
|
+
pinnedVersion: '4',
|
|
146
|
+
});
|
|
147
|
+
expect(version2).toBe('4.41.2');
|
|
148
|
+
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const addExpectedVersions: ({ pluginsOptions, autoPluginsDir, packageJson, packagePath, debug, logs, buildDir, testOpts, featureFlags, }: {
|
|
2
2
|
pluginsOptions: any;
|
|
3
3
|
autoPluginsDir: any;
|
|
4
4
|
packageJson: any;
|
|
5
|
+
packagePath: any;
|
|
5
6
|
debug: any;
|
|
6
7
|
logs: any;
|
|
7
8
|
buildDir: any;
|
|
8
9
|
testOpts: any;
|
|
9
10
|
featureFlags: any;
|
|
10
|
-
})
|
|
11
|
+
}) => Promise<any>;
|
|
@@ -7,15 +7,24 @@ import { getPluginsList } from './list.js';
|
|
|
7
7
|
// When using plugins in our official list, those are installed in .netlify/plugins/
|
|
8
8
|
// We ensure that the last version that's been approved is always the one being used.
|
|
9
9
|
// We also ensure that the plugin is our official list.
|
|
10
|
-
export const addExpectedVersions = async function ({ pluginsOptions, autoPluginsDir, packageJson, debug, logs, buildDir, testOpts, featureFlags, }) {
|
|
10
|
+
export const addExpectedVersions = async function ({ pluginsOptions, autoPluginsDir, packageJson, packagePath, debug, logs, buildDir, testOpts, featureFlags, }) {
|
|
11
11
|
if (!pluginsOptions.some(needsExpectedVersion)) {
|
|
12
12
|
return pluginsOptions;
|
|
13
13
|
}
|
|
14
14
|
const pluginsList = await getPluginsList({ debug, logs, testOpts });
|
|
15
|
-
return await Promise.all(pluginsOptions.map((pluginOptions) => addExpectedVersion({
|
|
15
|
+
return await Promise.all(pluginsOptions.map((pluginOptions) => addExpectedVersion({
|
|
16
|
+
pluginsList,
|
|
17
|
+
autoPluginsDir,
|
|
18
|
+
packageJson,
|
|
19
|
+
packagePath,
|
|
20
|
+
pluginOptions,
|
|
21
|
+
buildDir,
|
|
22
|
+
featureFlags,
|
|
23
|
+
testOpts,
|
|
24
|
+
})));
|
|
16
25
|
};
|
|
17
|
-
|
|
18
|
-
const addExpectedVersion = async function ({ pluginsList, autoPluginsDir, packageJson, pluginOptions, pluginOptions: { packageName, pluginPath, loadedFrom, nodeVersion, pinnedVersion }, buildDir, featureFlags, testOpts, }) {
|
|
26
|
+
/** Any `pluginOptions` with `expectedVersion` set will be automatically installed */
|
|
27
|
+
const addExpectedVersion = async function ({ pluginsList, autoPluginsDir, packageJson, packagePath, pluginOptions, pluginOptions: { packageName, pluginPath, loadedFrom, nodeVersion, pinnedVersion }, buildDir, featureFlags, testOpts, }) {
|
|
19
28
|
if (!needsExpectedVersion(pluginOptions)) {
|
|
20
29
|
return pluginOptions;
|
|
21
30
|
}
|
|
@@ -27,8 +36,8 @@ const addExpectedVersion = async function ({ pluginsList, autoPluginsDir, packag
|
|
|
27
36
|
const versions = filterVersions(unfilteredVersions, featureFlags);
|
|
28
37
|
const [{ version: latestVersion, migrationGuide }] = versions;
|
|
29
38
|
const [{ version: expectedVersion }, { version: compatibleVersion, compatWarning }] = await Promise.all([
|
|
30
|
-
getExpectedVersion({ versions, nodeVersion, packageJson, buildDir, pinnedVersion }),
|
|
31
|
-
getExpectedVersion({ versions, nodeVersion, packageJson, buildDir }),
|
|
39
|
+
getExpectedVersion({ versions, nodeVersion, packageJson, packagePath, buildDir, pinnedVersion }),
|
|
40
|
+
getExpectedVersion({ versions, nodeVersion, packageJson, packagePath, buildDir }),
|
|
32
41
|
]);
|
|
33
42
|
const isMissing = await isMissingVersion({ autoPluginsDir, packageName, pluginPath, loadedFrom, expectedVersion });
|
|
34
43
|
return {
|
|
@@ -47,8 +56,10 @@ const addExpectedVersion = async function ({ pluginsList, autoPluginsDir, packag
|
|
|
47
56
|
const filterVersions = function (unfilteredVersions, featureFlags) {
|
|
48
57
|
return unfilteredVersions.filter(({ featureFlag }) => featureFlag === undefined || featureFlags[featureFlag]);
|
|
49
58
|
};
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Checks whether plugin should be installed due to the wrong version being used
|
|
61
|
+
* (either outdated, or mismatching compatibility requirements)
|
|
62
|
+
*/
|
|
52
63
|
const isMissingVersion = async function ({ autoPluginsDir, packageName, pluginPath, loadedFrom, expectedVersion }) {
|
|
53
64
|
return (
|
|
54
65
|
// We always respect the versions specified in `package.json`, as opposed
|
|
@@ -62,6 +73,10 @@ const isMissingVersion = async function ({ autoPluginsDir, packageName, pluginPa
|
|
|
62
73
|
const getAutoPluginVersion = async function (packageName, autoPluginsDir) {
|
|
63
74
|
const packageJsonPath = await resolvePath(`${packageName}/package.json`, autoPluginsDir);
|
|
64
75
|
const { version } = await importJsonFile(packageJsonPath);
|
|
76
|
+
if (!version) {
|
|
77
|
+
// this should never happen
|
|
78
|
+
throw new Error('No version specified for the plugin!');
|
|
79
|
+
}
|
|
65
80
|
return version;
|
|
66
81
|
};
|
|
67
82
|
const needsExpectedVersion = function ({ loadedFrom }) {
|
package/lib/plugins/list.d.ts
CHANGED
|
@@ -1,9 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { BufferedLogs } from '../log/logger.js';
|
|
2
|
+
import { CONDITIONS } from './plugin_conditions.js';
|
|
3
|
+
/**
|
|
4
|
+
* The resolved and normalized Plugin list
|
|
5
|
+
*/
|
|
6
|
+
export type PluginList = Record<string, PluginVersion[]>;
|
|
7
|
+
export type PluginVersion = {
|
|
8
|
+
version: string;
|
|
9
|
+
migrationGuide?: string;
|
|
10
|
+
featureFlag?: string;
|
|
11
|
+
overridePinnedVersion?: string;
|
|
12
|
+
conditions: {
|
|
13
|
+
type: keyof typeof CONDITIONS;
|
|
14
|
+
condition: string | Record<string, string>;
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Retrieve the list of plugins officially vetted by us and displayed in our
|
|
19
|
+
* plugins directory UI.
|
|
20
|
+
* We fetch this list during each build (no caching) because we want new
|
|
21
|
+
* versions of plugins to be available instantly to all users. The time to
|
|
22
|
+
* make this request is somewhat ok (in the 100ms range).
|
|
23
|
+
* We only fetch this plugins list when needed, i.e. we defer it as much as
|
|
24
|
+
* possible.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getPluginsList: ({ debug, logs, testOpts: { pluginsListUrl }, }: {
|
|
27
|
+
testOpts?: {
|
|
28
|
+
pluginsListUrl?: string | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
debug?: boolean | undefined;
|
|
31
|
+
logs?: BufferedLogs | undefined;
|
|
32
|
+
}) => Promise<PluginList>;
|
package/lib/plugins/list.js
CHANGED
|
@@ -2,21 +2,23 @@ import { pluginsUrl, pluginsList as oldPluginsList } from '@netlify/plugins-list
|
|
|
2
2
|
import got from 'got';
|
|
3
3
|
import isPlainObj from 'is-plain-obj';
|
|
4
4
|
import { logPluginsList, logPluginsFetchError } from '../log/messages/plugins.js';
|
|
5
|
-
import { CONDITIONS } from './
|
|
6
|
-
|
|
5
|
+
import { CONDITIONS } from './plugin_conditions.js';
|
|
6
|
+
/** 1 minute HTTP request timeout */
|
|
7
7
|
const PLUGINS_LIST_TIMEOUT = 6e4;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve the list of plugins officially vetted by us and displayed in our
|
|
10
|
+
* plugins directory UI.
|
|
11
|
+
* We fetch this list during each build (no caching) because we want new
|
|
12
|
+
* versions of plugins to be available instantly to all users. The time to
|
|
13
|
+
* make this request is somewhat ok (in the 100ms range).
|
|
14
|
+
* We only fetch this plugins list when needed, i.e. we defer it as much as
|
|
15
|
+
* possible.
|
|
16
|
+
*/
|
|
17
|
+
export const getPluginsList = async function ({ debug, logs, testOpts: { pluginsListUrl } = {}, }) {
|
|
16
18
|
// We try not to mock in integration tests. However, sending a request for
|
|
17
19
|
// each test would be too slow and make tests unreliable.
|
|
18
20
|
if (pluginsListUrl === 'test') {
|
|
19
|
-
return
|
|
21
|
+
return {};
|
|
20
22
|
}
|
|
21
23
|
const pluginsListUrlA = pluginsListUrl === undefined ? pluginsUrl : pluginsListUrl;
|
|
22
24
|
const pluginsList = await fetchPluginsList({ logs, pluginsListUrl: pluginsListUrlA });
|
|
@@ -24,7 +26,7 @@ export const getPluginsList = async function ({ debug, logs, testOpts: { plugins
|
|
|
24
26
|
logPluginsList({ pluginsList: pluginsListA, debug, logs });
|
|
25
27
|
return pluginsListA;
|
|
26
28
|
};
|
|
27
|
-
const fetchPluginsList = async function ({ logs, pluginsListUrl }) {
|
|
29
|
+
const fetchPluginsList = async function ({ logs, pluginsListUrl, }) {
|
|
28
30
|
try {
|
|
29
31
|
const { body } = await got(pluginsListUrl, { responseType: 'json', timeout: { request: PLUGINS_LIST_TIMEOUT } });
|
|
30
32
|
if (!isValidPluginsList(body)) {
|
|
@@ -49,21 +51,23 @@ const isValidPluginsList = function (pluginsList) {
|
|
|
49
51
|
const normalizePluginsList = function (pluginsList) {
|
|
50
52
|
return Object.fromEntries(pluginsList.map(normalizePluginItem));
|
|
51
53
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
/**
|
|
55
|
+
* `version` in `plugins.json` is the latest version.
|
|
56
|
+
* A `compatibility` array of objects can be added to specify conditions to
|
|
57
|
+
* apply different versions.
|
|
58
|
+
* `netlify/plugins` ensures that `compatibility`:
|
|
59
|
+
* - Has the proper shape.
|
|
60
|
+
* - Is sorted from the highest to lowest version.
|
|
61
|
+
* - Does not include the latest `version`.
|
|
62
|
+
*/
|
|
59
63
|
const normalizePluginItem = function ({ package: packageName, version, compatibility = [] }) {
|
|
60
64
|
const versions = compatibility.length === 0 ? [{ version }] : compatibility;
|
|
61
65
|
const versionsA = versions.map(normalizeCompatVersion);
|
|
62
66
|
return [packageName, versionsA];
|
|
63
67
|
};
|
|
64
|
-
const normalizeCompatVersion = function ({ version, migrationGuide, featureFlag, ...otherProperties }) {
|
|
68
|
+
const normalizeCompatVersion = function ({ version, migrationGuide, featureFlag, overridePinnedVersion, ...otherProperties }) {
|
|
65
69
|
const conditions = Object.entries(otherProperties).filter(isCondition).map(normalizeCondition);
|
|
66
|
-
return { version, migrationGuide, featureFlag, conditions };
|
|
70
|
+
return { version, migrationGuide, overridePinnedVersion, featureFlag, conditions };
|
|
67
71
|
};
|
|
68
72
|
const isCondition = function ([type]) {
|
|
69
73
|
return type in CONDITIONS;
|
|
@@ -14,7 +14,8 @@ export type PluginsOptions = {
|
|
|
14
14
|
* usually the system's Node.js version.
|
|
15
15
|
* If the user Node version does not satisfy our supported engine range use our own system Node version
|
|
16
16
|
*/
|
|
17
|
-
export declare const addPluginsNodeVersion: ({ pluginsOptions, nodePath, userNodeVersion, logs }: {
|
|
17
|
+
export declare const addPluginsNodeVersion: ({ featureFlags, pluginsOptions, nodePath, userNodeVersion, logs }: {
|
|
18
|
+
featureFlags: any;
|
|
18
19
|
pluginsOptions: any;
|
|
19
20
|
nodePath: any;
|
|
20
21
|
userNodeVersion: any;
|
|
@@ -7,6 +7,7 @@ import { logWarning, logWarningSubHeader } from '../log/logger.js';
|
|
|
7
7
|
* If the users preferred Node.js version is below that we have to fall back to the system node version
|
|
8
8
|
*/
|
|
9
9
|
const MINIMUM_REQUIRED_NODE_VERSION = '^14.14.0 || >=16.0.0';
|
|
10
|
+
const UPCOMING_MINIMUM_REQUIRED_NODE_VERSION = '>=18.14.0';
|
|
10
11
|
/**
|
|
11
12
|
* Local plugins and `package.json`-installed plugins use user's preferred Node.js version if higher than our minimum
|
|
12
13
|
* supported version. Else default to the system Node version.
|
|
@@ -14,22 +15,33 @@ const MINIMUM_REQUIRED_NODE_VERSION = '^14.14.0 || >=16.0.0';
|
|
|
14
15
|
* usually the system's Node.js version.
|
|
15
16
|
* If the user Node version does not satisfy our supported engine range use our own system Node version
|
|
16
17
|
*/
|
|
17
|
-
export const addPluginsNodeVersion = function ({ pluginsOptions, nodePath, userNodeVersion, logs }) {
|
|
18
|
+
export const addPluginsNodeVersion = function ({ featureFlags, pluginsOptions, nodePath, userNodeVersion, logs }) {
|
|
18
19
|
const currentNodeVersion = semver.clean(currentVersion);
|
|
19
|
-
return pluginsOptions.map((pluginOptions) => addPluginNodeVersion({ pluginOptions, currentNodeVersion, userNodeVersion, nodePath, logs }));
|
|
20
|
+
return pluginsOptions.map((pluginOptions) => addPluginNodeVersion({ featureFlags, pluginOptions, currentNodeVersion, userNodeVersion, nodePath, logs }));
|
|
20
21
|
};
|
|
21
|
-
const addPluginNodeVersion = function ({ pluginOptions, pluginOptions: { loadedFrom, packageName }, currentNodeVersion, userNodeVersion, nodePath, logs, }) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
const addPluginNodeVersion = function ({ featureFlags, pluginOptions, pluginOptions: { loadedFrom, packageName }, currentNodeVersion, userNodeVersion, nodePath, logs, }) {
|
|
23
|
+
const systemNode = { ...pluginOptions, nodePath: execPath, nodeVersion: currentNodeVersion };
|
|
24
|
+
const userNode = { ...pluginOptions, nodePath, nodeVersion: userNodeVersion };
|
|
25
|
+
const isLocalPlugin = loadedFrom === 'local' || loadedFrom === 'package.json';
|
|
26
|
+
const isUIOrAutoInstalledPlugin = !isLocalPlugin;
|
|
27
|
+
if (isUIOrAutoInstalledPlugin) {
|
|
28
|
+
return systemNode;
|
|
29
|
+
}
|
|
30
|
+
if (featureFlags.build_warn_upcoming_system_version_change &&
|
|
31
|
+
!semver.satisfies(userNodeVersion, UPCOMING_MINIMUM_REQUIRED_NODE_VERSION)) {
|
|
32
|
+
logWarningSubHeader(logs, `Warning: Starting January 30, 2024 plugin "${packageName}" will be executed with Node.js version 20.`);
|
|
33
|
+
logWarning(logs, ` We're upgrading our system node version on that day, which means the plugin cannot be executed with your defined Node.js version ${userNodeVersion}.
|
|
34
|
+
|
|
35
|
+
Please make sure your plugin supports being run on Node.js 20.
|
|
36
|
+
|
|
37
|
+
Read more about our minimum required version in our ${link('forums announcement', 'https://answers.netlify.com/t/build-plugin-update-system-node-js-version-upgrade-to-20/108633')}`);
|
|
30
38
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
39
|
+
if (semver.satisfies(userNodeVersion, MINIMUM_REQUIRED_NODE_VERSION)) {
|
|
40
|
+
return userNode;
|
|
41
|
+
}
|
|
42
|
+
logWarningSubHeader(logs, `Warning: ${packageName} will be executed with Node.js version ${currentNodeVersion}`);
|
|
43
|
+
logWarning(logs, ` The plugin cannot be executed with your defined Node.js version ${userNodeVersion}
|
|
44
|
+
|
|
45
|
+
Read more about our minimum required version in our ${link('forums announcement', 'https://answers.netlify.com/t/build-plugins-dropping-support-for-node-js-12/79421')}`);
|
|
46
|
+
return systemNode;
|
|
35
47
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PackageJson } from 'read-pkg-up';
|
|
2
|
+
import { type PluginVersion } from './list.js';
|
|
3
|
+
type ConditionContext = {
|
|
4
|
+
nodeVersion: string;
|
|
5
|
+
packageJson: PackageJson;
|
|
6
|
+
buildDir: string;
|
|
7
|
+
packagePath?: string;
|
|
8
|
+
};
|
|
9
|
+
type PluginCondition = PluginVersion['conditions'][number]['condition'];
|
|
10
|
+
export type Condition = {
|
|
11
|
+
test: (condition: PluginCondition, ctx: ConditionContext) => boolean | Promise<boolean>;
|
|
12
|
+
warning: (condition: PluginCondition) => void;
|
|
13
|
+
};
|
|
14
|
+
export declare const CONDITIONS: {
|
|
15
|
+
nodeVersion: {
|
|
16
|
+
test: (allowedNodeVersion: string, { nodeVersion }: ConditionContext) => boolean;
|
|
17
|
+
warning: (allowedNodeVersion: string) => string;
|
|
18
|
+
};
|
|
19
|
+
siteDependencies: {
|
|
20
|
+
test: (allowedSiteDependencies: Record<string, string>, { packageJson: { devDependencies, dependencies }, packagePath, buildDir }: ConditionContext) => Promise<boolean>;
|
|
21
|
+
warning: (allowedSiteDependencies: any) => string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import _pEvery from 'p-every';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
import { importJsonFile } from '../utils/json.js';
|
|
5
|
+
import { resolvePath } from '../utils/resolve.js';
|
|
6
|
+
// the types of that package seem to be not correct and demand a `pEvery.default()` usage which is wrong
|
|
7
|
+
const pEvery = _pEvery;
|
|
8
|
+
/**
|
|
9
|
+
* Plugins can use `compatibility.{version}.nodeVersion: 'allowedNodeVersion'`
|
|
10
|
+
* to deliver different plugin versions based on the Node.js version
|
|
11
|
+
*/
|
|
12
|
+
const nodeVersionTest = (allowedNodeVersion, { nodeVersion }) => semver.satisfies(nodeVersion, allowedNodeVersion);
|
|
13
|
+
const nodeVersionWarning = (allowedNodeVersion) => `Node.js ${allowedNodeVersion}`;
|
|
14
|
+
const siteDependenciesTest = async function (allowedSiteDependencies, { packageJson: { devDependencies = {}, dependencies = {} }, packagePath, buildDir }) {
|
|
15
|
+
let siteDependencies = { ...devDependencies, ...dependencies };
|
|
16
|
+
// If there is a packagePath in a mono repository add the dependencies from the package as well
|
|
17
|
+
// the packageJson is in this case only the top root package json which does not contain all the dependencies to test for
|
|
18
|
+
const pkgJsonPath = packagePath && join(buildDir, packagePath, 'package.json');
|
|
19
|
+
if (pkgJsonPath) {
|
|
20
|
+
try {
|
|
21
|
+
const { devDependencies: devDepsPgk = {}, dependencies: depsPkg = {} } = await importJsonFile(pkgJsonPath);
|
|
22
|
+
siteDependencies = { ...siteDependencies, ...devDepsPgk, ...depsPkg };
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// noop
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return await pEvery(Object.entries(allowedSiteDependencies), ([dependencyName, allowedVersion]) => siteDependencyTest({ dependencyName, allowedVersion, siteDependencies, buildDir }));
|
|
29
|
+
};
|
|
30
|
+
const siteDependencyTest = async function ({ dependencyName, allowedVersion, siteDependencies, buildDir, }) {
|
|
31
|
+
const siteDependency = siteDependencies[dependencyName];
|
|
32
|
+
if (typeof siteDependency !== 'string') {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
// if this is a valid version we can apply the rule directly
|
|
36
|
+
if (semver.clean(siteDependency) !== null) {
|
|
37
|
+
return semver.satisfies(siteDependency, allowedVersion);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
// if this is a range we need to get the exact version
|
|
41
|
+
const packageJsonPath = await resolvePath(`${dependencyName}/package.json`, buildDir);
|
|
42
|
+
const { version } = await importJsonFile(packageJsonPath);
|
|
43
|
+
if (!version) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return semver.satisfies(version, allowedVersion);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const siteDependenciesWarning = function (allowedSiteDependencies) {
|
|
53
|
+
return Object.entries(allowedSiteDependencies).map(siteDependencyWarning).join(',');
|
|
54
|
+
};
|
|
55
|
+
const siteDependencyWarning = function ([dependencyName, allowedVersion]) {
|
|
56
|
+
return `${dependencyName}@${allowedVersion}`;
|
|
57
|
+
};
|
|
58
|
+
export const CONDITIONS = {
|
|
59
|
+
nodeVersion: { test: nodeVersionTest, warning: nodeVersionWarning },
|
|
60
|
+
siteDependencies: { test: siteDependenciesTest, warning: siteDependenciesWarning },
|
|
61
|
+
};
|
package/lib/plugins/resolve.js
CHANGED
|
@@ -15,6 +15,7 @@ export const resolvePluginsPath = async function ({ pluginsOptions, siteInfo, bu
|
|
|
15
15
|
const autoPluginsDir = getAutoPluginsDir(buildDir, packagePath);
|
|
16
16
|
const pluginsOptionsA = await Promise.all(pluginsOptions.map((pluginOptions) => resolvePluginPath({ pluginOptions, buildDir, autoPluginsDir })));
|
|
17
17
|
const pluginsOptionsB = addPluginsNodeVersion({
|
|
18
|
+
featureFlags,
|
|
18
19
|
pluginsOptions: pluginsOptionsA,
|
|
19
20
|
nodePath,
|
|
20
21
|
userNodeVersion,
|
|
@@ -25,6 +26,7 @@ export const resolvePluginsPath = async function ({ pluginsOptions, siteInfo, bu
|
|
|
25
26
|
pluginsOptions: pluginsOptionsC,
|
|
26
27
|
autoPluginsDir,
|
|
27
28
|
packageJson,
|
|
29
|
+
packagePath,
|
|
28
30
|
debug,
|
|
29
31
|
logs,
|
|
30
32
|
buildDir,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/build",
|
|
3
|
-
"version": "29.
|
|
3
|
+
"version": "29.32.0",
|
|
4
4
|
"description": "Netlify build module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": "./lib/index.js",
|
|
@@ -26,9 +26,12 @@
|
|
|
26
26
|
"postbuild": "npx copyfiles \"src/**/*.yml\" lib/ -u 1",
|
|
27
27
|
"build": "tsc",
|
|
28
28
|
"test:types": "tsd",
|
|
29
|
-
"test": "ava && tsd",
|
|
29
|
+
"test": "ava && tsd && vitest run",
|
|
30
30
|
"test:dev": "ava -w",
|
|
31
|
-
"test:ci": "
|
|
31
|
+
"test:ci": "run-p test:ci:*",
|
|
32
|
+
"test:ci:types": "tsd",
|
|
33
|
+
"test:ci:ava": "c8 -r lcovonly -r text -r json ava",
|
|
34
|
+
"test:ci:vitest": "vitest run",
|
|
32
35
|
"test:measure": "../../tools/tests-duration.js"
|
|
33
36
|
},
|
|
34
37
|
"keywords": [
|
|
@@ -127,6 +130,7 @@
|
|
|
127
130
|
"@netlify/nock-udp": "^3.1.2",
|
|
128
131
|
"@opentelemetry/sdk-trace-base": "^1.18.1",
|
|
129
132
|
"@types/node": "^14.18.53",
|
|
133
|
+
"@vitest/coverage-c8": "^0.30.1",
|
|
130
134
|
"atob": "^2.1.2",
|
|
131
135
|
"ava": "^4.0.0",
|
|
132
136
|
"c8": "^7.12.0",
|
|
@@ -139,11 +143,13 @@
|
|
|
139
143
|
"get-stream": "^6.0.0",
|
|
140
144
|
"has-ansi": "^5.0.0",
|
|
141
145
|
"moize": "^6.0.0",
|
|
146
|
+
"npm-run-all": "^4.1.5",
|
|
142
147
|
"path-key": "^4.0.0",
|
|
143
148
|
"process-exists": "^5.0.0",
|
|
144
149
|
"sinon": "^13.0.0",
|
|
145
150
|
"tmp-promise": "^3.0.2",
|
|
146
151
|
"tsd": "^0.29.0",
|
|
152
|
+
"vitest": "^0.30.1",
|
|
147
153
|
"yarn": "^1.22.4"
|
|
148
154
|
},
|
|
149
155
|
"peerDependencies": {
|
|
@@ -157,5 +163,5 @@
|
|
|
157
163
|
"engines": {
|
|
158
164
|
"node": "^14.16.0 || >=16.0.0"
|
|
159
165
|
},
|
|
160
|
-
"gitHead": "
|
|
166
|
+
"gitHead": "b2c3f6875aa5813e6d0caf3025452ea1bad2fecd"
|
|
161
167
|
}
|