1
1
#! /usr/bin/env bash
2
2
3
- #
4
- # Test runner based on docker and docker-compose.
5
- #
6
-
7
- # Function to write a .env file in Build/testing-docker/local
8
- # This is read by docker-compose and vars defined here are
9
- # used in Build/testing-docker/docker-compose.yml
10
- setUpDockerComposeDotEnv () {
11
- # Delete possibly existing local .env file if exists
12
- [ -e .env ] && rm .env
13
- # Set up a new .env file for docker-compose
14
- echo " COMPOSE_PROJECT_NAME=local" >> .env
15
- # To prevent access rights of files created by the testing, the docker image later
16
- # runs with the same user that is currently executing the script. docker-compose can't
17
- # use $UID directly itself since it is a shell variable and not an env variable, so
18
- # we have to set it explicitly here.
19
- echo " HOST_UID=` id -u` " >> .env
20
- # Your local home directory for composer and npm caching
21
- echo " HOST_HOME=${HOME} " >> .env
22
- # Your local user
23
- echo " ROOT_DIR" =${ROOT_DIR} >> .env
24
- echo " HOST_USER=${USER} " >> .env
25
- echo " PHP_XDEBUG_ON=${PHP_XDEBUG_ON} " >> .env
26
- echo " DOCKER_PHP_IMAGE=${DOCKER_PHP_IMAGE} " >> .env
27
- echo " SCRIPT_VERBOSE=${SCRIPT_VERBOSE} " >> .env
28
- echo " CGLCHECK_DRY_RUN=${CGLCHECK_DRY_RUN} " >> .env
29
- echo " IMAGE_PREFIX=${IMAGE_PREFIX} " >> .env
3
+ cleanUp () {
4
+ ATTACHED_CONTAINERS=$( ${CONTAINER_BIN} ps --filter network=${NETWORK} --format=' {{.Names}} 2>/dev/null' )
5
+ if [[ -n $ATTACHED_CONTAINERS ]]; then
6
+ for ATTACHED_CONTAINER in ${ATTACHED_CONTAINERS} ; do
7
+ ${CONTAINER_BIN} kill ${ATTACHED_CONTAINER} > /dev/null
8
+ done
9
+ ${CONTAINER_BIN} network rm ${NETWORK} > /dev/null
10
+ fi
30
11
}
31
12
32
13
# Load help text into $HELP
@@ -49,14 +30,22 @@ Options:
49
30
- phpstanGenerateBaseline: regenerate phpstan baseline, handy after phpstan updates
50
31
- unit (default): PHP unit tests
51
32
52
- -p <7.2|7.3|7.4|8.0|8.1|8.2>
33
+ -b <docker|podman>
34
+ Container environment:
35
+ - podman
36
+ - docker
37
+
38
+ If not provided, podman will be used first if both are installed.
39
+
40
+ -p <7.2|7.3|7.4|8.0|8.1|8.2|8.3>
53
41
Specifies the PHP minor version to be used
54
42
- 7.2 (default): use PHP 7.2
55
43
- 7.3: use PHP 7.3
56
44
- 7.4: use PHP 7.4
57
45
- 8.0: use PHP 8.0
58
46
- 8.1: use PHP 8.1
59
47
- 8.2: use PHP 8.2
48
+ - 8.3: use PHP 8.3
60
49
61
50
-x
62
51
Only with -s cgl|unit
@@ -68,56 +57,68 @@ Options:
68
57
Only with -s cgl
69
58
Activate dry-run in CGL check that does not actively change files and only prints broken ones.
70
59
71
- -v
72
- Enable verbose script output. Shows variables and docker commands.
73
-
74
60
-h
75
61
Show this help.
76
62
77
63
Examples:
78
64
# Run unit tests using default PHP version
79
65
./Build/Scripts/runTests.sh
80
66
81
- # Run unit tests using PHP 7.4
82
- ./Build/Scripts/runTests.sh -p 7.4
67
+ # Run unit tests using PHP 8.1
68
+ ./Build/Scripts/runTests.sh -p 8.1
83
69
EOF
84
70
85
- # Test if docker-compose exists, else exit out with error
86
- if ! type " docker-compose " > /dev/null; then
87
- echo " This script relies on docker and docker-compose . Please install" >&2
88
- exit 1
71
+ # Test if docker exists, else exit out with error
72
+ if ! type " docker" > /dev/null 2>&1 && ! type " podman " > /dev/null 2>&1 ; then
73
+ echo " This script relies on docker or podman . Please install" >&2
74
+ exit 1
89
75
fi
90
76
91
77
# Go to the directory this script is located, so everything else is relative
92
78
# to this dir, no matter from where this script is called.
93
79
THIS_SCRIPT_DIR=" $( cd " $( dirname " ${BASH_SOURCE[0]} " ) " > /dev/null && pwd ) "
94
80
cd " $THIS_SCRIPT_DIR " || exit 1
95
-
96
- # Go to directory that contains the local docker-compose.yml file
97
- cd ../testing-docker || exit 1
81
+ cd ../../ || exit 1
98
82
99
83
# Option defaults
100
- ROOT_DIR=` readlink -f ${PWD} /../../ `
84
+ ROOT_DIR=` readlink -f ${PWD} `
101
85
TEST_SUITE=" unit"
102
86
PHP_VERSION=" 7.2"
103
87
PHP_XDEBUG_ON=0
104
88
SCRIPT_VERBOSE=0
105
89
CGLCHECK_DRY_RUN=" "
106
- IMAGE_PREFIX=" ghcr.io/typo3/"
90
+ CONTAINER_BIN=" "
91
+ CONTAINER_INTERACTIVE=" -it --init"
92
+ HOST_UID=$( id -u)
93
+ HOST_PID=$( id -g)
94
+ USERSET=" "
95
+ SUFFIX=$( echo $RANDOM )
96
+ NETWORK=" testing-framework-${SUFFIX} "
97
+ CI_PARAMS=" "
98
+ CONTAINER_HOST=" host.docker.internal"
107
99
108
100
# Option parsing
109
101
# Reset in case getopts has been used previously in the shell
110
102
OPTIND=1
111
103
# Array for invalid options
112
104
INVALID_OPTIONS=();
113
105
# Simple option parsing based on getopts (! not getopt)
114
- while getopts " :s:p:hxnv " OPT; do
106
+ while getopts " :b: s:p:hxn " OPT; do
115
107
case ${OPT} in
116
108
s)
117
109
TEST_SUITE=${OPTARG}
118
110
;;
111
+ b)
112
+ if ! [[ ${OPTARG} =~ ^(docker| podman)$ ]]; then
113
+ INVALID_OPTIONS+=(" ${OPTARG} " )
114
+ fi
115
+ CONTAINER_BIN=${OPTARG}
116
+ ;;
119
117
p)
120
118
PHP_VERSION=${OPTARG}
119
+ if ! [[ ${PHP_VERSION} =~ ^(7.2| 7.3| 7.4| 8.0| 8.1| 8.2| 8.3)$ ]]; then
120
+ INVALID_OPTIONS+=(" ${OPTARG} " )
121
+ fi
121
122
;;
122
123
h)
123
124
echo " ${HELP} "
@@ -126,9 +127,6 @@ while getopts ":s:p:hxnv" OPT; do
126
127
n)
127
128
CGLCHECK_DRY_RUN=" -n"
128
129
;;
129
- v)
130
- SCRIPT_VERBOSE=1
131
- ;;
132
130
x)
133
131
PHP_XDEBUG_ON=1
134
132
;;
@@ -148,15 +146,62 @@ if [ ${#INVALID_OPTIONS[@]} -ne 0 ]; then
148
146
echo " -" ${I} >&2
149
147
done
150
148
echo >&2
151
- echo " ${HELP} " >&2
149
+ echo " Use \" .Build/Scripts/runTests.sh -h\" to display help and valid options" >&2
150
+ exit 1
151
+ fi
152
+
153
+ # ENV var "CI" is set by gitlab-ci. Use it to force some CI details.
154
+ if [ " ${CI} " == " true" ]; then
155
+ CONTAINER_INTERACTIVE=" "
156
+ # @todo Enforce pull-never once we have cached image folder similar to Core CI runner image caches.
157
+ # CI_PARAMS="--pull=never"
158
+ fi
159
+
160
+ # determine default container binary to use: 1. podman 2. docker
161
+ if [[ -z " ${CONTAINER_BIN} " ]]; then
162
+ if type " podman" > /dev/null 2>&1 ; then
163
+ CONTAINER_BIN=" podman"
164
+ elif type " docker" > /dev/null 2>&1 ; then
165
+ CONTAINER_BIN=" docker"
166
+ fi
167
+ fi
168
+
169
+ if [ $( uname) != " Darwin" ] && [ ${CONTAINER_BIN} = " docker" ]; then
170
+ # Run docker jobs as current user to prevent permission issues. Not needed with podman.
171
+ USERSET=" --user $HOST_UID "
172
+ fi
173
+
174
+ if ! type ${CONTAINER_BIN} > /dev/null 2>&1 ; then
175
+ echo " Selected container environment \" ${CONTAINER_BIN} \" not found. Please install or use -b option to select one." >&2
152
176
exit 1
153
177
fi
154
178
155
- # Move "7.2" to "php72", the latter is the docker container name
156
- DOCKER_PHP_IMAGE=` echo " php${PHP_VERSION} " | sed -e ' s/\.//' `
179
+ IMAGE_PHP=" ghcr.io/typo3/core-testing-$( echo " php${PHP_VERSION} " | sed -e ' s/\.//' ) :latest"
180
+
181
+ if [[ -d " ../../Build/testing-docker" ]]; then
182
+ rm -rf ../../Build/testing-docker
183
+ fi
184
+
185
+ # Remove handled options and leaving the rest in the line, so it can be passed raw to commands
186
+ shift $(( OPTIND - 1 ))
157
187
158
- if [ ${SCRIPT_VERBOSE} -eq 1 ]; then
159
- set -x
188
+ ${CONTAINER_BIN} network create ${NETWORK} > /dev/null
189
+
190
+ if [ ${CONTAINER_BIN} = " docker" ]; then
191
+ # docker needs the add-host for xdebug remote debugging. podman has host.container.internal built in
192
+ CONTAINER_COMMON_PARAMS=" ${CONTAINER_INTERACTIVE} --rm --network ${NETWORK} --add-host " ${CONTAINER_HOST} :host-gateway" ${USERSET} -v ${ROOT_DIR} :${ROOT_DIR} -w ${ROOT_DIR} "
193
+ else
194
+ # podman
195
+ CONTAINER_HOST=" host.containers.internal"
196
+ CONTAINER_COMMON_PARAMS=" ${CONTAINER_INTERACTIVE} ${CI_PARAMS} --rm --network ${NETWORK} -v ${ROOT_DIR} :${ROOT_DIR} -w ${ROOT_DIR} "
197
+ fi
198
+
199
+ if [ ${PHP_XDEBUG_ON} -eq 0 ]; then
200
+ XDEBUG_MODE=" -e XDEBUG_MODE=off"
201
+ XDEBUG_CONFIG=" "
202
+ else
203
+ XDEBUG_MODE=" -e XDEBUG_MODE=debug -e XDEBUG_TRIGGER=foo"
204
+ XDEBUG_CONFIG=" client_port=${PHP_XDEBUG_PORT} client_host=${CONTAINER_HOST} "
160
205
fi
161
206
162
207
# Suite execution
@@ -166,43 +211,36 @@ case ${TEST_SUITE} in
166
211
if [[ ! -z ${CGLCHECK_DRY_RUN} ]]; then
167
212
CGLCHECK_DRY_RUN=" --dry-run --diff"
168
213
fi
169
- setUpDockerComposeDotEnv
170
- docker-compose run cgl
214
+ COMMAND= " php -dxdebug.mode=off .Build/bin/php-cs-fixer fix -v ${CGLCHECK_DRY_RUN} --path-mode intersection --config=Build/php-cs-fixer/config.php "
215
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name cgl- ${SUFFIX} ${IMAGE_PHP} ${COMMAND}
171
216
SUITE_EXIT_CODE=$?
172
- docker-compose down
173
217
;;
174
218
clean)
175
219
rm -rf ../../composer.lock ../../.Build/ ../../public
176
220
;;
177
221
composerUpdate)
178
- setUpDockerComposeDotEnv
179
- docker-compose run composer_update
222
+ COMMAND=(composer update --no-progress --no-interaction)
223
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name composer-update- ${SUFFIX} -e COMPOSER_CACHE_DIR=.Build/.cache/composer ${IMAGE_PHP} " ${COMMAND[@]} "
180
224
SUITE_EXIT_CODE=$?
181
- docker-compose down
182
225
;;
183
226
lint)
184
- setUpDockerComposeDotEnv
185
- docker-compose run lint
227
+ COMMAND= " php -v | grep '^PHP'; find . -name '*.php' ! -path './.Build/*' ! -path './public/*' -print0 | xargs -0 -n1 -P4 php -dxdebug.mode=off -l >/dev/null "
228
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name lint-php- ${SUFFIX} ${IMAGE_PHP} /bin/sh -c " ${COMMAND} "
186
229
SUITE_EXIT_CODE=$?
187
- docker-compose down
188
230
;;
189
231
phpstan)
190
- setUpDockerComposeDotEnv
191
- docker-compose run phpstan
232
+ COMMAND=(php -dxdebug.mode=off .Build/bin/phpstan analyse -c Build/phpstan/phpstan.neon --no-progress --no-interaction --memory-limit 4G " $@ " )
233
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan- ${SUFFIX} ${IMAGE_PHP} " ${COMMAND[@]} "
192
234
SUITE_EXIT_CODE=$?
193
- docker-compose down
194
235
;;
195
236
phpstanGenerateBaseline)
196
- setUpDockerComposeDotEnv
197
- docker-compose run phpstan_generate_baseline
237
+ COMMAND= " php -dxdebug.mode=off .Build/bin/phpstan analyse -c Build/phpstan/phpstan.neon --no-progress --no-interaction --memory-limit 4G --generate-baseline=Build/phpstan/phpstan-baseline.neon "
238
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name phpstan-baseline- ${SUFFIX} ${IMAGE_PHP} /bin/sh -c " ${COMMAND} "
198
239
SUITE_EXIT_CODE=$?
199
- docker-compose down
200
240
;;
201
241
unit)
202
- setUpDockerComposeDotEnv
203
- docker-compose run unit
242
+ ${CONTAINER_BIN} run ${CONTAINER_COMMON_PARAMS} --name unit-${SUFFIX} ${XDEBUG_MODE} -e XDEBUG_CONFIG=" ${XDEBUG_CONFIG} " ${IMAGE_PHP} .Build/bin/phpunit Tests/Unit/ " $@ "
204
243
SUITE_EXIT_CODE=$?
205
- docker-compose down
206
244
;;
207
245
* )
208
246
echo " Invalid -s option argument ${TEST_SUITE} " >&2
@@ -211,4 +249,35 @@ case ${TEST_SUITE} in
211
249
exit 1
212
250
esac
213
251
252
+ cleanUp
253
+
254
+ # Print summary
255
+ echo " " >&2
256
+ echo " ###########################################################################" >&2
257
+ echo " Result of ${TEST_SUITE} " >&2
258
+ echo " Container runtime: ${CONTAINER_BIN} " >&2
259
+ echo " PHP: ${PHP_VERSION} " >&2
260
+ if [[ ${TEST_SUITE} =~ ^(functional| functionalDeprecated| acceptance| acceptanceInstall)$ ]]; then
261
+ case " ${DBMS} " in
262
+ mariadb|mysql|postgres)
263
+ echo " DBMS: ${DBMS} version ${DBMS_VERSION} driver ${DATABASE_DRIVER} " >&2
264
+ ;;
265
+ sqlite)
266
+ echo " DBMS: ${DBMS} " >&2
267
+ ;;
268
+ esac
269
+ fi
270
+ if [[ -n ${EXTRA_TEST_OPTIONS} ]]; then
271
+ echo " Note: Using -e is deprecated. Simply add the options at the end of the command."
272
+ echo " Instead of: Build/Scripts/runTests.sh -s ${TEST_SUITE} -e '${EXTRA_TEST_OPTIONS} ' $@ "
273
+ echo " use: Build/Scripts/runTests.sh -s ${TEST_SUITE} -- ${EXTRA_TEST_OPTIONS} $@ "
274
+ fi
275
+ if [[ ${SUITE_EXIT_CODE} -eq 0 ]]; then
276
+ echo " SUCCESS" >&2
277
+ else
278
+ echo " FAILURE" >&2
279
+ fi
280
+ echo " ###########################################################################" >&2
281
+ echo " " >&2
282
+
214
283
exit $SUITE_EXIT_CODE
0 commit comments