Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Poetry: select olddeps using poetry #12407

Merged
merged 14 commits into from
Apr 12, 2022
75 changes: 70 additions & 5 deletions .ci/scripts/test_old_deps.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#!/usr/bin/env bash
# this script is run by GitHub Actions in a plain `focal` container; it installs the
# minimal requirements for tox and hands over to the py3-old tox environment.
# this script is run by GitHub Actions in a plain `focal` container; it
# - installs the minimal system requirements, and poetry;
# - patches the project definition file to refer to old versions only;
# - creates a venv with these old versions using poetry; and finally
# - invokes `trial` to run the tests with old deps.

# Prevent tzdata from asking for user input
export DEBIAN_FRONTEND=noninteractive
Expand All @@ -9,12 +12,74 @@ set -ex

apt-get update
apt-get install -y \
python3 python3-dev python3-pip python3-venv \
libxml2-dev libxslt-dev xmlsec1 zlib1g-dev tox libjpeg-dev libwebp-dev
python3 python3-dev python3-pip python3-venv pipx \
libxml2-dev libxslt-dev xmlsec1 zlib1g-dev libjpeg-dev libwebp-dev

export LANG="C.UTF-8"

# Prevent virtualenv from auto-updating pip to an incompatible version
export VIRTUALENV_NO_DOWNLOAD=1

exec tox -e py3-old
# Patch the project definitions in-place:
# - Replace all lower and tilde bounds with exact bounds
# - Make the pyopenssl 17.0, which is the oldest version that works with
# a `cryptography` compiled against OpenSSL 1.1.
# - Delete all lines referring to psycopg2 --- so no testing of postgres support.
# - Omit systemd: we're not logging to journal here.

# TODO: we should also replace caret bounds, see
# https://python-poetry.org/docs/dependency-specification/#version-constraints
# We don't use these yet, but they are the default bound used when you `poetry add` from
# the commandline, rather than editing pyproject.toml directly.
# The sed expression 's/\^/==/g' ought to do the trick. But it would also change
# `python = "^3.7"` to `python = "==3.7"`, which would mean we fail because olddeps
# runs on 3.8 (#12343).

# TODO: I'd prefer to use something like this
# https://github.com/python-poetry/poetry/issues/3527
# https://github.com/pypa/pip/issues/8085
# rather than this sed script.

sed -i-backup \
DMRobertson marked this conversation as resolved.
Show resolved Hide resolved
-e "s/[~>]=/==/g" \
-e "/psycopg2/d" \
-e 's/pyOpenSSL = "==16.0.0"/pyOpenSSL = "==17.0.0"/' \
-e '/psycopg2/d' \
-e '/systemd/d' \
pyproject.toml

# TODO: once pyproject.toml uses poetry-core as its build-system, we may be able to
# simply `pip install .[all, test]` and run trial directly. (We would have to convince
# ourselves that pip will refuse to install if the olddeps are incompatible with each
# other: folklore contends that pip's resolver is more lax than poetry's.)
#
# Until then, setuptools is the build system. That means we need to use `poetry` to
# do the installation. `poetry lock` fails because of incompatibilities between dev
# dependencies and old deps. Workaround this by removing dev dependencies entirely.

pip install --user toml

REMOVE_DEV_DEPENDENCIES="
import toml
with open('pyproject.toml', 'r') as f:
data = toml.loads(f.read())

del data['tool']['poetry']['dev-dependencies']

with open('pyproject.toml', 'w') as f:
toml.dump(data, f)
"
python3 -c "$REMOVE_DEV_DEPENDENCIES"

pipx install poetry==1.1.12
~/.local/bin/poetry lock

echo "::group::Patched pyproject.toml"
cat pyproject.toml
echo "::endgroup::"
echo "::group::Lockfile after patch"
cat poetry.lock
echo "::endgroup::"

~/.local/bin/poetry install -E "all test"
~/.local/bin/poetry run trial --jobs=2 tests
5 changes: 3 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,19 @@ jobs:
|| true

trial-olddeps:
# Note: sqlite only; no postgres
if: ${{ !cancelled() && !failure() }} # Allow previous steps to be skipped, but not fail
needs: linting-done
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Test with old deps
uses: docker://ubuntu:focal # For old python and sqlite
# Note: focal seems to be using 3.8, but the oldest is 3.7?
# See https://github.com/matrix-org/synapse/issues/12343
with:
workdir: /github/workspace
entrypoint: .ci/scripts/test_old_deps.sh
env:
TRIAL_FLAGS: "--jobs=2"
Comment on lines -141 to -142
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved into the script file as an explicit argument rather than

I don't think TRIAL_FLAGS is something trial actually supports; I think we just hacked it into our tox config:

/usr/bin/env COVERAGE_PROCESS_START={toxinidir}/.coveragerc "{envbindir}/trial" {env:TRIAL_FLAGS:} {posargs:tests} {env:TOXSUFFIX:}

- name: Dump logs
# Logs are most useful when the command fails, always include them.
if: ${{ always() }}
Expand Down
1 change: 1 addition & 0 deletions changelog.d/12407.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Run the olddeps CI job using Poetry.
22 changes: 0 additions & 22 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -105,29 +105,7 @@ commands =
# )
usedevelop=true

# A test suite for the oldest supported versions of Python libraries, to catch
# any uses of APIs not available in them.
[testenv:py3-old]
skip_install = true
usedevelop = false
deps =
Automat == 0.8.0
lxml
Comment on lines -114 to -115
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see these being moved into the new bits, but maybe that's OK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be okay.

  • Automat isn't a direct dependency (it's not in python_dependencies,py nor pyproject.toml), so I don't think we have any business pinning it to a particular version anyway;
  • lxml will be installed it's part of all, and in the config we install all extras
  • markupsafe is also not a direct dependency.
  • the base dependencies are pip, setuptools, and stuff related to coverage. We've stopped using coverage (and I suspect it'd need some config fiddling to have it work in poetry anyway).

# markupsafe 2.1 introduced a change that breaks Jinja 2.x. Since we depend on
# Jinja >= 2.9, it means this test suite will fail if markupsafe >= 2.1 is installed.
markupsafe < 2.1
{[base]deps}

commands =
# Make all greater-thans equals so we test the oldest version of our direct
# dependencies, but make the pyopenssl 17.0, which can work against an
# OpenSSL 1.1 compiled cryptography (as older ones don't compile on Travis).
/bin/sh -c 'python -m synapse.python_dependencies | sed -e "s/>=/==/g" -e "/psycopg2/d" -e "s/pyopenssl==16.0.0/pyopenssl==17.0.0/" | xargs -d"\n" pip install'

# Install Synapse itself. This won't update any libraries.
pip install -e ".[test]"

{[testenv]commands}

[testenv:benchmark]
deps =
Expand Down