From 76bc4bf3392c821b370a40fecf256237c75e6385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Tue, 28 Jan 2025 13:22:49 +0100 Subject: [PATCH 1/9] test: switch to using a singular Dockerfile with build args this avoids the need to replace content in the Dockerfile using sed and makes it possible to run a quick test using `make quicktest` (using the defaults for the build arguments specified in the Dockerfile) --- Dockerfile | 21 +++++++++++++++++++ Makefile | 8 +++++++- run-tests.sh | 43 +++++++++++++++------------------------ tests/.gitignore | 1 - tests/Dockerfile.template | 12 ----------- 5 files changed, 44 insertions(+), 41 deletions(-) create mode 100644 Dockerfile delete mode 100644 tests/.gitignore delete mode 100644 tests/Dockerfile.template diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..14a6808 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# Dockerfile is run by `run-tests.sh` + +# used to define the python tag +ARG IMAGE=3.13-slim + + +FROM python:$IMAGE +LABEL maintainer="Marco M. (mmicu) " + +COPY . /app +WORKDIR /app + +# used to define which python package is installed with pip: +# - a value of `.` builds the images using the docker build context - aka the revision of the package which is currently checked out +# - using a value of `editorconfig-checker` will instead pull the image from PyPI +ARG PACKAGE=. + +RUN apt-get update \ + && apt-get install -y make \ + && python -m pip install --upgrade pip \ + && pip install --no-cache-dir $PACKAGE diff --git a/Makefile b/Makefile index 4948e11..c7b8776 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,14 @@ help: @echo " - coding-style : Run coding style tools." @echo " - publish : Publish package to PyPI." @echo " - test : Run coding style tools and tests." + @echo " - quicktest : Run coding style tools and only the test for the latest python and the current git revision." .PHONY: all all: help .PHONY: clean clean: - @rm -rf build dist editorconfig_checker.egg-info editorconfig_checker/bin tests/Dockerfile-* + @rm -rf build dist editorconfig_checker.egg-info editorconfig_checker/bin .PHONY: coding-style coding-style: @@ -26,3 +27,8 @@ publish: clean test .PHONY: test test: coding-style @bash run-tests.sh + +.PHONY: quicktest +quicktest: coding-style + docker build -t quicktest . + docker run quicktest ec -version diff --git a/run-tests.sh b/run-tests.sh index a76053b..1a03a15 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -2,8 +2,6 @@ set -e -DOCKERFILE_TEMPLATE="tests/Dockerfile.template" - PY_DOCKER_IMAGES=() PY_DOCKER_IMAGES+=("2.7.16-slim") PY_DOCKER_IMAGES+=("3.7.4-slim") @@ -12,33 +10,27 @@ PY_DOCKER_IMAGES+=("3.9-slim") PY_DOCKER_IMAGES+=("3.10-slim") PY_DOCKER_IMAGES+=("3.11-slim") -create_docker_file() { - local package="$1" - - # Generate a valid Dockerfile from a template file - local dockerfile="tests/Dockerfile-$py_docker_image-$package" - cp "$DOCKERFILE_TEMPLATE" "$dockerfile" - - # Replace docker image - sed -i '' "s/\$IMAGE/$py_docker_image/g" "$dockerfile" - - # Replace package name - if [[ "$package" == "local" ]]; then - package="." - fi - sed -i '' "s/\$PACKAGE/$package/g" "$dockerfile" - - echo "$dockerfile" -} build_docker_image_and_run() { local py_docker_image="$1" local package="$2" - local dockerfile="$3" # Build local docker_image="editorconfig-checker-$py_docker_image-$package:latest" - docker build -t "$docker_image" -f "$dockerfile" --no-cache --quiet . + + docker_package="$package" + if [[ "$package" == "local" ]]; then + docker_package="." + fi + + docker build \ + -t "$docker_image" \ + -f "Dockerfile" \ + --no-cache \ + --quiet \ + --build-arg "IMAGE=$py_docker_image" \ + --build-arg "PACKAGE=$docker_package" \ + . # Run `editorconfig-checker` docker run --rm "$docker_image" ec -version @@ -49,11 +41,8 @@ main() { for py_docker_image in "${PY_DOCKER_IMAGES[@]}"; do for package in local editorconfig-checker; do - local dockerfile=$(create_docker_file "$package") - echo "Dockerfile created at \"$dockerfile\" (\"$py_docker_image\" image and \"$package\" package)" - - echo "Building docker image. It could take some time..." - build_docker_image_and_run "$py_docker_image" "$package" "$dockerfile" + echo "Building docker image with python version $py_docker_image and $package package. It could take some time..." + build_docker_image_and_run "$py_docker_image" "$package" # docker image rm "$docker_image" &> /dev/null diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 2527e80..0000000 --- a/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -Dockerfile-* diff --git a/tests/Dockerfile.template b/tests/Dockerfile.template deleted file mode 100644 index 92d8138..0000000 --- a/tests/Dockerfile.template +++ /dev/null @@ -1,12 +0,0 @@ -# Dockerfile used as a template. Placeholders "$IMAGE" and "$PACKAGE" are replaced -# with their actual value by `run-tests.sh` -FROM python:$IMAGE -LABEL maintainer="Marco M. (mmicu) " - -COPY . /app -WORKDIR /app - -RUN apt-get update \ - && apt-get install -y make \ - && python -m pip install --upgrade pip \ - && pip install --no-cache-dir $PACKAGE From 304f2f6ad4447a6918f9a91fde6faeed16e69281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Tue, 28 Jan 2025 23:25:23 +0100 Subject: [PATCH 2/9] test: also test the latest python versions --- run-tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run-tests.sh b/run-tests.sh index 1a03a15..6b26fa0 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -9,6 +9,8 @@ PY_DOCKER_IMAGES+=("3.8-slim") PY_DOCKER_IMAGES+=("3.9-slim") PY_DOCKER_IMAGES+=("3.10-slim") PY_DOCKER_IMAGES+=("3.11-slim") +PY_DOCKER_IMAGES+=("3.12-slim") +PY_DOCKER_IMAGES+=("3.13-slim") build_docker_image_and_run() { From d39feeef79b8bfb3d8c874a7d810b8ae6d06a0b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Fri, 31 Jan 2025 08:52:46 +0100 Subject: [PATCH 3/9] test: allow caching the static portion This reduces the test runtime from about 5min to 3min on my machine. --- Dockerfile | 13 ++++++++----- run-tests.sh | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index 14a6808..cd98c11 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,13 @@ ARG IMAGE=3.13-slim -FROM python:$IMAGE +FROM python:$IMAGE AS pybase +RUN apt-get update \ + && apt-get install -y make \ + && python -m pip install --upgrade pip + +# separate the obtaining of the requirements from the actual test, so we can use build caching for the first step +FROM pybase as tester LABEL maintainer="Marco M. (mmicu) " COPY . /app @@ -15,7 +21,4 @@ WORKDIR /app # - using a value of `editorconfig-checker` will instead pull the image from PyPI ARG PACKAGE=. -RUN apt-get update \ - && apt-get install -y make \ - && python -m pip install --upgrade pip \ - && pip install --no-cache-dir $PACKAGE +RUN pip install --no-cache-dir $PACKAGE diff --git a/run-tests.sh b/run-tests.sh index 6b26fa0..54f2815 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -28,7 +28,7 @@ build_docker_image_and_run() { docker build \ -t "$docker_image" \ -f "Dockerfile" \ - --no-cache \ + --no-cache-filter tester \ --quiet \ --build-arg "IMAGE=$py_docker_image" \ --build-arg "PACKAGE=$docker_package" \ From a84754ea8acdceaf9b36cd0640b93cc7b53f866f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Fri, 31 Jan 2025 09:12:02 +0100 Subject: [PATCH 4/9] test: also turn packages into an array to allow changing it --- run-tests.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/run-tests.sh b/run-tests.sh index 54f2815..2c5f1de 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -12,6 +12,10 @@ PY_DOCKER_IMAGES+=("3.11-slim") PY_DOCKER_IMAGES+=("3.12-slim") PY_DOCKER_IMAGES+=("3.13-slim") +PY_PACKAGES=() +PY_PACKAGES+=("local") +PY_PACKAGES+=("editorconfig-checker") + build_docker_image_and_run() { local py_docker_image="$1" @@ -42,7 +46,7 @@ main() { echo -e "Running tests...\n\n" for py_docker_image in "${PY_DOCKER_IMAGES[@]}"; do - for package in local editorconfig-checker; do + for package in "${PY_PACKAGES[@]}"; do echo "Building docker image with python version $py_docker_image and $package package. It could take some time..." build_docker_image_and_run "$py_docker_image" "$package" From c5346b9def4b5b7aff339cf3bcf8b179dad6956b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Fri, 31 Jan 2025 09:26:11 +0100 Subject: [PATCH 5/9] test: allow external control of the test matrix with $TEST_PY_VERSION and $TEST_LOCAL_PKG/$TEST_PYPI_PKG --- run-tests.sh | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 2c5f1de..7cac84e 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -3,18 +3,26 @@ set -e PY_DOCKER_IMAGES=() -PY_DOCKER_IMAGES+=("2.7.16-slim") -PY_DOCKER_IMAGES+=("3.7.4-slim") -PY_DOCKER_IMAGES+=("3.8-slim") -PY_DOCKER_IMAGES+=("3.9-slim") -PY_DOCKER_IMAGES+=("3.10-slim") -PY_DOCKER_IMAGES+=("3.11-slim") -PY_DOCKER_IMAGES+=("3.12-slim") -PY_DOCKER_IMAGES+=("3.13-slim") +if [ -n "$TEST_PY_VERSION" ]; then + PY_DOCKER_IMAGES+=("$TEST_PY_VERSION") +else + PY_DOCKER_IMAGES+=("2.7.16-slim") + PY_DOCKER_IMAGES+=("3.7.4-slim") + PY_DOCKER_IMAGES+=("3.8-slim") + PY_DOCKER_IMAGES+=("3.9-slim") + PY_DOCKER_IMAGES+=("3.10-slim") + PY_DOCKER_IMAGES+=("3.11-slim") + PY_DOCKER_IMAGES+=("3.12-slim") + PY_DOCKER_IMAGES+=("3.13-slim") +fi PY_PACKAGES=() -PY_PACKAGES+=("local") -PY_PACKAGES+=("editorconfig-checker") +if [ -z "$TEST_LOCAL_PKG" ] || [ "$TEST_LOCAL_PKG" = "true" ]; then + PY_PACKAGES+=("local") +fi +if [ -z "$TEST_PYPI_PKG" ] || [ "$TEST_PYPI_PKG" = "true" ]; then + PY_PACKAGES+=("editorconfig-checker") +fi build_docker_image_and_run() { From e7fdf4cb46bb751f4de350b6e3bcb2fcce800e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Fri, 31 Jan 2025 20:17:52 +0100 Subject: [PATCH 6/9] test: refactor to specify which image variant we want only once --- run-tests.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 7cac84e..31b5080 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -4,16 +4,16 @@ set -e PY_DOCKER_IMAGES=() if [ -n "$TEST_PY_VERSION" ]; then - PY_DOCKER_IMAGES+=("$TEST_PY_VERSION") + PY_VERSIONS+=("$TEST_PY_VERSION") else - PY_DOCKER_IMAGES+=("2.7.16-slim") - PY_DOCKER_IMAGES+=("3.7.4-slim") - PY_DOCKER_IMAGES+=("3.8-slim") - PY_DOCKER_IMAGES+=("3.9-slim") - PY_DOCKER_IMAGES+=("3.10-slim") - PY_DOCKER_IMAGES+=("3.11-slim") - PY_DOCKER_IMAGES+=("3.12-slim") - PY_DOCKER_IMAGES+=("3.13-slim") + PY_VERSIONS+=("2.7.16") + PY_VERSIONS+=("3.7.4") + PY_VERSIONS+=("3.8") + PY_VERSIONS+=("3.9") + PY_VERSIONS+=("3.10") + PY_VERSIONS+=("3.11") + PY_VERSIONS+=("3.12") + PY_VERSIONS+=("3.13") fi PY_PACKAGES=() @@ -53,10 +53,10 @@ build_docker_image_and_run() { main() { echo -e "Running tests...\n\n" - for py_docker_image in "${PY_DOCKER_IMAGES[@]}"; do + for py_version in "${PY_VERSIONS[@]}"; do for package in "${PY_PACKAGES[@]}"; do - echo "Building docker image with python version $py_docker_image and $package package. It could take some time..." - build_docker_image_and_run "$py_docker_image" "$package" + echo "Building docker image with python version $py_version and $package package. It could take some time..." + build_docker_image_and_run "$py_version-slim" "$package" # docker image rm "$docker_image" &> /dev/null From 74be5db5e3afbb6bd2d93a9c9d401f7535538923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Fri, 31 Jan 2025 20:23:24 +0100 Subject: [PATCH 7/9] ci: build CI to ensure the local package always works this tests in two ways: - install the package locally in each major os/architecture combination supported by GitHub Actions, then run `editorconfig-checker --version` like `run-tests.sh` does - running `run-tests.sh` once in an ubuntu machines The workflow is triggered both by pushes to any of the branches and for each pull request. --- .github/workflows/ci.yaml | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/ci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..c6792e1 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,52 @@ +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: read-all + +jobs: + test-architectures: + name: test OS/arch combinations + strategy: + fail-fast: false + matrix: + os: + - 'ubuntu-24.04' + - 'ubuntu-24.04-arm' + - 'macos-13' # the last intel mac + - 'macos-15' # arm64 mac + - 'windows-2025' + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: install local package + run: | + python -m pip install . + + - name: test that editorconfig-checker works by letting it output it's version + run: | + ec --version + + + test-python-versions: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + + - name: install flake8 + run: | + python -m pip install flake8 + + - name: run testsuite verifying against all python versions + shell: bash + run: | + # only test the local package, since we assume that we only + # upload to PyPI once we are certain that the local package is fine + export TEST_LOCAL_PKG=true + export TEST_PYPI_PKG=false + + make test From 684bb409b0417f5bd18af5ba0af369b18631f3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=20Kl=C3=A4rner?= Date: Sat, 1 Feb 2025 16:12:25 +0100 Subject: [PATCH 8/9] test: run against latest python patch version in each series --- run-tests.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index 31b5080..28a3a0d 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -6,8 +6,8 @@ PY_DOCKER_IMAGES=() if [ -n "$TEST_PY_VERSION" ]; then PY_VERSIONS+=("$TEST_PY_VERSION") else - PY_VERSIONS+=("2.7.16") - PY_VERSIONS+=("3.7.4") + PY_VERSIONS+=("2.7") + PY_VERSIONS+=("3.7") PY_VERSIONS+=("3.8") PY_VERSIONS+=("3.9") PY_VERSIONS+=("3.10") From b7973ebc565af03221d8bccab0b7eebd892e4847 Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 14 Aug 2025 22:15:28 +0200 Subject: [PATCH 9/9] refactor: streamline CI configuration and Docker image build process --- .github/workflows/ci.yaml | 12 ++++++--- Dockerfile | 4 +-- Makefile | 12 ++++----- run-tests.sh | 54 +++++++++++++++++---------------------- 4 files changed, 39 insertions(+), 43 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c6792e1..76df8c2 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -31,7 +31,6 @@ jobs: run: | ec --version - test-python-versions: runs-on: ubuntu-24.04 steps: @@ -44,9 +43,14 @@ jobs: - name: run testsuite verifying against all python versions shell: bash run: | - # only test the local package, since we assume that we only - # upload to PyPI once we are certain that the local package is fine + # Only test the local package, since we assume that we only + # upload to PyPI once we are certain that the local package is fine. export TEST_LOCAL_PKG=true export TEST_PYPI_PKG=false - make test + # The same commands are defined in the `Makefile` and used for local development. + # We added them here to simplify the building process of the Docker + # image that points to `python:2.7-slim`. + # For such image, `apt-get` was not working as expected. + flake8 --ignore E501 setup.py + bash run-tests.sh diff --git a/Dockerfile b/Dockerfile index cd98c11..d4f8286 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,9 +5,7 @@ ARG IMAGE=3.13-slim FROM python:$IMAGE AS pybase -RUN apt-get update \ - && apt-get install -y make \ - && python -m pip install --upgrade pip +RUN python -m pip install --upgrade pip # separate the obtaining of the requirements from the actual test, so we can use build caching for the first step FROM pybase as tester diff --git a/Makefile b/Makefile index c7b8776..c297ac5 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ help: @echo " - clean : Remove generated files." @echo " - coding-style : Run coding style tools." @echo " - publish : Publish package to PyPI." + @echo " - quick-test : Run coding style tools and only the test for the latest python and the current git revision." @echo " - test : Run coding style tools and tests." - @echo " - quicktest : Run coding style tools and only the test for the latest python and the current git revision." .PHONY: all all: help @@ -24,11 +24,11 @@ publish: clean test @python3 setup.py sdist @twine upload dist/* +.PHONY: quick-test +quick-test: coding-style + docker build -t ec-quick-test . + docker run ec-quick-test ec -version + .PHONY: test test: coding-style @bash run-tests.sh - -.PHONY: quicktest -quicktest: coding-style - docker build -t quicktest . - docker run quicktest ec -version diff --git a/run-tests.sh b/run-tests.sh index 28a3a0d..16b382c 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -2,34 +2,10 @@ set -e -PY_DOCKER_IMAGES=() -if [ -n "$TEST_PY_VERSION" ]; then - PY_VERSIONS+=("$TEST_PY_VERSION") -else - PY_VERSIONS+=("2.7") - PY_VERSIONS+=("3.7") - PY_VERSIONS+=("3.8") - PY_VERSIONS+=("3.9") - PY_VERSIONS+=("3.10") - PY_VERSIONS+=("3.11") - PY_VERSIONS+=("3.12") - PY_VERSIONS+=("3.13") -fi - -PY_PACKAGES=() -if [ -z "$TEST_LOCAL_PKG" ] || [ "$TEST_LOCAL_PKG" = "true" ]; then - PY_PACKAGES+=("local") -fi -if [ -z "$TEST_PYPI_PKG" ] || [ "$TEST_PYPI_PKG" = "true" ]; then - PY_PACKAGES+=("editorconfig-checker") -fi - - build_docker_image_and_run() { local py_docker_image="$1" local package="$2" - # Build local docker_image="editorconfig-checker-$py_docker_image-$package:latest" docker_package="$package" @@ -46,20 +22,38 @@ build_docker_image_and_run() { --build-arg "PACKAGE=$docker_package" \ . - # Run `editorconfig-checker` docker run --rm "$docker_image" ec -version } main() { echo -e "Running tests...\n\n" - for py_version in "${PY_VERSIONS[@]}"; do - for package in "${PY_PACKAGES[@]}"; do - echo "Building docker image with python version $py_version and $package package. It could take some time..." - build_docker_image_and_run "$py_version-slim" "$package" + local py_versions=() + if [ -n "$TEST_PY_VERSION" ]; then + py_versions+=("$TEST_PY_VERSION") + else + py_versions+=("2.7") + py_versions+=("3.7") + py_versions+=("3.8") + py_versions+=("3.9") + py_versions+=("3.10") + py_versions+=("3.11") + py_versions+=("3.12") + py_versions+=("3.13") + fi - # docker image rm "$docker_image" &> /dev/null + local py_packages=() + if [ -z "$TEST_LOCAL_PKG" ] || [ "$TEST_LOCAL_PKG" = "true" ]; then + py_packages+=("local") + fi + if [ -z "$TEST_PYPI_PKG" ] || [ "$TEST_PYPI_PKG" = "true" ]; then + py_packages+=("editorconfig-checker") + fi + for py_version in "${py_versions[@]}"; do + for package in "${py_packages[@]}"; do + echo "Building docker image with Python version $py_version and $package package. It could take some time..." + build_docker_image_and_run "$py_version-slim" "$package" echo -e "\n" done done