Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Python linting situation (pin versions) #19986

Closed
allisonkarlitskaya opened this issue Feb 9, 2024 · 6 comments · Fixed by #20169
Closed

Improve Python linting situation (pin versions) #19986

allisonkarlitskaya opened this issue Feb 9, 2024 · 6 comments · Fixed by #20169

Comments

@allisonkarlitskaya
Copy link
Member

We currently run ruff out of:

  • the unit-tests container
  • the tasks container

and recently had to deal with a pain in the neck of an upgrade which changed a bunch of options (adding lint to section names). The change was mutually-incompatible because the complaints to stderr got interpreted by test/static-code as a failure.

We ended up needing to upgrade the tasks container in a hurry, which itself broke a bunch of stuff, including linting in all of the other projects.

We need a better approach here. For the node-based linters, we get them as part of our version-locked-in node_modules, and have direct support over upgrading those. For Python we could do something similar via requirements.txt or PEP 621 dependencies, but we don't.

I've done a couple of rounds of thinking up an idea workflow for "how do we create a venv with a bunch of dependencies installed in it in order to run a test command" before realizing that I don't need to invent tox, because it already exists.

Here's some other info I've discovered from research so far, so we don't lose it:

@martinpitt
Copy link
Member

martinpitt commented Feb 9, 2024

My two cents: We mostly had/have this problem with cockpit.git, as ruff runs in the unit-tests container which gets updated at a pace independently from cockpit/tasks. It should never break spontaneously though, as unit-tests-refresh runs all the unit tests and is supposed to stop the container update if anything fails. I wasn't here when that thing happened, but if it did happen spontaneously, then the tests in -refresh are broken.

That said, I'd much prefer a single source of truth. All other projects run ruff (and test/static-code) in our cockpit/tasks container, so we could just do the same for our unit tests. cockpit/tasks even has cockpit's build deps installed (for the very reason that we want to build it both in CI and also as developers in toolbox).

So the smallest possible move would be to run all x86 unit tests in cockpit/tasks instead of our custom unit-tests container (done in PR #20005), and figuring out a robust environment for tox instead of pip installing it all the time.

That may also be the final nail in the coffin for testing on i386 -- frankly, it's almost useless these days. New stuff gets written in Python, nobody cares about i386 any more, and we run the unit tests during rpm build in packit, so we already have i386/aarch64/s390x coverage there. update: done in PR #20005

I must say I don't like the requirements.txt/tox/venv overhead at all. Too many moving parts, introducing yet more stuff to download all the time (aside from cluttering up $HOME). If fixing our projects for new ruff versions is that much of a problem (it hasn't been in my experience), we could install multiple versions into the tasks container as well (it's just a single static binary after all), and let projects choose (i.e. test/static-code could call a particular ruff-$VERSION and read it from test/ruff-version or so) -- but honestly it feels like overkill to me.

@martinpitt
Copy link
Member

martinpitt commented Feb 9, 2024

Another thing: So far our maintenance and update process for the tasks container sucks. It'd be much better to auto-refresh it weekly, push to a :staging tag, and then create a couple of "test new container" PRs (with a staging label) against our projects to sort out the failures without the "OMG we need to unbreak everything now". We already have this problem due to new browser versions and other things (chrome-devtools-protocol versions etc.), so adding new ruff into the mix doesn't make the problem fundamentally worse.

Building this "staging" infra isn't terribly hard: We need a new PR label, tests-scan to look at it and push stuff into staging-* AMQP queues, and bots to listen to the queues. To not make this inefficient we should finally move to launching one single-shot container per task, instead of iterating a loop inside of it. We have also wanted this forever for e.g. this problem, but it never bubbled up to the top of the list.

@martinpitt
Copy link
Member

martinpitt commented Feb 10, 2024

we should finally move to launching one single-shot container per task

Some notes:

  • Setting up a "queue controller" on the host shouln't take much. Mostly python (which we already need for Ansible), and python-pika for connecting to AMQP, everything else is included batteries.

  • If pika is a problem (CoreOS? But there we could still do pip install), we don't have to introduce assumptions on the host: we can run the "queue controller" in a tasks container, and give it access to the host's podman with

podman run -it --rm -v /run/podman/podman.sock:/run/podman/podman.sock:Z -u root quay.io/cockpit/tasks bash

Inside, dnf install --setopt=install_weak_deps=False podman, then you can do podman --remote images or any other podman command (I tested launching a container).

  • With that we can run a main loop in the queue controller, let it run up to TEST_JOBS parallel containers. Most of cockpit-tasks main loop code is cleanup, all of which can disappear with one container per job. It's essentially just calling run-queue.

  • We could give run-queue some --exec-prefix option to wrap the queue command into a podman [--remote] run ... command with the appropriate options. Let's maintain that script in cockpituous. It can also take the code from cockpit-tasks for initializing the secrets in the container.

@martinpitt
Copy link
Member

We've spent a long time building the new CI infrastructure, but note that our recent encounter with this in #20149 was completely unrelated to our infra -- it started happening in the "tox" workflow, which dynamically installs the latest pip version from scratch. We need a solution for that, too, i.e. preferably run that in the tasks container too, and make it part of the unit tests?

@allisonkarlitskaya
Copy link
Member Author

Yes. Since we follow this logic that the container is our single authority, we should read the container file from git and run tox in that container.

@allisonkarlitskaya
Copy link
Member Author

#20154 went a long way towards addressing this. The last thing left here is to make sure we run our unit-tests workflows on github inside of the version of the container we find in .cockpit-ci/container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

2 participants