diff --git a/CHANGES/1000.removal b/CHANGES/1000.removal new file mode 100644 index 00000000..b1a7ec60 --- /dev/null +++ b/CHANGES/1000.removal @@ -0,0 +1 @@ +Deprecated publications and added documentation for migrating off of them. diff --git a/docs/index.md b/docs/index.md index 9414f9d1..80c26e43 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,7 @@ The REST API documentation for `pulp_python` is available [here](site:pulp_pytho - [Create local mirrors of PyPI](site:pulp_python/docs/user/guides/sync/) that you have full control over - [Upload your own Python packages](site:pulp_python/docs/user/guides/upload/) -- [Perform pip install](site:pulp_python/docs/user/guides/publish/) from your Pulp Python repositories +- [Perform pip install](site:pulp_python/docs/user/guides/host/) from your Pulp Python repositories - Download packages on-demand to reduce disk usage - Every operation creates a restorable snapshot with Versioned Repositories - Curate your Python repositories with allowed and disallowed packages diff --git a/docs/user/guides/_SUMMARY.md b/docs/user/guides/_SUMMARY.md index b10634fc..920b5be2 100644 --- a/docs/user/guides/_SUMMARY.md +++ b/docs/user/guides/_SUMMARY.md @@ -1,6 +1,6 @@ * [Set up your own PyPI](pypi.md) * [Sync from Remote Repositories](sync.md) * [Upload and Manage Content](upload.md) -* [Publish and Host Python Content](publish.md) +* [Host Python Content](host.md) * [Vulnerability Report](vulnerability_report.md) * [Attestation Hosting](attestation.md) diff --git a/docs/user/guides/publish.md b/docs/user/guides/host.md similarity index 55% rename from docs/user/guides/publish.md rename to docs/user/guides/host.md index 1f1eae4d..4bca5bdb 100644 --- a/docs/user/guides/publish.md +++ b/docs/user/guides/host.md @@ -1,50 +1,18 @@ -# Publish and Host Your Python Content +# Host Your Python Content This section assumes that you have a repository with content in it. To do this, see the [sync](site:pulp_python/docs/user/guides/sync/) or [upload](site:pulp_python/docs/user/guides/upload/) documentation. -## Create a Publication (manually) +## Make a Python Index (Create a Distribution) -Kick off a publish task by creating a new publication. The publish task will generate all the -metadata that `pip` needs to install packages (although it will need to be hosted through a -Distribution before it is consumable). +To host your Python content as a PyPI compatible index, (which makes it consumable by `pip`), users create a distribution which will serve the content in the repository at `${BASE_ADDR}/pypi/${DIST_BASE_PATH}/`. === "Run" ```bash - # Create a new publication specifying the repository_version. - # Alternatively, you can specify just the repository, and Pulp will assume the latest version. - pulp python publication create --repository foo --version 1 - - # Publications can only be referenced through their pulp_href - PUBLICATION_HREF=$(pulp python publication list | jq -r .[0].pulp_href) - ``` - -=== "Output" - - ``` - { - "pulp_href": "/pulp/api/v3/publications/python/pypi/0196ba31-cd04-7aba-a7b4-71a98a976745/", - "prn": "prn:python.pythonpublication:0196ba31-cd04-7aba-a7b4-71a98a976745", - "pulp_created": "2025-05-10T12:35:48.103758Z", - "pulp_last_updated": "2025-05-10T12:35:48.205361Z", - "repository_version": "/pulp/api/v3/repositories/python/python/0196ba30-e15e-71ea-9867-33aeceb5a87e/versions/1/", - "repository": "/pulp/api/v3/repositories/python/python/0196ba30-e15e-71ea-9867-33aeceb5a87e/", - "distributions": [] - } - ``` - -## Host a Publication (Create a Distribution) - -To host a publication, (which makes it consumable by `pip`), users create a distribution which -will serve the associated publication at `${BASE_ADDR}/pypi/${DIST_BASE_PATH}/`. - -=== "Run" - - ```bash - # Distributions are created asynchronously. Create one, and specify the publication that will + # Distributions are created asynchronously. Create one, and specify the repository that will # be served at the base path specified. - pulp python distribution create --name foo --base-path foo --publication "$PUBLICATION_HREF" + pulp python distribution create --name foo --base-path foo --repository foo ``` === "Output" @@ -62,29 +30,15 @@ will serve the associated publication at `${BASE_ADDR}/pypi/${DIST_BASE_PATH}/`. "hidden": false, "pulp_labels": {}, "name": "foo", - "repository": null, - "publication": "/pulp/api/v3/publications/python/pypi/0196ba31-cd04-7aba-a7b4-71a98a976745/", + "repository": "/pulp/api/v3/repositories/python/python/019cf738-6951-7b25-b26f-182683dc32f2/", + "repository_version": null, + "publication": null, "allow_uploads": true, "remote": null } ``` -## Automate Publication and Distribution - -With a little more initial setup, you can have publications and distributions for your repositories -updated automatically when new repository versions are created. - -```bash -# This configures the repository to produce new publications when a new version is created -pulp python repository update --name foo --autopublish -# This configures the distribution to track the latest repository version for a given repository -pulp python distribution update --name foo --repository foo -``` - -!!! warning - Support for automatic publication and distribution is provided as a tech preview in Pulp 3. - Functionality may not work or may be incomplete. Also, backwards compatibility when upgrading - is not guaranteed. +Setting the distribution's `repository` field will auto-serve the latest version of that repository. If you wish to only serve content from a specific version you can use the `repository_version` field. ## Enable Pull-Through Caching @@ -150,3 +104,18 @@ pip install --trusted-host localhost shelf-reader ``` See the [pip docs](https://pip.pypa.io/en/stable/topics/configuration) for more details. + + +## Migrating off Publications + +Ever since the release of `pulp-python` 3.4, publications have no longer been required to serve content to Python compatible tooling. Publications became deprecated in version 3.27, but it is recommended to move off of them even on early versions as many new features like pull-through caching, simple JSON, attestations, were not built to work with publications. To move off publications follow these three steps: + +1. Switch any distribution serving a publication to a repository or repository-version +2. Set `autopublish=False` for all repositories +3. Delete all python publications + +!!! warning + Publications may be removed in a future `pulp-python` version. + +!!! note + To maintain backwards compatibility, `/pypi/` endpoints will always try to use a publication if there is one available for the repository. We recommend deleting every publication for a repository if you wish to use the newer features. diff --git a/docs/user/guides/pypi.md b/docs/user/guides/pypi.md index cbf77b79..b1078638 100644 --- a/docs/user/guides/pypi.md +++ b/docs/user/guides/pypi.md @@ -60,6 +60,7 @@ Distributions serve the content stored in repositories so that it can be used by "pulp_labels": {}, "name": "my-pypi", "repository": "/pulp/api/v3/repositories/python/python/0196ba29-52b9-7cf4-b12e-f3247f0eb3dc/", + "repository_version": null, "publication": null, "allow_uploads": true, "remote": null diff --git a/docs/user/guides/sync.md b/docs/user/guides/sync.md index 3cafa354..bf9dd0f9 100644 --- a/docs/user/guides/sync.md +++ b/docs/user/guides/sync.md @@ -176,7 +176,7 @@ Python remotes involve syncing with PyPI which requires terabytes of disk space. modifying the "policy" field. Syncing all of PyPI can take a long time depending on your network and disk speeds. Check out -[pull-through caching](site:pulp_python/docs/user/guides/publish/#enable-pull-through-caching) +[pull-through caching](site:pulp_python/docs/user/guides/host/#enable-pull-through-caching) to learn about another way to mirror PyPI. ## Sync repository foo with remote diff --git a/pulp_python/app/replica.py b/pulp_python/app/replica.py index 0a11bfc3..eb7fced6 100644 --- a/pulp_python/app/replica.py +++ b/pulp_python/app/replica.py @@ -37,8 +37,7 @@ def url(self, upstream_distribution): return None def repository_extra_fields(self, remote): - # Use autopublish since publications result in faster serving times - return {"autopublish": True} + return {"autopublish": False} def sync_params(self, repository, remote): return {"remote_pk": str(remote.pk), "repository_pk": str(repository.pk), "mirror": True} diff --git a/pulp_python/app/serializers.py b/pulp_python/app/serializers.py index 38db2005..f8d93322 100644 --- a/pulp_python/app/serializers.py +++ b/pulp_python/app/serializers.py @@ -4,6 +4,7 @@ from gettext import gettext as _ from django.conf import settings from django.db.utils import IntegrityError +from drf_spectacular.utils import extend_schema_serializer from packaging.requirements import Requirement from rest_framework import serializers from pypi_attestations import AttestationError @@ -33,6 +34,11 @@ log = logging.getLogger(__name__) +@extend_schema_serializer( + deprecate_fields=[ + "autopublish", + ] +) class PythonRepositorySerializer(core_serializers.RepositorySerializer): """ Serializer for Python Repositories. @@ -41,7 +47,7 @@ class PythonRepositorySerializer(core_serializers.RepositorySerializer): autopublish = serializers.BooleanField( help_text=_( "Whether to automatically create publications for new repository versions, " - "and update any distributions pointing to this repository." + "and update any distributions pointing to this repository. [Deprecated]" ), default=False, required=False, @@ -52,6 +58,11 @@ class Meta: model = python_models.PythonRepository +@extend_schema_serializer( + deprecate_fields=[ + "publication", + ] +) class PythonDistributionSerializer(core_serializers.DistributionSerializer): """ Serializer for Pulp distributions for the Python type. @@ -59,7 +70,7 @@ class PythonDistributionSerializer(core_serializers.DistributionSerializer): publication = core_serializers.DetailRelatedField( required=False, - help_text=_("Publication to be served"), + help_text=_("Publication to be served. [Deprecated]"), view_name_pattern=r"publications(-.*/.*)?-detail", queryset=core_models.Publication.objects.exclude(complete=False), allow_null=True, diff --git a/pulp_python/app/viewsets.py b/pulp_python/app/viewsets.py index c9c9c314..9aa19fd8 100644 --- a/pulp_python/app/viewsets.py +++ b/pulp_python/app/viewsets.py @@ -1,6 +1,6 @@ from bandersnatch.configuration import BandersnatchConfig from django.db import transaction -from drf_spectacular.utils import extend_schema +from drf_spectacular.utils import extend_schema, extend_schema_view from pathlib import Path from rest_framework import status from rest_framework.decorators import action @@ -605,11 +605,21 @@ def from_bandersnatch(self, request): return Response(remote.data, status=status.HTTP_201_CREATED, headers=headers) +@extend_schema_view( + list=extend_schema(deprecated=True), + add_role=extend_schema(deprecated=True), + remove_role=extend_schema(deprecated=True), + list_roles=extend_schema(deprecated=True), + my_permissions=extend_schema(deprecated=True), +) class PythonPublicationViewSet(core_viewsets.PublicationViewSet, core_viewsets.RolesMixin): """ - Python Publications refer to the Python Package content in a repository version, and include - metadata about that content. + metadata about that content. [Deprecated] See + https://pulpproject.org/pulp_python/docs/user/guides/host/#migrating-off-publications for more + information. + + Use a repository or repository-version to serve content instead. """ @@ -677,7 +687,7 @@ class PythonPublicationViewSet(core_viewsets.PublicationViewSet, core_viewsets.R "python.pythonpublication_viewer": ["python.view_pythonpublication"], } - @extend_schema(responses={202: AsyncOperationResponseSerializer}) + @extend_schema(responses={202: AsyncOperationResponseSerializer}, deprecated=True) def create(self, request): """ @@ -698,3 +708,11 @@ def create(self, request): kwargs={"repository_version_pk": str(repository_version.pk)}, ) return core_viewsets.OperationPostponedResponse(result, request) + + @extend_schema(deprecated=True) + def retrieve(self, request, *args, **kwargs): + return super().retrieve(request, *args, **kwargs) + + @extend_schema(deprecated=True) + def destroy(self, request, *args, **kwargs): + return super().destroy(request, *args, **kwargs) diff --git a/pulp_python/tests/functional/api/test_domains.py b/pulp_python/tests/functional/api/test_domains.py index e12643f5..46d6ae10 100644 --- a/pulp_python/tests/functional/api/test_domains.py +++ b/pulp_python/tests/functional/api/test_domains.py @@ -182,7 +182,6 @@ def test_domain_content_replication( python_bindings.ContentPackagesApi, python_bindings.RepositoriesPythonApi, python_bindings.RemotesPythonApi, - python_bindings.PublicationsPypiApi, python_bindings.DistributionsPypiApi, ): result = api_client.list(pulp_domain=replica_domain.name) @@ -204,9 +203,6 @@ def test_domain_content_replication( response = python_bindings.ContentPackagesApi.list(pulp_domain=replica_domain.name) assert PYTHON_SM_PACKAGE_COUNT + 1 == response.count - response = python_bindings.PublicationsPypiApi.list(pulp_domain=replica_domain.name) - assert 2 == response.count - add_to_cleanup(python_bindings.PublicationsPypiApi, response.results[0]) assert 1 == python_bindings.RepositoriesPythonApi.list(pulp_domain=replica_domain.name).count assert 1 == python_bindings.DistributionsPypiApi.list(pulp_domain=replica_domain.name).count assert 1 == python_bindings.RemotesPythonApi.list(pulp_domain=replica_domain.name).count