From 50491b3c38ed61ce9c5a34a3627a585458e24ab8 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Mon, 15 Jan 2024 15:48:14 -0800 Subject: [PATCH 1/2] ci(docker-build): add python layer --- .github/citools/common/gh-setup-env | 20 ++ .github/citools/includes/wrapper-library | 27 +++ .github/citools/python/python-lint-formatter | 26 ++ .github/citools/python/python-setup-config | 24 ++ .github/citools/python/python-setup-install | 227 ++++++++++++++++++ .github/citools/python/python-setup-verify | 59 +++++ .../citools/python/python-test-with-coverage | 50 ++++ .github/docker/layer-18.00-exercism-python.sh | 65 +++++ Dockerfile | 2 + 9 files changed, 500 insertions(+) create mode 100755 .github/citools/python/python-lint-formatter create mode 100755 .github/citools/python/python-setup-config create mode 100755 .github/citools/python/python-setup-install create mode 100755 .github/citools/python/python-setup-verify create mode 100755 .github/citools/python/python-test-with-coverage create mode 100755 .github/docker/layer-18.00-exercism-python.sh diff --git a/.github/citools/common/gh-setup-env b/.github/citools/common/gh-setup-env index 8cf05fb6..ed23196d 100755 --- a/.github/citools/common/gh-setup-env +++ b/.github/citools/common/gh-setup-env @@ -131,6 +131,26 @@ main() { print_ruler + source /etc/profile.d/python.sh || track_errors + + printf "Adding Python paths to GITHUB_PATH...\n" + printf "%s\n" "/usr/local/pyenv/bin" "/usr/local/pyenv/shims" | tee -a "${GITHUB_PATH}" + + echo Adding source /etc/profile.d/ruby.sh to ~/.bashrc + echo '. /etc/profile.d/ruby.sh' | tee -a "${HOME}/.bashrc" || track_errors + printf "\n" + + printf "Setup Python symlinks for github user:\n" + cd "${HOME}" || track_errors + if [[ ! -d .pyenv ]]; then + ln -sv "/usr/local/pyenv" .pyenv || track_errors + fi + ls -l ~/.pyenv + cd - || track_errors + printf "\n" + + print_ruler + tail -n 1000 -v "${GITHUB_PATH}" print_ruler diff --git a/.github/citools/includes/wrapper-library b/.github/citools/includes/wrapper-library index 07e55f61..411d523d 100644 --- a/.github/citools/includes/wrapper-library +++ b/.github/citools/includes/wrapper-library @@ -207,3 +207,30 @@ show_tool_versions_node() { # md_code_tag printf "\n" } # show_tool_versions_node() + +show_tool_versions_python_short() { + # md_code_tag text + printf "Python versions:\n" + printf "\n" + python --version | paste /dev/null - + pyenv --version | paste /dev/null - + pip --version | paste /dev/null - + pdm --version | paste /dev/null - + # md_code_tag + printf "\n" +} # show_tool_versions_python_short() + +show_tool_versions_python() { + show_tool_versions_python_short + + if [[ -z ${GITHUB_ACTIONS} ]]; then + return + fi + + # md_code_tag text + printf "Installed Python packages:\n" + printf "\n" + pip list | paste /dev/null - + # md_code_tag + printf "\n" +} # show_tool_versions_python() diff --git a/.github/citools/python/python-lint-formatter b/.github/citools/python/python-lint-formatter new file mode 100755 index 00000000..5d6f3e26 --- /dev/null +++ b/.github/citools/python/python-lint-formatter @@ -0,0 +1,26 @@ +#!/bin/bash +# +# .github/citools/python/python-lint-formatter +# + +# shellcheck disable=SC1091 +source ../../.github/citools/includes/wrapper-library || exit + +declare -i retval=0 + +main() { + printf "\nRunning Python Formatter\n\n" + + show_tool_versions_python_short + + print_ruler + + run_command ruff . + + print_ruler + + echo Exit code: "${retval}" + return "${retval}" +} + +time main "${@}" diff --git a/.github/citools/python/python-setup-config b/.github/citools/python/python-setup-config new file mode 100755 index 00000000..4c690f39 --- /dev/null +++ b/.github/citools/python/python-setup-config @@ -0,0 +1,24 @@ +#!/bin/bash +# +# .github/citools/python/python-setup-config +# + +# shellcheck disable=SC1091 +source ../../.github/citools/includes/wrapper-library || exit + +declare -i retval=0 + +main() { + printf "Setup Python Environment\n\n" + + print_ruler + + ../../.github/citools/common/gh-setup-env || track_errors + + print_ruler + + echo Exit code: "${retval}" + return "${retval}" +} + +time main "${@}" diff --git a/.github/citools/python/python-setup-install b/.github/citools/python/python-setup-install new file mode 100755 index 00000000..9a7c75ba --- /dev/null +++ b/.github/citools/python/python-setup-install @@ -0,0 +1,227 @@ +#!/bin/bash +# +# .github/citools/python/python-setup-install +# + +# shellcheck disable=SC1091 +source ../../.github/citools/includes/wrapper-library || exit + +declare -i retval=0 + +main() { + printf "Python Installation\n\n" + + print_ruler + + echo Running: sudo apt update + time sudo apt update || track_errors + + print_ruler + + local -a debs + debs=( + autoconf + automake + bc + bison + build-essential + curl + g++ + gcc + git + gnupg + libbz2-dev + libc6-dev + libffi-dev + libgdbm-dev + libgmp-dev + liblzma-dev + libncurses5-dev + libreadline-dev + libsqlite3-dev + libssl-dev + libtool + libyaml-dev + make + pkg-config + sqlite3 + zlib1g-dev + ) + + echo Running: sudo apt install -y "${debs[@]}" + time sudo apt install -y "${debs[@]}" || track_errors + + print_ruler + + echo Running: export PYTHON_CONFIGURE_OPTS="--enable-shared" + export PYTHON_CONFIGURE_OPTS="--enable-shared" + + print_ruler + + export PYENV_ROOT="/usr/local/pyenv" + + echo Running: git clone --depth=1 https://github.com/pyenv/pyenv.git "${PYENV_ROOT}" + git clone --depth=1 https://github.com/pyenv/pyenv.git "${PYENV_ROOT}" || track_errors + + print_ruler + + echo Running: git clone https://github.com/pyenv/pyenv-virtualenv.git "${PYENV_ROOT}"/plugins/pyenv-virtualenv + git clone https://github.com/pyenv/pyenv-virtualenv.git "${PYENV_ROOT}"/plugins/pyenv-virtualenv || track_errors + + print_ruler + + { cd "${PYENV_ROOT}" && time src/configure && time make -C src; } || track_errors + + print_ruler + + printf "Configuring Shell: " + tee /etc/profile.d/python.sh <<-EOF + # + # /etc/profile.d/python.sh + # + + export PYENV_ROOT="/usr/local/pyenv" + + if [[ ! \${PATH} =~ \${PYENV_ROOT}/bin ]]; then + export PATH="\${PYENV_ROOT}/bin:\${PATH}" + fi + + if command -v pyenv 1>/dev/null 2>&1; then + if [[ ! \${PATH} =~ \${PYENV_ROOT}/shims ]]; then + eval "\$(pyenv init --path)" + fi + + if [[ -z \${PYENV_SHELL} ]]; then + eval "\$(pyenv init -)" + fi + + if [[ ! \${PATH} =~ \${PYENV_ROOT}/plugins/pyenv-virtualenv/shims ]]; then + eval "\$(pyenv virtualenv-init -)" + fi + fi + EOF + printf "done\n" + + # shellcheck disable=SC1090 + echo Running: source /etc/profile.d/python.sh + source /etc/profile.d/python.sh || track_errors + printf "done\n" + + print_ruler + + echo Running: pyenv -v + time pyenv -v || track_errors + + print_ruler + + echo Running: pyenv install --list + time pyenv install --list || track_errors + + print_ruler + + local python_version + python_version="$(pyenv install --list | grep -E "^\s+3" | grep -v -- -dev | grep -v "[a-z]" | tr -d ' ' | tail -n 1)" || track_errors + + echo Running: pyenv install "${python_version}" + time pyenv install "${python_version}" || track_errors + + print_ruler + + echo Running: pyenv global "${python_version}" + time pyenv global "${python_version}" || track_errors + + print_ruler + + echo Running: python --version + time python --version || track_errors + + print_ruler + + local -a pip_packages + pip_packages=( + ansible-lint + bandit[toml] + black + coverage + dagger-io + db-sqlite3 + flake8 + flawfinder + flynt + ipykernel + ipython + isort + itsdangerous + jsonlint + jsonschema + mccabe + mypy + mypy-extensions + pep8 + pep8-naming + pexpect + proselint + prospector + pycobertura + pycodestyle + pydantic + pydocstyle + pyflakes + pylint + pylint-flask + pyright + pysqlite3 + pytest + pytest-cov + pytest-docker + pytest-randomly + python-dateutil + python-lsp-black + python-lsp-jsonrpc + python-lsp-ruff + python-lsp-server + python-utils + pytype + refurb + rich-cli + ruff + safety + textual[dev] + textualize_see + tmuxp + toml + tomli + tomlkit + typeguard + types-Pygments + types-colorama + types-docutils + types-mock + types-setuptools + typing_extensions + xmlformatter + yamlfix + yamllint + yapf + ) + + echo Running: pip install --upgrade pip + time pip install --upgrade pip || track_errors + + print_ruler + + echo Running: pip install pdm + time pip install pdm || track_errors + + print_ruler + + echo Running: pip install "${pip_packages[@]}" + time pip install "${pip_packages[@]}" || track_errors + + print_ruler + + echo Exit code: "${retval}" + return "${retval}" +} + +time main "${@}" diff --git a/.github/citools/python/python-setup-verify b/.github/citools/python/python-setup-verify new file mode 100755 index 00000000..c493c83d --- /dev/null +++ b/.github/citools/python/python-setup-verify @@ -0,0 +1,59 @@ +#!/bin/bash +# +# .github/citools/python/python-setup-verify +# + +# shellcheck disable=SC1091 +source ../../.github/citools/includes/wrapper-library || exit + +declare -i retval=0 + +declare -A python_cmds + +python_cmds=( + [python]=$( + command -v python >&/dev/null + echo "$?" + ) + [pyenv]=$( + command -v pyenv >&/dev/null + echo "$?" + ) + [pip]=$( + command -v pip >&/dev/null + echo "$?" + ) +) + +main() { + printf "Verifying Python Installation\n\n" + + print_ruler + + echo Running: source /etc/profile.d/python.sh + source /etc/profile.d/python.sh || track_errors + + print_ruler + + for key in "${!python_cmds[@]}"; do + if [[ ${python_cmds[${key}]} -ne 0 ]]; then + printf "ERROR: command [%s] not found.\n" "${key}" + ((retval++)) + fi + done + + if [[ ${retval} -ne 0 ]]; then + return "${retval}" + fi + + print_ruler + + show_tool_versions_python + + print_ruler + + echo Exit code: "${retval}" + return "${retval}" +} + +time main "${@}" diff --git a/.github/citools/python/python-test-with-coverage b/.github/citools/python/python-test-with-coverage new file mode 100755 index 00000000..51c09c0c --- /dev/null +++ b/.github/citools/python/python-test-with-coverage @@ -0,0 +1,50 @@ +#!/bin/bash +# +# .github/citools/python/python-test-with-coverage +# + +# shellcheck disable=SC1091 +source ../../.github/citools/includes/wrapper-library || exit + +declare -i retval=0 + +main() { + printf "\nRunning Python Tests With Coverage\n\n" + + show_tool_versions_python_short + + print_ruler + + run_command rm -rf ./coverage + + print_ruler + + run_command pytest --verbose --cov=. --cov-branch --cov-report={term-missing,xml:.coverage.xml} -p no:randomly || ((retval++)) + + print_ruler + + echo Running: coverage report --show-missing + coverage report --show-missing + + print_ruler + + echo Running: coverage annotate + coverage annotate + + print_ruler + + local coverage_line + coverage_line="$(xq -q coverage -a line-rate .coverage.xml)" + printf "Line Coverage: %.1f%%\n" "$(bc <<<"scale=1; ${coverage_line}* 100")" + + local coverage_branch + coverage_branch="$(xq -q coverage -a line-rate .coverage.xml)" + printf "Branch Coverage: %.1f%%\n" "$(bc <<<"scale=1; ${coverage_branch}* 100")" + + print_ruler + + echo Exit code: "${retval}" + return "${retval}" +} + +time main "${@}" diff --git a/.github/docker/layer-18.00-exercism-python.sh b/.github/docker/layer-18.00-exercism-python.sh new file mode 100755 index 00000000..0ffa4fa3 --- /dev/null +++ b/.github/docker/layer-18.00-exercism-python.sh @@ -0,0 +1,65 @@ +#!/bin/bash +# +# .github/docker/layer-18.00-exercism-python.sh +# + +set -o pipefail + +# this path from for the container +# shellcheck disable=SC1091 +. /.github/docker/include + +# shellcheck disable=SC1091 +source /.github/citools/includes/wrapper-library || exit + +main() { + declare -i retval=0 + + layer_begin "${0}" "$@" + + export PYENV_ROOT="/usr/local/pyenv" + + echo Running: /.github/citools/python/python-setup-install + time /.github/citools/python/python-setup-install || track_errors + printf "\n" + + echo Running: /.github/citools/python/python-setup-config + time /.github/citools/python/python-setup-config || track_errors + printf "\n" + + echo Running: ln -sv /usr/local/pyenv "${HOME}/.pyenv" + ln -sv "${PYENV_ROOT}" "${HOME}/.pyenv" || track_errors + printf "\n" + + echo Running: ln -sv /usr/local/pyenv "/etc/skel/.pyenv" + ln -sv "${PYENV_ROOT}" "/etc/skel/.pyenv" || track_errors + printf "\n" + + echo Checking installation: + ls -lh /usr/local/ "${PYENV_ROOT}" "${HOME}"/.pyenv /etc/skel/.pyenv + printf "\n" + + echo Adding source /etc/profile.d/python.sh to ~/.bashrc and /etc/skel/.bashrc + echo '. /etc/profile.d/python.sh' | tee -a "${HOME}/.bashrc" | tee -a "${HOME}/.profile" | tee -a /etc/skel/.bashrc || track_errors + printf "\n" + + echo Running: source /etc/profile.d/python.sh + # shellcheck disable=SC1091 + source /etc/profile.d/python.sh || track_errors + printf "\n" + + echo Running: chgrp -R adm /usr/local/pyenv + chgrp -R adm "${PYENV_ROOT}" || track_errors + printf "\n" + + echo Running: setfacl -RPdm g:adm:w /usr/local/pyenv + setfacl -RPdm g:adm:w "${PYENV_ROOT}" || track_errors + printf "\n" + + layer_end "${0}" "$@" + + echo Running: return "${retval}" + return "${retval}" +} + +time main "${@}" |& tee "${HOME}"/layer-18.00-exercism-python.log diff --git a/Dockerfile b/Dockerfile index 366ac1d9..99454c16 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,6 +30,8 @@ RUN bash .github/docker/layer-16.00-exercism-go.sh ci-generic-debian && : 202401 RUN bash .github/docker/layer-17.00-exercism-ruby.sh ci-generic-debian && : 20231103-000 +RUN bash .github/docker/layer-18.00-exercism-python.sh ci-generic-debian && : 20231115-000 + RUN bash .github/docker/layer-25.00-tools-vscode.sh ci-generic-debian && : 20240102-000 RUN bash .github/docker/layer-35.00-tools-tailscale.sh ci-generic-debian && : 20240111-000 From 587294a6f85cd821ee3d8e623b3e6d7ba48c512c Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Mon, 15 Jan 2024 20:02:30 -0800 Subject: [PATCH 2/2] ci(docker-build): fix nodejs debug output in gh-setup-env --- .github/citools/common/gh-setup-env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/citools/common/gh-setup-env b/.github/citools/common/gh-setup-env index ed23196d..ed6682db 100755 --- a/.github/citools/common/gh-setup-env +++ b/.github/citools/common/gh-setup-env @@ -113,14 +113,14 @@ main() { source /etc/profile.d/nodejs.sh || track_errors - printf "Adding Ruby paths to GITHUB_PATH...\n" + printf "Adding NodeJS paths to GITHUB_PATH...\n" printf "%s\n" "/usr/local/nodenv/bin" "/usr/local/nodenv/shims" | tee -a "${GITHUB_PATH}" echo Adding source /etc/profile.d/nodejs.sh to ~/.bashrc echo '. /etc/profile.d/nodejs.sh' | tee -a "${HOME}/.bashrc" || track_errors printf "\n" - printf "Setup NodeJs symlinks for github user:\n" + printf "Setup NodeJS symlinks for github user:\n" cd "${HOME}" || track_errors if [[ ! -d .nodenv ]]; then ln -sv "/usr/local/nodenv" .nodenv || track_errors