diff --git a/CHANGES/406.feature b/CHANGES/406.feature new file mode 100644 index 000000000..db84c96e2 --- /dev/null +++ b/CHANGES/406.feature @@ -0,0 +1,3 @@ +Added autopublish functionality. +Creates a structured APT publication when used. +Cannot be used to create verbatim publications. diff --git a/pulp_deb/app/migrations/0032_add_autopublish.py b/pulp_deb/app/migrations/0032_add_autopublish.py new file mode 100644 index 000000000..b408491a8 --- /dev/null +++ b/pulp_deb/app/migrations/0032_add_autopublish.py @@ -0,0 +1,16 @@ +from django.db import migrations, models + +class Migration(migrations.Migration): + + dependencies = [ + ('deb', '0001_initial_squashed_0031_add_domains'), + ] + + operations = [ + migrations.AddField( + model_name='aptrepository', + name='autopublish', + field=models.BooleanField(default=False), + ), + ] + diff --git a/pulp_deb/app/models/repository.py b/pulp_deb/app/models/repository.py index 2c19628e5..d851b0e97 100644 --- a/pulp_deb/app/models/repository.py +++ b/pulp_deb/app/models/repository.py @@ -68,6 +68,30 @@ class AptRepository(Repository, AutoAddObjPermsMixin): ) # Implicit signing_service_release_overrides + autopublish = models.BooleanField(default=False) + + def on_new_version(self, version): + """ + Called when new repository versions are created. + + Args: + version: The new repository version. + """ + super().on_new_version(version) + + # avoid circular import issues + from pulp_deb.app import tasks + + if self.autopublish: + tasks.publish( + repository_version_pk=version.pk, + # We currently support only automatically creating a structured + # publication + simple=False, + structured=True, + signing_service_pk=getattr(self.signing_service, "pk", None), + ) + class Meta: default_related_name = "%(app_label)s_%(model_name)s" permissions = [ diff --git a/pulp_deb/app/serializers/repository_serializers.py b/pulp_deb/app/serializers/repository_serializers.py index 99b100b55..79a9f9c7c 100644 --- a/pulp_deb/app/serializers/repository_serializers.py +++ b/pulp_deb/app/serializers/repository_serializers.py @@ -44,6 +44,16 @@ class AptRepositorySerializer(RepositorySerializer): A Serializer for AptRepository. """ + autopublish = serializers.BooleanField( + help_text=_( + "Whether to automatically create publications for new repository versions, " + "and update any distributions pointing to this repository. Will create a " + "standard structured APT publication." + ), + default=False, + required=False, + ) + publish_upstream_release_fields = serializers.BooleanField( help_text=_( "Previously, pulp_deb only synced the Release file fields codename and suite, now " @@ -78,6 +88,7 @@ class AptRepositorySerializer(RepositorySerializer): class Meta: fields = RepositorySerializer.Meta.fields + ( + "autopublish", "publish_upstream_release_fields", "signing_service", "signing_service_release_overrides", diff --git a/pulp_deb/tests/functional/api/test_auto_publish.py b/pulp_deb/tests/functional/api/test_auto_publish.py new file mode 100644 index 000000000..0b4ed1bd7 --- /dev/null +++ b/pulp_deb/tests/functional/api/test_auto_publish.py @@ -0,0 +1,65 @@ +import pytest + +from pulpcore.client.pulp_deb import ( + AptRepositorySyncURL, +) + + +@pytest.fixture +def setup_autopublish( + deb_get_fixture_server_url, deb_repository_factory, deb_remote_factory, deb_distribution_factory +): + """Create remote, repo, publish settings, and distribution.""" + url = deb_get_fixture_server_url() + remote = deb_remote_factory(url=url) + repo = deb_repository_factory(autopublish=True) + distribution = deb_distribution_factory(repository=repo) + + return repo, remote, distribution + + +@pytest.mark.parallel +def test_01_sync(setup_autopublish, apt_repository_api, apt_publication_api, monitor_task): + """Assert that syncing the repository triggers auto-publish and auto-distribution.""" + repo, remote, distribution = setup_autopublish + assert apt_publication_api.list(repository=repo.pulp_href).count == 0 + assert distribution.publication is None + + # Sync the repository. + repository_sync_data = AptRepositorySyncURL(remote=remote.pulp_href) + sync_response = apt_repository_api.sync(repo.pulp_href, repository_sync_data) + task = monitor_task(sync_response.task) + + # Check that all the appropriate resources were created + assert len(task.created_resources) > 1 + publications = apt_publication_api.list(repository=repo.pulp_href) + assert publications.count == 1 + + # Sync the repository again. Since there should be no new repository version, there + # should be no new publications or distributions either. + sync_response = apt_repository_api.sync(repo.pulp_href, repository_sync_data) + task = monitor_task(sync_response.task) + + assert len(task.created_resources) == 0 + assert apt_publication_api.list(repository=repo.pulp_href).count == 1 + + +@pytest.mark.parallel +def test_02_modify( + setup_autopublish, apt_repository_api, apt_package_api, apt_publication_api, monitor_task +): + """Assert that modifying the repository triggers auto-publish and auto-distribution.""" + repo, remote, distribution = setup_autopublish + assert apt_publication_api.list(repository=repo.pulp_href).count == 0 + assert distribution.publication is None + + # Modify the repository by adding a content unit + content = apt_package_api.list().results[0].pulp_href + + modify_response = apt_repository_api.modify(repo.pulp_href, {"add_content_units": [content]}) + task = monitor_task(modify_response.task) + + # Check that all the appropriate resources were created + assert len(task.created_resources) > 1 + publications = apt_publication_api.list(repository=repo.pulp_href) + assert publications.count == 1