Skip to content

Commit

Permalink
Revive tests
Browse files Browse the repository at this point in the history
This PR gets the tests to pass with all the latest minor versions of all currently existing Python and Ansible versions.  It was not pleasant work. There have been a lot of Ansible versions and a lot of Python versions and a lot of changes to... just about everything involved here... since I last had the time to work on this!

By some miracle, the plugin itself has *NOT* needed *ANY* changes.  It still totally works.

* Add new Python and Ansible version combos to the generated tox.ini
* Restrict the Jinja2 version for some combos because it was [too broadly specified in the Ansible deps](ansible/ansible#77356)
* Remove the [deprecated](ansible/ansible#75828) `Templar.set_available_variables` method in a test util function (luckily there is another way to do this that works for all Ansible versions)
* Run each job in official python images: the [setup-python](https://github.com/actions/setup-python) action [no longer supports 2.7](actions/setup-python#672), and not all 3.x versions can be installed in the same Ubuntu runner anyway.
* Don't use [tox-gh-actions](https://pypi.org/project/tox-gh-actions/): the version that supports running in containers isn't compatible with all of the python versions that we need [issue](https://github.com/ymyzk/tox-gh-actions/pull/114/files)
* Restrict tox to a version that both supports Python 2.7 and supports filtering envs
* Explicitly call out `asdf` dependency for getting all tox combos to pass locally
* Add a link to [a proposed alternative way to do this](leapfrogonline#43) with pure Ansible to the Readme
  • Loading branch information
fajpunk committed Dec 18, 2023
1 parent b812d5b commit 07fb891
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 137 deletions.
67 changes: 48 additions & 19 deletions .github/workflows/ci.yaml
Expand Up @@ -12,35 +12,64 @@ on:

workflow_dispatch:


jobs:
test:
runs-on: ubuntu-latest
strategy:
max-parallel: 5
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9]

python-version:
- image: '2.7'
tox: py27
- image: '3.5'
tox: py35
- image: '3.6'
tox: py36
- image: '3.7'
tox: py37
- image: '3.8'
tox: py38
- image: '3.9'
tox: py39
- image: '3.10'
tox: py310
- image: '3.11'
tox: py311
- image: '3.12'
tox: py312
container:
image: python:${{ matrix.python-version.image }}
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
- name: Free disk space
# https://github.com/actions/virtual-environments/issues/709
run: |
python -m pip install --upgrade pip
pip install tox tox-gh-actions
echo "=========original CI disk space"
df -h
rm -rf "/usr/local/share/boost"
rm -rf "$AGENT_TOOLSDIRECTORY"
echo "=========after clean up, the left CI disk space"
df -h
- uses: actions/checkout@v4

- name: Test with tox
run: make ci-test
env:
# Can't include envs by regex, only exclude them :|
TOX_SKIP_ENV: '^(?!${{ matrix.python-version.tox }}-)'
run: |
set -x
pip install -U -r requirements.txt
python tests/bin/generate_tox_config.py
env | grep TOX
tox
lint:
runs-on: ubuntu-latest
container:
image: python:3.12
steps:
- uses: actions/checkout@v2
- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9
- uses: actions/checkout@v4

- name: Lint
run: make lint
run: |
apt-get update && apt-get install make
make lint
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -96,3 +96,5 @@ ENV/

# Generated MANIFEST
MANIFEST

.idea
59 changes: 5 additions & 54 deletions .pylintrc
Expand Up @@ -10,61 +10,12 @@
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=
import-star-module-level,
old-octal-literal,
oct-method,
print-statement,
unpacking-in-except,
parameter-unpacking,
backtick,
old-raise-syntax,
old-ne-operator,
long-suffix,
dict-view-method,
dict-iter-method,
metaclass-assignment,
next-method-called,
raising-string,
indexing-exception,
raw_input-builtin,
long-builtin,
file-builtin,
execfile-builtin,
coerce-builtin,
cmp-builtin,
buffer-builtin,
basestring-builtin,
apply-builtin,
filter-builtin-not-iterating,
using-cmp-argument,
useless-suppression,
range-builtin-not-iterating,
suppressed-message,
no-absolute-import,
old-division,
cmp-method,
reload-builtin,
zip-builtin-not-iterating,
intern-builtin,
unichr-builtin,
reduce-builtin,
standarderror-builtin,
unicode-builtin,
xrange-builtin,
coerce-method,
delslice-method,
getslice-method,
setslice-method,
input-builtin,
round-builtin,
hex-method,
nonzero-method,
map-builtin-not-iterating,
too-few-public-methods,
similarities,
missing-docstring,
consider-using-f-string,
redundant-u-string-prefix,
consider-using-f-string
missing-function-docstring,
missing-class-docstring,
missing-module-docstring,
R0801, # similar lines in two files

[REPORTS]

Expand Down
6 changes: 0 additions & 6 deletions .python-version

This file was deleted.

1 change: 1 addition & 0 deletions .tool-versions
@@ -0,0 +1 @@
python 3.12.1 3.6.12 3.5.10 3.7.9 3.8.6 3.9.0 3.10.13 3.11.7 2.7.18
7 changes: 0 additions & 7 deletions Makefile
Expand Up @@ -23,13 +23,6 @@ lint: dev-deps generate-tox-config
test-all: dev-deps generate-tox-config
$(TOX) --parallel auto

# No venv needed in CI; let the GH Actions tox plugin handle the Python
# versions
ci-test:
pip install -U -r requirements.txt
python tests/bin/generate_tox_config.py
tox

clean:
rm -rf venv .tox .hypothesis dist tox.ini

Expand Down
54 changes: 30 additions & 24 deletions README.md
Expand Up @@ -27,9 +27,12 @@ newer versions of Python. The following combinations are tested:
| Python | Ansible |
|---------------|---------|
| 2.7 | >= 2.1 |
| >= 3.5, < 3.8 | >= 2.5 |
| >= 3.7, < 3.8 | >= 2.5 |
| >= 3.8 | >= 2.8 |

Above Ansible 2.8, _at least_ all of the combinations in the [Ansible Core Support Matrix](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html#ansible-core-support-matrix)
are tested. Some other combinations are tested too (even if the Ansible maintainers [may get salty about it](https://github.com/ansible/ansible/issues/81946))

## Installation

1. Pick a name that you want to use to call this plugin in Ansible playbooks.
Expand Down Expand Up @@ -216,7 +219,7 @@ merged_ports:
A note about `dedup`:
* It has no effect when the merged vars are dictionaries.

### Recursive merging ###
### Recursive merging

When dealing with complex data structures, you may want to do a deep (recursive) merge.

Expand Down Expand Up @@ -272,7 +275,7 @@ When merging dictionaries and the same key exists in both, the recursive merge c
* if the entry value is a dict, it merges the values (recursively) as dicts (merge_dict)
* any other values: just replace (use last)

### Module options ###
### Module options

| parameter | required | default | choices | comments |
| --------- | -------- | ------- | ------- | -------- |
Expand Down Expand Up @@ -309,23 +312,26 @@ PLAY RECAP *********************************************************************
localhost : ok=6 changed=0 unreachable=0 failed=0
```

## Example Playbooks
## Example playbooks

There are some example playbooks in the `examples` directory that show how the
various features work in the context of an actual Ansible playbook. These
example playbooks are run as part of the test suite for this plugin; if you
would like to run them yourself, please see the [Contributing](#contributing)
section for instructions on how to run the test suite.

## If you don't want to use this plugin
You may be able to do what you need with pure Ansible using [this strategy](https://github.com/leapfrogonline/ansible-merge-vars/issues/43).

## Contributing

Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.

There is only one prerequisite to working on this project locally:

1. You have the Python versions in the [.python-version](.python-version)
1. You have the Python versions in the [.tool-versions](.tool-versions)
installed and on your path (probably with
[pyenv](https://github.com/pyenv/pyenv)
[asdf](https://asdf-vm.com/)

A development workflow may look like this:

Expand All @@ -347,24 +353,24 @@ A development workflow may look like this:
available and tell tox to only run the tests for one combination:

```
$ venv/bin/tox -l
py27-ansible-2.1
py27-ansible-2.2
py27-ansible-2.3
py27-ansible-2.4
py27-ansible-2.5
py27-ansible-2.6
...
py35-ansible-2.5
py35-ansible-2.6
py36-ansible-2.7
py36-ansible-2.8
...
$ venv/bin/tox -e py36-ansible-2.5
...
```
$ venv/bin/tox -l
py27-ansible-2.1
py27-ansible-2.2
py27-ansible-2.3
py27-ansible-2.4
py27-ansible-2.5
py27-ansible-2.6
...
py37-ansible-2.5
py37-ansible-2.6
py38-ansible-2.7
py38-ansible-2.8
...
...
$ venv/bin/tox -e py36-ansible-2.5
```

If you have any ideas about things to add or improve, or find any bugs to fix, we're all ears! Just a few guidelines:

Expand Down
6 changes: 5 additions & 1 deletion requirements.txt
@@ -1,6 +1,10 @@
# Explicitly not pinnning most versions here to get valid versions for different python versions
pip
setuptools
wheel
twine
tox

# TOX_SKIP_ENV broke with an earlier version of 4, but we can't use the latest 4 with 2.7 :|
# https://github.com/tox-dev/tox/issues/2698
tox<4
requests
70 changes: 59 additions & 11 deletions tests/bin/generate_tox_config.py
Expand Up @@ -22,16 +22,36 @@
TOX_INI = os.path.join(ROOT_DIR, 'tox.ini')


def filter_releases(releases, min_release):
def filter_releases(releases, min_release, max_release=None, exclude=None):
"""
min_release inclusive, max_release exclusive
"""
exclude = exclude or []
finished = [release for release in releases
if not re.search(r'[a-zA-z]', release)]
minor = list(set(
[re.match(r'^(\d+\.\d+)', release).groups()[0] for release in finished]
))
relevant = [
release for release in minor
if LooseVersion(release) >= LooseVersion(min_release)
]

relevant = minor
if min_release:
relevant = [
release for release in relevant
if LooseVersion(release) >= LooseVersion(min_release)
]

if max_release:
relevant = [
release for release in relevant
if LooseVersion(release) < LooseVersion(max_release)
]

if exclude:
for excluded in exclude:
relevant = [
release for release in relevant
if not (str(release).startswith(str(excluded)))
]
return sorted(relevant, key=LooseVersion)


Expand All @@ -43,24 +63,52 @@ def tox_dep_specs(releases):
return '\n'.join(spec_strings)


def jinja_dep_specs(releases):
spec_strings = [
' ansible-{release}: jinja2<3.1'.format(release=release)
for release in releases
]
return '\n'.join(spec_strings)


def main():
# Get available releases
response = requests.get('https://pypi.python.org/pypi/ansible/json').json()
releases = response['releases'].keys()

py2_releases = filter_releases(releases, '2.1')
py3_releases = filter_releases(releases, '2.5')
py38_releases = filter_releases(releases, '2.8')
all_releases = filter_releases(releases, min_release='2.1')
py27_releases = filter_releases(releases, min_release='2.1', max_release='5.0')
py35_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py36_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py37_releases = filter_releases(releases, min_release='2.5', max_release='5.0')
py38_releases = filter_releases(releases, min_release='2.8', max_release='7.0')
py39_releases = filter_releases(releases, min_release='2.8', max_release='9.0')
py310_releases = filter_releases(releases, min_release='2.8')
py311_releases = filter_releases(releases, min_release='2.8')

# https://github.com/ansible/ansible/issues/81946
py312_releases = filter_releases(releases, min_release='2.8', exclude=[2.9])

# Some old releases didn't constrain Jinja properly and a newer version breaks some filters
# https://github.com/ansible/ansible/issues/77356
old_jinja_releases = filter_releases(releases, min_release=None, max_release='2.10')

print('Reading template {}'.format(TOX_TMPL))
with open(TOX_TMPL, 'r') as f:
tmpl = Template(f.read())

generated = tmpl.substitute(
py2_releases=','.join(py2_releases),
py3_releases=','.join(py3_releases),
py27_releases=','.join(py27_releases),
py35_releases=','.join(py35_releases),
py36_releases=','.join(py36_releases),
py37_releases=','.join(py37_releases),
py38_releases=','.join(py38_releases),
ansible_dep_specs=tox_dep_specs(py2_releases)
py39_releases=','.join(py39_releases),
py310_releases=','.join(py310_releases),
py311_releases=','.join(py311_releases),
py312_releases=','.join(py312_releases),
ansible_dep_specs=tox_dep_specs(all_releases),
jinja_dep_specs=jinja_dep_specs(old_jinja_releases)
)
print('\nWriting {TOX_INI}:\n{generated}'.format(TOX_INI=TOX_INI, generated=generated))

Expand Down

0 comments on commit 07fb891

Please sign in to comment.