13

I am running a fairly complex Django application, for about a year now. It has about 50 packages in requirements.txt

Whenever I need a new package, I install it with pip, and then manually add it in the requirements.txt file with a fixed version:

SomeNewModule==1.2.3

That means that most of my packages are now outdated after a year. I have updated couple of them manually when I specifically needed a new feature.

I am beginning to think that there might be security patches that I am missing out, but I am reluctant to update them all blindly, due to backward incompatibility.

Is there a standard best practice for this?

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Martin Taleski
  • 6,033
  • 10
  • 40
  • 78

6 Answers6

12

The common pattern for versioning python modules (and many other software) is major.minor.patch where after the initial release, patch versions don't change the api, minor releases may change the api in a backward compatible way, and major releases usually aren't backward compatible

so if you have module==x.y.z a relatively safe requirement specification would be:

module>=x.y.z,<x.y+1.0

note that while this will usually be OK, it's based on common practices, and not guaranteed to work, and it's more likely to be stable with more "organized" modules

Ophir Yoktan
  • 8,149
  • 7
  • 58
  • 106
4

Do not update packages in production, you can brake things, if you have a package which has tables in database, and you update it you can brake your database. I used for example python social auth, I wanted to upgrade it to the last version, so for that, I need it to upgrade do version x, run migrations and after that got to last version and migrate. Upgrade the packages in your development environment, test it. If you have a pre-production, do that there after testing in dev.

jalanga
  • 1,456
  • 2
  • 17
  • 44
  • yes, that was my idea, but this does include a lot of manual testing and maintenance work. Also the db consideration is only for django modules that interact with the database. I am talking more generally about all python packages – Martin Taleski Oct 06 '17 at 08:58
  • You can face this situation in which I was. You are using package 1.3, upgrade your package to 2.0, this "package" has some dependencies which you don't have in your req file, and those dependencies can be broken, and you need to add in the req file that dependency at a lower version to work. I had this issue with some packages from google. – jalanga Oct 06 '17 at 09:17
2

One of the most robust practices in the industry is to ensure that your code is well unit-tested, well property-tested, and well regression-tested. Once you've got good coverage and the tests are green, begin upgrading your dependencies. You might want to do this one at a time if you're feeling ambitious, or you might give it all a go and try your luck. If after upgrading your tests are still green and you can manually go through all workflows, chances are you're in the clear! Those tests you spent time on can then be leveraged going forward for any smaller, incremental upgrades.

Dane Hillard
  • 890
  • 1
  • 11
  • 27
1

First, a little background on me. I'm a security test engineer and work heavily on Python, that being said most of my work is test code and the products I typically work on do not ship with Python running on the box so I cannot give you direct answers to questions about specific Python packages. I can give you some rules of thumb about what most companies do when faced with such questions in a general sense.

Figure out if you need to update:

  1. Run a security scanner (like Nessus). If you have any glaring version problems with your application stack or hosts Nessus will give you some idea of things that should be fixed immediately

  2. Check the release notes for all of the packages to see if anything actually needs updating. Pay extra close attention to any package that opens a socket. If there are no security fixes it probably isn't worth your time to update. In some cases even if there is a security problem in a package, it may be something you aren't using so pay attention to the problem description. If you have an application in production now, typically the goal is to change as little as possible to limit the amount of code update and testing that needs to be done.

If you've discovered that you need an update to start resolving dependencies:

  1. Probably the easiest way to do this is to set up a test environment and start installing the updated versions that you need. Once more, try to make a few changes as possible while installing your code in the test environment. In Python, there is a reliance for C libraries for much of the security stuff, In your test environment be sure to have the same lower level system libs as well...

  2. Create a list of changes that need to be made and start devising a test plan for the sections of code that you need to replace.

Once your development environment is set up, test test test. You'll probably want to rerun your security scanner and be assured to exercise all of the new code.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
sehafoc
  • 866
  • 6
  • 9
1

It depends. Most of the time, updating the packages for minor version changes (eg: 2.45.1 -> 2.56.1) is unlikely to break your system. However, it is still advisable to run extensive regression testing. However, major version changes(eg. 2.45.1 to 3.13.0) should definitely be avoided as most of them have little backward compatibility. An example of this would be the selenium web driver which in version 3.0 cannot run without geckodriver compared to version 2.56. Regardless, extensive unit and regressive testing should be carried out on the old and new code to ensure there are no unexpected changes, especially at the corner cases.

Considering that you have mentioned that you have mentioned that you only use a single python pip, I can say that this will be an issue for future programs as you may need to use different versions of the same package for different projects.

An acceptable practice to avoid such issues would be to use a virtual environment for each project. Just create a makefile in your project root and use: virtualenv --python=${PYTHON} env env/bin/pip install --upgrade pip env/bin/pip --upgrade setuptools wheel pip-tools

Then have env/bin/pip install the requirements from your requirements.txt file.

N M
  • 596
  • 4
  • 18
  • I am using virtual environments, but I still have the issue of updating the packets withing the environemnt – Martin Taleski Oct 17 '17 at 09:22
  • Typically, it isn't that much of an issue to handle the updating of packages in a single project as long as you write extensive tests. The AGILE development methodology typically works well with this. As long as you write extensive regression and unit tests (if you include mocking, remember to check the coverage of your code). Also, if you connect to any external servers, you can record the requests and responses and play it back for the testing purposes. As long as you ensure that your code coverage is extensive and handles possible corner cases, updating packages will not be too much hassle. – N M Oct 19 '17 at 01:09
0

You are absolutely right. There will be backward incompatibility issue. Do not update packages to the latest blindly. Most likely, you will have package/module/class/variable/key undefined/notFound issues. Especially you have a complex system. Even if you use pip install --upgrade somepackage

This is lesson from my real experience.

Diansheng
  • 1,081
  • 12
  • 19