ЁЯУо рдзрдбрд╛ 11 тАФ CI рдЖрдгрд┐ containers рдордзрд▓реНрдпрд╛ scripts: рдореЗрд▓рд░реВрдо
ЁЯУН рддреБрдореНрд╣реА рдЗрдереЗ рдЖрд╣рд╛рдд: 12 рдкреИрдХреА рдзрдбрд╛ 11 ┬╖ рдкреБрдвреЗ: lesson-12-debugging-testing
ЁЯУж рдпрд╛ рдмреНрд░рдБрдЪрдордзреНрдпреЗ рдХрд╛рдп рдЖрд╣реЗ
рдзрдбреЗ 01тАУ11. рддреНрдпрд╛рдЪ scripts, CI runner рдиреЗ рдЖрдгрд┐ container рдЪреНрдпрд╛ рдЖрдд рдЪрд╛рд▓рд╡рд▓реЗрд▓реНрдпрд╛ тАФ рдХрд╛рдп рдмрджрд▓рддреЗ, рдЖрдгрд┐ рдкреНрд░рддреНрдпреЗрдХ entrypoint рд▓рд╛ рд▓рд╛рдЧрдгрд╛рд▒реНрдпрд╛ рддреАрди рдУрд│реА.
- tests/run_tests.sh тАФ CI step рдЬреЗ рдЪрд╛рд▓рд╡рддреЗ рддреЗ
- bin/backup.sh тАФ terminal, prompt, рд░рдВрдЧ рдпрд╛рдВрдЪреНрдпрд╛рд╢рд┐рд╡рд╛рдп рдЪрд╛рд▓рдгрд╛рд░реА script
ЁЯзТ 5 рд╡рд░реНрд╖рд╛рдВрдЪреНрдпрд╛ рдореБрд▓рд╛рд▓рд╛ рд╕рдордЬрд╛рд╡рд▓реНрдпрд╛рд╕рд╛рд░рдЦреЗ
рдореЗрд▓рд░реВрдо (CI) рдордзреНрдпреЗ рдЖрдгрд┐ shipping container (Docker) рдЪреНрдпрд╛ рдЖрдд рдХреЗрдЕрд░рдЯреЗрдХрд░рдЪреЗ
рдСрдлрд┐рд╕ рдирд╕рддреЗ: screen рдирд╛рд╣реА, keyboard рдирд╛рд╣реА, рдкреНрд░рд╢реНрдирд╛рдЪреЗ рдЙрддреНрддрд░ рджреНрдпрд╛рдпрд▓рд╛ рдХреЛрдгреА рдирд╛рд╣реА.
script рд▓рд╛ рдЬреЗ environment рджрд┐рд▓реЗ рдЬрд╛рддреЗ рддреНрдпрд╛рддреВрдирдЪ рддрд┐рд▓рд╛ рд╕рдЧрд│реЗ рдХрд│рд╛рдпрд▓рд╛ рд╣рд╡реЗ, рддрд┐рдиреЗ рдХрд╛рдп рдХреЗрд▓реЗ рддреЗ
log рдордзреНрдпреЗ рд╕рд╛рдВрдЧрд╛рдпрд▓рд╛ рд╣рд╡реЗ, рдЖрдгрд┐ рдПрдХ exit code рдкрд░рдд рджреНрдпрд╛рдпрд▓рд╛ рд╣рд╡рд╛. container рдЪреНрдпрд╛ рдЖрдд
script рд╣реА рдмрд▒реНрдпрд╛рдЪрджрд╛ рдЗрдорд╛рд░рддреАрддрд▓реА рдЕрдЧрджреА рдкрд╣рд┐рд▓реА рд╡реНрдпрдХреНрддреА рдЕрд╕рддреЗ тАФ PID 1 тАФ
рдореНрд╣рдгреВрди рддрд┐рдЪреА рд╢реЗрд╡рдЯрдЪреА рдХреГрддреА рдореНрд╣рдгрдЬреЗ рдмрд╛рдЬреВрд▓рд╛ рд╣реЛрдКрди рдЦрд▒реНрдпрд╛ program рд▓рд╛ badge рдШреЗрдК
рджреЗрдгреЗ: exec "$@".
ЁЯЧ║я╕П рдЖрдХреГрддреА
flowchart LR
G["ЁЯУо GitHub Actions<br/>run: bash tests/run_tests.sh"] --> X["exit 0 тЖТ green tick<br/>exit 1 тЖТ red cross"]
D["ЁЯР│ docker run img"] --> E["entrypoint.sh<br/>set -euo pipefail ┬╖ read $ENV ┬╖ exec \"$@\""] --> A["the app as PID 1"]
тЭУ рдХрд╛рдп
- Shebang:
#!/usr/bin/env bashPATHрд╡рд░ bash рд╢реЛрдзрддреЛ;#!/bin/shрдореНрд╣рдгрдЬреЗ POSIX sh тАФ alpine рдЖрдгрд┐ busybox рдордзреНрдпреЗ bash рдирд╕рддреЛ. Bashisms:[[ ]], arrays,${x//a/b},local,pipefail. - CI: non-interactive (
TERMdumb рдЕрд╕реВ рд╢рдХрддреЛ; prompts рдирд╛рд╣реАрдд;< /dev/null), рдирд╡рд╛ checkout, secrets env vars рдореНрд╣рдгреВрди, exit code рд╣рд┐рд░рд╡реА рдЦреВрдг рдард░рд╡рддреЛ. - Containers:
ENTRYPOINT ["bin/entrypoint.sh"],CMD ["app"]; script рддрдпрд╛рд░реА рдХрд░рддреЗ (env, config, migrations) рдордЧexec "$@"; TERM app рдкрд░реНрдпрдВрдд рдкреЛрд╣реЛрдЪрд╛рд╡рд╛ рдореНрд╣рдгреВрдиtiniрдХрд┐рдВрд╡рд╛exec. - Secrets: script рдордзреНрдпреЗ рдХрд┐рдВрд╡рд╛ image рдордзреНрдпреЗ рдХрдзреАрдЪ рдирд╛рд╣реАрдд; environment рдордзреВрди рдХрд┐рдВрд╡рд╛ store рдордзреВрди;
рддреНрдпрд╛ рдЫрд╛рдкреВ рд╢рдХрдгрд╛рд▒реНрдпрд╛ рдХреЛрдгрддреНрдпрд╛рд╣реА рдЧреЛрд╖реНрдЯреАрднреЛрд╡рддреА
set +x. - Locale рдЖрдгрд┐ tools рд╡реЗрдЧрд│реЗ рдЕрд╕рддрд╛рдд:
sed -i,date,readlink -fрд╣реЗ macOS рдЖрдгрд┐ Linux рдордзреНрдпреЗ рд╡реЗрдЧрд│реЗ рд╡рд╛рдЧрддрд╛рдд тАФ рддреБрдореНрд╣реА ship рдХрд░рддрд╛ рддреНрдпрд╛рдЪ container рдордзреНрдпреЗ test рдХрд░рд╛.
ЁЯдФ рдХрд╛
"рдорд╛рдЭреНрдпрд╛ machine рд╡рд░ рдЪрд╛рд▓рддреЗ" рдпрд╛рдЪреЗ рдХрд╛рд░рдг рдЬрд╡рд│рдЬрд╡рд│ рдиреЗрд╣рдореА environment рдЕрд╕рддреЗ: PATH, HOME,
shell, locale, рддреБрдордЪреНрдпрд╛ laptop рд╡рд░ рдЕрд╕рд▓реЗрд▓рд╛ рдкрдг image рдордзреНрдпреЗ рдирд╕рд▓реЗрд▓рд╛ рдПрдЦрд╛рджрд╛ tool.
рд╕реБрд░реБрд╡рд╛рддреАрдкрд╛рд╕реВрдирдЪ рдореЗрд▓рд░реВрдорд╕рд╛рдареА рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ scripts рдирд╛ рд╣рд╛ рддреНрд░рд╛рд╕ рдХрдзреАрдЪ рд╣реЛрдд рдирд╛рд╣реА.
ЁЯФз рдХрд╕реЗ (рдпрд╛ repo рдордзреНрдпреЗ)
рдЗрдерд▓реНрдпрд╛ рдкреНрд░рддреНрдпреЗрдХ script рдордзреНрдпреЗ #!/usr/bin/env bash, strict mode рдЖрд╣реЗ, prompts рдирд╛рд╣реАрдд, рдЖрдгрд┐
рддреА рдЖрдкрд▓реЗ inputs flags рдордзреВрди рдХрд┐рдВрд╡рд╛ SCHOOL_REGISTER рдордзреВрди рдШреЗрддреЗ. CI/CD рд╢рд╛рд│рд╛ рдпрд╛ repo рдЪреНрдпрд╛
рдкреНрд░рддреНрдпреЗрдХ push рд╡рд░ tests/run_tests.sh рдЪрд╛рд▓рд╡рддреЗ.
ЁЯзк рдХрд░реВрди рдкрд╛рд╣рд╛
bash -n bin/*.sh && echo "syntax ok" # what a CI lint step does first
env -i PATH=/usr/bin:/bin HOME=/nonexistent bash tests/run_tests.sh | tail -1 # a bare environment, like cron or CI
docker run --rm -v "$PWD:/s" -w /s bash:5 bash tests/run_tests.sh | tail -1 # (if Docker) inside a container
docker run --rm -v "$PWD:/s" -w /s alpine sh -c 'sh bin/school.sh list' # alpine has no bash: watch it fail on [[ ]]
cat > /tmp/entrypoint.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
echo "preparing with REGISTER=${SCHOOL_REGISTER:-default}" >&2
exec "$@"
EOF
chmod +x /tmp/entrypoint.sh; SCHOOL_REGISTER=x /tmp/entrypoint.sh echo "now I am the app"
тЬЕ рддрдкрд╛рд╕рд╛ тАФ рддреБрдореНрд╣рд╛рд▓рд╛ рдХрд╛рдп рджрд┐рд╕рд╛рдпрд▓рд╛ рд╣рд╡реЗ
syntax ok; рдореЛрдХрд│реНрдпрд╛ environment рдордзреНрдпреЗ рдЖрдгрд┐ bash container рдордзреНрдпреЗ 14 passed, 0 failed;
alpine рдЪрд╛ run рдкрд╣рд┐рд▓реНрдпрд╛рдЪ bashism рд╡рд░ fail рд╣реЛрддреЛ; entrypoint рдЖрдкрд▓реА рддрдпрд╛рд░реА stderr рд╡рд░ log
рдХрд░рддреЗ рдЖрдгрд┐ echo рдмрджрд▓рд▓реЗрд▓рд╛ process рдореНрд╣рдгреВрди рдЪрд╛рд▓рддреЛ.
ЁЯПБ рддреБрдореНрд╣реА рдЖрддреНрддрд╛рдЪ рдХрд╛рдп рд╕рд┐рджреНрдз рдХреЗрд▓реЗ
рддреБрдордЪреНрдпрд╛ scripts рдореЛрдХрд│реНрдпрд╛ environment рдордзреНрдпреЗ рдЖрдгрд┐ container рдордзреНрдпреЗ рдЯрд┐рдХрддрд╛рдд, рдЖрдгрд┐ PID 1 рдЦрд▒реНрдпрд╛ program рдХрдбреЗ рд╕реЛрдкрд╡рдгрд╛рд░реА entrypoint рддреБрдореНрд╣реА рд▓рд┐рд╣реВ рд╢рдХрддрд╛.
тЪая╕П рдиреЗрд╣рдореАрдЪреНрдпрд╛ рдЪреБрдХрд╛
[[ ]]рдиреЗ рднрд░рд▓реЗрд▓реНрдпрд╛ script рд╡рд░#!/bin/shтАФ Ubuntu рд╡рд░ рдЪрд╛рд▓рддреЗ (dash рддреБрдореНрд╣рд╛рд▓рд╛ рд╡рд╛рдЯрддреЗ рддреНрдпрд╛рдкреЗрдХреНрд╖рд╛ рдХрдореА рд╕рд╣рди рдХрд░рддреЛ), alpine рд╡рд░ рдорд░рддреЗ.set -xрдЪрд╛рд▓реВ рдЕрд╕рддрд╛рдирд╛ secret рдЫрд╛рдкрдгреЗ.exec ./appрдРрд╡рдЬреА./appрдиреЗ рд╕рдВрдкрдгрд╛рд░реА entrypoint тАФ app рд▓рд╛ TERM рдХрдзреАрдЪ рдорд┐рд│рдд рдирд╛рд╣реА.
ЁЯПн рдкреНрд░рддреНрдпрдХреНрд╖ рд╡рд╛рдкрд░рд╛рдд рд╣реЗ рдХрд╛ рдорд╣рддреНрддреНрд╡рд╛рдЪреЗ: рдкреНрд░рддреНрдпреЗрдХ Dockerfile рдЪрд╛
ENTRYPOINT, рдкреНрд░рддреНрдпреЗрдХ CIrun:block, рдкреНрд░рддреНрдпреЗрдХkubectl exec тАж shрдореНрд╣рдгрдЬреЗ рд╣рд╛рдЪ рдзрдбрд╛. Docker рдЖрдгрд┐ CI/CD рд╢рд╛рд│рд╛ рдореНрд╣рдгрдЬреЗ рдЬрд┐рдереЗ рдпрд╛ scripts рд░рд╛рд╣рддрд╛рдд.
тПня╕П рдкреБрдвреЗ
рдзрдбрд╛ 12 тАФ debugging рдЖрдгрд┐ testing: script рдХрд╛рдп рдХрд░рддреЗ рддреЗ рдкрд╛рд╣рд╛, рдЖрдгрд┐ bash рдордзреНрдпреЗ рд▓рд┐рд╣рд┐рд▓реЗрд▓реНрдпрд╛ test runner рдиреЗ рддреЗ рд╕рд┐рджреНрдз рдХрд░рд╛.