From e73f75ef5a69483c55055785cee3772ca30a0a38 Mon Sep 17 00:00:00 2001 From: Gyeongjae Choi Date: Mon, 12 Aug 2024 21:01:54 +0900 Subject: [PATCH] TST Add integration tests for building recipes (#16) This adds an integration test for `pyodide-build`, which builds a few selected recipes. Unlike unit test, integration tests are not run in CI by default. So users ned to run it locally, or include `[integration]` in the commit message to trigger the test. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 55 ++++++++++++++++++++++ .gitignore | 8 +++- integration_tests/Makefile | 26 ++++++++++ integration_tests/README.md | 11 +++++ integration_tests/recipes/README.md | 13 +++++ integration_tests/recipes/geos/meta.yaml | 28 +++++++++++ integration_tests/recipes/numpy/meta.yaml | 33 +++++++++++++ integration_tests/recipes/orjson/meta.yaml | 20 ++++++++ integration_tests/recipes/zlib/meta.yaml | 25 ++++++++++ tools/check_integration_test_trigger.sh | 13 +++++ 10 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 integration_tests/Makefile create mode 100644 integration_tests/README.md create mode 100644 integration_tests/recipes/README.md create mode 100644 integration_tests/recipes/geos/meta.yaml create mode 100644 integration_tests/recipes/numpy/meta.yaml create mode 100644 integration_tests/recipes/orjson/meta.yaml create mode 100644 integration_tests/recipes/zlib/meta.yaml create mode 100755 tools/check_integration_test_trigger.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 88303a2..9b57d0e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -64,6 +64,61 @@ jobs: with: fail_ci_if_error: false + check-integration-test-trigger: + name: test-integration-test-trigger + runs-on: ubuntu-latest + outputs: + run-integration-test: ${{ steps.check-integration-test-trigger.outputs.trigger }} + + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - id: check-integration-test-trigger + name: Check integration test trigger + run: bash tools/check_integration_test_trigger.sh + + integration-test: + runs-on: ubuntu-latest + needs: [check-integration-test-trigger] + if: needs.check-integration-test-trigger.outputs.run-integration-test + steps: + - uses: actions/checkout@v4 + with: + # include tags so that hatch-vcs can infer the version + fetch-depth: 0 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install the package + run: | + python -m pip install --upgrade pip + python -m pip install . + + - name: Install xbuildenv + run: | + pyodide xbuildenv install + echo EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) >> $GITHUB_ENV + + - name: Install Emscripten + uses: mymindstorm/setup-emsdk@v12 + with: + version: ${{ env.EMSCRIPTEN_VERSION }} + + - name: Run the integration tests (recipes) + run: | + cd integration_tests + make test-recipe + publish: name: >- Publish to PyPI diff --git a/.gitignore b/.gitignore index c6d0f13..e7ce965 100644 --- a/.gitignore +++ b/.gitignore @@ -21,10 +21,16 @@ build ccache dist*/ docs/_build/ -emsdk/emsdk +emsdk geckodriver.log node_modules dist/ pyodide_build/**/build.log xbuildenv/ .pyodide-xbuildenv* +pyodide/ +venv/ + +# integration tests +integration_tests/**/build.log +integration_tests/**/.libs diff --git a/integration_tests/Makefile b/integration_tests/Makefile new file mode 100644 index 0000000..45de4cf --- /dev/null +++ b/integration_tests/Makefile @@ -0,0 +1,26 @@ +all: + @echo "Please specify a target" + @exit 1 + +.PHONY: test-recipe +test-recipe: check + @echo "... Running integration tests for building recipes" + + pyodide build-recipes --recipe-dir=recipes --force-rebuild "*" + + @echo "... Passed" + +.PHONY: check +check: + @echo "... Checking dependencies" + + @which pyodide > /dev/null || (echo "pyodide-build is not installd"; exit 1) + @which emsdk > /dev/null || (echo "emscripten is not installed"; exit 1) + + @echo "... Passed" + +.PHONY: clean +clean: + rm -rf .pyodide-xbuildenv* + rm -rf recipes/*/build + rm -rf dist diff --git a/integration_tests/README.md b/integration_tests/README.md new file mode 100644 index 0000000..b2a0d2f --- /dev/null +++ b/integration_tests/README.md @@ -0,0 +1,11 @@ +This directory contains assets to run integration tests for pyodide-build. + +Tests in this directory are not run by default in CI. To run these tests, add `[integration]` in the commit message. + +## Running integration tests locally + +To run the integration tests locally, use `make` command in this directory. + +```bash +make test-recipe +``` diff --git a/integration_tests/recipes/README.md b/integration_tests/recipes/README.md new file mode 100644 index 0000000..28cc894 --- /dev/null +++ b/integration_tests/recipes/README.md @@ -0,0 +1,13 @@ +This directory contains a few curated recipes to test the build process of pyodide-build. + +### List of recipes and their purpose + +- numpy: The most popular and widely used library in the scientific computing community. +- orjson: Tests rust extension modules. +- zlib: Tests static libraries. +- geos: Tests shared libraries. + +### For maintainers + +- Do not put too many recipes in this directory. It is meant to be a small collection of recipes that are representative of the build process. +- The recipes in this directory is originally copied from `pyodide/pyodide`. It does not need to be updated frequently unless there is a change in the build process. diff --git a/integration_tests/recipes/geos/meta.yaml b/integration_tests/recipes/geos/meta.yaml new file mode 100644 index 0000000..77d763d --- /dev/null +++ b/integration_tests/recipes/geos/meta.yaml @@ -0,0 +1,28 @@ +package: + name: geos + version: 3.12.1 + tag: + - library +source: + url: https://github.com/libgeos/geos/releases/download/3.12.1/geos-3.12.1.tar.bz2 + sha256: d6ea7e492224b51193e8244fe3ec17c4d44d0777f3c32ca4fb171140549a0d03 + +build: + type: shared_library + script: | + LDFLAGS="${SIDE_MODULE_LDFLAGS}" emcmake cmake \ + -DDISABLE_GEOS_INLINE=ON \ + -DBUILD_TESTING=OFF \ + -DBUILD_BENCHMARKS=OFF \ + -DBUILD_DOCUMENTATION=OFF \ + -DBUILD_GEOSOP=OFF \ + -DCMAKE_C_FLAGS="-fPIC" \ + -DCMAKE_CXX_FLAGS="-fPIC" \ + -DCMAKE_INSTALL_PREFIX=${WASM_LIBRARY_DIR} \ + ./ + + emmake make -j ${PYODIDE_JOBS:-3} + emmake make install + + mkdir -p dist + cp ${WASM_LIBRARY_DIR}/lib/libgeos* dist/ diff --git a/integration_tests/recipes/numpy/meta.yaml b/integration_tests/recipes/numpy/meta.yaml new file mode 100644 index 0000000..9c3a8fe --- /dev/null +++ b/integration_tests/recipes/numpy/meta.yaml @@ -0,0 +1,33 @@ +package: + name: numpy + version: 1.26.4 + tag: + - min-scipy-stack + top-level: + - numpy +source: + url: https://files.pythonhosted.org/packages/65/6e/09db70a523a96d25e115e71cc56a6f9031e7b8cd166c1ac8438307c14058/numpy-1.26.4.tar.gz + sha256: 2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010 + +build: + # numpy uses vendored meson, so we need to pass the cross file manually + backend-flags: | + setup-args=-Dallow-noblas=true + setup-args=--cross-file=${MESON_CROSS_FILE} + # numpy creates numpy/distutils/__pycache__ directory during the build. + # It breaks our test because there is a .pyc in the directory. + post: | + rm -rf numpy/distutils/__pycache__ + cflags: | + -Wno-return-type + cross-build-env: true + cross-build-files: + - numpy/core/include/numpy/numpyconfig.h + - numpy/core/include/numpy/_numpyconfig.h + - numpy/core/lib/libnpymath.a + - numpy/random/lib/libnpyrandom.a +about: + home: https://www.numpy.org + PyPI: https://pypi.org/project/numpy + summary: NumPy is the fundamental package for array computing with Python. + license: BSD diff --git a/integration_tests/recipes/orjson/meta.yaml b/integration_tests/recipes/orjson/meta.yaml new file mode 100644 index 0000000..c0816d7 --- /dev/null +++ b/integration_tests/recipes/orjson/meta.yaml @@ -0,0 +1,20 @@ +package: + name: orjson + version: 3.10.1 + top-level: + - orjson +source: + url: https://files.pythonhosted.org/packages/f5/af/0daa12a907215a5af6d97db8adf301ef14a1b1c651f7e176ee04e0998433/orjson-3.10.1.tar.gz + sha256: a883b28d73370df23ed995c466b4f6c708c1f7a9bdc400fe89165c96c7603204 +requirements: + executable: + - rustup +build: + script: export RUSTFLAGS="-Z link-native-libraries=yes" +about: + home: https://github.com/ijl/orjson + PyPI: https://pypi.org/project/orjson + summary: + Fast, correct Python JSON library supporting dataclasses, datetimes, and + numpy + license: Apache-2.0 OR MIT diff --git a/integration_tests/recipes/zlib/meta.yaml b/integration_tests/recipes/zlib/meta.yaml new file mode 100644 index 0000000..6be360a --- /dev/null +++ b/integration_tests/recipes/zlib/meta.yaml @@ -0,0 +1,25 @@ +package: + name: zlib + version: 1.3.1 + tag: + - library +source: + sha256: 9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23 + url: https://github.com/madler/zlib/releases/download/v1.3.1/zlib-1.3.1.tar.gz + +build: + type: static_library + script: | + mkdir -p "build" + pushd "build" + LDFLAGS="${SIDE_MODULE_LDFLAGS}" emcmake cmake \ + -DBUILD_TESTING=OFF \ + -DBUILD_BENCHMARKS=OFF \ + -DBUILD_DOCUMENTATION=OFF \ + -DCMAKE_C_FLAGS="-fPIC -Wno-deprecated-non-prototype" \ + -DCMAKE_CXX_FLAGS="-fPIC -Wno-deprecated-non-prototype" \ + -DCMAKE_INSTALL_PREFIX=${WASM_LIBRARY_DIR} \ + ../ + emmake make -j ${PYODIDE_JOBS:-3} + emmake make install + popd diff --git a/tools/check_integration_test_trigger.sh b/tools/check_integration_test_trigger.sh new file mode 100755 index 0000000..19b88b4 --- /dev/null +++ b/tools/check_integration_test_trigger.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +set -x + +COMMIT_MSG=$(git log --no-merges -1 --oneline) + +# The integration tests will be triggered on push or on pull_request when the commit +# message contains "[integration]" +if [[ "$GITHUB_EVENT_NAME" == push || + "$COMMIT_MSG" =~ \[integration\] ]]; then + echo "trigger=true" >> "$GITHUB_OUTPUT" +fi