From 19008dce1397cdc9716c9de6fc4bffd52185eecb Mon Sep 17 00:00:00 2001 From: Asuka Minato Date: Mon, 26 Jan 2026 16:04:25 +0900 Subject: [PATCH] refactor: api/controllers/console/version.py to v3 (#31463) Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- api/controllers/console/version.py | 110 ++++++++---------- .../console/test_fastopenapi_version.py | 35 ++++++ 2 files changed, 84 insertions(+), 61 deletions(-) create mode 100644 api/tests/unit_tests/controllers/console/test_fastopenapi_version.py diff --git a/api/controllers/console/version.py b/api/controllers/console/version.py index 419261ba2a..fdb23acf52 100644 --- a/api/controllers/console/version.py +++ b/api/controllers/console/version.py @@ -1,15 +1,11 @@ -import json import logging import httpx -from flask import request -from flask_restx import Resource, fields from packaging import version from pydantic import BaseModel, Field from configs import dify_config - -from . import console_ns +from controllers.fastopenapi import console_router logger = logging.getLogger(__name__) @@ -18,69 +14,61 @@ class VersionQuery(BaseModel): current_version: str = Field(..., description="Current application version") -console_ns.schema_model( - VersionQuery.__name__, - VersionQuery.model_json_schema(ref_template="#/definitions/{model}"), +class VersionFeatures(BaseModel): + can_replace_logo: bool = Field(description="Whether logo replacement is supported") + model_load_balancing_enabled: bool = Field(description="Whether model load balancing is enabled") + + +class VersionResponse(BaseModel): + version: str = Field(description="Latest version number") + release_date: str = Field(description="Release date of latest version") + release_notes: str = Field(description="Release notes for latest version") + can_auto_update: bool = Field(description="Whether auto-update is supported") + features: VersionFeatures = Field(description="Feature flags and capabilities") + + +@console_router.get( + "/version", + response_model=VersionResponse, + tags=["console"], ) +def check_version_update(query: VersionQuery) -> VersionResponse: + """Check for application version updates.""" + check_update_url = dify_config.CHECK_UPDATE_URL - -@console_ns.route("/version") -class VersionApi(Resource): - @console_ns.doc("check_version_update") - @console_ns.doc(description="Check for application version updates") - @console_ns.expect(console_ns.models[VersionQuery.__name__]) - @console_ns.response( - 200, - "Success", - console_ns.model( - "VersionResponse", - { - "version": fields.String(description="Latest version number"), - "release_date": fields.String(description="Release date of latest version"), - "release_notes": fields.String(description="Release notes for latest version"), - "can_auto_update": fields.Boolean(description="Whether auto-update is supported"), - "features": fields.Raw(description="Feature flags and capabilities"), - }, + result = VersionResponse( + version=dify_config.project.version, + release_date="", + release_notes="", + can_auto_update=False, + features=VersionFeatures( + can_replace_logo=dify_config.CAN_REPLACE_LOGO, + model_load_balancing_enabled=dify_config.MODEL_LB_ENABLED, ), ) - def get(self): - """Check for application version updates""" - args = VersionQuery.model_validate(request.args.to_dict(flat=True)) # type: ignore - check_update_url = dify_config.CHECK_UPDATE_URL - result = { - "version": dify_config.project.version, - "release_date": "", - "release_notes": "", - "can_auto_update": False, - "features": { - "can_replace_logo": dify_config.CAN_REPLACE_LOGO, - "model_load_balancing_enabled": dify_config.MODEL_LB_ENABLED, - }, - } - - if not check_update_url: - return result - - try: - response = httpx.get( - check_update_url, - params={"current_version": args.current_version}, - timeout=httpx.Timeout(timeout=10.0, connect=3.0), - ) - except Exception as error: - logger.warning("Check update version error: %s.", str(error)) - result["version"] = args.current_version - return result - - content = json.loads(response.content) - if _has_new_version(latest_version=content["version"], current_version=f"{args.current_version}"): - result["version"] = content["version"] - result["release_date"] = content["releaseDate"] - result["release_notes"] = content["releaseNotes"] - result["can_auto_update"] = content["canAutoUpdate"] + if not check_update_url: return result + try: + response = httpx.get( + check_update_url, + params={"current_version": query.current_version}, + timeout=httpx.Timeout(timeout=10.0, connect=3.0), + ) + content = response.json() + except Exception as error: + logger.warning("Check update version error: %s.", str(error)) + result.version = query.current_version + return result + latest_version = content.get("version", result.version) + if _has_new_version(latest_version=latest_version, current_version=f"{query.current_version}"): + result.version = latest_version + result.release_date = content.get("releaseDate", "") + result.release_notes = content.get("releaseNotes", "") + result.can_auto_update = content.get("canAutoUpdate", False) + return result + def _has_new_version(*, latest_version: str, current_version: str) -> bool: try: diff --git a/api/tests/unit_tests/controllers/console/test_fastopenapi_version.py b/api/tests/unit_tests/controllers/console/test_fastopenapi_version.py new file mode 100644 index 0000000000..c5b4e0dfcf --- /dev/null +++ b/api/tests/unit_tests/controllers/console/test_fastopenapi_version.py @@ -0,0 +1,35 @@ +import builtins +from unittest.mock import patch + +import pytest +from flask import Flask +from flask.views import MethodView + +from configs import dify_config +from extensions import ext_fastopenapi + +if not hasattr(builtins, "MethodView"): + builtins.MethodView = MethodView # type: ignore[attr-defined] + + +@pytest.fixture +def app() -> Flask: + app = Flask(__name__) + app.config["TESTING"] = True + return app + + +def test_console_version_fastopenapi_returns_current_version(app: Flask): + ext_fastopenapi.init_app(app) + + with patch("controllers.console.version.dify_config.CHECK_UPDATE_URL", None): + client = app.test_client() + response = client.get("/console/api/version", query_string={"current_version": "0.0.0"}) + + assert response.status_code == 200 + data = response.get_json() + assert data["version"] == dify_config.project.version + assert data["release_date"] == "" + assert data["release_notes"] == "" + assert data["can_auto_update"] is False + assert "features" in data