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

Only offer latest release if it is semver-newer than current #715

Conversation

jonathanperret
Copy link
Contributor

@jonathanperret jonathanperret commented Sep 26, 2024

Problem

Fixes #647.

Proposed solution

In this PR the update check is changed from an equality comparison (suggest an update if the current version is different from the latest) to a semver check, so that:

  • if you are running 1.0.0 and 1.1.0 is the latest release, you'll be prompted to download it (this already worked);
  • if you are running 1.1.0-beta1 and 1.1.0 is the latest release, you will be prompted (already worked too);
  • if you are running 1.1.0-beta1 and 1.0.0 is the latest release, you won't be prompted (differs from current behavior).

So the main difference is that beta testers won't be prompted to revert to a stable release.

Ideally we'd suggest 1.1.0-beta2 to users of 1.1.0-beta1 while keeping 1.0.0 users on 1.0.0 (in other words, proper release channels), but this would require the ability to ask GitHub for the latest prerelease which their API doesn't make easy unfortunately (the only way I can see is to download the whole release list, which can be hundreds of kilobytes and possibly require multiple requests — note that you can't even rely on releases being listed in any order, see https://github.com/orgs/community/discussions/8226). Alternatively, we could publish a JSON file with a list of current versions, but this is more work.

This PR also changes the update check to run in the background so that it does not slow down application startup, and removes the requests dependency in favor of Qt's built-in HTTP client.

Summary by CodeRabbit

  • New Features

    • Introduced a new VersionChecker class for checking the latest software version from GitHub.
    • Enhanced version checking process now includes user notifications for new releases.
  • Bug Fixes

    • Improved error handling in the package version retrieval process.
  • Chores

    • Updated dependencies, replacing requests with semver for better version management.
    • Removed unnecessary type definitions for requests and added for Pillow.
  • Documentation

    • Clarified comments in the .gitignore file regarding file generation by CI.
    • Removed the PACKAGE_VERSION file, affecting version management.

Copy link
Contributor

coderabbitai bot commented Sep 26, 2024

Walkthrough

The pull request introduces several changes across multiple files. Key modifications include updates to dependency management in requirements.txt and requirements.build.txt, a refactor of the package_version function in utils.py, the addition of a new VersionChecker class in version_checker.py, and the integration of this class into the AppContext in main.py. Additionally, the PACKAGE_VERSION file has been removed, which may affect version tracking.

Changes

File(s) Change Summary
.gitignore Updated comment from "# File is changed by CI" to "# File is generated by CI."
requirements.build.txt, requirements.txt Removed requests==2.31.0 and types-requests==2.31.0; added semver==3.0.2 and types-Pillow==10.
src/main/python/main/ayab/utils.py Refactored package_version function for error handling; removed latest_version function.
src/main/python/main/ayab/version_checker.py Added VersionChecker class for checking the latest version from GitHub.
src/main/python/main/main.py Integrated VersionChecker into AppContext; removed old version checking logic.
src/main/resources/base/ayab/package_version Removed PACKAGE_VERSION file.

Assessment against linked issues

Objective Addressed Explanation
Outdated "New version" dialog appears on launch (#647)

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 06bea53 and 879c776.

📒 Files selected for processing (7)
  • .gitignore (1 hunks)
  • requirements.build.txt (1 hunks)
  • requirements.txt (0 hunks)
  • src/main/python/main/ayab/utils.py (1 hunks)
  • src/main/python/main/ayab/version_checker.py (1 hunks)
  • src/main/python/main/main.py (1 hunks)
  • src/main/resources/base/ayab/package_version (0 hunks)
💤 Files not reviewed due to no reviewable changes (2)
  • requirements.txt
  • src/main/resources/base/ayab/package_version
🚧 Files skipped from review as they are similar to previous changes (5)
  • .gitignore
  • requirements.build.txt
  • src/main/python/main/ayab/utils.py
  • src/main/python/main/ayab/version_checker.py
  • src/main/python/main/main.py

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 99c6502 and 7cfd7bd.

📒 Files selected for processing (7)
  • .gitignore (1 hunks)
  • requirements.build.txt (1 hunks)
  • requirements.txt (0 hunks)
  • src/main/python/main/ayab/utils.py (1 hunks)
  • src/main/python/main/ayab/version_checker.py (1 hunks)
  • src/main/python/main/main.py (1 hunks)
  • src/main/resources/base/ayab/package_version (0 hunks)
💤 Files not reviewed due to no reviewable changes (2)
  • requirements.txt
  • src/main/resources/base/ayab/package_version
🔇 Additional comments (9)
requirements.build.txt (1)

11-11: LGTM! Changes align with PR objectives.

The replacement of requests==2.31.0 with semver==3.0.2 is in line with the PR objectives:

  1. Removing the requests dependency
  2. Implementing a semantic versioning check

These changes should help address the issue of incorrect update prompts and improve version comparison.

To ensure the complete implementation of the PR objectives, please run the following script to verify the removal of requests and the use of Qt's HTTP client:

This script will help confirm that:

  1. The requests library is no longer used in the codebase.
  2. Qt's network module and HTTP client (QNetworkAccessManager) are being used as a replacement.

Please review the results and ensure that the appropriate changes have been made throughout the codebase.

✅ Verification successful

Verified! Changes align with PR objectives.

  • The requests dependency has been successfully removed.
  • QNetworkAccessManager from Qt's network module is implemented as intended.

These changes ensure the removal of the requests library and the adoption of Qt's built-in HTTP client, addressing the issue of incorrect update prompts and enhancing version comparison.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify removal of requests and implementation of Qt's HTTP client

# Test 1: Check if 'requests' is still imported anywhere
echo "Checking for 'requests' imports:"
rg 'import requests' --type python

# Test 2: Look for Qt's network module usage
echo "Checking for Qt's network module usage:"
rg 'from PySide6 import QtNetwork' --type python

# Test 3: Look for QNetworkAccessManager usage (Qt's HTTP client)
echo "Checking for QNetworkAccessManager usage:"
rg 'QNetworkAccessManager' --type python

Length of output: 487


Script:

#!/bin/bash
# Description: Verify removal of requests and implementation of Qt's HTTP client using file globs

# Test 1: Check if 'requests' is still imported anywhere
echo "Checking for 'requests' imports:"
rg 'import requests' --glob '*.py'

# Test 2: Look for Qt's network module usage
echo "Checking for Qt's network module usage:"
rg 'from PySide6 import QtNetwork' --glob '*.py'

# Test 3: Look for QNetworkAccessManager usage (Qt's HTTP client)
echo "Checking for QNetworkAccessManager usage:"
rg 'QNetworkAccessManager' --glob '*.py'

Length of output: 720

.gitignore (1)

11-11: Approved: Clarification of CI-generated file comment

The change from "# File is changed by CI" to "# File is generated by CI" provides a more accurate description of how the package_version file is handled in the CI process. This aligns well with the PR's focus on improving version management and clarity.

src/main/python/main/ayab/utils.py (3)

Line range hint 1-116: Summary of changes in utils.py

The modifications to this file align with the PR objectives:

  1. The package_version function has been updated to use a resource file and handle errors, which improves maintainability and robustness.
  2. The latest_version function has been removed, likely as part of the effort to remove the requests dependency and improve the update check mechanism.

These changes contribute to the overall goal of improving the version checking system. However, ensure that the suggestions for improving the package_version function are addressed, and verify that the update checking functionality has been properly implemented elsewhere in the codebase.


Line range hint 1-116: Verify replacement of latest_version functionality

The latest_version function has been removed from this file. While this aligns with the PR objectives to improve the update check mechanism and remove the requests dependency, we need to ensure that this functionality has been adequately replaced.

Please run the following verification to confirm that the update checking functionality has been implemented elsewhere:

#!/bin/bash
# Search for new update checking implementation
rg --type python -A 10 "def.*version.*check|class.*version.*check"

This will help us locate any new classes or methods that have been introduced to handle version checking, ensuring that we haven't lost this important functionality.


109-116: 🛠️ Refactor suggestion

Improve error handling and type safety in package_version function

The refactored package_version function is an improvement over the previous version, but there are a few areas that could be enhanced:

  1. Consider using a more specific type for app_context instead of Any to improve type safety.
  2. Add logging for the FileNotFoundError to aid in debugging.
  3. Consider using a more distinctive fake version number for local development.

Here's a suggested improvement:

from typing import Protocol
import logging

class AppContext(Protocol):
    def get_resource(self, path: str) -> str:
        ...

def package_version(app_context: AppContext) -> str:
    try:
        filename_version = app_context.get_resource("ayab/package_version")
        with open(filename_version) as version_file:
            return version_file.read().strip()
    except FileNotFoundError:
        logging.warning("Version file not found. Using development version.")
        # Use a distinctive version number for local development
        return "0.0.0-dev"

This implementation:

  1. Uses a Protocol for better type hinting of app_context.
  2. Adds logging for the FileNotFoundError.
  3. Uses a more distinctive version number for local development.

To ensure that this change doesn't break existing functionality, please run the following verification:

This will help us confirm that all calls to package_version are compatible with the new signature.

✅ Verification successful

package_version function usage verified and correct

All instances of the package_version function are correctly passing a valid app_context. Specifically:

  • In main.py, self is an instance of AppContext, which inherits from ApplicationContext and possesses the get_resource method.
  • In about.py, parent.app_context is appropriately passed, ensuring type compatibility.

No further actions are required.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the usage of package_version function
rg --type python -A 5 "package_version\("

Length of output: 99


Script:

#!/bin/bash
# Verify the usage of package_version function in Python files
rg -g "*.py" -A 5 "package_version\("

Length of output: 1409


Script:

#!/bin/bash
# Extract package_version function calls with their arguments
rg -g "*.py" "package_version\(" --pretty

Length of output: 323


Script:

#!/bin/bash
# Extract context around line 42 in main.py to verify the structure of 'self'
rg -C 5 "^\s*def " src/main/python/main/main.py | rg -B 10 -A 10 "package_version("

Length of output: 168


Script:

#!/bin/bash
# Extract context around the package_version function call in main.py to verify the structure of 'self'
rg -C 5 "^\s*def " src/main/python/main/main.py | rg -B 10 -A 10 "package_version\("

Length of output: 902

src/main/python/main/main.py (4)

17-17: Importing VersionChecker in type-checking block

The import statement correctly adds VersionChecker to the TYPE_CHECKING block, ensuring that type hints are properly resolved during static analysis without affecting runtime performance.


25-25: Importing VersionChecker in the main import block

The addition of VersionChecker to the main import block ensures that the class is available at runtime, which is necessary for the application's functionality.


29-29: Handling alternate import paths for VersionChecker

Including VersionChecker in the exception block accommodates different execution environments where the package structure may vary. This maintains compatibility when the module is imported differently, such as during development or packaging.


34-34: Adding _version_checker attribute with type hint

Defining _version_checker: VersionChecker provides a type hint for the attribute, enhancing code readability and enabling better static type checking.

src/main/python/main/ayab/version_checker.py Outdated Show resolved Hide resolved
src/main/python/main/ayab/version_checker.py Show resolved Hide resolved
src/main/python/main/ayab/version_checker.py Show resolved Hide resolved
src/main/python/main/main.py Show resolved Hide resolved
 * Move version checking logic to new VersionChecker class.
 * Use Qt network classes instead of pulling in requests.
 * Use an async request to avoid blocking the main thread while the check is being done.
 * Display current version in "new version available" pop-up.
This lets the app run without a `package_version` file, so it can
be removed from source control which is a bit cleaner than
overwriting it during the build.
This is to avoid suggesting 1.0.0 (assuming it is the latest non-prerelease)
to people running e.g. 1.1.0-beta1.

Ideally we'd offer 1.1.0-beta2 to users of 1.1.0-beta1 while keeping 1.0.0
users on 1.0.0, but this would require the ability to ask GitHub for the
latest prerelease which their API doesn't make easy unfortunately.
@jonathanperret jonathanperret force-pushed the 647-mac-outdated-new-version-dialog-appears-on-launch branch from 06bea53 to 879c776 Compare September 26, 2024 12:15
Copy link

sonarcloud bot commented Sep 26, 2024

Copy link
Contributor

@dl1com dl1com left a comment

Choose a reason for hiding this comment

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

LGTM. Only improvement I can imagine currently is to prepare the message string for translation. But translations are a bigger piece of work anyway.

@dl1com dl1com merged commit 1adb7fb into AllYarnsAreBeautiful:main Sep 30, 2024
2 checks passed
@jonathanperret
Copy link
Contributor Author

LGTM. Only improvement I can imagine currently is to prepare the message string for translation. But translations are a bigger piece of work anyway.

Agreed. I saw #484 but wasn't sure whether it was in scope for 1.0.

@jonathanperret jonathanperret deleted the 647-mac-outdated-new-version-dialog-appears-on-launch branch September 30, 2024 19:53
@jonathanperret
Copy link
Contributor Author

LGTM. Only improvement I can imagine currently is to prepare the message string for translation. But translations are a bigger piece of work anyway.

Since I was in this code, I made #717 to fix #484. Left it in draft but it works as far as I can tell.

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

Successfully merging this pull request may close these issues.

Outdated "New version" dialog appears on launch
2 participants