diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a68bfe..fd15760 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,3 +17,13 @@ jobs: shellcheck -P SCRIPTDIR -x test/utils test/test-* - run: ./run_tests.sh + + test-macos: + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + runs-on: macos-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v3 + + - run: ./run_tests.sh diff --git a/README.md b/README.md index 76896e1..3a9674e 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ heroku buildpacks:add https://github.com/moneymeets/python-poetry-buildpack.git heroku buildpacks:add heroku/python ``` -**Note:** this buildpack is _only_ for generating `requirements.txt` and `runtime.txt` for subsequent use by the official `heroku/python` buildpack. Do not depend on the installed Poetry's location, or its venv remaining functional at app runtime. If you need Poetry for other purposes (for example CI checks), make your own separate Poetry installation accordingly. +**Note:** this buildpack is _only_ for generating `requirements.txt` and `runtime.txt` for subsequent use by the official `heroku/python` buildpack. Do not depend on the installed Poetry's location, or its virtual environment remaining functional at app runtime. If you need Poetry for other purposes (for example CI checks), make your own separate Poetry installation accordingly. ## Configuration @@ -26,9 +26,19 @@ Python version can be forced by setting the `PYTHON_RUNTIME_VERSION` variable. O heroku config:set PYTHON_RUNTIME_VERSION=3.9.1 ``` +### `runtime.txt` + +Generation of the `runtime.txt` can be skipped by setting `DISABLE_POETRY_CREATE_RUNTIME_FILE` to `1`: + +``` +heroku config:set DISABLE_POETRY_CREATE_RUNTIME_FILE=1 +``` + +If `DISABLE_POETRY_CREATE_RUNTIME_FILE` is set, the required Python version can be specified in `runtime.txt`. Otherwise, if `runtime.txt` is present in the repository, the buildpack will prevent the app from being deployed in order to avoid possible ambiguities. + ### Poetry -Poetry version can be specified by setting `POETRY_VERSION` in Heroku config vars. Otherwise, it will default to a hardcoded version. +Poetry version can be specified by setting `POETRY_VERSION` in Heroku config vars. Otherwise, it will attempt to be inferred from `poetry.lock` or default to the latest version. ``` heroku config:set POETRY_VERSION=1.1.13 @@ -36,6 +46,8 @@ heroku config:set POETRY_VERSION=1.1.13 Generally all variables starting with `POETRY_` are passed on to Poetry by this buildpack; see the corresponding [Poetry documentation](https://python-poetry.org/docs/configuration/#using-environment-variables) section for possible uses. +### `requirements.txt` + Exporting of development dependencies (e.g. to run tests in CI pipelines) can be optionally enabled by setting `POETRY_EXPORT_DEV_REQUIREMENTS` to `1`: ``` @@ -48,16 +60,6 @@ If you want to override the default export parameters (`--without-hashes --with- heroku config:set POETRY_EXPORT_PARAMS=--with-hashes ``` -### runtime.txt - -Generation of the `runtime.txt` can be skipped by setting `DISABLE_POETRY_CREATE_RUNTIME_FILE` to `1`: - -``` -heroku config:set DISABLE_POETRY_CREATE_RUNTIME_FILE=1 -``` - -If `DISABLE_POETRY_CREATE_RUNTIME_FILE` is set, the required Python version can be specified in `runtime.txt`. Otherwise, if `runtime.txt` is present in the repository, the buildpack will prevent the app from being deployed in order to avoid possible ambiguities. - ## Contributing To test your changes locally run the (TAP-compatible) test suite: diff --git a/bin/compile b/bin/compile index 6a67e2a..3667289 100755 --- a/bin/compile +++ b/bin/compile @@ -25,9 +25,18 @@ for env_file in $BUILDPACK_VARIABLES ; do [ -f "$ENV_DIR/$env_file" ] && export "$(basename "$env_file")=$(cat "$ENV_DIR/$env_file" 2>/dev/null)" done -if [ -z "${POETRY_VERSION:-}" ] ; then - export POETRY_VERSION=1.5.1 - log "No Poetry version specified in POETRY_VERSION config var. Defaulting to $POETRY_VERSION." +POETRY_VERSION="${POETRY_VERSION:-}" + +if [ -z "$POETRY_VERSION" ] ; then + if [ -f "$BUILD_DIR/poetry.lock" ] ; then + POETRY_VERSION=$(head --lines=1 "$BUILD_DIR/poetry.lock" | grep --only-matching '[0-9]\+\.[0-9]\+\.[0-9]\+' || true) + fi + if [ -n "$POETRY_VERSION" ] ; then + export POETRY_VERSION + log "Read Poetry version $POETRY_VERSION from poetry.lock" + else + log "No Poetry version specified in POETRY_VERSION config var. Defaulting to latest." + fi else log "Using Poetry version from POETRY_VERSION config var: $POETRY_VERSION" fi @@ -88,7 +97,7 @@ fi if [ -z "${PYTHON_RUNTIME_VERSION:-}" ] ; then log "Read Python version from poetry.lock" - PYTHON_RUNTIME_VERSION="$(sed -n -e '/^\[metadata\]/,/^\[/p' poetry.lock | sed -n -e 's/^python-versions\s*=\s*//p' | tr -d \"'[:space:]'\')" + PYTHON_RUNTIME_VERSION="$(sed -n -e '/^\[metadata\]/,/^\[/p' poetry.lock | sed -n -e 's/^python-versions[[:space:]]*=[[:space:]]*//p' | tr -d \"'[:space:]'\')" else log "Force Python version to $PYTHON_RUNTIME_VERSION, because PYTHON_RUNTIME_VERSION is set!" fi diff --git a/test/fixtures/compile-exact_version_specifier.stdout.txt b/test/fixtures/compile-exact_version_specifier.stdout.txt index 21b6eb2..29ef818 100644 --- a/test/fixtures/compile-exact_version_specifier.stdout.txt +++ b/test/fixtures/compile-exact_version_specifier.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-export_dev.stdout.txt b/test/fixtures/compile-export_dev.stdout.txt index 92a0475..94febff 100644 --- a/test/fixtures/compile-export_dev.stdout.txt +++ b/test/fixtures/compile-export_dev.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-export_params-0.stdout.txt b/test/fixtures/compile-export_params-0.stdout.txt index abb9dba..6f4f5aa 100644 --- a/test/fixtures/compile-export_params-0.stdout.txt +++ b/test/fixtures/compile-export_params-0.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-export_params-1.stdout.txt b/test/fixtures/compile-export_params-1.stdout.txt index 419a6bc..84956de 100644 --- a/test/fixtures/compile-export_params-1.stdout.txt +++ b/test/fixtures/compile-export_params-1.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-force_python_version.stdout.txt b/test/fixtures/compile-force_python_version.stdout.txt index d1a3a34..7768eb3 100644 --- a/test/fixtures/compile-force_python_version.stdout.txt +++ b/test/fixtures/compile-force_python_version.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-invalid_python_version.stdout.txt b/test/fixtures/compile-invalid_python_version.stdout.txt index b6dba98..925dab8 100644 --- a/test/fixtures/compile-invalid_python_version.stdout.txt +++ b/test/fixtures/compile-invalid_python_version.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-no_vars_success.stdout.txt b/test/fixtures/compile-no_vars_success.stdout.txt index 21b6eb2..29ef818 100644 --- a/test/fixtures/compile-no_vars_success.stdout.txt +++ b/test/fixtures/compile-no_vars_success.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-poetry_version_comment.stderr.txt b/test/fixtures/compile-poetry_version_comment.stderr.txt new file mode 100644 index 0000000..e69de29 diff --git a/test/fixtures/compile-poetry_version_comment.stdout.txt b/test/fixtures/compile-poetry_version_comment.stdout.txt new file mode 100644 index 0000000..753de16 --- /dev/null +++ b/test/fixtures/compile-poetry_version_comment.stdout.txt @@ -0,0 +1,10 @@ +-----> Read Poetry version 1.5.1 from poetry.lock +-----> Generate requirements.txt with Poetry +-----> Install Poetry + >>> mocked curl call <<< +-----> Add Poetry to the PATH +-----> Export requirements.txt from Poetry + >>> mocked poetry call <<< +-----> Export Python version from Poetry to Heroku runtime.txt file +-----> Read Python version from poetry.lock +-----> Write 3.8.3 into runtime.txt diff --git a/test/fixtures/compile-skip_runtime_error.stdout.txt b/test/fixtures/compile-skip_runtime_error.stdout.txt index 7e57b37..f15a6e5 100644 --- a/test/fixtures/compile-skip_runtime_error.stdout.txt +++ b/test/fixtures/compile-skip_runtime_error.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-skip_runtime_success.stdout.txt b/test/fixtures/compile-skip_runtime_success.stdout.txt index 4fff94d..02ab9f0 100644 --- a/test/fixtures/compile-skip_runtime_success.stdout.txt +++ b/test/fixtures/compile-skip_runtime_success.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/compile-trailing_space.stdout.txt b/test/fixtures/compile-trailing_space.stdout.txt index 21b6eb2..29ef818 100644 --- a/test/fixtures/compile-trailing_space.stdout.txt +++ b/test/fixtures/compile-trailing_space.stdout.txt @@ -1,4 +1,4 @@ ------> No Poetry version specified in POETRY_VERSION config var. Defaulting to 1.5.1. +-----> No Poetry version specified in POETRY_VERSION config var. Defaulting to latest. -----> Generate requirements.txt with Poetry -----> Install Poetry >>> mocked curl call <<< diff --git a/test/fixtures/poetry.lock-invalid b/test/fixtures/poetry.lock-invalid index 0eabd30..cf583db 100644 --- a/test/fixtures/poetry.lock-invalid +++ b/test/fixtures/poetry.lock-invalid @@ -1,3 +1,4 @@ +[[package]] python-versions = "3.8.1" [metadata] diff --git a/test/fixtures/poetry.lock-valid b/test/fixtures/poetry.lock-valid index efc0488..46672c0 100644 --- a/test/fixtures/poetry.lock-valid +++ b/test/fixtures/poetry.lock-valid @@ -1,3 +1,4 @@ +[[package]] python-versions = "3.8.1" [metadata] diff --git a/test/fixtures/poetry.lock-valid_exact_version_specifier b/test/fixtures/poetry.lock-valid_exact_version_specifier index 8659ef6..4fea6c0 100644 --- a/test/fixtures/poetry.lock-valid_exact_version_specifier +++ b/test/fixtures/poetry.lock-valid_exact_version_specifier @@ -1,3 +1,4 @@ +[[package]] python-versions = "3.8.1" [metadata] diff --git a/test/fixtures/poetry.lock-valid_version_comment b/test/fixtures/poetry.lock-valid_version_comment new file mode 100644 index 0000000..540db3f --- /dev/null +++ b/test/fixtures/poetry.lock-valid_version_comment @@ -0,0 +1,11 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +python-versions = "3.8.1" + +[metadata] +lock-version = "1.1" +python-versions = "3.8.3" +content-hash = "da2fc19cb5e10ad726a3f8e65247221010b8dc20a38e571ec66de2fec53e9ad4" + +[metadata.files] diff --git a/test/test-compile b/test/test-compile index f181da9..7c3b723 100644 --- a/test/test-compile +++ b/test/test-compile @@ -9,12 +9,14 @@ run_test sanity-2 compile BUILD_DIR CACHE_DIR cp fixtures/poetry.lock-valid "$INPUT_DIR"/poetry.lock run_test no_vars_success compile "$INPUT_DIR" CACHE_DIR fixtures/env_dir +cp fixtures/poetry.lock-valid_version_comment "$INPUT_DIR"/poetry.lock +run_test poetry_version_comment compile "$INPUT_DIR" CACHE_DIR fixtures/env_dir + cp fixtures/poetry.lock-valid_exact_version_specifier "$INPUT_DIR"/poetry.lock run_test exact_version_specifier compile "$INPUT_DIR" CACHE_DIR fixtures/env_dir -cp fixtures/poetry.lock-valid "$INPUT_DIR"/poetry.lock # add trailing space to python-versions to test if it will be removed -sed -i 's/^python-versions.*/& /g' "$INPUT_DIR"/poetry.lock +sed -e 's/^python-versions.*/& /g' fixtures/poetry.lock-valid > "$INPUT_DIR"/poetry.lock run_test trailing_space compile "$INPUT_DIR" CACHE_DIR fixtures/env_dir cp fixtures/poetry.lock-valid "$INPUT_DIR"/poetry.lock