Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
epm-docker-test
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
epm-docker-test
Commits
b77649b2
Commit
b77649b2
authored
Apr 06, 2026
by
Ivan Mazhukin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add multisystem tests
parent
2edfc216
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
230 additions
and
45 deletions
+230
-45
README.md
README.md
+41
-4
epm-docker-test.sh
epm-docker-test.sh
+189
-41
No files found.
README.md
View file @
b77649b2
...
@@ -25,6 +25,20 @@
...
@@ -25,6 +25,20 @@
./epm-docker-test.sh ayugram fedora
./epm-docker-test.sh ayugram fedora
```
```
Запуск одного приложения сразу на нескольких системах:
```
bash
./epm-docker-test.sh ayugram fedora debian ubuntu
```
Запуск по пресету:
```
bash
./epm-docker-test.sh ayugram
--preset
mainstream
./epm-docker-test.sh ayugram
--preset
russian
./epm-docker-test.sh ayugram
--preset
all
```
Запуск с явным путём к
`eepm`
:
Запуск с явным путём к
`eepm`
:
```
bash
```
bash
...
@@ -46,8 +60,9 @@
...
@@ -46,8 +60,9 @@
## Формат команды
## Формат команды
```
bash
```
bash
./epm-docker-test.sh
[
options] play <app> <system>
./epm-docker-test.sh
[
options] play <app> <system>
[
<system> ...]
./epm-docker-test.sh
[
options] <app> <system>
./epm-docker-test.sh
[
options] <app> <system>
[
<system> ...]
./epm-docker-test.sh
[
options] <app>
--preset
<name>
```
```
Сейчас поддерживается только команда
`play`
.
Сейчас поддерживается только команда
`play`
.
...
@@ -57,6 +72,13 @@
...
@@ -57,6 +72,13 @@
-
`<app>`
: имя приложения для
`epm play`
-
`<app>`
: имя приложения для
`epm play`
-
`<system>`
: целевая система или docker image
-
`<system>`
: целевая система или docker image
Можно передать:
-
одну систему;
-
несколько систем через пробел;
-
один или несколько
`--preset`
;
-
комбинацию явных систем и
`--preset`
.
Примеры нормализации
`<system>`
:
Примеры нормализации
`<system>`
:
-
`fedora`
->
`fedora:latest`
-
`fedora`
->
`fedora:latest`
...
@@ -74,8 +96,19 @@
...
@@ -74,8 +96,19 @@
-
`--eepm-dir <path>`
: явный путь к каталогу
`eepm`
-
`--eepm-dir <path>`
: явный путь к каталогу
`eepm`
-
`--builder-user <user>`
: пользователь для builder64-источника
-
`--builder-user <user>`
: пользователь для builder64-источника
-
`--builder-path <path>`
: явный builder64-путь вместо дефолта
-
`--builder-path <path>`
: явный builder64-путь вместо дефолта
-
`--preset <all|russian|mainstream>`
: добавить набор систем
-
`--log-root <path>`
: каталог для логов
-
`--log-root <path>`
: каталог для логов
## Пресеты
Сейчас определены такие пресеты:
-
`mainstream`
:
`fedora`
,
`debian`
,
`ubuntu`
,
`opensuse/leap`
,
`alpine`
,
`void`
-
`russian`
:
`alt:sisyphus`
-
`all`
:
`mainstream`
+
`russian`
Повторы автоматически удаляются после нормализации имени системы.
## Источник eepm
## Источник eepm
### local
### local
...
@@ -169,8 +202,10 @@ Runner: local docker (inside ssh session, user: builder-robot)
...
@@ -169,8 +202,10 @@ Runner: local docker (inside ssh session, user: builder-robot)
Сейчас bootstrap завязан на семейство системы:
Сейчас bootstrap завязан на семейство системы:
-
`altlinux|alt`
:
`repo set etersoft`
,
`update`
, затем установка
`wget glibc-pthread file`
-
`altlinux|alt`
:
`repo set etersoft`
,
`update`
, затем установка
`wget glibc-pthread file`
-
`debian|ubuntu`
:
`update`
, затем установка
`bash wget ca-certificates coreutils file`
-
`debian|ubuntu`
:
`update`
, затем установка
`wget ca-certificates coreutils file`
-
все остальные: установка
`wget file bash`
-
`alpine`
:
`apk update`
,
`apk add bash`
, затем
`update`
и установка
`wget file`
-
`void`
:
`xbps-install -Syu`
,
`xbps-install -Sy bash`
, затем
`update`
и установка
`wget file`
-
все остальные:
`update`
, затем установка
`wget file bash`
## Логи
## Логи
...
@@ -202,6 +237,8 @@ ayugram-fedora-latest-20260331-185448.log
...
@@ -202,6 +237,8 @@ ayugram-fedora-latest-20260331-185448.log
При ошибке скрипт дополнительно выводит короткую выборку критичных строк из лога.
При ошибке скрипт дополнительно выводит короткую выборку критичных строк из лога.
Если систем было несколько, в конце дополнительно печатается сводная таблица
`PASS/FAIL`
со ссылкой на лог каждого прогона.
## Типовые сценарии
## Типовые сценарии
Запустить локально, если Docker доступен:
Запустить локально, если Docker доступен:
...
...
epm-docker-test.sh
View file @
b77649b2
...
@@ -10,7 +10,6 @@ DEFAULT_LOG_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test"
...
@@ -10,7 +10,6 @@ DEFAULT_LOG_ROOT="${XDG_STATE_HOME:-$HOME/.local/state}/epm-docker-test"
COMMAND
=
"play"
COMMAND
=
"play"
APP_NAME
=
""
APP_NAME
=
""
SYSTEM_INPUT
=
""
SYSTEM_IMAGE
=
""
SYSTEM_IMAGE
=
""
RUN_MODE
=
"auto"
RUN_MODE
=
"auto"
REMOTE_HOST
=
"
$DEFAULT_REMOTE_HOST
"
REMOTE_HOST
=
"
$DEFAULT_REMOTE_HOST
"
...
@@ -25,22 +24,19 @@ LOG_FILE=""
...
@@ -25,22 +24,19 @@ LOG_FILE=""
REMOTE_ARGS
=()
REMOTE_ARGS
=()
REMOTE_SYNC_DIR
=
""
REMOTE_SYNC_DIR
=
""
RUN_TOKEN
=
"
$(
date
+%Y%m%d-%H%M%S
)
-
$$
"
RUN_TOKEN
=
"
$(
date
+%Y%m%d-%H%M%S
)
-
$$
"
SYSTEM_INPUTS
=()
# TODO(next):
PRESET_NAMES
=()
# - support one app across multiple systems in a single run:
TARGET_SYSTEMS
=()
# epm-docker-test.sh ayugram fedora:43 debian ubuntu alt:sisyphus
SUMMARY_SYSTEMS
=()
# - support system presets such as:
SUMMARY_RESULTS
=()
# --preset all
SUMMARY_LOGS
=()
# --preset russian
# --preset mainstream
# - print a final summary table with PASS/FAIL per system
# - keep multi-app runs out of scope for now; parallel shell is enough there
COLOR_RESET
=
""
COLOR_RESET
=
""
COLOR_WARN
=
""
COLOR_WARN
=
""
COLOR_ERROR
=
""
COLOR_ERROR
=
""
COLOR_LOG_FATAL
=
""
COLOR_LOG_FATAL
=
""
COLOR_LOG_ERROR
=
""
COLOR_LOG_ERROR
=
""
COLOR_PASS
=
""
SSH_BASE_ARGS
=(
SSH_BASE_ARGS
=(
-o
BatchMode
=
yes
-o
BatchMode
=
yes
-o
StrictHostKeyChecking
=
accept-new
-o
StrictHostKeyChecking
=
accept-new
...
@@ -52,13 +48,15 @@ if [[ -t 2 && -z "${NO_COLOR:-}" ]]; then
...
@@ -52,13 +48,15 @@ if [[ -t 2 && -z "${NO_COLOR:-}" ]]; then
COLOR_ERROR
=
$'
\0
33[31m'
COLOR_ERROR
=
$'
\0
33[31m'
COLOR_LOG_FATAL
=
$'
\0
33[31m'
COLOR_LOG_FATAL
=
$'
\0
33[31m'
COLOR_LOG_ERROR
=
$'
\0
33[33m'
COLOR_LOG_ERROR
=
$'
\0
33[33m'
COLOR_PASS
=
$'
\0
33[32m'
fi
fi
usage
()
{
usage
()
{
cat
<<
'
EOF
'
cat
<<
'
EOF
'
Usage:
Usage:
epm-docker-test.sh [options] play <app> <system>
epm-docker-test.sh [options] play <app> <system> [<system> ...]
epm-docker-test.sh [options] <app> <system>
epm-docker-test.sh [options] <app> <system> [<system> ...]
epm-docker-test.sh [options] <app> --preset <name>
Options:
Options:
--mode <auto|local|remote> Runner mode. Default: auto
--mode <auto|local|remote> Runner mode. Default: auto
...
@@ -71,11 +69,15 @@ Options:
...
@@ -71,11 +69,15 @@ Options:
--eepm-dir <path> Explicit eepm tree path
--eepm-dir <path> Explicit eepm tree path
--builder-user <user> Preferred owner for ~/Projects/... lookup
--builder-user <user> Preferred owner for ~/Projects/... lookup
--builder-path <path> Explicit builder64 source path
--builder-path <path> Explicit builder64 source path
--preset <all|russian|mainstream>
Add a named system preset
--log-root <path> Directory for saved logs
--log-root <path> Directory for saved logs
-h, --help Show this help
-h, --help Show this help
Examples:
Examples:
epm-docker-test.sh nginx fedora
epm-docker-test.sh nginx fedora
epm-docker-test.sh nginx fedora debian ubuntu
epm-docker-test.sh nginx --preset mainstream
epm-docker-test.sh play nginx Fedora/43
epm-docker-test.sh play nginx Fedora/43
epm-docker-test.sh --remote-user builder-robot --eepm-source builder64 nginx fedora:43
epm-docker-test.sh --remote-user builder-robot --eepm-source builder64 nginx fedora:43
EOF
EOF
...
@@ -132,7 +134,7 @@ normalize_system_name() {
...
@@ -132,7 +134,7 @@ normalize_system_name() {
image_tag
=
"
${
normalized
##*/
}
"
image_tag
=
"
${
normalized
##*/
}
"
case
"
$image_tag
"
in
case
"
$image_tag
"
in
[
0-9]
*
|
v[0-9]
*
)
[
0-9]
*
|
v[0-9]
*
|
p[0-9]
*
)
normalized
=
"
${
image_name
}
:
${
image_tag
}
"
normalized
=
"
${
image_name
}
:
${
image_tag
}
"
;;
;;
*
)
*
)
...
@@ -154,6 +156,61 @@ normalize_system_name() {
...
@@ -154,6 +156,61 @@ normalize_system_name() {
esac
esac
}
}
expand_preset_systems
()
{
case
"
$1
"
in
mainstream
)
printf
'%s\n'
\
fedora
\
debian
\
ubuntu
\
opensuse/leap
\
alpine
\
void
;;
russian
)
printf
'%s\n'
\
alt:sisyphus
;;
all
)
expand_preset_systems mainstream
expand_preset_systems russian
;;
*
)
fatal
"Unknown preset:
$1
"
;;
esac
}
build_target_systems
()
{
local
raw_system
local
normalized_system
local
preset_name
local
seen
=
"|"
TARGET_SYSTEMS
=()
for
preset_name
in
"
${
PRESET_NAMES
[@]
}
"
;
do
while
IFS
=
read
-r
raw_system
;
do
[[
-n
"
$raw_system
"
]]
||
continue
normalized_system
=
"
$(
normalize_system_name
"
$raw_system
"
)
"
if
[[
"
$seen
"
!=
*
"|
$normalized_system
|"
*
]]
;
then
TARGET_SYSTEMS+
=(
"
$normalized_system
"
)
seen
=
"
${
seen
}${
normalized_system
}
|"
fi
done
< <
(
expand_preset_systems
"
$preset_name
"
)
done
for
raw_system
in
"
${
SYSTEM_INPUTS
[@]
}
"
;
do
normalized_system
=
"
$(
normalize_system_name
"
$raw_system
"
)
"
if
[[
"
$seen
"
!=
*
"|
$normalized_system
|"
*
]]
;
then
TARGET_SYSTEMS+
=(
"
$normalized_system
"
)
seen
=
"
${
seen
}${
normalized_system
}
|"
fi
done
((
${#
TARGET_SYSTEMS
[@]
}
>
0
))
||
fatal
"No target systems were provided"
}
can_use_local_docker
()
{
can_use_local_docker
()
{
command
-v
docker
>
/dev/null 2>&1
||
return
1
command
-v
docker
>
/dev/null 2>&1
||
return
1
docker info
>
/dev/null 2>&1
docker info
>
/dev/null 2>&1
...
@@ -319,19 +376,63 @@ EOF
...
@@ -319,19 +376,63 @@ EOF
}
}
create_log_file
()
{
create_log_file
()
{
local
safe_app safe_system timestamp log_name
local
safe_app safe_system timestamp log_name
log_root
if
!
mkdir
-p
"
$LOG_ROOT
"
2>/dev/null
;
then
log_root
=
"
$LOG_ROOT
"
if
!
mkdir
-p
"
$log_root
"
2>/dev/null
||
[[
!
-w
"
$log_root
"
]]
;
then
warn
"Cannot write to log root
$LOG_ROOT
; falling back to
${
TMPDIR
:-
/tmp
}
/epm-docker-test"
warn
"Cannot write to log root
$LOG_ROOT
; falling back to
${
TMPDIR
:-
/tmp
}
/epm-docker-test"
LOG_ROOT
=
"
${
TMPDIR
:-
/tmp
}
/epm-docker-test"
log_root
=
"
${
TMPDIR
:-
/tmp
}
/epm-docker-test"
mkdir
-p
"
$LOG_ROOT
"
||
fatal
"Could not create log root:
$LOG_ROOT
"
mkdir
-p
"
$log_root
"
||
fatal
"Could not create log root:
$log_root
"
[[
-w
"
$log_root
"
]]
||
fatal
"Could not write to log root:
$log_root
"
fi
fi
safe_app
=
"
$(
sanitize_name
"
$APP_NAME
"
)
"
safe_app
=
"
$(
sanitize_name
"
$APP_NAME
"
)
"
safe_system
=
"
$(
sanitize_name
"
$SYSTEM_IMAGE
"
)
"
safe_system
=
"
$(
sanitize_name
"
$SYSTEM_IMAGE
"
)
"
timestamp
=
"
$(
date
+%Y%m%d-%H%M%S
)
"
timestamp
=
"
$(
date
+%Y%m%d-%H%M%S
)
"
log_name
=
"
${
safe_app
}
-
${
safe_system
}
-
${
timestamp
}
.log"
log_name
=
"
${
safe_app
}
-
${
safe_system
}
-
${
timestamp
}
.log"
printf
'%s\n'
"
$LOG_ROOT
/
$log_name
"
printf
'%s\n'
"
$log_root
/
$log_name
"
}
record_summary_result
()
{
SUMMARY_SYSTEMS+
=(
"
$1
"
)
SUMMARY_RESULTS+
=(
"
$2
"
)
SUMMARY_LOGS+
=(
"
$3
"
)
}
print_summary_table
()
{
local
i
local
system_width
=
6
local
result_label
local
result_output
((
${#
SUMMARY_SYSTEMS
[@]
}
>
1
))
||
return
0
for
i
in
"
${
!SUMMARY_SYSTEMS[@]
}
"
;
do
if
((
${#
SUMMARY_SYSTEMS
[i]
}
>
system_width
))
;
then
system_width
=
${#
SUMMARY_SYSTEMS
[i]
}
fi
done
printf
'\nSummary:\n'
printf
'%-*s %-6s %s\n'
"
$system_width
"
"System"
"Result"
"Log"
printf
'%-*s %-6s %s\n'
"
$system_width
"
"
$(
printf
'%*s'
"
$system_width
"
''
|
tr
' '
'-'
)
"
"------"
"---"
for
i
in
"
${
!SUMMARY_SYSTEMS[@]
}
"
;
do
if
((
SUMMARY_RESULTS[i]
==
0
))
;
then
result_label
=
"PASS"
result_output
=
"
${
COLOR_PASS
}${
result_label
}${
COLOR_RESET
}
"
else
result_label
=
"FAIL"
result_output
=
"
${
COLOR_ERROR
}${
result_label
}${
COLOR_RESET
}
"
fi
printf
'%-*s %s %s\n'
\
"
$system_width
"
\
"
${
SUMMARY_SYSTEMS
[i]
}
"
\
"
$result_output
"
\
"
${
SUMMARY_LOGS
[i]
}
"
done
}
}
print_failure_excerpt
()
{
print_failure_excerpt
()
{
...
@@ -571,6 +672,41 @@ run_once() {
...
@@ -571,6 +672,41 @@ run_once() {
esac
esac
}
}
run_for_system
()
{
local
system_image
=
"
$1
"
local
index
=
"
$2
"
local
total
=
"
$3
"
local
status
SYSTEM_IMAGE
=
"
$system_image
"
LOG_FILE
=
"
$(
create_log_file
)
"
if
((
total
>
1
))
;
then
info
"Run [
$index
/
$total
]: epm
$COMMAND
$APP_NAME
on
$SYSTEM_IMAGE
"
fi
info
"Log file:
$LOG_FILE
"
info
"Normalized system:
$SYSTEM_IMAGE
"
info
"Test command: epm
$COMMAND
$APP_NAME
"
if
run_once 2>&1 |
tee
"
$LOG_FILE
"
;
then
status
=
0
else
status
=
$?
fi
if
((
status
==
0
))
;
then
printf
'\nTest passed: epm %s %s on %s\n'
"
$COMMAND
"
"
$APP_NAME
"
"
$SYSTEM_IMAGE
"
printf
'Log: %s\n'
"
$LOG_FILE
"
else
printf
'\nTest failed: epm %s %s on %s\n'
"
$COMMAND
"
"
$APP_NAME
"
"
$SYSTEM_IMAGE
"
>
&2
printf
'Log: %s\n'
"
$LOG_FILE
"
>
&2
print_failure_excerpt
fi
record_summary_result
"
$SYSTEM_IMAGE
"
"
$status
"
"
$LOG_FILE
"
return
"
$status
"
}
parse_args
()
{
parse_args
()
{
local
positional
=()
local
positional
=()
...
@@ -623,6 +759,11 @@ parse_args() {
...
@@ -623,6 +759,11 @@ parse_args() {
BUILDER_PATH
=
"
$2
"
BUILDER_PATH
=
"
$2
"
shift
2
shift
2
;;
;;
--preset
)
[[
$#
-ge
2
]]
||
fatal
"--preset requires a value"
PRESET_NAMES+
=(
"
$2
"
)
shift
2
;;
--log-root
)
--log-root
)
[[
$#
-ge
2
]]
||
fatal
"--log-root requires a value"
[[
$#
-ge
2
]]
||
fatal
"--log-root requires a value"
LOG_ROOT
=
"
$2
"
LOG_ROOT
=
"
$2
"
...
@@ -649,49 +790,56 @@ parse_args() {
...
@@ -649,49 +790,56 @@ parse_args() {
*
)
*
)
positional+
=(
"
$1
"
)
positional+
=(
"
$1
"
)
shift
shift
;;
;;
esac
esac
done
done
if
((
${#
positional
[@]
}
!=
2
))
;
then
if
((
${#
positional
[@]
}
< 1
))
;
then
usage
>
&2
usage
>
&2
exit
1
exit
1
fi
fi
APP_NAME
=
"
${
positional
[0]
}
"
APP_NAME
=
"
${
positional
[0]
}
"
SYSTEM_INPUT
=
"
${
positional
[1]
}
"
SYSTEM_INPUTS
=(
"
${
positional
[@]
:1
}
"
)
if
((
${#
SYSTEM_INPUTS
[@]
}
==
0
&&
${#
PRESET_NAMES
[@]
}
==
0
))
;
then
fatal
"At least one target system or --preset is required"
fi
}
}
main
()
{
main
()
{
local
status
local
system_image
local
status
=
0
local
run_status
local
total
local
index
=
0
parse_args
"
$@
"
parse_args
"
$@
"
SYSTEM_IMAGE
=
"
$(
normalize_system_name
"
$SYSTEM_INPUT
"
)
"
if
((
INTERNAL_LOCAL_RUN
))
;
then
if
((
INTERNAL_LOCAL_RUN
))
;
then
build_target_systems
if
((
${#
TARGET_SYSTEMS
[@]
}
!=
1
))
;
then
fatal
"Internal local run expects exactly one target system"
fi
SYSTEM_IMAGE
=
"
${
TARGET_SYSTEMS
[0]
}
"
run_once
run_once
return
0
return
0
fi
fi
LOG_FILE
=
"
$(
create_log_file
)
"
build_target_systems
info
"Log file:
$LOG_FILE
"
total
=
"
${#
TARGET_SYSTEMS
[@]
}
"
info
"Normalized system:
$SYSTEM_IMAGE
"
info
"Test command: epm
$COMMAND
$APP_NAME
"
if
run_once 2>&1 |
tee
"
$LOG_FILE
"
;
then
for
system_image
in
"
${
TARGET_SYSTEMS
[@]
}
"
;
do
status
=
0
((
index +
=
1
))
else
if
run_for_system
"
$system_image
"
"
$index
"
"
$total
"
;
then
status
=
$?
run_status
=
0
fi
else
run_status
=
$?
status
=
"
$run_status
"
fi
done
if
((
status
==
0
))
;
then
print_summary_table
printf
'\nTest passed: epm %s %s on %s\n'
"
$COMMAND
"
"
$APP_NAME
"
"
$SYSTEM_IMAGE
"
printf
'Log: %s\n'
"
$LOG_FILE
"
else
printf
'\nTest failed: epm %s %s on %s\n'
"
$COMMAND
"
"
$APP_NAME
"
"
$SYSTEM_IMAGE
"
>
&2
printf
'Log: %s\n'
"
$LOG_FILE
"
>
&2
print_failure_excerpt
fi
return
"
$status
"
return
"
$status
"
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment