From b1de9564da451309af109a321a0059a856492815 Mon Sep 17 00:00:00 2001 From: Atom <65351520+atom-tr@users.noreply.github.com> Date: Fri, 13 Oct 2023 17:26:11 +0700 Subject: [PATCH 1/8] Update action.yml --- action.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index fd0f263..4933675 100644 --- a/action.yml +++ b/action.yml @@ -36,4 +36,8 @@ inputs: runs: using: "docker" - image: "Dockerfile" \ No newline at end of file + image: "Dockerfile" + +branding: + icon: 'activity' + color: 'blue' From 61c1f7a73579fde26f03513d36a9c69e876e3231 Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:20:56 +0700 Subject: [PATCH 2/8] logger --- .github/workflows/python.yml | 2 +- requirements.txt | 4 +- src/{manager_github.py => _github.py} | 10 +-- src/_logger.py | 53 ++++++++++++++++ src/main.py | 89 ++++++++++++++++----------- 5 files changed, 117 insertions(+), 41 deletions(-) rename src/{manager_github.py => _github.py} (87%) create mode 100644 src/_logger.py diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index aaaf6df..31a86ae 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -11,7 +11,7 @@ jobs: with: python-version: "3.11" - - name: Lint + - name: Lint with flake8 run: | pip install flake8 flake8 --ignore E501,E402 src/ \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index e4922ad..8d6f2b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,6 @@ google-auth-oauthlib # GitHub integration modules: PyGithub~=1.58 -GitPython~=3.1 \ No newline at end of file +GitPython~=3.1 + +humanize \ No newline at end of file diff --git a/src/manager_github.py b/src/_github.py similarity index 87% rename from src/manager_github.py rename to src/_github.py index e79ba72..cbb9fc1 100644 --- a/src/manager_github.py +++ b/src/_github.py @@ -6,7 +6,9 @@ from git import Repo from github import Github, AuthenticatedUser, Repository -from manager_environment import EnvironmentManager as EM +# from manager_environment import EnvironmentManager as EM + +GH_TOKEN = environ["INPUT_GH_TOKEN"] class GitHubManager: @@ -26,13 +28,13 @@ def prepare_github_env(cls): - Named repo of the user [username]/[username]. - Clone of the named repo. """ - github = Github(EM.GH_TOKEN) + github = Github(GH_TOKEN) clone_path = "repo" # cls.USER = github.get_user() rmtree(clone_path, ignore_errors=True) - cls._REMOTE_NAME = EM.GITHUB_REPOSITORY - cls._REPO_PATH = f"https://{EM.GH_TOKEN}@github.com/{cls._REMOTE_NAME}.git" + cls._REMOTE_NAME = environ["GITHUB_REPOSITORY"] + cls._REPO_PATH = f"https://{GH_TOKEN}@github.com/{cls._REMOTE_NAME}.git" cls.REMOTE = github.get_repo(cls._REMOTE_NAME) cls.REPO = Repo.clone_from(cls._REPO_PATH, to_path=clone_path) diff --git a/src/_logger.py b/src/_logger.py new file mode 100644 index 0000000..061b0b9 --- /dev/null +++ b/src/_logger.py @@ -0,0 +1,53 @@ +from datetime import datetime +from logging import getLogger, Logger, StreamHandler +from string import Template +from typing import Dict + +from humanize import precisedelta + + +class Logger: + _COLOR_RESET = "\u001B[0m" + _COLOR_RED = "\u001B[31m" + _COLOR_GREEN = "\u001B[32m" + _COLOR_BLUE = "\u001B[34m" + _COLOR_YELLOW = "\u001B[33m" + + _DATE_TEMPLATE = "date" + _TIME_TEMPLATE = "time" + + _logger: Logger + + def __init__(self, level: str): + self._logger = getLogger(__name__) + self._logger.setLevel(level) + self._logger.addHandler(StreamHandler()) + + @classmethod + def _process_template(cls, message: str, kwargs: Dict) -> str: + if cls._DATE_TEMPLATE in kwargs: + kwargs[cls._DATE_TEMPLATE] = f"{datetime.strftime(kwargs[cls._DATE_TEMPLATE], '%d-%m-%Y %H:%M:%S:%f')}" + if cls._TIME_TEMPLATE in kwargs: + kwargs[cls._TIME_TEMPLATE] = precisedelta(kwargs[cls._TIME_TEMPLATE], minimum_unit="microseconds") + + return Template(message).substitute(kwargs) + + @classmethod + def g(cls, message: str, **kwargs): + message = cls._process_template(message, kwargs) + cls._logger.info(f"{cls._COLOR_GREEN}{message}{cls._COLOR_RESET}") + + @classmethod + def i(cls, message: str, **kwargs): + message = cls._process_template(message, kwargs) + cls._logger.debug(f"{cls._COLOR_BLUE}{message}{cls._COLOR_RESET}") + + @classmethod + def w(cls, message: str, **kwargs): + message = cls._process_template(message, kwargs) + cls._logger.warning(f"{cls._COLOR_YELLOW}{message}{cls._COLOR_RESET}") + + @classmethod + def p(cls, message: str, **kwargs): + message = cls._process_template(message, kwargs) + cls._logger.error(message) diff --git a/src/main.py b/src/main.py index a63da2b..56b4f35 100644 --- a/src/main.py +++ b/src/main.py @@ -6,24 +6,38 @@ from __future__ import print_function import os.path +from os import getenv, environ import json - +from datetime import datetime from google.oauth2.credentials import Credentials -from googleapiclient import errors +# from googleapiclient import errors from googleapiclient.discovery import build - -from manager_environment import EnvironmentManager as ENV -from manager_github import GitHubManager +from _github import GitHubManager +from _logger import Logger # If modifying these scopes, delete the file token.json. SCOPES = ['https://www.googleapis.com/auth/script.projects'] +# Get environment variables +TIMEZONE = getenv("INPUT_TIMEZONE", "Asia/Ho_Chi_Minh") + +# Google Script +PROJECT_ID = environ["INPUT_PROJECT_ID"] +PROJECT_PATH = environ["INPUT_PROJECT_PATH"] +# Google app +CLIENT_TYPE = environ["INPUT_CLIENT_TYPE"] +CLIENT_ID = environ["INPUT_CLIENT_ID"] +CLIENT_SECRET = environ["INPUT_CLIENT_SECRET"] +REFRESH_TOKEN = environ["INPUT_REFRESH_TOKEN"] + MANIFEST = { - "timeZone": f"{ENV.TIMEZONE}", + "timeZone": f"{TIMEZONE}", "exceptionLogging": "CLOUD" } +_TRUTHY = ["true", "1", "t", "y", "yes"] +logger = Logger("DEBUG" if getenv("DEBUG_RUN", "False").lower() in _TRUTHY else "INFO") def main(): @@ -35,41 +49,46 @@ def main(): # created automatically when the authorization flow completes for the first # time. token = { - 'refresh_token': ENV.REFRESH_TOKEN, + 'refresh_token': REFRESH_TOKEN, "token_uri": "https://oauth2.googleapis.com/token", - "client_id": ENV.CLIENT_ID, - "client_secret": ENV.CLIENT_SECRET, + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, "scopes": [ "https://www.googleapis.com/auth/script.projects" ], } creds = Credentials.from_authorized_user_info(token, SCOPES) - try: - service = build('script', 'v1', credentials=creds) - # Call the Apps Script API - # Upload two files to the project - request = { - 'files': [{ - 'name': 'appsscript', - 'type': 'JSON', - 'source': json.dumps(MANIFEST) - }] - } - # loop through gs files in webflow directory - repo_path = f'repo/{ENV.PROJECT_PATH}' - for file in os.listdir(repo_path): - if file.endswith('.gs'): - with open(os.path.join(repo_path, file), 'r') as f: - request['files'].append({ - 'name': file, - 'type': 'SERVER_JS', - 'source': f.read() - }) - service.projects().updateContent(body=request, scriptId=ENV.PROJECT_ID).execute() - except errors.HttpError as error: - # The API encountered a problem. - print(error.content) + service = build('script', 'v1', credentials=creds) + # Call the Apps Script API + # Upload two files to the project + request = { + 'files': [{ + 'name': 'appsscript', + 'type': 'JSON', + 'source': json.dumps(MANIFEST) + }] + } + # loop through gs files in webflow directory + repo_path = f'repo/{PROJECT_PATH}' + for file in os.listdir(repo_path): + if file.endswith('.gs'): + logger.i("Found file $file.", file=file) + with open(os.path.join(repo_path, file), 'r') as f: + request['files'].append({ + 'name': file, + 'type': 'SERVER_JS', + 'source': f.read() + }) + else: + logger.i("Skipping file $file.", file=file) + service.projects().updateContent(body=request, scriptId=PROJECT_ID).execute() if __name__ == '__main__': - main() + start_time = datetime.now() + logger.g("Program execution started at $date.", date=start_time) + try: main() + except Exception as e: logger.p("Program execution failed with error: $error.", error=e) + end_time = datetime.now() + logger.g("Program execution finished at $date.", date=end_time) + logger.p("Program finished in $time.", time=end_time - start_time) From dda00c2d786f95c025fbfb52405c7b7c994c378e Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:21:50 +0700 Subject: [PATCH 3/8] . --- src/main.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 56b4f35..6535134 100644 --- a/src/main.py +++ b/src/main.py @@ -87,8 +87,10 @@ def main(): if __name__ == '__main__': start_time = datetime.now() logger.g("Program execution started at $date.", date=start_time) - try: main() - except Exception as e: logger.p("Program execution failed with error: $error.", error=e) + try: + main() + except Exception as e: + logger.p("Program execution failed with error: $error.", error=e) end_time = datetime.now() logger.g("Program execution finished at $date.", date=end_time) logger.p("Program finished in $time.", time=end_time - start_time) From 6ab5249d43af91d5696a788923099ce093cbca0f Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:28:29 +0700 Subject: [PATCH 4/8] fix logger --- src/_logger.py | 55 +++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/src/_logger.py b/src/_logger.py index 061b0b9..89142f8 100644 --- a/src/_logger.py +++ b/src/_logger.py @@ -7,11 +7,11 @@ class Logger: - _COLOR_RESET = "\u001B[0m" - _COLOR_RED = "\u001B[31m" - _COLOR_GREEN = "\u001B[32m" - _COLOR_BLUE = "\u001B[34m" - _COLOR_YELLOW = "\u001B[33m" + _RESET = "\u001B[0m" + _RED = "\u001B[31m" + _GREEN = "\u001B[32m" + _BLUE = "\u001B[34m" + _YELLOW = "\u001B[33m" _DATE_TEMPLATE = "date" _TIME_TEMPLATE = "time" @@ -23,31 +23,26 @@ def __init__(self, level: str): self._logger.setLevel(level) self._logger.addHandler(StreamHandler()) - @classmethod - def _process_template(cls, message: str, kwargs: Dict) -> str: - if cls._DATE_TEMPLATE in kwargs: - kwargs[cls._DATE_TEMPLATE] = f"{datetime.strftime(kwargs[cls._DATE_TEMPLATE], '%d-%m-%Y %H:%M:%S:%f')}" - if cls._TIME_TEMPLATE in kwargs: - kwargs[cls._TIME_TEMPLATE] = precisedelta(kwargs[cls._TIME_TEMPLATE], minimum_unit="microseconds") + def _process_template(self, message: str, kwargs: Dict) -> str: + if self._DATE_TEMPLATE in kwargs: + kwargs[self._DATE_TEMPLATE] = f"{datetime.strftime(kwargs[self._DATE_TEMPLATE], '%d-%m-%Y %H:%M:%S:%f')}" + if self._TIME_TEMPLATE in kwargs: + kwargs[self._TIME_TEMPLATE] = precisedelta(kwargs[self._TIME_TEMPLATE], minimum_unit="microseconds") return Template(message).substitute(kwargs) - @classmethod - def g(cls, message: str, **kwargs): - message = cls._process_template(message, kwargs) - cls._logger.info(f"{cls._COLOR_GREEN}{message}{cls._COLOR_RESET}") - - @classmethod - def i(cls, message: str, **kwargs): - message = cls._process_template(message, kwargs) - cls._logger.debug(f"{cls._COLOR_BLUE}{message}{cls._COLOR_RESET}") - - @classmethod - def w(cls, message: str, **kwargs): - message = cls._process_template(message, kwargs) - cls._logger.warning(f"{cls._COLOR_YELLOW}{message}{cls._COLOR_RESET}") - - @classmethod - def p(cls, message: str, **kwargs): - message = cls._process_template(message, kwargs) - cls._logger.error(message) + def g(self, message: str, **kwargs): + message = self._process_template(message, kwargs) + self._logger.info(f"{self._GREEN}{message}{self._RESET}") + + def i(self, message: str, **kwargs): + message = self._process_template(message, kwargs) + self._logger.debug(f"{self._BLUE}{message}{self._RESET}") + + def w(self, message: str, **kwargs): + message = self._process_template(message, kwargs) + self._logger.warning(f"{self._YELLOW}{message}{self._RESET}") + + def p(self, message: str, **kwargs): + message = self._process_template(message, kwargs) + self._logger.error(message) From 4d064bacb2408bb1853357bc758500faa247bd82 Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:47:20 +0700 Subject: [PATCH 5/8] . --- Dockerfile | 2 +- src/main.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bcd2530..58a32ce 100644 --- a/Dockerfile +++ b/Dockerfile @@ -10,4 +10,4 @@ RUN apk add --no-cache g++ zlib-dev make git && pip3 install -r /app/requirement ADD src/* /app/ ENV PYTHONPATH /app -ENTRYPOINT cd /app/ && python3 main.py \ No newline at end of file +ENTRYPOINT cd /app/ && python3 main.py >> $GITHUB_OUTPUT \ No newline at end of file diff --git a/src/main.py b/src/main.py index 6535134..bb13b73 100644 --- a/src/main.py +++ b/src/main.py @@ -89,8 +89,12 @@ def main(): logger.g("Program execution started at $date.", date=start_time) try: main() + print("status=succeeded") except Exception as e: logger.p("Program execution failed with error: $error.", error=e) + print("status=failed") + end_time = datetime.now() logger.g("Program execution finished at $date.", date=end_time) logger.p("Program finished in $time.", time=end_time - start_time) + From 641b9c1bd81181fe3afabf49b055c945ae54d122 Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:47:42 +0700 Subject: [PATCH 6/8] . --- src/main.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index bb13b73..193f818 100644 --- a/src/main.py +++ b/src/main.py @@ -93,8 +93,6 @@ def main(): except Exception as e: logger.p("Program execution failed with error: $error.", error=e) print("status=failed") - end_time = datetime.now() logger.g("Program execution finished at $date.", date=end_time) - logger.p("Program finished in $time.", time=end_time - start_time) - + logger.p("Program finished in $time.", time=end_time - start_time) From ebba84b085591c182b72437ca4126dee1263202e Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:53:26 +0700 Subject: [PATCH 7/8] exit if error --- src/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main.py b/src/main.py index 193f818..eb418ca 100644 --- a/src/main.py +++ b/src/main.py @@ -85,6 +85,7 @@ def main(): if __name__ == '__main__': + error = False start_time = datetime.now() logger.g("Program execution started at $date.", date=start_time) try: @@ -93,6 +94,9 @@ def main(): except Exception as e: logger.p("Program execution failed with error: $error.", error=e) print("status=failed") + error = True end_time = datetime.now() logger.g("Program execution finished at $date.", date=end_time) - logger.p("Program finished in $time.", time=end_time - start_time) + logger.p("Program finished in $time.", time=end_time - start_time) + if error: + exit(1) From 39de19b5bba6af0d2e6e1fa0d75bc65fb689a165 Mon Sep 17 00:00:00 2001 From: atom-tr Date: Fri, 13 Oct 2023 21:56:46 +0700 Subject: [PATCH 8/8] error log --- src/_logger.py | 4 ++++ src/main.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/_logger.py b/src/_logger.py index 89142f8..2b13611 100644 --- a/src/_logger.py +++ b/src/_logger.py @@ -42,6 +42,10 @@ def i(self, message: str, **kwargs): def w(self, message: str, **kwargs): message = self._process_template(message, kwargs) self._logger.warning(f"{self._YELLOW}{message}{self._RESET}") + + def e(self, message: str, **kwargs): + message = self._process_template(message, kwargs) + self._logger.error(f"{self._RED}{message}{self._RESET}") def p(self, message: str, **kwargs): message = self._process_template(message, kwargs) diff --git a/src/main.py b/src/main.py index eb418ca..bcf98a0 100644 --- a/src/main.py +++ b/src/main.py @@ -92,8 +92,8 @@ def main(): main() print("status=succeeded") except Exception as e: - logger.p("Program execution failed with error: $error.", error=e) - print("status=failed") + logger.e("Program execution failed with error: $error.", error=e) + print(f"status=failed\nerror={e}") error = True end_time = datetime.now() logger.g("Program execution finished at $date.", date=end_time)