diff --git a/action/main.py b/action/main.py index cad9642..573b1b8 100644 --- a/action/main.py +++ b/action/main.py @@ -1,5 +1,5 @@ # standard imports -from datetime import datetime +import datetime import io import json import os @@ -28,6 +28,48 @@ GITHUB_HEADERS = {'Authorization': f'token {GITHUB_API_TOKEN}'} +class TimestampUTC: + """ + Timestamp class to handle the timestamp conversion. + + Attributes + ---------- + timestamp : datetime.datetime + The timestamp in datetime format. + year : int + The year of the timestamp. + month : str + The month of the timestamp, zero-padded. + day : str + The day of the timestamp, zero-padded. + hour : str + The hour of the timestamp, zero-padded. + minute : str + The minute of the timestamp, zero-padded. + second : str + The second of the timestamp, zero-padded. + """ + def __init__(self, iso_timestamp: str): + # use datetime.datetime and convert created at to yyyy.m.d-hhmmss + # GitHub can provide timestamps in different formats, ensure we handle them all using `fromisoformat` + # timestamp: "2023-01-25T10:43:35Z" + # timestamp "2024-07-14T13:17:25-04:00" + self.timestamp = datetime.datetime.fromisoformat(iso_timestamp).astimezone(datetime.timezone.utc) + self.year = self.timestamp.year + self.month = str(self.timestamp.month).zfill(2) + self.day = str(self.timestamp.day).zfill(2) + self.hour = str(self.timestamp.hour).zfill(2) + self.minute = str(self.timestamp.minute).zfill(2) + self.second = str(self.timestamp.second).zfill(2) + + def __repr__(self): + class_name = type(self).__name__ + return f"{class_name}(y{self.year}.m{self.month}.d{self.day}.h{self.hour}.m{self.minute}.s{self.second})" + + def __str__(self): + return f"{self.year=}, {self.month=}, {self.day=}, {self.hour=}, {self.minute=}, {self.second=}" + + def append_github_step_summary(message: str): """ Append a message to the GitHub Status Summary. @@ -212,27 +254,17 @@ def get_push_event_details() -> dict: # get the commit commit_timestamp = github_event["commits"][0]['timestamp'] - # use regex and convert created at to yyyy.m.d-hhmmss - # GitHub can provide timestamps in different formats, ensure we handle them all using `fromisoformat` - # timestamp: "2023-01-25T10:43:35Z" - # timestamp "2024-07-14T13:17:25-04:00" - timestamp = datetime.fromisoformat(commit_timestamp) - year = timestamp.year - month = str(timestamp.month).zfill(2) - day = str(timestamp.day).zfill(2) - hour = str(timestamp.hour).zfill(2) - minute = str(timestamp.minute).zfill(2) - second = str(timestamp.second).zfill(2) + ts = TimestampUTC(iso_timestamp=commit_timestamp) if os.getenv('INPUT_DOTNET', 'false').lower() == 'true': # dotnet versioning - build = f"{hour}{minute}" - revision = second - release_version = f"{year}.{int(month)}{day}.{int(build)}.{int(revision)}" + build = f"{ts.hour}{ts.minute}" + revision = ts.second + release_version = f"{ts.year}.{int(ts.month)}{ts.day}.{int(build)}.{int(revision)}" else: # default versioning - build = f"{hour}{minute}{second}" - release_version = f"{year}.{int(month)}{day}.{int(build)}" + build = f"{ts.hour}{ts.minute}{ts.second}" + release_version = f"{ts.year}.{int(ts.month)}{ts.day}.{int(build)}" push_event_details['release_version'] = release_version return push_event_details diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index f614f09..0d27acf 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -1,5 +1,6 @@ # standard imports import os +from typing import Dict, Tuple, Union # lib imports import pytest @@ -8,6 +9,90 @@ from action import main +@pytest.mark.parametrize('iso_timestamp', [ + ('1970-01-01T00:00:00Z', dict( + year=1970, + month='01', + day='01', + hour='00', + minute='00', + second='00', + )), + ('2023-11-27T23:58:28Z', dict( + year=2023, + month='11', + day='27', + hour='23', + minute='58', + second='28', + )), + ('2023-01-25T10:43:35Z', dict( + year=2023, + month='01', + day='25', + hour='10', + minute='43', + second='35', + )), + ('2024-07-14T17:17:25Z', dict( + year=2024, + month='07', + day='14', + hour='17', + minute='17', + second='25', + )), + ('2024-07-14T13:17:25-04:00', dict( + year=2024, + month='07', + day='14', + hour='17', # include timezone offset + minute='17', + second='25', + )), + ('2024-07-14T13:17:25+04:00', dict( + year=2024, + month='07', + day='14', + hour='09', # include timezone offset + minute='17', + second='25', + )), + ('2024-07-22T22:17:25-04:00', dict( + year=2024, + month='07', + day='23', + hour='02', # include timezone offset + minute='17', + second='25', + )), +]) +def test_timestamp_class(iso_timestamp: Tuple[str, Dict[str, Union[int, str]]]): + timestamp = main.TimestampUTC(iso_timestamp=iso_timestamp[0]) + + assert timestamp.year == iso_timestamp[1]['year'] + assert timestamp.month == iso_timestamp[1]['month'] + assert timestamp.day == iso_timestamp[1]['day'] + assert timestamp.hour == iso_timestamp[1]['hour'] + assert timestamp.minute == iso_timestamp[1]['minute'] + assert timestamp.second == iso_timestamp[1]['second'] + + assert repr(timestamp) == ("TimestampUTC(" + f"y{iso_timestamp[1]['year']}." + f"m{iso_timestamp[1]['month']}." + f"d{iso_timestamp[1]['day']}." + f"h{iso_timestamp[1]['hour']}." + f"m{iso_timestamp[1]['minute']}." + f"s{iso_timestamp[1]['second']})") + + assert str(timestamp) == (f"self.year={iso_timestamp[1]['year']}, " + f"self.month='{iso_timestamp[1]['month']}', " + f"self.day='{iso_timestamp[1]['day']}', " + f"self.hour='{iso_timestamp[1]['hour']}', " + f"self.minute='{iso_timestamp[1]['minute']}', " + f"self.second='{iso_timestamp[1]['second']}'") + + @pytest.mark.parametrize('message', [ 'foo', 'bar',