From 7a047b75e187fc90801e8bc1d28e7ff1d0aa99f5 Mon Sep 17 00:00:00 2001 From: Santos Gallegos Date: Tue, 12 Aug 2025 11:40:46 -0500 Subject: [PATCH 1/2] API: don't rely on the version object for builds --- readthedocs/api/v2/serializers.py | 2 +- readthedocs/api/v2/views/model_views.py | 2 +- readthedocs/rtd_tests/tests/test_api.py | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/readthedocs/api/v2/serializers.py b/readthedocs/api/v2/serializers.py index 787953742e8..80d8cf65fd2 100644 --- a/readthedocs/api/v2/serializers.py +++ b/readthedocs/api/v2/serializers.py @@ -225,7 +225,7 @@ class BuildCommandReadOnlySerializer(BuildCommandSerializer): command = serializers.SerializerMethodField() def get_command(self, obj): - return normalize_build_command(obj.command, obj.build.project.slug, obj.build.version.slug) + return normalize_build_command(obj.command, obj.build.project.slug, obj.build.get_version_slug()) class BuildSerializer(serializers.ModelSerializer): diff --git a/readthedocs/api/v2/views/model_views.py b/readthedocs/api/v2/views/model_views.py index 911d99d968d..f4dfc5aad35 100644 --- a/readthedocs/api/v2/views/model_views.py +++ b/readthedocs/api/v2/views/model_views.py @@ -355,7 +355,7 @@ def retrieve(self, *args, **kwargs): buildcommand["command"] = normalize_build_command( buildcommand["command"], instance.project.slug, - instance.version.slug, + instance.get_version_slug(), ) except Exception: log.exception( diff --git a/readthedocs/rtd_tests/tests/test_api.py b/readthedocs/rtd_tests/tests/test_api.py index 8179b2770aa..2a23492b0db 100644 --- a/readthedocs/rtd_tests/tests/test_api.py +++ b/readthedocs/rtd_tests/tests/test_api.py @@ -707,6 +707,29 @@ def test_build_filter_by_commit(self): build = resp.data self.assertEqual(len(build["results"]), 1) + def test_build_without_version(self): + build = get( + Build, + project=self.project, + version=None, + state=BUILD_STATE_FINISHED, + exit_code=0, + ) + command = "python -m pip install --upgrade --no-cache-dir pip setuptools<58.3.0" + get( + BuildCommandResult, + build=build, + command=command, + output="Running...", + exit_code=0, + ) + client = APIClient() + client.force_authenticate(user=self.user) + r = client.get(reverse("build-detail", args=(build.pk,))) + assert r.status_code == 200 + assert r.data["version"] is None + assert r.data["commands"][0]["command"] == command + class APITests(TestCase): fixtures = ["eric.json", "test_data.json"] From 0ec1f980cb2f8e3800cd6f0e416c17aaea889664 Mon Sep 17 00:00:00 2001 From: Santos Gallegos Date: Tue, 12 Aug 2025 11:43:19 -0500 Subject: [PATCH 2/2] Format --- readthedocs/api/v2/serializers.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readthedocs/api/v2/serializers.py b/readthedocs/api/v2/serializers.py index 80d8cf65fd2..11dedd16999 100644 --- a/readthedocs/api/v2/serializers.py +++ b/readthedocs/api/v2/serializers.py @@ -225,7 +225,9 @@ class BuildCommandReadOnlySerializer(BuildCommandSerializer): command = serializers.SerializerMethodField() def get_command(self, obj): - return normalize_build_command(obj.command, obj.build.project.slug, obj.build.get_version_slug()) + return normalize_build_command( + obj.command, obj.build.project.slug, obj.build.get_version_slug() + ) class BuildSerializer(serializers.ModelSerializer):