Repository: OctoPrint/OctoPrint

Issue:
GitHub tags are only read up to the first `-` character, breaking tags such as `1.0.0-rc1`
### The problem

The software update plugin does a load of parsing to compare the GitHub tag version to the one from the installed Python packages. I unwrapped some of it to figure out what was going on here.

We have a tag on GitHub with the name `1.0.0-rc1`, which according to [PEP440](https://www.python.org/dev/peps/pep-0440/#pre-release-separators) is allowed but would be normalized to `1.0.0rc1`, which is how it comes through if this tag is set in setup.py.

The plugin runs it through (as far as I could trace) `octoprint.plugins.softwareupdate.version_checks.github_release.get_comparable_version`. This calls some functions in `octoprint.util.version` including `normalize_version`, which only reads the tag up to and including the `-`, stripping it down to just `1.0.0` in this case, which would be seen as 'ahead' of `1.0.0rc1` of course.

Some testing to demonstrate, the first line is the problem one:
```python
>>> get_comparable_version("1.1.1-rc1")
<Version('1.1.1')>
>>> get_comparable_version("1.1.1rc1")
<Version('1.1.1rc1')>
>>> get_comparable_version("1.1.1.rc1")
<Version('1.1.1rc1')>
>>> get_comparable_version("1.1.1_rc1")
<Version('1.1.1rc1')>
```

They should all be parsed equally according to PEP440.

This resulted in an update loop where `1.0.0-rc1` was set the same in both `setup.py` and the GitHub tag, but it became GitHub tag = 1.0.0 and setup.py = 1.0.0rc1 when parsed and the comparison would always show an update available.

**TLDR**; everything after the `-` in a GitHub tag is ignored, when it should be included.

Discussion on discord: https://discord.com/channels/704958479194128507/708230829050036236/928402397435420775

### Did the issue persist even in safe mode?

Yes, it did persist

### If you could not test in safe mode, please state why

NA

### Version of OctoPrint

1.7.2

### Operating system running OctoPrint

All

### Printer model & used firmware incl. version

All

### Browser and version of browser, operating system running browser

All

### Checklist of files to include below

- [X] Systeminfo Bundle (always include!)
- [ ] Contents of the JavaScript browser console (always include in cases of issues with the user interface)
- [ ] Screenshots and/or videos showing the problem (always include in case of issues with the user interface)
- [ ] GCODE file with which to reproduce (always include in case of issues with GCODE analysis or printing behaviour)

### Additional information & file uploads

_No response_


Discussion:
This issue has been mentioned on **OctoPrint Community Forum**. There might be relevant details there:

https://community.octoprint.org/t/mix-and-match-update-types/40177/9

I love bots looking out of us :).  Hopefully they don't murder all of us post singularity.

The discussion the bot tagged here is for a different issue.   @cp2004 is addressing an issue specific to tag parsing.  the issue covered in the tagged discussion is tied to the `github_commit` release type not properly applying pip args.  Basically, octoprint needs to tell pip to force a reinstall with this strategy rather than comparing version information.

I'm pretty sure this "only up until -" thing stems from a former OctoPrint versioning scheme that has not been used for half a decade now, so it should be an easy fix really.

Resolving patch:
diff --git a/src/octoprint/util/version.py b/src/octoprint/util/version.py
--- a/src/octoprint/util/version.py
+++ b/src/octoprint/util/version.py
@@ -208,8 +208,6 @@ def is_prerelease(version_string):
 
 
 def normalize_version(version):
-    if "-" in version:
-        version = version[: version.find("-")]
 
     # Debian has the python version set to 2.7.15+ which is not PEP440 compliant (bug 914072)
     if version.endswith("+"):


Test patch:
diff --git a/tests/util/test_version.py b/tests/util/test_version.py
--- a/tests/util/test_version.py
+++ b/tests/util/test_version.py
@@ -46,7 +46,6 @@ def test_get_comparable_version_base(self):
         ("V1.6.0", "1.6.0"),
         ("1.6.0+", "1.6.0"),
         ("\t1.6.0  \r\n", "1.6.0"),
-        ("1.6.0-dev123", "1.6.0"),
     )
     @ddt.unpack
     def test_normalize_version(self, version, expected):