@wordpress/env 5.16.0 → 7.0.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/README.md +189 -120
- package/lib/build-docker-compose-config.js +67 -96
- package/lib/cache.js +1 -0
- package/lib/cli.js +23 -3
- package/lib/commands/clean.js +14 -1
- package/lib/commands/destroy.js +12 -37
- package/lib/commands/index.js +1 -0
- package/lib/commands/install-path.js +1 -0
- package/lib/commands/logs.js +1 -0
- package/lib/commands/run.js +79 -15
- package/lib/commands/start.js +32 -10
- package/lib/commands/stop.js +1 -0
- package/lib/config/add-or-replace-port.js +41 -0
- package/lib/config/db-env.js +1 -0
- package/lib/config/detect-directory-type.js +1 -1
- package/lib/config/get-cache-directory.js +39 -0
- package/lib/config/get-config-from-environment-vars.js +86 -0
- package/lib/config/index.js +7 -5
- package/lib/config/load-config.js +92 -0
- package/lib/config/merge-configs.js +104 -0
- package/lib/config/parse-config.js +418 -157
- package/lib/config/parse-source-string.js +164 -0
- package/lib/config/post-process-config.js +202 -0
- package/lib/config/read-raw-config-file.js +7 -33
- package/lib/config/test/__snapshots__/config-integration.js.snap +271 -0
- package/lib/config/test/add-or-replace-port.js +81 -0
- package/lib/config/test/config-integration.js +143 -0
- package/lib/config/test/get-cache-directory.js +57 -0
- package/lib/config/test/merge-configs.js +111 -0
- package/lib/config/test/parse-config.js +342 -0
- package/lib/config/test/parse-source-string.js +154 -0
- package/lib/config/test/post-process-config.js +295 -0
- package/lib/config/test/read-raw-config-file.js +19 -63
- package/lib/config/test/validate-config.js +305 -0
- package/lib/config/validate-config.js +103 -40
- package/lib/env.js +2 -0
- package/lib/execute-after-setup.js +51 -0
- package/lib/get-host-user.js +31 -0
- package/lib/init-config.js +181 -63
- package/lib/md5.js +1 -0
- package/lib/parse-xdebug-mode.js +1 -0
- package/lib/retry.js +1 -0
- package/lib/test/__snapshots__/md5.js.snap +9 -0
- package/lib/test/build-docker-compose-config.js +134 -0
- package/lib/test/cache.js +154 -0
- package/lib/test/cli.js +149 -0
- package/lib/test/execute-after-setup.js +66 -0
- package/lib/test/md5.js +35 -0
- package/lib/test/parse-xdebug-mode.js +41 -0
- package/lib/wordpress.js +5 -33
- package/package.json +2 -2
- package/lib/config/config.js +0 -357
- package/lib/config/test/__snapshots__/config.js.snap +0 -83
- package/lib/config/test/config.js +0 -1203
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @typedef {import('./
|
|
5
|
-
* @typedef {import('./config').WPSource} WPSource
|
|
4
|
+
* @typedef {import('./parse-source-string').WPSource} WPSource
|
|
6
5
|
*/
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -12,81 +11,145 @@
|
|
|
12
11
|
class ValidationError extends Error {}
|
|
13
12
|
|
|
14
13
|
/**
|
|
15
|
-
* Validates
|
|
16
|
-
* do not match the required format.
|
|
14
|
+
* Validates that the value is a string.
|
|
17
15
|
*
|
|
18
|
-
* @param {
|
|
19
|
-
* @param {
|
|
20
|
-
* @
|
|
16
|
+
* @param {string} configFile The configuration file we're validating.
|
|
17
|
+
* @param {string} configKey The configuration key we're validating.
|
|
18
|
+
* @param {number} value The value to check.
|
|
21
19
|
*/
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
if ( config.core !== null && typeof config.core !== 'string' ) {
|
|
20
|
+
function checkString( configFile, configKey, value ) {
|
|
21
|
+
if ( typeof value !== 'string' ) {
|
|
25
22
|
throw new ValidationError(
|
|
26
|
-
`Invalid
|
|
23
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string.`
|
|
27
24
|
);
|
|
28
25
|
}
|
|
26
|
+
}
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Validates the port and throws if it isn't valid.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} configFile The configuration file we're validating.
|
|
32
|
+
* @param {string} configKey The configuration key we're validating.
|
|
33
|
+
* @param {number} port The port to check.
|
|
34
|
+
*/
|
|
35
|
+
function checkPort( configFile, configKey, port ) {
|
|
36
|
+
if ( ! Number.isInteger( port ) ) {
|
|
34
37
|
throw new ValidationError(
|
|
35
|
-
`Invalid
|
|
38
|
+
`Invalid ${ configFile }: "${ configKey }" must be an integer.`
|
|
36
39
|
);
|
|
37
40
|
}
|
|
38
41
|
|
|
39
|
-
if (
|
|
40
|
-
! Array.isArray( config.themes ) ||
|
|
41
|
-
config.themes.some( ( theme ) => typeof theme !== 'string' )
|
|
42
|
-
) {
|
|
42
|
+
if ( port < 0 || port > 65535 ) {
|
|
43
43
|
throw new ValidationError(
|
|
44
|
-
`Invalid
|
|
44
|
+
`Invalid ${ configFile }: "${ configKey }" must be a valid port.`
|
|
45
45
|
);
|
|
46
46
|
}
|
|
47
|
+
}
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Validates the array and throws if it isn't valid.
|
|
51
|
+
*
|
|
52
|
+
* @param {string} configFile The config file we're validating.
|
|
53
|
+
* @param {string} configKey The configuration key we're validating.
|
|
54
|
+
* @param {string[]} array The array that we're checking.
|
|
55
|
+
*/
|
|
56
|
+
function checkStringArray( configFile, configKey, array ) {
|
|
57
|
+
if ( ! Array.isArray( array ) ) {
|
|
49
58
|
throw new ValidationError(
|
|
50
|
-
`Invalid
|
|
59
|
+
`Invalid ${ configFile }: "${ configKey }" must be an array.`
|
|
51
60
|
);
|
|
52
61
|
}
|
|
53
62
|
|
|
54
|
-
if ( typeof
|
|
63
|
+
if ( array.some( ( value ) => typeof value !== 'string' ) ) {
|
|
55
64
|
throw new ValidationError(
|
|
56
|
-
`Invalid
|
|
65
|
+
`Invalid ${ configFile }: "${ configKey }" must be an array of strings.`
|
|
57
66
|
);
|
|
58
67
|
}
|
|
68
|
+
}
|
|
59
69
|
|
|
60
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Validates the object and throws if it isn't valid.
|
|
72
|
+
*
|
|
73
|
+
* @param {string} configFile The config file we're validating.
|
|
74
|
+
* @param {string} configKey The configuration key we're validating.
|
|
75
|
+
* @param {string[]} obj The object that we're checking.
|
|
76
|
+
* @param {string[]} allowTypes The types that are allowed.
|
|
77
|
+
*/
|
|
78
|
+
function checkObjectWithValues( configFile, configKey, obj, allowTypes ) {
|
|
79
|
+
if ( allowTypes === undefined ) {
|
|
80
|
+
allowTypes = [];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if ( typeof obj !== 'object' || Array.isArray( obj ) ) {
|
|
61
84
|
throw new ValidationError(
|
|
62
|
-
`Invalid
|
|
85
|
+
`Invalid ${ configFile }: "${ configKey }" must be an object.`
|
|
63
86
|
);
|
|
64
87
|
}
|
|
65
88
|
|
|
66
|
-
for ( const
|
|
67
|
-
if ( !
|
|
89
|
+
for ( const key in obj ) {
|
|
90
|
+
if ( ! obj[ key ] && ! allowTypes.includes( 'empty' ) ) {
|
|
91
|
+
throw new ValidationError(
|
|
92
|
+
`Invalid ${ configFile }: "${ configKey }.${ key }" must not be empty.`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Identify arrays uniquely.
|
|
97
|
+
const type = Array.isArray( obj[ key ] ) ? 'array' : typeof obj[ key ];
|
|
98
|
+
|
|
99
|
+
if ( ! allowTypes.includes( type ) ) {
|
|
68
100
|
throw new ValidationError(
|
|
69
|
-
`Invalid
|
|
101
|
+
`Invalid ${ configFile }: "${ configKey }.${ key }" must be a ${ allowTypes.join(
|
|
102
|
+
' or '
|
|
103
|
+
) }.`
|
|
70
104
|
);
|
|
71
105
|
}
|
|
72
106
|
}
|
|
107
|
+
}
|
|
73
108
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Validates the version and throws if it isn't valid.
|
|
111
|
+
*
|
|
112
|
+
* @param {string} configFile The config file we're validating.
|
|
113
|
+
* @param {string} configKey The configuration key we're validating.
|
|
114
|
+
* @param {string} version The version that we're checking.
|
|
115
|
+
*/
|
|
116
|
+
function checkVersion( configFile, configKey, version ) {
|
|
117
|
+
if ( typeof version !== 'string' ) {
|
|
81
118
|
throw new ValidationError(
|
|
82
|
-
`Invalid
|
|
119
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string.`
|
|
83
120
|
);
|
|
84
121
|
}
|
|
85
122
|
|
|
86
|
-
|
|
123
|
+
if ( ! version.match( /[0-9]+(?:\.[0-9]+)*/ ) ) {
|
|
124
|
+
throw new ValidationError(
|
|
125
|
+
`Invalid ${ configFile }: "${ configKey }" must be a string of the format "X", "X.X", or "X.X.X".`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Validates the url and throws if it isn't valid.
|
|
132
|
+
*
|
|
133
|
+
* @param {string} configFile The config file we're validating.
|
|
134
|
+
* @param {string} configKey The configuration key we're validating.
|
|
135
|
+
* @param {string} url The URL that we're checking.
|
|
136
|
+
*/
|
|
137
|
+
function checkValidURL( configFile, configKey, url ) {
|
|
138
|
+
try {
|
|
139
|
+
new URL( url );
|
|
140
|
+
} catch {
|
|
141
|
+
throw new ValidationError(
|
|
142
|
+
`Invalid ${ configFile }: "${ configKey }" must be a valid URL.`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
87
145
|
}
|
|
88
146
|
|
|
89
147
|
module.exports = {
|
|
90
|
-
validateConfig,
|
|
91
148
|
ValidationError,
|
|
149
|
+
checkString,
|
|
150
|
+
checkPort,
|
|
151
|
+
checkStringArray,
|
|
152
|
+
checkObjectWithValues,
|
|
153
|
+
checkVersion,
|
|
154
|
+
checkValidURL,
|
|
92
155
|
};
|
package/lib/env.js
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* Internal dependencies
|
|
4
4
|
*/
|
|
5
5
|
const { ValidationError } = require( './config' );
|
|
6
|
+
const { AfterSetupError } = require( './execute-after-setup' );
|
|
6
7
|
const commands = require( './commands' );
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
...commands,
|
|
10
11
|
ValidationError,
|
|
12
|
+
AfterSetupError,
|
|
11
13
|
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const { execSync } = require( 'child_process' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {import('./config').WPConfig} WPConfig
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Error subtype which indicates that the afterSetup command failed.
|
|
13
|
+
*/
|
|
14
|
+
class AfterSetupError extends Error {}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Executes any defined afterSetup command.
|
|
18
|
+
*
|
|
19
|
+
* @param {WPConfig} config The config object to use.
|
|
20
|
+
* @param {Object} spinner A CLI spinner which indciates progress.
|
|
21
|
+
*/
|
|
22
|
+
function executeAfterSetup( config, spinner ) {
|
|
23
|
+
if ( ! config.afterSetup ) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
spinner.text = 'Executing Script: afterSetup';
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
let output = execSync( config.afterSetup, {
|
|
31
|
+
encoding: 'utf-8',
|
|
32
|
+
stdio: 'pipe',
|
|
33
|
+
env: process.env,
|
|
34
|
+
} );
|
|
35
|
+
|
|
36
|
+
// Remove any trailing whitespace for nicer output.
|
|
37
|
+
output = output.trimRight();
|
|
38
|
+
|
|
39
|
+
// We don't need to bother with any output if there isn't any.
|
|
40
|
+
if ( output ) {
|
|
41
|
+
spinner.info( `After Setup:\n${ output }` );
|
|
42
|
+
}
|
|
43
|
+
} catch ( error ) {
|
|
44
|
+
throw new AfterSetupError( `After Setup:\n${ error.stderr }` );
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
module.exports = {
|
|
49
|
+
AfterSetupError,
|
|
50
|
+
executeAfterSetup,
|
|
51
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* External dependencies
|
|
4
|
+
*/
|
|
5
|
+
const os = require( 'os' );
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Gets information about the host user.
|
|
9
|
+
*
|
|
10
|
+
* @return {Object} The host user's name, uid, and gid.
|
|
11
|
+
*/
|
|
12
|
+
module.exports = function getHostUser() {
|
|
13
|
+
const hostUser = os.userInfo();
|
|
14
|
+
|
|
15
|
+
// On Windows the uid and gid will be -1. Since there isn't a great way to handle this,
|
|
16
|
+
// we're just going to say that the host user is root. On Windows you'll likely be
|
|
17
|
+
// using WSL to run commands inside the container, which has a uid and gid. If
|
|
18
|
+
// you aren't, you'll be mounting directories from Windows, to a Linux
|
|
19
|
+
// VM (Docker Desktop uses one), to the guest OS. I assume that
|
|
20
|
+
// when dealing with this configuration that file ownership
|
|
21
|
+
// has the same kind of magic handling that macOS uses.
|
|
22
|
+
const uid = ( hostUser.uid === -1 ? 0 : hostUser.uid ).toString();
|
|
23
|
+
const gid = ( hostUser.gid === -1 ? 0 : hostUser.gid ).toString();
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
name: hostUser.username,
|
|
27
|
+
uid,
|
|
28
|
+
gid,
|
|
29
|
+
fullUser: uid + ':' + gid,
|
|
30
|
+
};
|
|
31
|
+
};
|
package/lib/init-config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use strict';
|
|
1
2
|
/**
|
|
2
3
|
* External dependencies
|
|
3
4
|
*/
|
|
@@ -5,12 +6,11 @@ const path = require( 'path' );
|
|
|
5
6
|
const { writeFile, mkdir } = require( 'fs' ).promises;
|
|
6
7
|
const { existsSync } = require( 'fs' );
|
|
7
8
|
const yaml = require( 'js-yaml' );
|
|
8
|
-
const os = require( 'os' );
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Internal dependencies
|
|
12
12
|
*/
|
|
13
|
-
const {
|
|
13
|
+
const { loadConfig, ValidationError } = require( './config' );
|
|
14
14
|
const buildDockerComposeConfig = require( './build-docker-compose-config' );
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -39,8 +39,7 @@ module.exports = async function initConfig( {
|
|
|
39
39
|
xdebug = 'off',
|
|
40
40
|
writeChanges = false,
|
|
41
41
|
} ) {
|
|
42
|
-
const
|
|
43
|
-
const config = await readConfig( configPath );
|
|
42
|
+
const config = await loadConfig( path.resolve( '.' ) );
|
|
44
43
|
config.debug = debug;
|
|
45
44
|
|
|
46
45
|
// Adding this to the config allows the start command to understand that the
|
|
@@ -81,13 +80,23 @@ module.exports = async function initConfig( {
|
|
|
81
80
|
yaml.dump( dockerComposeConfig )
|
|
82
81
|
);
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
// Write four Dockerfiles for each service we provided.
|
|
84
|
+
// (WordPress and CLI services, then a development and test environment for each.)
|
|
85
|
+
for ( const imageType of [ 'WordPress', 'CLI' ] ) {
|
|
86
|
+
for ( const envType of [ 'development', 'tests' ] ) {
|
|
87
|
+
await writeFile(
|
|
88
|
+
path.resolve(
|
|
89
|
+
config.workDirectoryPath,
|
|
90
|
+
`${
|
|
91
|
+
envType === 'tests' ? 'Tests-' : ''
|
|
92
|
+
}${ imageType }.Dockerfile`
|
|
93
|
+
),
|
|
94
|
+
imageType === 'WordPress'
|
|
95
|
+
? wordpressDockerFileContents( envType, config )
|
|
96
|
+
: cliDockerFileContents( envType, config )
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
91
100
|
} else if ( ! existsSync( config.workDirectoryPath ) ) {
|
|
92
101
|
spinner.fail(
|
|
93
102
|
'wp-env has not yet been initialized. Please run `wp-env start` to install the WordPress instance before using any other commands. This is only necessary to set up the environment for the first time; it is typically not necessary for the instance to be running after that in order to use other commands.'
|
|
@@ -99,80 +108,189 @@ module.exports = async function initConfig( {
|
|
|
99
108
|
};
|
|
100
109
|
|
|
101
110
|
/**
|
|
102
|
-
*
|
|
103
|
-
* against the minimum version supported by Xdebug
|
|
111
|
+
* Generates the Dockerfile used by wp-env's `wordpress` and `tests-wordpress` instances.
|
|
104
112
|
*
|
|
105
|
-
* @param {
|
|
106
|
-
* @
|
|
113
|
+
* @param {string} env The environment we're installing -- development or tests.
|
|
114
|
+
* @param {WPConfig} config The configuration object.
|
|
115
|
+
* @return {string} The dockerfile contents.
|
|
107
116
|
*/
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// If PHP version is defined
|
|
114
|
-
// ensure it meets the Xdebug minimum compatibility requirment.
|
|
115
|
-
if ( config.env.development.phpVersion ) {
|
|
116
|
-
const versionTokens = config.env.development.phpVersion.split( '.' );
|
|
117
|
-
const majorVer = parseInt( versionTokens[ 0 ] );
|
|
118
|
-
const minorVer = parseInt( versionTokens[ 1 ] );
|
|
117
|
+
function wordpressDockerFileContents( env, config ) {
|
|
118
|
+
const phpVersion = config.env[ env ].phpVersion
|
|
119
|
+
? ':php' + config.env[ env ].phpVersion
|
|
120
|
+
: '';
|
|
119
121
|
|
|
120
|
-
|
|
121
|
-
throw new Error(
|
|
122
|
-
'Something went wrong when parsing the PHP version.'
|
|
123
|
-
);
|
|
124
|
-
}
|
|
122
|
+
return `FROM wordpress${ phpVersion }
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
124
|
+
# Update apt sources for archived versions of Debian.
|
|
125
|
+
|
|
126
|
+
# stretch (https://lists.debian.org/debian-devel-announce/2023/03/msg00006.html)
|
|
127
|
+
RUN sed -i 's|deb.debian.org/debian stretch|archive.debian.org/debian stretch|g' /etc/apt/sources.list
|
|
128
|
+
RUN sed -i 's|security.debian.org/debian-security stretch|archive.debian.org/debian-security stretch|g' /etc/apt/sources.list
|
|
129
|
+
RUN sed -i '/stretch-updates/d' /etc/apt/sources.list
|
|
132
130
|
|
|
133
|
-
|
|
131
|
+
# Create the host's user so that we can match ownership in the container.
|
|
132
|
+
ARG HOST_USERNAME
|
|
133
|
+
ARG HOST_UID
|
|
134
|
+
ARG HOST_GID
|
|
135
|
+
# When the IDs are already in use we can still safely move on.
|
|
136
|
+
RUN groupadd -g $HOST_GID $HOST_USERNAME || true
|
|
137
|
+
RUN useradd -m -u $HOST_UID -g $HOST_GID $HOST_USERNAME || true
|
|
138
|
+
|
|
139
|
+
# Install any dependencies we need in the container.
|
|
140
|
+
${ installDependencies( 'wordpress', env, config ) }`;
|
|
134
141
|
}
|
|
135
142
|
|
|
136
143
|
/**
|
|
137
|
-
* Generates the Dockerfile used by wp-env's
|
|
144
|
+
* Generates the Dockerfile used by wp-env's `cli` and `tests-cli` instances.
|
|
138
145
|
*
|
|
139
|
-
* @param {string}
|
|
146
|
+
* @param {string} env The environment we're installing -- development or tests.
|
|
140
147
|
* @param {WPConfig} config The configuration object.
|
|
141
|
-
*
|
|
142
148
|
* @return {string} The dockerfile contents.
|
|
143
149
|
*/
|
|
144
|
-
function
|
|
145
|
-
|
|
146
|
-
|
|
150
|
+
function cliDockerFileContents( env, config ) {
|
|
151
|
+
const phpVersion = config.env[ env ].phpVersion
|
|
152
|
+
? '-php' + config.env[ env ].phpVersion
|
|
153
|
+
: '';
|
|
154
|
+
|
|
155
|
+
return `FROM wordpress:cli${ phpVersion }
|
|
156
|
+
|
|
157
|
+
# Switch to root so we can create users.
|
|
158
|
+
USER root
|
|
159
|
+
|
|
160
|
+
# Create the host's user so that we can match ownership in the container.
|
|
161
|
+
ARG HOST_USERNAME
|
|
162
|
+
ARG HOST_UID
|
|
163
|
+
ARG HOST_GID
|
|
164
|
+
# When the IDs are already in use we can still safely move on.
|
|
165
|
+
RUN addgroup -g $HOST_GID $HOST_USERNAME || true
|
|
166
|
+
RUN adduser -h /home/$HOST_USERNAME -G $( getent group $HOST_GID | cut -d: -f1 ) -u $HOST_UID $HOST_USERNAME || true
|
|
167
|
+
|
|
168
|
+
# Install any dependencies we need in the container.
|
|
169
|
+
${ installDependencies( 'cli', env, config ) }
|
|
170
|
+
|
|
171
|
+
# Switch back to the original user now that we're done.
|
|
172
|
+
USER www-data
|
|
173
|
+
|
|
174
|
+
# Have the container sleep infinitely to keep it alive for us to run commands on it.
|
|
175
|
+
CMD [ "/bin/sh", "-c", "while true; do sleep 2073600; done" ]
|
|
176
|
+
`;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Generates content for the Dockerfile to install dependencies.
|
|
181
|
+
*
|
|
182
|
+
* @param {string} service The kind of service that we're installing dependencies on ('wordpress' or 'cli').
|
|
183
|
+
* @param {string} env The environment we're installing dependencies for ('development' or 'tests').
|
|
184
|
+
* @param {WPConfig} config The configuration object.
|
|
185
|
+
* @return {string} The Dockerfile content for installing dependencies.
|
|
186
|
+
*/
|
|
187
|
+
function installDependencies( service, env, config ) {
|
|
188
|
+
let dockerFileContent = '';
|
|
189
|
+
|
|
190
|
+
// At times we may need to evaluate the environment. This is because the
|
|
191
|
+
// WordPress image uses Ubuntu while the CLI image uses Alpine.
|
|
147
192
|
|
|
148
|
-
|
|
149
|
-
|
|
193
|
+
// Start with some environment-specific dependency installations.
|
|
194
|
+
switch ( service ) {
|
|
195
|
+
case 'wordpress': {
|
|
196
|
+
dockerFileContent += `
|
|
197
|
+
# Make sure we're working with the latest packages.
|
|
198
|
+
RUN apt-get -qy update
|
|
150
199
|
|
|
151
|
-
|
|
152
|
-
|
|
200
|
+
# Install some basic PHP dependencies.
|
|
201
|
+
RUN apt-get -qy install $PHPIZE_DEPS && touch /usr/local/etc/php/php.ini
|
|
202
|
+
|
|
203
|
+
# Set up sudo so they can have root access.
|
|
204
|
+
RUN apt-get -qy install sudo
|
|
205
|
+
RUN echo "$HOST_USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers`;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
case 'cli': {
|
|
209
|
+
dockerFileContent += `
|
|
210
|
+
RUN apk update
|
|
211
|
+
RUN apk --no-cache add $PHPIZE_DEPS && touch /usr/local/etc/php/php.ini
|
|
212
|
+
RUN apk --no-cache add sudo linux-headers
|
|
213
|
+
RUN echo "$HOST_USERNAME ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers`;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
default: {
|
|
217
|
+
throw new Error( `Invalid service "${ service }" given` );
|
|
153
218
|
}
|
|
154
219
|
}
|
|
155
220
|
|
|
156
|
-
|
|
221
|
+
dockerFileContent += getXdebugConfig(
|
|
222
|
+
config.xdebug,
|
|
223
|
+
config.env[ env ].phpVersion
|
|
224
|
+
);
|
|
157
225
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
226
|
+
// Add better PHP settings.
|
|
227
|
+
dockerFileContent += `
|
|
228
|
+
RUN echo 'upload_max_filesize = 1G' >> /usr/local/etc/php/php.ini
|
|
229
|
+
RUN echo 'post_max_size = 1G' >> /usr/local/etc/php/php.ini`;
|
|
230
|
+
|
|
231
|
+
// Make sure Composer is available for use in all services.
|
|
232
|
+
dockerFileContent += `
|
|
233
|
+
RUN curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
|
|
234
|
+
RUN export COMPOSER_HASH=\`curl -sS https://composer.github.io/installer.sig\` && php -r "if (hash_file('SHA384', '/tmp/composer-setup.php') === '$COMPOSER_HASH') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('/tmp/composer-setup.php'); } echo PHP_EOL;"
|
|
235
|
+
RUN php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
|
|
236
|
+
RUN rm /tmp/composer-setup.php`;
|
|
237
|
+
|
|
238
|
+
// Install any Composer packages we might need globally.
|
|
239
|
+
// Make sure to do this as the user and ensure the binaries are available in the $PATH.
|
|
240
|
+
dockerFileContent += `
|
|
241
|
+
USER $HOST_USERNAME
|
|
242
|
+
ENV PATH="\${PATH}:/home/$HOST_USERNAME/.composer/vendor/bin"
|
|
243
|
+
RUN composer global require --dev yoast/phpunit-polyfills:"^1.0"
|
|
244
|
+
USER root`;
|
|
245
|
+
|
|
246
|
+
return dockerFileContent;
|
|
161
247
|
}
|
|
162
248
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
249
|
+
/**
|
|
250
|
+
* Gets the Xdebug config based on the options in the config object.
|
|
251
|
+
*
|
|
252
|
+
* @param {string} xdebugMode The Xdebug mode set in the config.
|
|
253
|
+
* @param {string} phpVersion The php version set in the environment.
|
|
254
|
+
* @return {string} The Xdebug config -- can be an empty string when it's not used.
|
|
255
|
+
*/
|
|
256
|
+
function getXdebugConfig( xdebugMode = 'off', phpVersion ) {
|
|
257
|
+
if ( xdebugMode === 'off' ) {
|
|
258
|
+
return '';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
let xdebugVersion = 'xdebug';
|
|
262
|
+
|
|
263
|
+
if ( phpVersion ) {
|
|
264
|
+
const versionTokens = phpVersion.split( '.' );
|
|
265
|
+
const majorVer = parseInt( versionTokens[ 0 ] );
|
|
266
|
+
const minorVer = parseInt( versionTokens[ 1 ] );
|
|
267
|
+
|
|
268
|
+
if ( isNaN( majorVer ) || isNaN( minorVer ) ) {
|
|
269
|
+
throw new ValidationError(
|
|
270
|
+
'Something went wrong when parsing the PHP version.'
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Throw an error if someone tries to use Xdebug with an unsupported PHP version.
|
|
275
|
+
// Xdebug 3 only supports 7.2 and higher.
|
|
276
|
+
if ( majorVer < 7 || ( majorVer === 7 && minorVer < 2 ) ) {
|
|
277
|
+
throw new ValidationError(
|
|
278
|
+
`Cannot use XDebug 3 with PHP < 7.2. Your PHP version is ${ phpVersion }.`
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// For now, we support PHP 7 by installing the final version of Xdebug to
|
|
283
|
+
// support PHP 7 when the environment uses that version. By default, use the
|
|
284
|
+
// latest version.
|
|
285
|
+
if ( majorVer === 7 ) {
|
|
286
|
+
xdebugVersion = 'xdebug-3.1.6';
|
|
287
|
+
}
|
|
288
|
+
}
|
|
169
289
|
|
|
170
290
|
return `
|
|
171
|
-
|
|
172
|
-
RUN if [ -z "$(pecl list | grep xdebug)" ] ; then pecl install xdebug ; fi
|
|
291
|
+
RUN if [ -z "$(pecl list | grep ${ xdebugVersion })" ] ; then pecl install ${ xdebugVersion } ; fi
|
|
173
292
|
RUN docker-php-ext-enable xdebug
|
|
174
293
|
RUN echo 'xdebug.start_with_request=yes' >> /usr/local/etc/php/php.ini
|
|
175
|
-
RUN echo 'xdebug.mode=${
|
|
176
|
-
RUN echo '
|
|
177
|
-
`;
|
|
294
|
+
RUN echo 'xdebug.mode=${ xdebugMode }' >> /usr/local/etc/php/php.ini
|
|
295
|
+
RUN echo 'xdebug.client_host="host.docker.internal"' >> /usr/local/etc/php/php.ini`;
|
|
178
296
|
}
|
package/lib/md5.js
CHANGED
package/lib/parse-xdebug-mode.js
CHANGED
package/lib/retry.js
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`md5 creates a hash of a number 1`] = `"55587a910882016321201e6ebbc9f595"`;
|
|
4
|
+
|
|
5
|
+
exports[`md5 creates a hash of a object 1`] = `"a0294b0e88367a0ff800d78413356538"`;
|
|
6
|
+
|
|
7
|
+
exports[`md5 creates a hash of a string 1`] = `"5d41402abc4b2a76b9719d911017c592"`;
|
|
8
|
+
|
|
9
|
+
exports[`md5 creates a hash of null 1`] = `"37a6259cc0c1dae299a7866489dff0bd"`;
|