From 4d64ae4f35f93ed4039ad3a27d14938b92278f3b Mon Sep 17 00:00:00 2001 From: Alex Lowe Date: Thu, 12 Dec 2024 18:10:19 -0500 Subject: [PATCH] fix: add tests --- charmcraft/services/store.py | 14 +++++++++-- .../commands/test_store_commands.py | 24 +++++++++++++++++++ .../store/charm-upload-and-release/task.yaml | 6 +++++ tests/unit/services/test_store.py | 23 ++++++++++++++++++ uv.lock | 4 ++-- 5 files changed, 67 insertions(+), 4 deletions(-) diff --git a/charmcraft/services/store.py b/charmcraft/services/store.py index c6bc135fb..d591bb12b 100644 --- a/charmcraft/services/store.py +++ b/charmcraft/services/store.py @@ -207,12 +207,22 @@ def setup(self) -> None: def create_tracks( self, name: str, *tracks: publisher.CreateTrackRequest ) -> Sequence[publisher.TrackMetadata]: - """Create tracks in the store.""" + """Create tracks in the store. + + :param name: The package name to which the tracks should be attached. + :param tracks: Each item is a dictionary of the track request. + :returns: A sequence of the created tracks as dictionaries. + """ + track_names = {track.get("name") for track in tracks} self._publisher.create_tracks(name, *tracks) metadata = self._publisher.get_package_metadata(name) # "or []" here because tracks could be None. - return metadata["tracks"] or [] + return [ + track + for track in metadata["tracks"] or [] + if track.get("name") in track_names + ] def set_resource_revisions_architectures( self, name: str, resource_name: str, updates: dict[int, list[str]] diff --git a/tests/integration/commands/test_store_commands.py b/tests/integration/commands/test_store_commands.py index 3b1f12e59..a54f279c2 100644 --- a/tests/integration/commands/test_store_commands.py +++ b/tests/integration/commands/test_store_commands.py @@ -23,6 +23,7 @@ from charmcraft import env from charmcraft.application.commands import FetchLibCommand +from charmcraft.application.commands.store import CreateTrack from charmcraft.store.models import Library from tests import factory @@ -510,3 +511,26 @@ def test_fetchlib_store_same_versions_different_hash( # endregion + + +def test_create_track(emitter, service_factory, config): + cmd = CreateTrack(config) + args = argparse.Namespace( + name="my-charm", + track=["my-track"], + automatic_phasing_percentage=None, + format="json", + ) + mock_create_tracks = mock.Mock() + mock_get_package_metadata = mock.Mock( + return_value={"tracks": [{"name": "latest"}, {"name": "my-track"}]} + ) + + service_factory.store._publisher.create_tracks = mock_create_tracks + service_factory.store._publisher.get_package_metadata = mock_get_package_metadata + + cmd.run(args) + + emitter.assert_json_output( + [{"name": "my-track", "automatic-phasing-percentage": None}] + ) diff --git a/tests/spread/store/charm-upload-and-release/task.yaml b/tests/spread/store/charm-upload-and-release/task.yaml index 00ce216d6..7ca9287e7 100644 --- a/tests/spread/store/charm-upload-and-release/task.yaml +++ b/tests/spread/store/charm-upload-and-release/task.yaml @@ -42,6 +42,11 @@ execute: | # release that last revision to edge charmcraft release $CHARM_DEFAULT_NAME -r $uploaded_revno -c edge + # Create a track and release it to that, too. + track_name=$(date +%s) + charmcraft create-track $CHARM_DEFAULT_NAME $track_name + charmcraft release $CHARM_DEFAULT_NAME -r $uploaded_revno -c ${track_name}/edge + # Releases may have some delay in the craft store, so sleep for a bit before trying and try up to 10 times. sleep 10 for i in {1..10} @@ -57,6 +62,7 @@ execute: | break fi done + track_release=$(charmcraft status $CHARM_DEFAULT_NAME --format=json | jq -r ".[] | select(.track==\"${track_name}\") | .mappings[0].releases | .[] | select(.channel==\"${track_name}/edge\")") if [ $edge_revision -lt $uploaded_revno ]; then ERROR "Revision wasn't released. Uploaded revision: $uploaded_revno; Currently on edge: $edge_revision" fi diff --git a/tests/unit/services/test_store.py b/tests/unit/services/test_store.py index 55dadff43..983d88212 100644 --- a/tests/unit/services/test_store.py +++ b/tests/unit/services/test_store.py @@ -29,6 +29,7 @@ import charmcraft from charmcraft import application, errors, services from charmcraft.models.project import CharmLib +from charmcraft.services.store import StoreService from charmcraft.store import client from tests import get_fake_revision @@ -47,6 +48,7 @@ def store(service_factory) -> services.StoreService: def reusable_store(): store = services.StoreService(app=application.APP_METADATA, services=None) store.client = mock.Mock(spec_set=craft_store.StoreClient) + store._publisher = mock.Mock(spec_set=craft_store.PublisherGateway) return store @@ -168,6 +170,27 @@ def test_logout(store): client.logout.assert_called_once_with() +def test_create_tracks(reusable_store: StoreService): + mock_create = cast(mock.Mock, reusable_store._publisher.create_tracks) + mock_md = cast(mock.Mock, reusable_store._publisher.get_package_metadata) + user_track = { + "name": "my-track", + "automatic-phasing-percentage": None, + } + mock_md.return_value = { + "tracks": [ + user_track, + { + "name": "latest", + "automatic-phasing-percentage": None, + }, + ] + } + + assert reusable_store.create_tracks("my-name", user_track) == [user_track] + mock_create.assert_called_once_with("my-name", user_track) + + @pytest.mark.parametrize( ("updates", "expected_request"), [ diff --git a/uv.lock b/uv.lock index 3b09c7db6..096b8edce 100644 --- a/uv.lock +++ b/uv.lock @@ -112,7 +112,7 @@ wheels = [ ] [[package]] -name = "astroid" +name = "asteroid" version = "3.3.6" source = { registry = "https://pypi.org/simple" } dependencies = [ @@ -2433,7 +2433,7 @@ name = "pylint" version = "3.3.2" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "astroid" }, + { name = "asteroid" }, { name = "colorama", marker = "sys_platform == 'win32' or (extra == 'extra-10-charmcraft-apt-jammy' and extra == 'extra-10-charmcraft-apt-noble') or (extra == 'extra-10-charmcraft-apt-jammy' and extra == 'extra-10-charmcraft-apt-oracular') or (extra == 'extra-10-charmcraft-apt-jammy' and extra == 'extra-10-charmcraft-apt-plucky') or (extra == 'extra-10-charmcraft-apt-noble' and extra == 'extra-10-charmcraft-apt-oracular') or (extra == 'extra-10-charmcraft-apt-noble' and extra == 'extra-10-charmcraft-apt-plucky') or (extra == 'extra-10-charmcraft-apt-oracular' and extra == 'extra-10-charmcraft-apt-plucky')" }, { name = "dill" }, { name = "isort" },