Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
Version 0.69.0
-------------

**Bugfixes**
- Fix `firebase-app-distribution` actions `get-latest-build-version` and `releases list`. The Firebase App Distribution API changed `orderBy` query parameter validation and rejects the previously tolerated `createTimeDesc`, requiring the documented space-separated grammar `createTime desc` instead.

Version 0.68.0
-------------

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "codemagic-cli-tools"
version = "0.68.0"
version = "0.69.0"
description = "CLI tools used in Codemagic builds"
authors = [{ name = "Priit Lätt", email = "priit@nevercode.io" }]
requires-python = ">=3.8,<4"
Expand Down
2 changes: 1 addition & 1 deletion src/codemagic/__version__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__title__ = "codemagic-cli-tools"
__description__ = "CLI tools used in Codemagic builds"
__version__ = "0.68.0.dev"
__version__ = "0.69.0.dev"
__url__ = "https://github.com/codemagic-ci-cd/cli-tools"
__licence__ = "GNU General Public License v3.0"
8 changes: 7 additions & 1 deletion src/codemagic/google/resources/firebase/order_by.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,11 @@


class OrderBy(ResourceEnum):
CREATE_TIME_DESC = "createTimeDesc"
"""
Values follow the Firebase App Distribution `releases.list` `orderBy` grammar, which uses a
space-separated `desc` suffix, see
https://firebase.google.com/docs/reference/app-distribution/rest/v1/projects.apps.releases/list
"""

CREATE_TIME_DESC = "createTime desc"
CREATE_TIME_ASC = "createTime"
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from codemagic import cli
from codemagic.cli import Colors
from codemagic.google.errors import GoogleError
from codemagic.google.resources.firebase import OrderBy
from codemagic.google.resources.firebase import Release

from ..argument_types import ReleasesOrderByArgument
from ..arguments import ReleasesArgument
from ..arguments import ResourcesArgument
from ..errors import FirebaseAppDistributionError
Expand All @@ -26,15 +26,15 @@ def list_releases(
self,
app_id: str,
limit: int = ResourcesArgument.LIMIT.get_default(),
order_by: OrderBy = ResourcesArgument.ORDER_BY.get_default(),
order_by: ReleasesOrderByArgument = ResourcesArgument.ORDER_BY.get_default(),
should_print: bool = True,
) -> List[Release]:
"""
List releases for the Firebase application
"""

try:
releases = self.client.releases.list(self.project_number, app_id, order_by, limit)
releases = self.client.releases.list(self.project_number, app_id, order_by.order_by, limit)
except GoogleError as e:
raise FirebaseAppDistributionError(str(e))

Expand Down
11 changes: 11 additions & 0 deletions src/codemagic/tools/firebase_app_distribution/argument_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
from typing import Dict

from codemagic import cli
from codemagic.google.resources.firebase import OrderBy
from codemagic.models.enums import ResourceEnum


class ReleasesOrderByArgument(ResourceEnum):
CREATE_TIME_DESC = "createTimeDesc"
CREATE_TIME_ASC = "createTime"

@property
def order_by(self) -> OrderBy:
return OrderBy[self.name]


class CredentialsArgument(cli.EnvironmentArgumentValue[dict]):
Expand Down
8 changes: 4 additions & 4 deletions src/codemagic/tools/firebase_app_distribution/arguments.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from codemagic import cli
from codemagic.cli.colors import Colors
from codemagic.google.resources.firebase import OrderBy

from .argument_types import CredentialsArgument
from .argument_types import ReleasesOrderByArgument

select_project_group = cli.MutuallyExclusiveGroup(
name="select project",
Expand Down Expand Up @@ -50,12 +50,12 @@ class ResourcesArgument(cli.Argument):
ORDER_BY = cli.ArgumentProperties(
key="order_by",
flags=("--order-by", "-o"),
type=OrderBy,
type=ReleasesOrderByArgument,
description="Sort resources in the specified order",
argparse_kwargs={
"required": False,
"default": OrderBy.CREATE_TIME_DESC,
"choices": list(OrderBy),
"default": ReleasesOrderByArgument.CREATE_TIME_DESC,
"choices": list(ReleasesOrderByArgument),
},
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

from codemagic.google.firebase_client import FirebaseClient
from codemagic.google.resources import ResourcePrinter
from codemagic.google.resources.firebase import OrderBy
from codemagic.google.resources.firebase import Release

from .argument_types import ReleasesOrderByArgument


class FirebaseAppDistributionAction(ABC):
client: FirebaseClient
Expand Down Expand Up @@ -37,7 +38,7 @@ def list_releases(
self,
app_id: str,
limit: int = 25,
order_by: OrderBy = OrderBy.CREATE_TIME_DESC,
order_by: ReleasesOrderByArgument = ReleasesOrderByArgument.CREATE_TIME_DESC,
should_print: bool = True,
) -> List[Release]:
from .action_groups.releases_action_group import ReleasesActionGroup
Expand Down
23 changes: 23 additions & 0 deletions tests/google/firebase_client/test_firebase_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ def test_list_releases(firebase_client, release, mock_releases):
assert releases[1].buildVersion == "71"


@pytest.mark.parametrize(
("order_by", "expected_order_by_param"),
(
(OrderBy.CREATE_TIME_DESC, "createTime desc"),
(OrderBy.CREATE_TIME_ASC, "createTime"),
),
)
def test_list_releases_order_by(firebase_client, mock_releases, order_by, expected_order_by_param):
firebase_client.releases.list(
"firebase-project-id",
"firebase-app-id",
order_by=order_by,
page_size=2,
)

mock_releases.return_value.list.assert_called_once_with(
orderBy=expected_order_by_param,
parent="projects/firebase-project-id/apps/firebase-app-id",
pageSize=2,
pageToken="",
)


def test_list_releases_limit(firebase_client, mock_releases):
releases = firebase_client.releases.list(
"firebase-project-number",
Expand Down
20 changes: 20 additions & 0 deletions tests/tools/test_firebase_app_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from codemagic.google.services.firebase import ReleasesService
from codemagic.tools.firebase_app_distribution import FirebaseAppDistribution
from codemagic.tools.firebase_app_distribution.argument_types import CredentialsArgument
from codemagic.tools.firebase_app_distribution.argument_types import ReleasesOrderByArgument
from codemagic.tools.firebase_app_distribution.arguments import FirebaseArgument
from codemagic.tools.firebase_app_distribution.errors import FirebaseAppDistributionError

Expand All @@ -26,6 +27,25 @@
json_output_argument = FirebaseArgument.JSON_OUTPUT


@pytest.mark.parametrize(
("argument", "expected_order_by", "expected_cli_token"),
(
(ReleasesOrderByArgument.CREATE_TIME_DESC, OrderBy.CREATE_TIME_DESC, "createTimeDesc"),
(ReleasesOrderByArgument.CREATE_TIME_ASC, OrderBy.CREATE_TIME_ASC, "createTime"),
),
)
def test_releases_order_by_argument(argument, expected_order_by, expected_cli_token):
# CLI parameter value stays a single, backwards-compatible token and maps to the API-facing OrderBy.
assert argument.value == expected_cli_token
assert argument.order_by is expected_order_by


def test_every_releases_order_by_argument_maps_to_order_by():
# Guards against adding a CLI ordering choice without a matching API-facing OrderBy member.
for argument in ReleasesOrderByArgument:
assert isinstance(argument.order_by, OrderBy)


@pytest.fixture
def releases() -> List[Release]:
mock_response_path = pathlib.Path(__file__).parent / "mocks" / "firebase_releases.json"
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.