-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unify Google API clients for Google Play and Firebase #443
Conversation
…facor/unify-google-api-clients
…facor/unify-google-api-clients
_OMIT_KEYS: Tuple[str, ...] = ("_raw",) | ||
_OMIT_IF_NONE_KEYS: Tuple[str, ...] = tuple() | ||
|
||
class AppleDictSerializable(DictSerializable): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DictSerializable
is now defined in codemagic.models
. It is identical to what is here apart from how datetime
objects are serialized.
def __init__(cls, *args, **kwargs): | ||
super().__init__(*args, **kwargs) | ||
deprecated_environment_variable_key = getattr(cls, "deprecated_environment_variable_key", None) | ||
environment_variable_key = getattr(cls, "environment_variable_key", None) | ||
if deprecated_environment_variable_key and not environment_variable_key: | ||
raise ValueError( | ||
"deprecated_environment_variable_key can only be set if environment_variable_key is also set", | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard check to ensure that deprecated environment variable keys can only be defined in case environment_variable_key
is defined to avoid developer errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaces GooglePlayDeveloperAPIClient
from codemagic.google_play
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functionally identical to old ReleaseManager
that was defined in src/codemagic/google/resource_managers/release_manager.py
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Google services are different enough that such an abstraction is just a burden. Request execution lives now in the base ResourceManager
class but request building and response handling is left for manager implementations.
def resource_type(self) -> Type[ResourceT]: | ||
raise NotImplementedError() | ||
|
||
def _execute_request( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used to be part of ActingManagerMixin
which is removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As there are naming conflicts between different services, then it is better to isolate service specific definitions into relevant namespaces.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this was very Firebase specific and could not be extended to other APIs. It was removed altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This Resource
definition combines old implementations of Firebase and Google Play resources so that all needs are covered. String representation is modified slightly to be easier to read by following some patterns from Yaml.
|
||
from codemagic import cli | ||
|
||
|
||
class CredentialsArgument(cli.EnvironmentArgumentValue[str]): | ||
environment_variable_key = "GCLOUD_SERVICE_ACCOUNT_CREDENTIALS" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Environment variable name GCLOUD_SERVICE_ACCOUNT_CREDENTIALS
is ambiguous and can be confusing. Use GOOGLE_PLAY_SERVICE_ACCOUNT_CREDENTIALS
instead, but keep the old version also functional with deprecation warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Package codemagic.google.resource_managers
was refactored to codemagic.google.services
to better reflect how Google organizes their APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't needed at all. Service can build the parent URI from explicit project number and app ID arguments without another layer of abstraction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That used to be ReleasesManager
before.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method _execute_request
from here was moved to new base service class ResourceService
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good refactoring job and nice comments to help the reviewing job.
I left couple of comments.
class Resource(ABC): | ||
__google_api_label__: ClassVar[Optional[str]] = None | ||
class Resource(DictSerializable, JsonSerializable): | ||
@staticmethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any other purpose than the str
representation of the object for all these code?
Now the object is DictSerializable/JsonSerializable
so probably we can get rid of all this and just use a prettify version of the dict/json
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Base Resource
class is indeed mostly just to have a nice string representation of the object which is displayed to the user.
JsonSerializable
is just nice to have and adds a convenience method resource.json(**dump_options)
, which is just a shorthand for json.dumps(resource.dict(), **dump_options)
. As it exists and is also widely used for App Store Connect resources, then I don't see any reasons not to have it here.
DictSerializable
does a little more than just dataclasses.asdict
though. It generates a dictionary representation of the resource in a way that the dictionary can be directly passed along to different API calls which require the dictionary to be JSON serializable. That is, the whole dictionary is recursively transformed to contain only basic JSON serializable types. For example ISO8601 representation is used for datetimes, enums are converted to their respective values etc.
Co-authored-by: fran-tirapu <129050941+fran-tirapu@users.noreply.github.com>
Unify Google APIs usage under a common package
codemagic.google
which can be used for bothfirebase-app-distribution
andgoogle-play
tools.Note
This PR contains some breaking changes to internal Python APIs, but all CLI usage remains backwards compatible.
Updated actions:
firebase-app-distribution get-latest-build-version
firebase-app-distribution releases list
google-play get-latest-build-number
google-play tracks get
google-play tracks list
google-play tracks promote-release
For more detailed list of changes refer to
CHANGELOG.md
.QA
Full feature parity with current production version is ensured on updated actions.